스프린트 2의 첫날인 오늘은 앞으로 스프린트 2에서 진행해야 할 이슈들에 대한 회의를 진행하는데 많은 시간을 보냈다.
생각보다 스프린트 2 일정은 빡빡하다고 생각했다. 2차 데모 요구사항이 생각한 것 보다 많이 나왔기 때문이다.
기능에 대한 추가는 예상했지만, 스프린트 2부터 AWS 환경에 배포 후 데모를 진행, 심지어 백엔드는 CI 도구를 이용한 배포 자동화까지 이루어져야 한다는 예상은 하지 못했다. 게다가 발표에서 브랜치 전략과 API 설계를 공유하기까지 해야 해서 준비해야 할 것이 많다.
때문에 우리가 할 과정들에 대해 일정을 정하는 것이 중요하다고 생각하여 팀원들끼리 서로 이 날까지 마무리 해서 결과를 주겠다 하는 데드라인을 설정하는 시간을 가졌다.
백엔드의 경우 스프린트 2에서 개발과 배포 자동화를 동시에 진행해야 했기 때문에 어쩔 수 없이 개발팀과 배포팀, 두 개의 팀으로 나눴다. 나, 티키, 칙촉은 핵심 기능인 프로필 기능을 구현하는 개발팀, 클레이와 코린은 쉘 스크립트 또는 CI 도구를 활용해서 AWS에 배포 자동화를 구축하는 배포팀으로 배정되었다. (정말 공평하게 사다리를 탔다.) 배포 자동화가 된다는 가정 하에, 22일에 데모데이인 만큼 최소 19일까지는 목표로 하는 기능들을 모두 구현하고 테스트까지 완료한 뒤 배포 및 연결 테스트를 진행하고, 배포 자동화 대상인 main
브랜치는 20일을 기준으로 건드리지 않도록 하기로 했다. 혹여나 새로운 기능을 추가하다가 자동 배포 시스템이 깨지면 안되지 않는가. 그렇게 하다 보니 상당히 빡빡한 일정이 나왔다.
스프린트 2에서는 인증 / 인가가 들어가고 마이 프로필 페이지가 들어가는 만큼 해당 화면에 대한 디자인을 설계해야 할 필요가 있었다. 이전 스프린트에서는 디자인에 대해 백엔드 팀원들도 모두 참여하는 회의가 별로 없었다면, 이번에는 시작부터 백엔드까지 전부 참여해서 디자인을 진행하기로 했다. 지난 스프린트가 끝난 뒤 다같이 디자인 회의에 참여했으면 더 좋은 디자인이 나오고 UI/UX 적으로 부족한 부분도 미리 잡을 수 있었을 것 같다는 의견이 나왔기 때문이다.
아직 디자인이 확정이 아니어서 공개할 수는 없지만, 프로필 화면의 경우 우리가 최종적으로 목표하는 그림으로 보유 장비를 보여주는 것 보다는 우선 텍스트를 기반으로 한 프로필을 구현하는 것을 목적으로 하여 좀 더 간소한 프로필 디자인을 만들었다. 그 과정에서 처음에 생각했던 드래그 앤 드롭 방식이 모바일 환경에서 불편할거라는 의견에 따라 클릭을 통한 프로필 설정 방식으로 변경했다.
기존에 있던 페이지에도 피드백을 하고 수정하는 시간을 가졌는데, 전체 페이지의 헤더 부분을 조금 더 키우고 로고도 크게 가운데로 옮기는 등 로고의 가시성을 좋게 만드는 작업을 진행했고, 제품 상세 조회에서 리뷰 작성 부분을 계속 남겨두는 것이 아니라 리뷰 작성 버튼을 누르면 아래에서 리뷰 작성 폼이 올라오도록 하여 리뷰 작성 시점 외에는 리뷰 리스트만 볼 수 있도록 디자인을 개선했다.
일정 및 디자인 회의가 끝난 후에 백엔드 팀원들끼리 따로 스프린트 2에서 새로 생성하거나 변경할 도메인들에 대해 설계하는 회의를 가졌다. 스프린트 2부터는 새로 회원이라는 개념이 들어가는 만큼 Review
가 Member
를 참조하도록 추가하기로 했고, 메인 화면에서 보여주는 리뷰에는 제품 정보도 들어가야 했기 때문에 Product
에 대한 참조 방식을 id를 통한 간접 참조에서 엔티티를 직접 참조하는 것으로 변경하기로 했다.
문제는 Member
- Product
간, 즉 회원과 회원이 프로필에 보유하고 있는 장비의 연관관계를 맺어주는 일이었다. 우선 가장 단순하게 생각했을때는 Member
도 다(N), Product
도 다(N)지만 Member
→ Product
참조는 필요해도 Product
→ Member
참조는 불필요하므로 다대다(@ManyToMany
) 단방향 매핑을 생각했다. 하지만 이 경우 프로필, 정확히는 인벤토리에 등록된 장비 중 대표 장비로 설정해놓을 정보를 매핑하기 힘들기 때문에 Member
- Product
연결 테이블을 InventoryItem
이라는 새로운 엔티티로 분리하였다.
분리하고 나니 문제가 생겼는데, InventoryItem
- Product
쪽은 InventoryItem
이 Product
의 정보가 필요한 것이므로 다대일 단방향 매핑을 사용하면 됐지만, Member
- InventoryItem
쪽은 Member
가 InventoryItem
의 정보가 필요하지만 반대쪽 객체 그래프 탐색은 필요 없다는 점에서 일대다 단방향 매핑이 되는 상황이었다. 하지만 외래 키 관리의 문제 때문에 일대다 단방향 매핑은 피해야 하는 상황. 처음에는 일대다 단방향을 피하기 위해 양방향으로 만드는 것을 고려했다. 이렇게 하면 외래 키 관리로 인해 UPDATE
쿼리가 한 번 더 나가는 것을 방지할 수 있기 때문이다. 하지만, 굳이 필요 없는 연관 관계가(InventoryItem
→ Member
) 맺어진다는 점이 어색하다는 의견이 많았다.
마침 코치 네오
가 근처를 지나가고 있어서 이 부분에 대한 의견을 구했다. 네오로부터 돌아온 답변은 굳이 모든 부분에 연관관계를 맺어줄 필요가 없다. 끊을 수 있는 부분은 연관관계를 끊고 간접 참조를 사용하는 것도 고려해 볼 수 있다.
라는 대답이었다.
그래서 또다른 대안으로 쿼리가 추가로 날아가더라도 InventoryItem
→ Member
쪽을 id값을 이용해 간접 참조를 하고, 프로필 조회 시 Member
와 InventoryItem
에 대해 각각 조회 쿼리를 날린 뒤 DTO를 만드는 과정에서 합치는 방법을 제시했다.
이 경우 쿼리가 두 개 날아간다는 단점은 있지만, 일대다 단방향 매핑을 피할 수 있고, 일대다 단방향을 피하기 위해 양방향을 써서 불필요한 연관관계를 사용하지 않을 수 있다는 장점이 있다. 또한 실제로는 절대 일어나서는 안되는 InventoryItem
이 Member
의 값을 수정하는 상황을 미연에 방지할 수 있다는 장점이 있다. 실제로 DDD의 관점에서는 간접 참조를 권장한다는 내용이 있었다. [DDD] 간접 참조 (feat. JPA) 다만 DDD 개념은 현재 고려하기엔 어려운 개념이기에 간접 참조의 근거로는 부적절했다.
바로 결정되지는 못하고 어떤 방법이 더 좋은 지 조금 더 토론이 이어졌는데, 특이한 점이라면 처음에 간접 참조를 주장했던 티키가 객체 매핑으로, 처음에 객체 매핑을 주장한 내가 간접 참조로 의견을 정반대로 선회했다는 점이었다. (하지만 둘 다 모든 방법에 대해 찝찝해 하기는 마찬가지였다.)
결국에는 간접 참조로 정했다. 다만 완전히 간접 참조가 더 좋아서
라기 보다는 우선 간접 참조로 해 놓고 나중에 필요하면 연관관계 매핑을 하는 것이 더 변경하기 쉽기 때문이라는 코린의 의견 덕분이었다. 이 부분은 결국 우선은 찝찝하지만 일단 가장 나아보이는 방법인 간접 참조 방식을 하고 필요할 때 설계를 변경하는 것을 다시 고려하는 방식으로 결정했다.
내일 오전에 Git 브랜치 특강이 있다. 일단 현재 우리 팀의 Git 브랜치 전략을 대충 짜 두었긴 하지만, 완벽히 확정을 지은 것은 아니기 때문에 특강을 일종의 컨펌받는 느낌으로 듣고 전략을 확정지을 예정이다. 브랜치 전략을 확정지은 뒤에는 해당 전략에 맞게(아마도 dev
브랜치를 새로 만들어서 해당 브랜치에서 개발하고 main
은 배포용 브랜치로 남길 것이 유력하다.) 브랜치를 새로 만들고 조정할 예정이다. 그리고 팀 내부에서도 다시 팀이 나눠진 만큼 Pull Request의 open, approve, 코드 리뷰에 관한 규칙을 정하는 시간을 가지고, 시간이 된다면 개발팀은 인증 / 인가에 대한 코드 작성을 시작하는 것을 목표로 하고 있다.