개발 slecs

CMS 포스트 조회를 실제 DB에 연결하며 money 패턴으로 전환

목차

CMS 포스트 조회를 실제 DB와 연결하는 작업을 마무리했다. stub으로 틀만 잡아두었던 db.ts를 money 패턴으로 전면 교체한 시점이기도 하다.


왜 stub이었나

초반에 db.ts를 stub으로 남겨둔 건 의도적인 결정이었다. UI/라우팅/비즈니스 로직 레이어를 먼저 잡고, DB 연결은 인터페이스만 맞춰두면 나중에 갈아끼우기 쉽다는 판단이었다. 실제로 그렇게 흘러갔다.

문제는 stub이 길어질수록 팀 내에서 "이거 실제로 붙어있는 거 맞아?" 하는 혼선이 생긴다는 거다. PR을 보는 사람 입장에서 stub과 실 구현이 섞여 있으면 코드리뷰 포인트도 흐려진다. 그래서 이번처럼 stub → 실 연동으로 전환하는 시점은 커밋 하나로 명확하게 끊어주는 게 맞다고 생각한다.


money 패턴으로 전환한 이유

db.ts 리팩터링에서 money 패턴을 선택한 건 cms_post 특성 때문이었다. CMS 데이터는 조회 경로가 여러 갈래(admin, public API, 내부 서비스 등)로 나뉘는 경우가 많다. 이때 DB 접근 로직을 함수 한 덩어리로 뭉쳐두면, 호출 측마다 같은 쿼리를 조금씩 다르게 복붙하는 사태가 벌어진다.

money 패턴은 DB 접근 객체를 값 객체처럼 조합 가능하게 구성하는 방식이다. 연결 설정, 쿼리 빌드, 결과 매핑을 각각 명시적으로 분리해서, 어디서 어떻게 호출해도 동일한 흐름을 보장한다. 아래처럼 흐름이 정리된다.

// before: stub
export const db = {
  getCmsPost: async (id: string) => {
    return { id, title: 'stub', content: '' }; // 가짜 데이터
  },
};

// after: money 패턴 적용
export const db = buildDb(adminDbConfig, {
  getCmsPost: (query) => query<CmsPost>('cms_post').findById,
});

stub 시절엔 타입만 맞으면 통과였지만, 이제는 실제 admin_db 연결 설정이 빠지면 빌드 타임에 잡힌다. 그게 훨씬 낫다.


변경 파일 세 개의 역할

파일 변경 내용 의미
.env.example admin_db 접속 정보 키 추가 신규 투입 팀원이 로컬 세팅 시 누락 방지
package.json DB 클라이언트 의존성 추가 실 연동에 필요한 드라이버 명시
src/lib/db.ts stub → money 패턴 실 구현 핵심 전환점

.env.example 업데이트가 사소해 보이지만 팀 운영 관점에서는 절대 사소하지 않다. 환경변수 키가 example에 없으면 신규 개발자가 로컬에서 연결 실패를 마주쳤을 때 원인을 찾는 데 불필요한 시간을 쓴다. 이런 류의 "문서화 커밋"은 feature 커밋과 반드시 같이 묶어야 한다고 팀에 계속 강조하는 부분이다.

package.json 변경도 마찬가지다. 의존성이 추가됐다는 건 이 PR을 병합하면 npm install을 다시 해야 한다는 신호다. 커밋 메시지나 PR 본문에 이 사실을 명시해두면 리뷰어나 배포 담당자가 놓치지 않는다.


회고

stub → 실 연동 전환은 단순 기술 작업처럼 보이지만, 타이밍을 잘못 잡으면 꽤 피곤해진다. 너무 일찍 붙이면 DB 스키마가 안 정해진 상태에서 계속 마이그레이션을 쫓아다니게 되고, 너무 늦게 붙이면 stub 위에서 만들어진 가정들이 쌓여서 실 연동 시 예상치 못한 타입 불일치가 터진다.

이번엔 cms_post 스키마가 어느 정도 안정화된 시점에 붙였는데, 그게 맞는 타이밍이었다고 본다. 연동하고 나서 타입 에러 한 건 없었고, 리뷰도 깔끔하게 통과했다.

다음은 admin_db 연결 오류 시 fallback 처리와, 로컬/스테이징/프로덕션 환경별 설정 분기를 정리할 예정이다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.