PR 댓글 이벤트를 Query 캐시에 반영한 이유와 재조회 경계
PR 댓글 이벤트를 Query 캐시에 반영한 이유와 재조회 경계
현재 구현 안내 (2026-10-13): 아래 Socket 이벤트 기반 캐시 반영은 과거 구현 기록입니다. 현재 일반 댓글 패널은 10초 간격으로 조회하고, 작성·수정·삭제 뒤 관련 Query를 다시 조회합니다. PR 상세의 파일별 댓글 조회 훅 자체에는 주기 조회 설정이 없습니다. Socket.io는 별도 공동 리뷰방에서 사용합니다. 과거 synthetic 요청 수 비교는 현재 운영 결과가 아닙니다.
기록 정정: 기존 제목의 요청 수 비교는 제한된 synthetic 이벤트 조건의 측정이었습니다. 실제 댓글 작성·수정·삭제까지 재조회가 없어졌다는 뜻으로 읽히지 않도록 본문을 고쳤습니다. 기존 글 주소는 유지합니다.
CodeMate의 PR 댓글은 Socket 이벤트와 사용자의 직접 변경이 같은 화면에 도착합니다. 처음에는 변경을 받을 때마다 invalidateQueries로 목록을 다시 읽는 방식이었습니다. 댓글 하나가 바뀌어도 전체 목록의 fetching 상태가 반복되는 점이 문제였습니다.
여기서 모든 재조회를 없애는 것이 목표는 아니었습니다. Socket 이벤트가 전달하는 변경분은 화면 캐시에 바로 반영하고, 사용자가 댓글을 작성·수정·삭제한 뒤에는 서버가 확정한 상태를 다시 확인해야 했습니다.
Socket 이벤트는 해당 댓글만 갱신
댓글에는 답글이 중첩됩니다. 단순히 최상위 배열에 새 항목을 붙이면 reply나 수정 이벤트를 올바른 위치에 반영할 수 없습니다. setQueryData에서 댓글 ID로 tree를 재귀 순회하고, create 이벤트는 같은 ID가 이미 있는지 확인한 뒤 반영했습니다. update·delete·reaction payload도 기존 tree를 직접 변경하지 않고 새 객체로 갱신했습니다.
Socket이 정상적으로 연결된 동안에는 create mutation의 local append와 socket echo가 같은 댓글을 두 번 넣지 않도록 경로를 나눴습니다. 연결 실패 시에는 polling fallback이 DB 상태를 다시 읽습니다.
Mutation 뒤에는 재조회
브라우저가 보낸 mutation의 성공 응답과 다른 클라이언트의 이벤트가 겹칠 수 있습니다. 그래서 댓글 작성·수정·삭제 뒤에는 관련 Query를 재조회해 최종 DB 상태와 맞춥니다. Socket 이벤트를 cache patch로 처리한다는 말이 모든 댓글 작업에서 네트워크 요청이 0이라는 뜻은 아닙니다.
두 경로의 책임은 다음처럼 구분했습니다.
- Socket 이벤트 수신: payload의 댓글 ID와 변경 유형을 확인해 Query 캐시를 갱신합니다.
- 클라이언트 mutation 완료: 관련 Query를 재조회합니다.
- Socket 연결 실패: polling fallback으로 DB 상태를 읽습니다.
확인 범위와 남은 문제
과거의 synthetic 비교는 실제 Socket 네트워크·DB 왕복 시간이나 mutation 뒤 재조회까지 포함하지 않았습니다. 운영 환경에서 댓글 요청 수와 지연이 얼마나 달라졌는지는 이 글에서 주장하지 않습니다.
직접 cache를 갱신하면 이벤트 순서와 동시성의 책임도 클라이언트에 생깁니다. 현재 이벤트에는 sequence/version 경계가 없어 늦게 도착한 payload가 최신 상태를 덮을 수 있고, reaction 동시 변경도 별도 검증이 필요합니다. 빠른 화면 반영과 서버 상태 재확인을 각각 어디서 할지 정하는 것이 이 작업의 핵심이었습니다.