와, 이 주제는 정말 모든 개발자가 한 번쯤 겪고, 또 가장 헷갈리는 부분이기도 합니다.
저도 처음에 도커 DB를 붙이면서 볼륨 설정할 때마다 "이거 영구 저장되는 건가요?", "껐다 켜면 데이터 사라지나요?" 이 질문만 백 번은 한 것 같습니다.
결론부터 말씀드리자면, 질문자님이 원하시는 "가장 깔끔하고 정석적인 방법"은 Docker Compose를 사용하고, Named Volume을 활용하며, 초기화 스크립트(Initialization Scripts)를 활용하는 조합입니다.
이게 왜 정석인지, 그리고 상황별로 어떻게 접근해야 하는지 조금 더 자세하게 풀어서 설명드릴게요.
--- ###
1.
도커 볼륨의 종류 이해하기 (가장 중요!) 먼저, 데이터 영속성 관점에서 볼륨의 세 가지 종류를 구분하는 게 핵심입니다.
1.
Bind Mount (바인드 마운트): 호스트 PC의 특정 폴더 경로를 컨테이너 내부 폴더에 직접 연결하는 방식입니다.
./data:/var/lib/postgresql/data 이런 식으로 설정하는 거죠.
장점은 호스트 PC에서 파일을 직접 열어보거나 수정할 수 있어서 디버깅이 편하다는 점입니다.
단점은, 호스트 PC의 구조에 종속적이고, 여러 개발자 간의 환경 일관성이 깨지기 쉽다는 점입니다.
(A 개발자는 C 드라이브에, B 개발자는 D 드라이브에 같은 경로로 설정할 수 없죠.) 2.
Anonymous/Ephemeral Volume (임시 볼륨): 볼륨을 지정해주지 않고 단순히 컨테이너가 사용할 공간을 주는 겁니다.
가장 가볍지만, 컨테이너가 중지되거나 삭제되면 데이터가 100% 사라집니다. 테스트용으로 "딱 이것만 돌려보고 휘발시켜도 되는" 임시 테스트에만 적합합니다.
3.
Named Volume (이름 지정 볼륨): Docker가 내부적으로 관리하는 이름의 볼륨입니다.
db_data:/var/lib/postgresql/data 이런 식으로 사용합니다.
실무에서 DB 데이터를 다룰 때 가장 많이 쓰이고, 가장 추천하는 방식입니다. 장점은 Docker가 알아서 호스트 PC의 어느 곳에, 어떻게 안전하게 저장할지 관리해 주기 때문에, 개발자 간의 환경 의존성이 사라지고 "데이터는 Docker가 알아서 잘 보관해 줄 거야"라는 안정감을 줍니다.
--- ###
2.
상황별 최적의 데이터 관리 전략 (시나리오 분리) 질문자님이 원하는 두 가지 시나리오(초기화 vs.
유지)에 맞춰 볼륨 사용법을 분리해서 설명드릴게요.
🧪 시나리오 A: 매번 깨끗한 상태에서 테스트하고 싶을 때 (Clean Slate Test) 이건 주로 단위 테스트(Unit Test)나, 특정 기능을 처음부터 다시 테스트할 때 유용합니다.
어제 돌렸던 데이터가 오늘 테스트에 영향을 주는 걸 원치 않을 때 쓰는 방법이죠.
추천 방법: Named Volume 사용 + 데이터 초기화 스크립트 활용 1.
볼륨 설정: docker-compose.yml에서 db_volume 같은 이름의 Named Volume을 정의합니다.
2.
데이터 초기화: PostgreSQL 컨테이너가 처음 시작될 때, 컨테이너 내부의 특정 디렉토리(pgdata/init)에 SQL 파일들을 넣어주면, 컨테이너가 부팅되면서 해당 SQL 파일들을 순서대로 실행해 줍니다.
3.
데이터 삭제: 만약 데이터를 완전히 초기화하고 싶다면, 가장 간단한 방법은 해당 Named Volume을 직접 삭제하는 겁니다.
docker volume rm [your_volume_name] 명령어를 실행하면, 그 볼륨에 있던 모든 데이터가 깨끗하게 사라집니다.
실무 팁: 매번 삭제하고 다시 띄우는 게 번거롭다면, 테스트 전에 docker-compose down -v를 한 번 돌려주는 습관을 들이는 게 가장 빠릅니다.
(-v 옵션이 볼륨까지 같이 삭제해 줍니다.) ####
시나리오 B: 특정 시점의 데이터를 유지하며 테스트하고 싶을 때 (State Retention Test) 예를 들어, '회원 가입' 기능 테스트를 할 때, 이미 가입된 사용자 데이터가 사라지면 안 되고, 그 상태에서 '비밀번호 찾기' 기능을 테스트하고 싶을 때가 있죠.
추천 방법: Named Volume 사용 + 데이터 백업/복원 (Dump/Restore) 이 경우에는 볼륨 자체를 건드리는 것보다, 데이터베이스 자체의 기능을 쓰는 게 훨씬 안전하고 깔끔합니다.
1.
데이터 덤프 (Export): 테스트를 시작하기 전에, 현재 DB의 데이터를 pg_dump 같은 툴로 SQL 파일 형태로 백업합니다.
pg_dump -U user -h localhost -p 5432 dbname > backup_pre_test.sql 2.
데이터 로드 (Import): 테스트가 끝나고, 다음 테스트 세션을 시작할 때 이 backup_pre_test.sql 파일을 이용해 DB를 덮어씌우거나(Overwrite), 아니면 필요한 부분만 복원(Restore)합니다.
주의점: 만약 컨테이너가 너무 커서 덤프/복원이 부담스럽다면, Named Volume을 사용하되, 테스트 직전에 컨테이너를 멈추고, 볼륨을 잠깐 다른 곳에 백업본으로 복사해두는 수동적인 방법도 있습니다.
--- ###
️ 3.
가장 깔끔한 '표준 템플릿' 구성 (Docker Compose 예시) 실제로 제가 가장 많이 쓰고, 가장 안정적이라고 느끼는 구조는 아래와 같은 docker-compose.yml 기반의 설정입니다.
volumes: # 1.
데이터를 영구 보존할 Named Volume 사용 - db_data:/var/lib/postgresql/data # 2.
초기화 스크립트가 들어갈 위치 (컨테이너 시작 시 자동 실행됨) - ./scripts/init:/docker-entrypoint-initdb.d ports: - "5432:5432" restart: always volumes: # 여기에 이름을 지정하여 Docker가 관리하게 합니다.
db_data: ``` **이 설정의 장점을 다시 정리하자면:** 1.
**`db_data:` (Named Volume):** 데이터는 Docker 엔진이 관리하는 영역에 안전하게 저장됩니다.
2.
**`./scripts/init:` (Init Scripts):** 이 폴더에 `01_create_user.sql`, `02_create_table.sql` 같은 SQL 파일을 넣어두면, `docker-compose up`을 할 때 **컨테이너가 처음 실행되는 시점에 이 파일들이 순서대로 실행**되면서 DB 구조가 세팅됩니다.
3.
**환경 변수 사용:** 비밀번호나 DB 이름 같은 민감한 정보는 YAML 파일에 직접 적지 말고, `.env` 파일을 만들어서 `environment:` 섹션에서 참조하는 것이 보안상 가장 좋습니다.
--- ### ⚠️ 개발자가 자주 하는 실수 3가지와 해결책 1.
**실수 1: `docker-compose up`만 돌리고, `docker-compose down`을 안 하는 경우** * **문제:** 컨테이너만 멈추고 볼륨 데이터는 남아있기 때문에, 다음 테스트 시점의 데이터가 꼬여서 원인을 알 수 없는 버그가 발생합니다.
* **해결:** 테스트 세션이 끝날 때는 무조건 `docker-compose down -v`를 사용하세요.
(`-v`가 볼륨까지 깔끔하게 삭제해 줍니다.) 2.
**실수 2: 환경 변수를 코드에 하드코딩하는 경우** * **문제:** 로컬 개발용으로 하드코딩하면, 다른 팀원이 이 코드를 받거나 다른 환경에 적용할 때마다 DB 접속 정보가 꼬이게 됩니다.
* **해결:** 반드시 `.env` 파일을 도입하고, 코드 레벨에서도 환경 변수(`process.env.DB_PASSWORD` 등)를 읽어오도록 수정해야 합니다.
3.
**실수 3: Bind Mount를 DB 데이터 디렉토리에 사용하는 경우** * **문제:** 호스트 PC의 파일 시스템 권한 문제나, OS가 가진 파일 시스템의 특성 때문에 데이터 쓰기/읽기 권한 문제가 터질 확률이 높습니다.
* **해결:** DB의 데이터 디렉토리(`data/` 폴더)는 **항상 Named Volume**을 사용하세요.
이 정도면 충분히 복잡한 내용을 커버했을 거라고 생각합니다.
결국 핵심은 **"데이터는 Docker가 관리하게 (Named Volume)"** 하고, **"초기 세팅은 스크립트가 맡고 (Init Scripts)"**, **"테스트 종료 시에는 깨끗하게 정리한다 (down -v)"** 이 루틴을 몸에 익히는 겁니다.
이거 한 번만 제대로 세팅해 놓으면, 이후 프로젝트에서는 DB 환경 구축 시간이 10분도 안 걸릴 겁니다.
화이팅하시고요!