
보통 API를 만들 때는 다음과 같은 순서로 개발을 진행한다.
- API 시그니처 구현
- API 시그니처를 바탕으로 swagger에 명세
- 데이터베이스와 연결하는 부분 구현
- 비즈니스 로직 구현
- 컨트롤러 완성
- validation 처리
몇가지 단계를 상세하게 설명해보겠다.
다음과 같은 과정을 의미한다.
- 응답과 요청 DTO 구현
- 컨트롤러에서 어떤 형태를 리턴하는지, 어떤 파라미터가 필요한지, URI는 무엇인지, HTTP Method는 무엇인지만 정해둠
- 컨버터 정의만
참고로 컨버터 정의만 해두는 예시 코드는 다음과 같다.
public static StoreResponseDTO.ReviewPreViewListDTO reviewPreViewListDTO(List<Review> reviewList){
return null;
}
API가 완성되지 않았음에도 Controller 메서드 정의만 해두자.
이렇게 하는 이유는 프론트엔드 개발자와 개발 과정에서 병목을 최대한 줄이기 위함이다.
//내가 작성한 리뷰 조회 (토큰 받는다고 가정)
@GetMapping("/{memberId}/reviews")
@Operation(summary = "내가 작성한 리뷰 조회 API",description = "내가 작성한 리뷰 목록을 조회하는 API이며, 페이징을 포함합니다. query String 으로 page 번호를 주세요")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "COMMON200",description = "OK, 성공"),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH003", description = "access 토큰을 주세요!",content = @Content(schema = @Schema(implementation = ApiResponse.class))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH004", description = "access 토큰 만료",content = @Content(schema = @Schema(implementation = ApiResponse.class))),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "AUTH006", description = "access 토큰 모양이 이상함",content = @Content(schema = @Schema(implementation = ApiResponse.class))),
})
@Parameters({
@Parameter(name = "memberId", description = "멤버의 아이디, path variable 입니다!"),
@Parameter(name = "page", description = "페이지 번호, 1페이지부터 넘겨주세요"),
})
public ApiResponse<MemberResponseDTO.ReviewPreViewListDTO> getReviewList(@ExistStore @PathVariable(name = "memberId") Long memberId, @CheckPage @RequestParam(name = "page") Integer page){
Integer realPage = page - 1;
Page<Review> reviewList = memberQueryService.getReviewList(memberId, realPage);
return ApiResponse.onSuccess(MemberConverter.reviewPreViewListDTO(reviewList));
}
서비스와 리포지토리 메서드를 구현하는 로직을 명확하게 구분하기 쉽지않다.
서비스 로직을 구현하다 보면 리포지토리의 필요성을 알게 되므로 이 두 과정을 섞어서 동시에 진행하게 된다.
조회 API에서 정보가 너무 많을 경우 한번에 이 데이터를 가져오려고하면 엄청난 렉이 발생한다.
따라서 이를 끊어서 보여주는 것을 페이징이라고 한다.
다음과 같이 Spring Data JPA에서 메서드 이름만드로 SQL을 만들어주는 기능을 사용할 수 있다.
repository
public interface ReviewRepository extends JpaRepository<Review, Long> {
Page<Review> findAllByStore(Store store, PageRequest pageRequest);
}
service
Page<Review> StorePage = reviewRepository.findAllByStore(store, PageRequest.of(page, 10));