24.05.17. 코드리뷰 후기

develemon·2024년 5월 17일

Doran

목록 보기
5/13

지난 이야기


어제는 프로젝트 중간결과에 대해 코드리뷰를 받았다. 우선 현재까지 진행상황은 크게 다음과 같다.

  1. H2에서 MySQL로 마이그레이션
  2. 각 서비스에 스프링 클라우드 적용

1번 마이그레이션 작업은 처음이었지만 생각보다 간단하게 해결할 수 있었고, 2번 스프링 클라우드를 적용할 때에는 Gradle에서는 Java 및 Spring Boot 버전 제한이 있어 도중에 Maven으로 빌드툴을 변경하였다. 이 작업에서 어느 라이브러리가 빠졌는지 일일이 찾아보기도 해야했고, 특히 QueryDSL 적용에 있어서 많은 시간이 소요되었다. 그리고 서비스간 통신 기능을 테스트할 때에도 기초지식의 부실함으로 인해 많은 시간이 소모되었다. 추가로 인증 서비스도 간소화하여 적용하였는데, 웹 서비스에서는 일반적으로 회원가입 및 로그인이 필수적이다보니 스프링 시큐리티를 본격적으로 공부를 해봐야하나 고민이 들기 시작했다.

이외에도 BFF를 어떻게 구현할까, 템플릿을 받아 수정해서 사용할까 하는 고민도 들게 되었는데, 아무래도 처음인만큼 BFF를 직접 구현해보는 게 좋지 않을까 싶다. 물론 Spring docs로만 간단히 구성할 수도 있지만, Thymeleaf 적용 경험도 필요하겠고, 또 CORS를 경험해보는 것도 중요한 경험일테니까. CORS를 경험하려면 React로 프론트를 구현해야 하는 건 아닌가 걱정했는데, Thymeleaf로 만들어도 상관없다고 하니까 더 확신이 들게 되었다.

그리고 어제 멘토링 직전까지 Docker 강의를 듣고 있는 중이었다. 강의를 다시 듣기 시작하면서 생각보다 어려움은 느끼지 않는데, Docker를 잘 이해하려면 명령어 자체보다도 오히려 Docker를 처음 설치하고 구성하는 부분, 그리고 리눅스 시스템에 대한 이해가 중요하겠다는 생각이 들었다.

코드리뷰


지난 3월부터 설계해서 개발하기 시작한 프로젝트가 이제 어느덧 3개월째 진행중이다. 강의를 들으면서 지식을 쌓다가 프로젝트에 적용하고, 다시 강의를 듣는 형태로 병행이 이루어지다보니 진척이 상당히 느린 부분은 있다. 그럼에도 지난 2월의 멘토링에 비해 기술적 성숙도가 많이 높아졌다는 이야기를 들으면서 자신감을 가질 수 있게 되었다. 실력이 늘었다는 기분보다는 정체감이 더 들어 힘들었는데, 이런 이야기를 들으니 좀더 힘을 낼 수 있을 것 같았다. 물론 아무래도 기술적 너비가 넓어지긴 했지만, 깊이는 아직 얕다는 것을 스스로도 알고 있었다. 당분간은 이런 부분들을 보완하는 시간을 가지려고 한다.

코드리뷰를 통한 보완사항은 다음과 같다.

  • 엔티티 클래스에서 @Data 애노테이션 대신 @Setter를 제외한 @Getter만 적용할 것.
  • userUuid, itemUuid와 같이 각 서비스에서 DB에 저장되는 UUID 값들이 있는데, 일반적으로 UUID 값은 DB에 저장하지 않는다. 물론 서비스간 통신에서 객체 식별을 위해 UUID를 생성하여 다루긴 하지만, DB에는 저장하지 않는다.
  • 컨트롤러 계층에서 UUID 값을 받을 때마다 검증 로직이 들어가는데, 이처럼 많은 메서드에 반복되어 적용될 때에는 AOP로 구현할 것. 이때 모니터링도 가능하게끔 AOP로 로그를 남길 수 있으면 좋다.
  • 컨트롤러 영역에서 객체 변환 로직(예: VO → DTO)이 길어졌는데, 이때 Stream을 적용하여 코드를 줄일 것.
  • DB 성능 향상을 고려한다면 DB에서 인덱스를 타게끔 하는 것을 고려할 것. 인덱스를 고려할만큼 데이터가 많지는 않지만, 실무에서는 고려할 필요가 있다.
  • SQL 쿼리문의 성능을 테스트하는 방법으로 쿼리 플랜(EXPLAIN SELECT ...)을 사용할 수도 있다.
  • 테스트 코드는 주로 비즈니스 로직이 담긴 서비스 계층의 메서드들에 대해 1:1 적용할 것. 리포지토리는 ORM 프레임워크와 직접 맞닿는 부분이다보니 신뢰도 높은 프레임워크에 대해서는 테스트할 필요가 없고, 컨트롤러도 굳이 테스트를 하지 않는다.
  • 서비스 계층을 1인터페이스 1구현체로 작성하였는데, 당장 확장을 염두할 필요가 없다면 굳이 인터페이스를 둘 필요가 없다. 성급한 추상화를 주의할 것.
  • ModelMapper보다 MapStruct를 적용할 것.
  • 서비스간 통신을 하다보면 요청 중에 각 서비스에서 응답하지 못하는 에러가 발생할 가능성이 있는데, 이때 에러가 발생한 서비스에서 예외처리 로직을 두어 정상 응답이 가능하도록 해야한다. 이를 보상 트랜잭션이라고 하는데, 이때 CircuitBreakerResilience4J Retry 모듈을 활용할 수 있다. 추가로 타임아웃 전략에 대해서도 고민해볼 것.
  • REST API 호출 모듈로 RestTemplateRestClient, WebClient 등이 있는데, 이들과 비교하여 FeignClient를 적용한 이유를 설명할 수 있을 것.

보완 이후 BFF와 CI/CD 적용까지 달려보자!

profile
유랑하는 백엔드 개발자 새싹 블로그

0개의 댓글