DB 시드 소스를 코드 트리 안에 두지 않는다
콘텐츠 (마크다운·JSON·CSV 등) 를 시드 로 DB 에 넣는 프로젝트에서, 그 시드 파일을 어디에 둘 것인가 는 의외로 큰 결정입니다. 직관적으로 "그 콘텐츠를 쓰는 앱 폴더 안 (frontend/myapp/content/)" 에 두기 쉽지만, 장기적으로는 모노레포 루트 에 두는 편이 거의 항상 옳습니다.
목차
콘텐츠 (마크다운·JSON·CSV 등) 를 시드 로 DB 에 넣는 프로젝트에서, 그 시드 파일을 어디에 둘 것인가 는 의외로 큰 결정입니다. 직관적으로 "그 콘텐츠를 쓰는 앱 폴더 안 (frontend/myapp/content/)" 에 두기 쉽지만, 장기적으로는 모노레포 루트 에 두는 편이 거의 항상 옳습니다.
1. 앱 폴더 안에 두면 생기는 사고
| 사고 | 원인 |
|---|---|
| 시드 walker 가 v1 폴더와 v2 폴더 둘 다 스캔 → 중복 insert | 마이그 source 와 SSOT 가 같은 폴더에 공존 |
| 앱 빌드 시 시드 파일이 image 에 포함 → 컨테이너 크기 증가 | 앱 코드와 한 디렉터리에 묶임 |
| 시드 파일을 수정하면 앱이 재빌드 | Next/Vite 가 content 폴더를 watch |
| docker-compose 가 마운트 경로 를 앱 디렉터리로 잡음 → 운영자 직관 어긋남 | 콘텐츠 ≠ 코드 라는 분리가 흐림 |
2. 모노레포 루트 배치의 이점
my-monorepo/
├── notes/ ← 시드 SSOT (모노레포 루트)
│ ├── backend/
│ │ ├── 01-...ko.md
│ │ └── 01-...en.md
│ └── frontend/...
├── courses/ ← 시드 SSOT
│ └── <series>/...
├── frontend/
│ └── admin/ ← 앱 (시더가 ../../notes 를 walk)
└── docker-compose.yml (../../notes:/notes:ro 마운트)
루트에 두면:
- 어느 앱 폴더와도 기계적으로 분리 — 콘텐츠 ≠ 코드 가 폴더 자체로 명시됨
- docker 마운트 경로가 콘텐츠 =
/notes· 코드 =/app으로 깔끔 - 시드 수정 시 앱 재빌드 트리거 0
- v1 → v2 마이그 후 v1 폴더를 삭제 해도 앱 코드는 흠 없음
3. 마이그 후 dead path 청소 — 한 번에 끝낸다
이 패턴을 도입할 때 가장 흔한 사고는 v1 폴더를 남겨 두는 것. "혹시 모르니 보관" 으로 두면:
- 시더가 v1 + v2 둘 다 walk → 중복 insert 또는 누락
- 신규 작업자가 "어느 게 SSOT 인지" 못 잡음
docker-compose.yml의 v1 마운트가 stale dead mount 로 남음
옳은 처리는 한 번에 끝내는 것 — git rm -rf + 마운트 라인 삭제 + helper 함수 삭제 + 5 개 문서 정합. 이 다섯 자리를 한 커밋으로 묶지 않으면 한 자리만 남아도 다음 작업자가 헷갈립니다.
4. 적용 전 / 적용 후
| 측면 | 앱 폴더 안 | 모노레포 루트 |
|---|---|---|
| 콘텐츠와 코드 경계 | 흐림 | 폴더 자체로 분리 |
| 시드 수정 시 빌드 | 트리거 됨 | 트리거 안 됨 |
| 컨테이너 이미지 크기 | 시드 포함 | 시드 미포함 (런타임 마운트) |
| v1 → v2 마이그 후 정리 | 남기기 쉬움 | 한 번에 git rm |
| 신규 작업자 SSOT 인식 | "어느 게?" | 루트가 명시 |
5. 자신의 프로젝트에 적용하려면
-
app/content/또는src/seed/안에 콘텐츠 가 있다면 모노레포 루트로 이동. - 시더가
process.cwd() + ../../를 base 로 walk 하도록 수정. - docker-compose 의 마운트를
../../notes:/notes:ro형태로 통일. - v1 → v2 마이그가 끝났다면 v1 폴더 + 마운트 + helper 를 한 커밋 으로 삭제.
- README · 폴더 구조 문서에 "콘텐츠 SSOT 는 루트
/notes/courses" 명시.
코드와 콘텐츠는 변경 주기가 다른 자산. 변경 주기가 다른 것은 폴더부터 다르게 두는 게 운영 비용이 가장 낮습니다.
data 카테고리의 다른 글
카테고리 전체 보기 →관련 글
여러 PostgreSQL 풀 한 앱에서 관리하기
관리 콘솔이나 백오피스는 한 프로세스에서 콘텐츠·카탈로그·운영 로그처럼 서로 다른 DB에 접근해야 할 수 있습니다. HTTP 경유 대신 풀 직접 접속을 선택할 때는 연결 수, 권한, 장애 격리를 함께 설계해야 합니다.
Git Submodule · Subtree · LFS — 저장소 안에 다른 저장소
한 저장소가 다른 저장소의 코드를 함께 가져가야 할 때, 또는 큰 바이너리 파일을 저장소에 넣어야 할 때 떠오르는 옵션. Submodule · Subtree · Sparse Checkout · Git LFS 가 그것. 각자 강점이 다르고 함정도 다릅니다. 이 글은 네 도구의 출자 · 동작 · 자주 만나는 함정 · 모노레…
모노레포와 가벼운 도구 선택
모노레포 (monorepo) 는 여러 프로젝트의 소스코드를 하나의 버전 관리 저장소에 모아 두는 방식. 이 글은 모노레포의 정의 · 역사 · pnpm workspace 같은 가벼운 구성으로 어디까지 가능한지 · Nx · Turborepo · Lerna · Bazel · Rush 같은 풀스케일 도구가 풀어 주는 문제.
pnpm
pnpm 은 Node.js 생태계의 패키지 매니저 가운데 하나. 이 글은 pnpm 의 출자 · 동작 방식 · 다른 매니저와의 차이를 사실 기준으로 정리합니다.