본문 바로가기
Essay

프로젝트 회고(당근마켓 API 클론코딩)

by 어썸오184 2021. 11. 8.
728x90
반응형

2주간 데브코스 팀원들과 함께 당근마켓 API 서버를 클론코딩 해보는 시간을 가졌습니다. 짧은 시간동안 협업을 진행하면서 느꼈던 점들을 정리해보려고 합니다.

 

1. 협업, 정말 쉽지 않구나

사실 이번에 제대로 된 협업을 처음 해봤습니다. 이전에도 웹 프로젝트 협업을 한 번 해보긴 했지만, 저는 서비스에 필요한 데이터를 수집하는 역할이었어서 프로젝트 내내 크롤러만 만드느라 다른 사람의 코드를 읽거나 고치는 경험을 못 해봤었거든요. 다른 팀원들도 웹 프로젝트는 처음이었기 때문에 프로젝트 기간 동안 기술적인 고민보다는 협업에 대한 고민을 한 시간이 더 많았어서 아쉬웠습니다. 작업은 어느 정도로 분할해야 하고, 기능은 어떻게 나눠서 작업해야 하는지도 잘 모르겠고, 작업 내용을 합칠 때마다 Conflict를 해결하느라 시간을 많이 보냈습니다. 스토리 포인트를 예측하고 작업 계획을 세우는 일도 어려웠구요. 아무튼 다 어려웠습니다 ㅠㅠ.

 

2. 제대로된 설계 위에서 시작하자.

프로젝트 중간즈음에 협업에서 발생하는 문제 중 상당수가 프로젝트 초기에 제대로 된 설계를 하지 않아서 발생한다는 것을 깨달았습니다. API 서버를 처음 만들어보기도 하고 프로젝트 기간이 짧아서 마음이 급하기도 해서 프로젝트 초반에 설계나 API 스펙 등을 충분히 고민하지 않고 “작업을 진행하면서 천천히 맞춰보자”는 마인드로 출발을 했습니다. 어떤 API가 필요할지, 요청에는 어떤 데이터가 필요하고 응답은 어떤 형식으로 할지 미리 고민하고 합의하지 않다 보니 각자의 작업물을 통합할 때마다 이곳저곳에서 충돌이 펑펑 터졌습니다. 그러다 보니 결국에는 작업시간이 더 길어졌습니다. 나중에 현행 서비스들의 API 문서(API Docs – Open APIs)를 보면서 “아 이렇게 했어야 하는구나” 하는 생각이 들었습니다. 다음 프로젝트 때는 설계에 대해서 충분히 고민하고, 스켈레톤 코드를 어느정도 만든 후에 작업을 시작하는 것이 좋겠습니다.

 

3. 규율과 강제성은 필요하다.

작업을 시작하기 전에 커밋 컨벤션을 정하고 “PR은 코드리뷰를코드 리뷰를 하고 머지하자” 같은 규칙들을 만들었는데요, 사실 지켜지지 않은 부분들이 많았습니다. 커밋 단위와 메시지가 맞지 않는 경우도 많았고 코드 리뷰를 제대로 하지 않고 급하게 머지한 작업들도 많았습니다. 기업 면접이나 코딩 테스트 같은 다른 일정들이 겹치다 보니까 프로젝트에 충분한 애정과 시간을 들이지 못한 것도 있구요. 스터디도 규칙을 지키지 않을 때 페널티를 부여했던 스터디가 그렇지 않은 스터디보다 더 오랫동안 잘 유지됐었는데 협업 프로젝트도 그런 강제성이 필요하지 않았나 하는 생각이 듭니다.

 

4. 필요한 것만, 제대로 공부해서 사용하자


롬복은 정말 꼭 필요할 때만, 주의해서 사용해야 한다는 걸 느꼈습니다. 편하다고 무지성으로 롬복 애너테이션을 남발하다가는 큰 낭패를 볼 수 있습니다. 아래는 프로젝트에서 사용한 User 엔티티의 일부인데요.

@Getter
@Builder
@Entity(name = "user")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {

    ...

    @OneToMany(mappedBy = "seller")
    private List<Product> products = new ArrayList<>();

}

프로젝트 초반에 객체 생성은 모두 빌더 패턴으로 통일하자고 합의했습니다. 그냥… 멋져보여서 써보고 싶었어요. 빌더 패턴은 객체에 필드가 너무 많을 때 생성자의 파라미터가 너무 많아져서 실수를 하거나 가독성이 떨어지는 것이 염려될 때 고려할만한 패턴인데요, 사실 돌이켜보니 IDE가 잘 개발되어있는 요즘 시대에 굳이 이게 필요한가 싶기도 합니다. 인텔리제이에서는 생성자에 커서를 대고 command+P를 누르면 생성자에 어떤 파라미터가 어떤 순서로 필요한지 다 보여주거든요.

DC5C2537-0C94-4FD0-9986-9D11FCCDE036

아무튼 빌더 애너테이션을 사용할 때, 값을 주입하지 않은 필드는 자동으로 null이 채워집니다. 위의 products처럼 필드에서 초기화를 한다고 하더라고 말이죠.

User tester = User.builder().name("tester").build();
tester.getProducts().size();  // NullPointerException이 터진다.

그래서 초기값을 주입받지 않는 경우는 @Builder.Default 애너테이션을 추가적으로 붙여줘야합니다.

@Builder.Default
@OneToMany(mappedBy = "seller")
private List<Product> products = new ArrayList<>();

근데 이걸 모르고 그냥 아무 생각 없이 쓰다가 버그를 찾는다고 수십 분을 낭비하는 사태가 있었습니다. 저희 프로젝트에서는 빌더를 고려할 만큼 파라미터가 많이 필요한 객체가 없었는데도 무지성 빌더를 남발해서 오히려 코드가 더 지저분해 보이는 문제도 있었습니다. 뭔가 새로운 것을 도입할 때는 꼭 그 필요성을 따져본 후에 잘 알아보고 도입하자는 교훈을 얻었습니다. 특히 롬복은 해당 애너테이션이 어떤 코드를 생산하는지 제대로 파악하지 않고 쓰면 정말 위험한 것 같아요. 대표적으로 @Data@ToString 같은 애너테이션들이 있죠.

여러모로 아쉬운 점이 많이 남지만 협업을 해본 것 자체로도 큰 의미가 있었던 시간이라고 생각됩니다. 또 이번 경험을 통해서 다음에는 어떻게 하면 더 잘할 수 있을지 대략적인 감을 잡을 수 있게 된 것 같습니다. 다음 프로젝트는 협업으로 인한 비용을 줄이고 기술적인 문제에 대해 깊게 고민해볼 수 있도록 노력해야겠습니다.

728x90
반응형

댓글