|
| 1 | +# 트러블슈팅: Docker Compose Named Volume으로 인한 의존성 동기화 문제 |
| 2 | + |
| 3 | +## 문제 상황 |
| 4 | + |
| 5 | +### 컨테이너에서 npm 패키지를 찾을 수 없음 |
| 6 | + |
| 7 | +Sentry 모니터링 도구를 추가한 후 Docker 컨테이너에서 개발 서버를 실행하려 하니 다음과 같은 에러가 발생했습니다: |
| 8 | + |
| 9 | +``` |
| 10 | +failed to load config from /app/vite.config.ts |
| 11 | +
|
| 12 | +error when starting dev server: |
| 13 | +
|
| 14 | +Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sentry/vite-plugin' |
| 15 | +imported from /app/node_modules/.vite-temp/vite.config.ts.timestamp-1769575784050-9b415a926660a.mjs |
| 16 | +
|
| 17 | + at Object.getPackageJSONURL (node:internal/modules/package_json_reader:267:9) |
| 18 | + at packageResolve (node:internal/modules/esm/resolve:768:81) |
| 19 | + ... |
| 20 | +``` |
| 21 | + |
| 22 | +**증상**: |
| 23 | +- `package.json`에 `@sentry/vite-plugin` 패키지가 명확히 존재 |
| 24 | +- 호스트에서는 `npm install`로 정상 설치됨 |
| 25 | +- 컨테이너 내부에서만 패키지를 찾을 수 없음 |
| 26 | +- 다른 기존 패키지들은 정상 작동 |
| 27 | + |
| 28 | +## 원인 분석 |
| 29 | + |
| 30 | +### Named Volume의 동작 방식 |
| 31 | + |
| 32 | +기존 `docker-compose.yml` 설정: |
| 33 | + |
| 34 | +```yaml |
| 35 | +version: "1.0.0" |
| 36 | +services: |
| 37 | + web: |
| 38 | + volumes: |
| 39 | + - ./:/app |
| 40 | + - node_modules:/app/node_modules |
| 41 | + environment: |
| 42 | + - NODE_ENV=development |
| 43 | + - VITE_SENTRY_DSN=${VITE_SENTRY_DSN} |
| 44 | + |
| 45 | +volumes: |
| 46 | + node_modules: |
| 47 | + name: docker-ko-node_modules |
| 48 | +``` |
| 49 | +
|
| 50 | +**문제의 근본 원인**: |
| 51 | +
|
| 52 | +1. **Named Volume의 영속성** |
| 53 | + - `node_modules` named volume은 컨테이너 재시작 후에도 유지됨 |
| 54 | + - 볼륨이 한 번 생성되면 내용이 업데이트되지 않음 |
| 55 | + |
| 56 | +2. **package.json 변경 시 동기화 실패** |
| 57 | + - 호스트에서 `npm install`로 새 패키지 추가 |
| 58 | + - 볼륨은 이전 상태를 유지 (새 패키지가 볼륨에 반영 안 됨) |
| 59 | + - 컨테이너는 오래된 볼륨의 `node_modules`를 사용 |
| 60 | + |
| 61 | +3. **수동 관리 필요** |
| 62 | + - 의존성이 변경될 때마다 `docker-compose down -v`로 볼륨 삭제 필요 |
| 63 | + - 개발자가 이를 잊으면 의존성 불일치 발생 |
| 64 | + |
| 65 | +### Named Volume vs Anonymous Volume |
| 66 | + |
| 67 | +| 특성 | Named Volume | Anonymous Volume | |
| 68 | +|------|-------------|------------------| |
| 69 | +| 식별자 | 사용자 지정 이름 | Docker가 자동 생성 | |
| 70 | +| 생명주기 | 컨테이너 삭제 후에도 유지 | `docker-compose down` 시 자동 삭제 | |
| 71 | +| 의존성 동기화 | 수동 삭제 필요 | 자동 동기화 | |
| 72 | +| 사용 사례 | DB 데이터 등 영속성 필요 | node_modules 등 빌드 산출물 | |
| 73 | + |
| 74 | +## 해결 방법 |
| 75 | + |
| 76 | +### 1. Named Volume을 Anonymous Volume으로 변경 |
| 77 | + |
| 78 | +**수정 전**: |
| 79 | +```yaml |
| 80 | +volumes: |
| 81 | + - ./:/app |
| 82 | + - node_modules:/app/node_modules |
| 83 | +
|
| 84 | +volumes: |
| 85 | + node_modules: |
| 86 | + name: docker-ko-node_modules |
| 87 | +``` |
| 88 | + |
| 89 | +**수정 후**: |
| 90 | +```yaml |
| 91 | +volumes: |
| 92 | + - ./:/app |
| 93 | + # 익명 볼륨으로 node_modules 보호 |
| 94 | + # 호스트의 node_modules가 컨테이너 것을 덮어쓰지 않도록 방지 |
| 95 | + - /app/node_modules |
| 96 | +``` |
| 97 | + |
| 98 | +### 2. 기존 Named Volume 제거 및 재시작 |
| 99 | + |
| 100 | +```bash |
| 101 | +# 1. 컨테이너와 볼륨 완전 제거 |
| 102 | +docker-compose down -v |
| 103 | +
|
| 104 | +# 2. 이미지 재빌드 및 컨테이너 시작 |
| 105 | +docker-compose up --build -d |
| 106 | +
|
| 107 | +# 3. 로그 확인 |
| 108 | +docker-compose logs --tail=20 |
| 109 | +``` |
| 110 | + |
| 111 | +### 3. 추가 개선: deprecated 경고 제거 |
| 112 | + |
| 113 | +```yaml |
| 114 | +# version 필드 제거 (Docker Compose v2에서 불필요) |
| 115 | +- version: "1.0.0" |
| 116 | +services: |
| 117 | + web: |
| 118 | + ... |
| 119 | +``` |
| 120 | + |
| 121 | +## 결과 |
| 122 | + |
| 123 | +### Before |
| 124 | + |
| 125 | +**문제점**: |
| 126 | +- ❌ package.json 변경 시 수동으로 볼륨 삭제 필요 |
| 127 | +- ❌ 브랜치 전환 시 의존성 충돌 가능 |
| 128 | +- ❌ 팀원들이 볼륨 삭제를 잊어 에러 발생 |
| 129 | +- ❌ `version` 필드로 인한 경고 메시지 |
| 130 | + |
| 131 | +**워크플로우**: |
| 132 | +```bash |
| 133 | +# package.json 변경 후 |
| 134 | +npm install # 호스트에서 설치 |
| 135 | +docker-compose down -v # 볼륨 삭제 (잊기 쉬움!) |
| 136 | +docker-compose up --build # 재시작 |
| 137 | +``` |
| 138 | + |
| 139 | +### After |
| 140 | + |
| 141 | +**개선 사항**: |
| 142 | +- ✅ package.json 변경 시 자동 동기화 |
| 143 | +- ✅ `docker-compose down` 시 볼륨 자동 정리 |
| 144 | +- ✅ 브랜치별로 깨끗한 의존성 환경 |
| 145 | +- ✅ 경고 메시지 없음 |
| 146 | + |
| 147 | +**워크플로우**: |
| 148 | +```bash |
| 149 | +# package.json 변경 후 |
| 150 | +docker-compose up --build # 이것만으로 충분! |
| 151 | +``` |
| 152 | + |
| 153 | +### 실제 빌드 로그 |
| 154 | + |
| 155 | +``` |
| 156 | +✅ Sentry Vite 플러그인 정상 작동 |
| 157 | +✅ Vite 개발 서버 시작 완료 (555ms) |
| 158 | +✅ 접속 가능: http://localhost:5173/ |
| 159 | +``` |
| 160 | +
|
| 161 | +## 교훈 |
| 162 | +
|
| 163 | +### 1. Docker Volume의 올바른 사용법 |
| 164 | +
|
| 165 | +**Named Volume을 사용해야 하는 경우**: |
| 166 | +- 데이터베이스 데이터 (PostgreSQL, MySQL 등) |
| 167 | +- 영속적 스토리지가 필요한 경우 |
| 168 | +- 여러 컨테이너 간 데이터 공유 |
| 169 | +
|
| 170 | +**Anonymous Volume을 사용해야 하는 경우**: |
| 171 | +- `node_modules`, `vendor` 등 빌드 산출물 |
| 172 | +- 캐시 디렉토리 |
| 173 | +- 일시적 파일 저장소 |
| 174 | +
|
| 175 | +### 2. 개발 환경의 재현 가능성 |
| 176 | +
|
| 177 | +개발 환경에서는 **재현 가능성**이 더 중요합니다: |
| 178 | +- 브랜치를 전환할 때마다 깨끗한 환경 |
| 179 | +- package.json 변경이 즉시 반영 |
| 180 | +- 팀원 간 일관된 개발 환경 |
| 181 | +
|
| 182 | +### 3. Docker Compose 버전 관리 |
| 183 | +
|
| 184 | +Docker Compose v2부터는: |
| 185 | +- `version` 필드가 더 이상 필요하지 않음 |
| 186 | +- 명시하면 deprecated 경고 발생 |
| 187 | +- 제거하는 것이 권장사항 |
| 188 | +
|
| 189 | +### 4. Volume Mount 우선순위 |
| 190 | +
|
| 191 | +Docker는 더 구체적인 마운트 경로가 우선순위를 가집니다: |
| 192 | +
|
| 193 | +```yaml |
| 194 | +volumes: |
| 195 | + - ./:/app # 전체 디렉토리 마운트 |
| 196 | + - /app/node_modules # node_modules만 보호 (우선순위 높음) |
| 197 | +``` |
| 198 | + |
| 199 | +이를 통해 호스트의 빈 `node_modules`가 컨테이너의 것을 덮어쓰는 것을 방지합니다. |
| 200 | + |
| 201 | +## 참고 자료 |
| 202 | + |
| 203 | +- [Docker Compose - Volumes](https://docs.docker.com/compose/compose-file/07-volumes/) |
| 204 | +- [Docker Compose version field (deprecated)](https://docs.docker.com/compose/compose-file/04-version-and-name/) |
| 205 | +- [Anonymous vs Named Volumes](https://docs.docker.com/storage/volumes/) |
| 206 | + |
| 207 | +## 관련 커밋 |
| 208 | + |
| 209 | +``` |
| 210 | +057f5be [fix] Docker Compose 및 gitignore 설정 업데이트 |
| 211 | +- Docker Compose: named volume에서 anonymous volume으로 변경 |
| 212 | +- node_modules 자동 정리 및 패키지 변경 시 자동 반영 지원 |
| 213 | +``` |
0 commit comments