반응형

이번에는 RESTful API 설계 원칙에 따라 API를 설계하고, 대량의 데이터를 효율적으로 다룰 수 있도록 페이징(Pagination) 기능을 구현하는 방법을 알아보겠습니다.


1. RESTful API 설계 원칙

RESTful API는 웹에서 자원을 구조적으로 접근할 수 있도록 설계된 API입니다. 다음과 같은 설계 원칙을 따릅니다:

  • 자원(Resource): API는 URL을 통해 자원을 표현합니다.
    예: /users, /users/{id}
  • HTTP 메서드:
    • GET: 자원 조회
    • POST: 자원 생성
    • PUT: 자원 업데이트
    • DELETE: 자원 삭제
  • 표현(Representation): JSON 또는 XML 형식으로 데이터를 반환합니다.
  • 무상태성(Statelessness): API 호출 간 상태를 서버에 저장하지 않습니다.

2. RESTful API 페이징의 필요성

대량의 데이터를 한 번에 반환하면 네트워크 성능 및 응답 시간이 저하될 수 있습니다.
페이징을 구현하면 데이터를 페이지 단위로 나누어 반환할 수 있어 효율적인 데이터 전송이 가능합니다.


3. API 설계 예시: 사용자 목록 조회

  • URL: /api/users
  • HTTP 메서드: GET
  • 쿼리 파라미터:
    • page: 요청 페이지 번호 (기본값: 1)
    • size: 페이지 크기 (기본값: 10)

응답 예시:

{
  "page": 1,
  "size": 10,
  "totalPages": 5,
  "totalElements": 50,
  "data": [
    {"id": 1, "name": "User 1", "email": "user1@example.com"},
    {"id": 2, "name": "User 2", "email": "user2@example.com"},
    ...
  ]
}

4. Pagination 구현: Controller, Service, DAO

Controller 코드

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public ResponseEntity<?> getUsers(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "10") int size) {
        return ResponseEntity.ok(userService.getUsers(page, size));
    }
}

Service 코드

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    public Map<String, Object> getUsers(int page, int size) {
        int offset = (page - 1) * size;
        List<User> users = userDao.fetchUsers(offset, size);
        int totalElements = userDao.countUsers();
        int totalPages = (int) Math.ceil((double) totalElements / size);

        Map<String, Object> response = new HashMap<>();
        response.put("page", page);
        response.put("size", size);
        response.put("totalPages", totalPages);
        response.put("totalElements", totalElements);
        response.put("data", users);

        return response;
    }
}

DAO 코드

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<User> fetchUsers(int offset, int size) {
        String sql = "SELECT * FROM users ORDER BY id LIMIT ? OFFSET ?";
        return jdbcTemplate.query(sql, new Object[]{size, offset}, new UserRowMapper());
    }

    public int countUsers() {
        String sql = "SELECT COUNT(*) FROM users";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }
}

UserRowMapper

public class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setName(rs.getString("name"));
        user.setEmail(rs.getString("email"));
        return user;
    }
}

5. 테스트 결과

API 호출 예:
GET /api/users?page=2&size=5

결과:

{
  "page": 2,
  "size": 5,
  "totalPages": 10,
  "totalElements": 50,
  "data": [
    {"id": 6, "name": "User 6", "email": "user6@example.com"},
    {"id": 7, "name": "User 7", "email": "user7@example.com"},
    ...
  ]
}

6. 페이징 구현 시 고려사항

  1. 대용량 데이터 처리 최적화
    • 적절한 인덱스 설정.
    • 필요한 컬럼만 조회.
  2. 응답 속도 최적화
    • 페이지 크기를 제한하여 대규모 데이터를 반환하지 않도록 설정.
  3. 에러 처리
    • 페이지 범위를 벗어난 요청에 대한 처리.
    • 잘못된 쿼리 파라미터에 대한 검증.
반응형

+ Recent posts