← 염승준
06

댓글 시스템 공통화

네 도메인에 흩어져 있던 댓글을 하나의 계약으로.

문제
  • 댓글이 네 영역에 시차를 두고 추가되면서 담당자마다 요청·응답 타입이 제각각
  • 대댓글이나 멘션 하나를 손보려면 네 곳을 서로 다른 방식으로 고쳐야 했음
해결
  • 프론트 변환 코드로 덮지 않고 응답 형태 통일을 백엔드에 제안해 합의
  • Header·Content·Footer·Reply로 나눈 컴파운드 컴포넌트. 조회·작성 훅은 Footer에 주입
  • 도메인마다 다른 콘텐츠 ID 타입만 제네릭으로 열고 나머지 시그니처는 고정
결과
  • 새 도메인은 훅 한 세트(약 50줄)만 추가하면 재사용
  • 대댓글·멘션 같은 공통 기능을 한 곳에서 유지

문제

댓글이 네 영역에 시차를 두고 추가되면서 담당자마다 요청·응답 타입이 제각각이었습니다. 대댓글이나 멘션 하나를 손보려면 네 곳을 서로 다른 방식으로 고쳐야 했습니다.

먼저 응답 형태를 맞추기

프론트에서 변환 코드로 덮으면 복잡함이 프론트로 옮겨올 뿐이라 보고, 응답 형태 통일을 백엔드에 제안해 합의했습니다. 근거는 양쪽의 이득이었습니다. 프론트는 도메인별 래퍼 없이 공통 컴포넌트로 묶을 수 있고, 백엔드도 새 도메인에 같은 형태를 재사용할 수 있습니다.

조합하고, 주입받기

그 위에 댓글 UI를 역할별로 나누고, 데이터 조회·변경 훅만 밖에서 주입받도록 설계했습니다. 화면마다 필요한 조각이 달라 하나로 뭉친 컴포넌트에 플래그를 다는 대신 조합하는 쪽을 택했습니다.

Comment
├── Header    작성자 · 고정 표시 · 더보기(수정/삭제/신고)
├── Content   본문 · 멘션 렌더링 · 수정 모드
├── Footer    대댓글 토글/목록 ← 주입 지점
└── Reply     대댓글 입력 · 멘션 연동

도메인 결합은 Footer 한 곳에 모입니다. 조회 훅과 작성 훅을 props로 받기 때문에, 컴포넌트는 자기가 어느 API를 쓰는지 모릅니다.

// 이벤트 댓글
<Comment.Footer
  useRepliesQuery={useEventRepliesList}
  useCreateReplyMutation={useCreateEventComment}
/>

// 영상 댓글 - 훅만 교체
<Comment.Footer
  useRepliesQuery={useVideoRepliesList}
  useCreateReplyMutation={useCreateVideoComment}
/>

변하는 것과 지킬 것

도메인마다 다른 건 콘텐츠 ID 타입뿐이라 그것만 제네릭으로 열고 나머지 시그니처는 고정했습니다. 변하는 것과 지켜야 할 것을 계약으로 분리한 것이 이 설계의 핵심입니다.

새 도메인은 훅 한 세트(약 50줄)만 추가하면 재사용되고, 대댓글·멘션 같은 공통 기능은 한 곳에서만 유지됩니다. 캐시는 도메인별로 키를 나눠 섞이지 않게 하되, 댓글을 새로 쓰면 댓글 목록과 대댓글 목록을 함께 무효화합니다.