메가테라 20주차 주간회고 (프로젝트 4주차 회고)

20주 차 회고


메가 테라 20주 차를 진행하면서 있었던 일을 종합해서 회고하였습니다.

 

프로젝트 4주 차의 목표는 전체 게시판의 완성도를 높이고 게시판의 CRUD기능 구현하는 것과 월, 화에 아샬 님이 말씀해주신 내용을 바탕으로 controller와 service를 리팩터링 하는 것이 목표였다. 그래서 아래와 같이 작업 계획을 세웠고 작업에 대한 결과이다.

최종적으로 HOT 게시판 구현을 하지 못해서 계획했던 작업들을 모두 하지 못했기 때문에 계획한 작업을 다 하지 못한 이유에 대해서 회고를 해보려고 한다.

 

우연의 산물

이번 주 계획한 작업을 모두 달성하지 못한 첫 번째 이유는 컨트롤러와 서비스를 리팩터링 하는 부분에서 생각했던 것보다 수정해야 하는 부분들이 많아서 기존에 계획했던 스토리 포인트의 2배를 사용한 게 첫 번째 문제이다.

처음에 수정해야 할 부분은 전체 게시글을 불러올 때 여러 api를 호출해 프론트엔드에서 그 정보들을 조합해 posts들을 나타내는 것들을 백엔드 PostController에서 한 번에 처리하도록 바꾸면 끝나는 문제인 줄 알았는데 코드를 수정해나가다 보니 바꿔야 할 부분이 이것뿐만이 아니었던 것이었다.

우선 service에 대한 부분인데 기존 백엔드 Layer를 아래와 같이 설계를 했었다.

  1. UI Layer  → PostController 
  2. Application Layer  → PostService
  3. Domain Layer  → Post, PostRepository
  4. Infrastructure Layer  → PostRepository

Post와 관련된 것들은 PostService에서 모두 처리를 해줬었는데 그러지 말고 PostService를 기능 단위로 나누는 작업이 필요했다.  왜냐하면 PostController -> PostService -> PostRepository처럼 Post라는 도메인 모델로 뭔가 그럴싸하게 이어지는 건 우연의 산물이었을 뿐이란 걸 알게 되었기 때문이다. 그래서 Post뿐 아니라 모든 Service를 기능 단위로 나눠야 했다.

예를 들어 게시글을 불러오는 기능이 필요하면 GetPostService에서 처리하고 게시글을 작성하는 건 CreatePostService에서 처리하는 것처럼 구현하려는 기능에 맞게 Service를 작성해야 했다.

그렇게 기능 별로 나눠주니까 PostService에 대한 Service가 GetPostService, CreatePostService, DeletePostService, UpdatePostService 4개가 생겼고 post뿐만 아니라 각각의 도메인 모델에 대해 기능별로 나눈 Get, Create 같은 서비스를 만들고 테스트를 작성해줌으로써 기존에 생각했던 스토리 포인트보다 2배나 더 사용하게 되었다.

 

 

Value Object

그리고 또 엔티티의 값 객체에 대한 부분이다. 기존 post의 엔티티에는 게시글 아이디, 게시글을 작성한 유저 아이디, 해당 게시글이 포함되어 있는 카테고리의 아이디, 게시글의 조회수 등등 Long 타입으로 받는 필드 값이 여러 개 존재했다.

하지만 이렇게 돼버리면 post라는 객체를 만들 때 인자로 숫자를 4개 이상이 들어가 버리게 되어서 아래와 같이 1L이 4개가 post의 인자로 들어갈 때 어떤 필드 값인지 단번에 알지 못하는 문제가 발생한다.

Post post = new Post(1L, 1L, 1L, 1L)

똑같은 값 1L이 4개인데 어떤 1L이 유저 아이디인지 게시글 아이디인지 post 모델 안으로 들어가서 확인하거나 post 생성자의 인자를 받는 순서를 완전히 외우지 않는 이상 알기가 매우 어렵다.

 

이 문제를 해결하기 위해 값 객체를 만들 수가 있다.  new Post(new UserId(1L))처럼 1L이 어떤 값인지 바로 파악할 수가 있어진다.

값 객체를 이용하면 코드의 가독성적인 부분이 매우 좋아지고 도메인에 집중할 수 있게 되기 때문에 보다 나은 객체지향 프로그래밍을 할 수 있게 되는 것을 알게 되었다. 

 

그렇다고 무지성으로 모든 필드를 값 객체로 사용하면 안 되고 해당 필드를 값 객체로 사용하면 얻을 수 있는 이점들에 대해 충분히 고민을 하고 사용할 필요가 있다. 

 

설계 디테일함 부족

이번 주 계획한 작업을 모두 달성하지 못한 두 번째 이유는 댓글 / 대댓글 삭제 기능에 대한 설계 디테일함의 부족이었다.

댓글 삭제를 구현할 때는 비슷한 기능인 게시글 삭제 기능을 구현하고 시작했기 때문에 게시글 삭제와 비슷하게 구현하면 되겠지라는 안일한 생각으로 설계도 디테일하지 못하게 했다. 댓글 삭제 버튼을 누르면 해당 댓글이 삭제가 되는 당연한 설계를 한 것이었다.

이렇게 설계를 대충 하고 기능을 구현하고 제대로 작동하는지 직접 사용해보는데 당연히 문제가 발생했다.

댓글을 삭제하면 해당 댓글은 잘 삭제가 되는데 대댓글이 달려있는 댓글을 삭제하면 대댓글까지 삭제가 돼버리는 것이었다.

댓글 삭제 기능을 설계할 때  대댓글이 있는 댓글을 삭제할 때는 대댓글은 어떻게 처리할 것인지 같은 대댓글에 대한 생각을 전혀 하지 않았었다. 뒤늦게 다시 대댓글 처리 방법을 생각하고 기존에 구현했던 댓글 삭제 기능을 다시 갈아엎게 되어 한번 해도 될 일을 두 번 하게 되어 기존에 생각했던 스토리 포인트보다 4포인트 정도 초과되었던 것이었다.

 

빠른 작업 속도를 위해서 기능 구현을 위한 설계를 대충 해버리면 오히려 작업 속도는 예상치 못한 문제 떄문에 생각했던것보다 더 늘어날 수 있다는 것을 알게 되었고 디테일한 설계의 필요성도 느끼게 되었다. 설계가 다 되었다고 생각해도 한번 더 살펴보면서 처리해줘야 하는 부분은 없는지 생각해보자. 설계할 때 시간을 더 써야 구현할 때 시간을 절약할 수 있다.

 

그리고 이번주에 시작되는 5주 차 프로젝트 주간에는 작업 설계와 기획 문서를 작성하는 작업에 더 신경을 써서 프로젝트를 기록하는 습관을 들이자.