[Toy Project] API 설계 및 개인 퀘스트 공유(공동 Controller 설정)

최지나·2024년 1월 10일

개요

  • 지난 회의 에 이은 3번째 회의 시간
  • 2024.01.03~2024.01.10 기간 동안 각자 API와 개인 퀘스트 수행해온 내용을 발표하고 피드백하는 시간을 가졌다!

API 리뷰

  • ERD, UI 리뷰와 마찬가지로 각자 필요한 API들의 method, endpoint를 설계해서 공유하였다
    • 합칠 수 있는 API, 필요 없는 pathvariable, API endpoint의 RESTFUL한 naming에 초점을 맞춰 서로 피드백을 주고 받았다

개인 퀘스트 리뷰

  • 이번주의 개인 퀘스트는 각각 다음과 같았다:
- ErrorCode 및 공동 Domain 정의 
- JPA entity 생성 및 공동 Controller 정의 
- Spring Security, Swagger 설정
- Junit test 설정

그 중 내 파트인 JPA entity 생성 및 공동 Controller 정의 중 공동 Controller 정의에 대해 기록하고자 한다. 참고로 JPA entity 생성 관련된 글은 여기에 기록해 놓았다!

  • 기존
@RestController
public class ExampleController {

    @PostMapping("/api/comment")
    public DTOResCommon createUser(@RequestBody DTOReqCommon userRequest) {

        // 댓글이 없는 상황 예시
        // 에러 응답이 'Requested resource comment is not found'
        if (userRequest == null) {
            String resourceName = "comment";
            ErrorCode errorCode = ErrorCode.NOT_FOUND;
            return createErrorResponse(errorCode, resourceName);
        }

        return createSuccessResponse();
    }

    // 성공 시 response 생성
    private DTOResCommon createSuccessResponse() {
        DTOResCommon response = new DTOResCommon();
        response.setRetCode(ErrorCode.OK.getCode());
        response.setRetMsg(ErrorCode.OK.getMessage());
        return response;
    }

    // 에러 시 response 생성
    private DTOResCommon createErrorResponse(ErrorCode errorCode, String resourceName) {
        DTOResCommon response = new DTOResCommon();
        response.setRetCode(errorCode.getCode());
        response.setRetMsg(errorCode.getMessage(resourceName));
        return response;
    }
  • 공동 Controller 생성 전, 예시 Controller에서는 response를 생성하기 위해 createSuccessResponse() 또는 createErrorResponse()를 호출하는 구조로 구성되어 있었다. 메서드화를 하는 것은 좋았지만, 이렇게 되면 Controller마다 해당 메서드들을 생성해야 하기 때문에, 공동 Controller를 만들고, 이를 상속받아 응답을 생성하는 구조로 변경하였다

  • 변경

  1. ExampleController.java
@Tag(name = "예시 컨트롤러")
@SecurityRequirement(name = "bearer-key")
@RequestMapping(path = "/api/v1/common")
@RestController
public class ExampleController extends CommonController {

    @Operation(summary = "공동 Domain 적용 API", description = "1. 그대로 요청 2. sendDate \"string\"에서 null로 바꾼 뒤 요청")
    @PostMapping("/comment")
    public DTOResCommon createUser(@RequestBody DTOReqCommon userRequest) {

        // 댓글이 없는 상황 예시
        // 에러 응답: 'comment not found'
        if (userRequest.getSendDate() == null) {
            return setResult(ErrorCode.NOT_FOUND, "comment");
        }

        return setResult(ErrorCode.OK);
    }
  1. CommonController.java
public class CommonController {

    protected ObjectMapper objectMapper = new ObjectMapper()
            .enable(SerializationFeature.INDENT_OUTPUT);

    @Value("${study.systemId}")
    protected String systemId;

    protected DTOResCommon setResult(ErrorCode result, String... vars) {
        DTOResCommon res = new DTOResCommon();
        res.setSendDate(DateUtil.getCurrentDateTime());
        res.setSystemId(systemId);
        res.setRetCode(result.getCode());

        if (vars.length > 0 && vars[0] != null && !vars[0].isEmpty()) {
            res.setRetMsg(result.getMessage(vars[0]));
        } else {
            res.setRetMsg(result.getMessage());
        }
        return res;
    }
  • 이를 통해 각 Controller에서 동일한 로직을 반복적으로 구현할 필요를 없애 재사용성을 없앴고, CommonController만 수정하면 되기 때문에 유지보수성도 높였다
  • 또한 objectMapper도 CommonController에서 한 번만 생성되어 사용되도록 했다
  • 또한 DateUtil도 생성해서 현재 날짜/ 시간 정보를 일관된 규칙으로 가져오게 설정하였다

정리

  • 이번 회의시간은 약 1시간 10분 정도 소요되었다 적당했다고 생각했다!
  • 다음 Backend API 개발 완료 목표는 다음과 같다:

2024.01.26

  • 개인적인 일정들도 있고, TDD를 처음 적용해볼 예정이라 여유롭게 기한을 잡았다!

  • 대신 기한이 지나치게 길면 효율성이 떨어질 수 있기에 중간 점검일을 두었다

2024.01.15
2024.01.22

  • 내가 26일까지 해와야 하는 일들이다:
    • 게시판 관련 API 생성
    • 로깅 설정

생각

  • 회사에서 개발을 할 때는 당연하게 생각했던 것들이 많다. 예를 들어 현재 시간을 가져오는 메서드라든지, 공동 Controller 등의 구조나 구현을 생각할 필요가 잘 없었는데, 이번 기회에 전체적인 구조를 살필 수 있어 너무 좋은 것 같다! 😄
profile
의견 나누는 것을 좋아합니다 ლ(・ヮ・ლ)

0개의 댓글