도커 개발환경, 팀 프로젝트에서 직접 써본 장단점
제 노트북에서는 멀쩡한 웹개발 프로젝트가 동료 컴퓨터에서 실행되지 않았습니다. Node.js 버전부터 데이터베이스 포트, 운영체제별 명령어까지 조금씩 달랐기 때문입니다. 설치 방법을 문서로 길게 적어도 새 팀원이 합류할 때마다 같은 문제가 반복되어, 결국 도커 개발환경을 실제 프로젝트에 적용해 봤습니다.
대상은 프론트엔드, API 서버, PostgreSQL로 구성된 소규모 서비스였습니다. 처음에는 설정 파일만 늘어나는 듯했지만 한 달가량 운영해 보니 편해진 부분과 예상 밖의 불편이 명확하게 보였습니다. 이 글은 도커를 무조건 추천하기보다, 직접 사용하며 확인한 장단점과 시행착오를 중심으로 설명합니다.
설치 문서보다 먼저 해결하고 싶었던 환경 차이
버전 하나가 팀의 반나절을 잡아먹었습니다
도입 전에는 각자 Node.js와 PostgreSQL을 직접 설치했습니다. 그런데 한 사람은 Node.js 최신 버전을, 다른 사람은 장기 지원 버전을 사용했고 데이터베이스 확장 모듈의 버전도 달랐습니다. 오류 메시지만 보면 애플리케이션 코드 문제처럼 보여서, 실제 원인이 실행 환경이라는 사실을 찾는 데 반나절이 걸리기도 했습니다.
도커를 적용한 뒤에는 이미지와 설정 파일이 실행 조건을 대신 설명했습니다. 저장소를 내려받고 정해진 명령을 실행하면 동일한 버전의 서버와 데이터베이스가 올라왔습니다. 코딩 자체보다 환경 맞추기에 더 많은 시간을 쓰고 있지는 않은가요? 그런 상황이라면 도커의 효과를 비교적 빠르게 체감할 수 있습니다.
- Node.js 버전 고정: 팀원마다 런타임이 달라 생기는 빌드 오류를 줄였습니다.
- 데이터베이스 통일: 로컬 설치 여부와 관계없이 같은 PostgreSQL 환경을 사용했습니다.
- 환경 변수 구분: 샘플 파일을 두고 비밀 값은 저장소에 올리지 않았습니다.
- 포트 명시: 어떤 서비스가 어느 포트를 점유하는지 설정에서 확인할 수 있었습니다.
처음부터 모든 도구를 컨테이너로 옮기기보다, 팀에서 가장 자주 충돌하는 데이터베이스나 API 서버부터 옮기는 편이 부담이 적었습니다.
Docker Compose로 세 서비스를 묶어 본 과정
한 명령으로 실행되는 상태를 목표로 삼았습니다
제가 만든 첫 구성은 프론트엔드, 백엔드, PostgreSQL을 각각 서비스로 정의한 형태였습니다. 백엔드가 데이터베이스보다 먼저 실행되어 접속에 실패하는 문제가 있었기 때문에 단순한 실행 순서만 믿지 않고 상태 확인을 추가했습니다. 도커 파일을 작성하는 행위도 결국 컴퓨터가 수행할 절차를 명확히 표현하는 프로그래밍의 한 과정이라는 점을 체감했습니다.
설정을 한 번에 완성하려 하니 오히려 원인을 찾기 어려웠습니다. 그래서 데이터베이스만 먼저 실행하고, 연결을 확인한 뒤 백엔드와 프론트엔드를 차례로 추가했습니다. 이 방식은 느려 보여도 어느 단계에서 문제가 생겼는지 바로 알 수 있어 결과적으로 더 빨랐습니다.
- PostgreSQL 컨테이너와 데이터 볼륨을 먼저 구성했습니다.
- 백엔드에서 서비스 이름을 데이터베이스 호스트로 사용했습니다.
- 상태 확인이 통과한 뒤 API 서버가 연결되도록 설정했습니다.
- 프론트엔드의 개발 서버 포트와 API 주소를 환경 변수로 분리했습니다.
- 새 저장소에서 실행 명령 하나로 재현되는지 다시 시험했습니다.
가장 유용했던 검증법은 깨끗한 디렉터리에서 처음부터 실행하는 것이었습니다. 기존 노트북에 남아 있던 패키지나 로컬 데이터베이스가 실수를 가려 줄 수 있기 때문입니다. 팀원에게 전달하기 전 새로 복제한 저장소에서 테스트하니 누락된 환경 변수와 초기화 스크립트를 발견할 수 있었습니다.
써보니 분명했던 장점과 기대보다 작은 효과
재현성은 좋았지만 모든 문제가 사라지지는 않았습니다
가장 큰 장점은 새 팀원의 준비 시간이 줄었다는 점입니다. 예전에는 설치 문서를 따라가며 버전을 확인하고 데이터베이스 계정을 만드는 데 한두 시간이 필요했지만, 도입 후에는 도커 설치와 환경 변수 입력을 제외하면 대부분 자동으로 진행됐습니다. 장애를 재현할 때도 동일한 이미지를 사용하니 대화가 훨씬 구체적으로 바뀌었습니다.
반면 도커가 운영체제 차이를 완전히 없애 주지는 않았습니다. 파일 권한, 줄바꿈, 볼륨 성능, CPU 아키텍처 차이는 여전히 남았습니다. 특히 macOS에서 대량의 소스 파일을 마운트했을 때 파일 감지와 패키지 설치가 느려졌고, Windows 사용자는 경로와 셸 명령 때문에 별도 안내가 필요했습니다.
- 체감이 컸던 장점: 버전 통일, 데이터베이스 초기화, 환경 제거와 재생성이 쉬웠습니다.
- 기대보다 작은 장점: 운영체제별 파일 시스템 차이까지 자동으로 해결되지는 않았습니다.
- 새로 생긴 비용: 이미지 빌드, 로그 확인, 네트워크 개념을 팀이 함께 익혀야 했습니다.
- 유지할 가치가 있던 부분: 재현 절차가 코드로 남아 구두 설명에 덜 의존했습니다.
코딩을 소프트웨어에 명령을 부여하는 활동으로 이해하려면 코딩 용어 설명도 참고할 만합니다. 도커 설정 역시 복사해 둔 주문이 아니라 팀의 실행 조건을 표현하는 코드이므로, 변경 이유와 검증 방법을 함께 기록해야 오래 사용할 수 있었습니다.
개발 속도를 떨어뜨린 세 가지 시행착오
느린 이유는 도커 자체보다 설정에 있었습니다
첫 번째 실수는 소스 디렉터리 전체를 무분별하게 마운트한 것입니다. 호스트의 의존성 폴더까지 컨테이너와 섞이면서 네이티브 모듈 충돌이 발생했고 파일 감지 속도도 떨어졌습니다. 이후 의존성 폴더는 별도 볼륨으로 분리하고, 개발 중 수정할 소스만 마운트하자 체감 속도가 나아졌습니다.
두 번째는 캐시를 이해하지 못한 채 빌드가 이상할 때마다 모든 이미지를 새로 만드는 습관이었습니다. 문제는 해결됐지만 빌드 시간이 길어졌고 원인도 남지 않았습니다. 세 번째는 로그를 한 화면에서만 보는 방식이었습니다. 여러 서비스의 출력이 섞이니 요청이 어디에서 실패했는지 파악하기 어려웠습니다.
- 의존성 분리: 호스트와 컨테이너의 패키지 폴더가 섞이지 않게 했습니다.
- 레이어 순서 조정: 패키지 명세를 먼저 복사해 의존성 설치 캐시를 활용했습니다.
- 서비스별 로그: 문제가 발생한 API나 데이터베이스 로그만 따로 확인했습니다.
- 정리 명령 주의: 볼륨을 지우기 전 필요한 로컬 데이터가 있는지 확인했습니다.
오류가 나면 곧바로 전체 삭제부터 하지 마세요. 컨테이너 상태, 최근 로그, 환경 변수, 네트워크 연결 순으로 확인해야 같은 문제의 재발을 막을 수 있습니다.
이후 팀에서는 오류 제보에 실행 명령, 서비스 이름, 마지막 로그 일부를 포함하도록 했습니다. “도커가 안 돼요”라는 표현보다 “API 컨테이너가 데이터베이스 이름을 찾지 못합니다”라는 설명이 나오기 시작했고, 디버깅에 필요한 질문도 크게 줄었습니다.
로컬 설치와 도커를 실제 업무 기준으로 나눠 보니
도구마다 적합한 실행 방식이 달랐습니다
처음에는 모든 개발 도구를 컨테이너 안에 넣는 것이 일관성에 좋다고 생각했습니다. 하지만 에디터와 Git까지 억지로 격리하면 작은 작업에도 진입 절차가 늘어났습니다. 저는 데이터베이스와 백엔드처럼 버전 및 외부 의존성이 중요한 구성은 도커에 넣고, 에디터와 브라우저처럼 즉각적인 반응이 필요한 도구는 호스트에서 사용하는 혼합 방식을 선택했습니다.
아래 기준은 실제 프로젝트에서 어느 쪽이 편했는지를 정리한 것입니다. 정답이라기보다 팀의 규모, 노트북 성능, 배포 방식에 따라 판단할 출발점에 가깝습니다. 혼자 만드는 짧은 정적 페이지라면 도커 설정 시간이 더 큰 비용일 수 있지만, 여러 서비스가 연결되는 웹개발이라면 이점이 커집니다.
| 판단 항목 | 로컬 설치 | 도커 개발환경 |
|---|---|---|
| 초기 실행 | 단순 프로젝트에서 빠름 | 이미지 다운로드와 빌드 필요 |
| 팀 환경 통일 | 문서 준수에 의존 | 설정 파일로 재현하기 쉬움 |
| 파일 접근 속도 | 대체로 빠름 | 운영체제와 마운트 방식에 영향 |
| 환경 제거 | 잔여 파일 확인 필요 | 컨테이너 단위로 처리 가능 |
| 학습 부담 | 익숙한 도구라면 낮음 | 이미지·볼륨·네트워크 이해 필요 |
- 서비스가 하나뿐이고 실행 기간이 짧다면 로컬 설치가 간단했습니다.
- 팀원이 자주 합류하거나 여러 저장소를 오간다면 도커가 편했습니다.
- 운영 배포도 컨테이너 기반이면 개발 단계에서 얻는 학습 효과가 컸습니다.
저의 선택 기준은 기술의 유행이 아니라 반복되는 불편의 크기였습니다. 환경 문제를 거의 겪지 않는 개인 프로젝트에 복잡한 구성을 추가할 이유는 없었습니다. 반대로 매주 버전 충돌을 해결하는 팀이라면 작은 도커 구성만으로도 투자 시간을 회수할 수 있었습니다.
팀원이 편해진 설정 파일과 운영 습관
명령어보다 실패했을 때의 설명이 중요했습니다
도커 도입 뒤 가장 반응이 좋았던 것은 화려한 자동화가 아니라 짧은 시작 문서였습니다. 필요한 프로그램, 환경 변수 복사 방법, 첫 실행 명령, 정상 상태를 확인할 주소를 위에서부터 순서대로 적었습니다. 실행이 실패했을 때 확인할 로그 명령과 포트 충돌 해결법도 바로 아래에 배치했습니다.
또한 이미지 태그를 무조건 최신값으로 두지 않았습니다. 팀원이 같은 날 실행해도 서로 다른 기반 이미지를 받을 수 있기 때문입니다. 주요 버전을 명시하고 업그레이드는 별도 작업으로 처리했으며, 변경 후에는 새 환경에서 빌드와 테스트를 수행했습니다. 넓은 의미의 프로그래밍 개념처럼 실행 절차와 유지보수 가능성까지 함께 고려해야 했습니다.
- README 첫 화면에 최소 요구 사항과 실행 명령을 배치했습니다.
- 실제 비밀값이 없는 환경 변수 예시 파일을 제공했습니다.
- 데이터베이스 초기 데이터 생성 명령을 반복 실행해도 안전하게 만들었습니다.
- 서비스가 정상인지 확인할 상태 확인 주소를 마련했습니다.
- 설정 변경 Pull Request에는 깨끗한 환경에서 시험한 결과를 적었습니다.
비밀정보 관리에는 특히 주의해야 합니다. 이미지 내부에 API 키를 복사하면 저장소에서 지운 뒤에도 빌드 기록이나 레이어에 남을 수 있습니다. 개발용 기본값과 실제 인증정보를 구분하고, 커밋 전 제외 파일을 확인하는 습관을 팀 규칙으로 만들었습니다.
15분짜리 데이터베이스 컨테이너로 감을 잡아보세요
기존 프로젝트를 뜯지 않고 작게 시험하는 방법
도커가 필요한지 아직 판단하기 어렵다면 전체 웹개발 환경을 옮기지 않아도 됩니다. 지금 사용하는 프로젝트의 데이터베이스 하나만 임시 컨테이너로 실행해 보세요. 애플리케이션 코드는 그대로 두고 접속 주소와 포트만 바꾸면 되므로 실패해도 기존 개발 흐름에 미치는 영향이 작습니다.
시험할 때는 단순히 실행 성공 여부만 보지 말고 준비 시간과 복구 과정을 기록하는 것이 좋습니다. 컨테이너를 중지했다 다시 실행했을 때 데이터가 유지되는지, 초기화가 필요할 때 원하는 범위만 지울 수 있는지 확인하세요. 여기서 편리함을 느낀다면 다음 단계로 백엔드 서비스를 추가할 근거가 생깁니다.
- 현재 데이터베이스의 종류와 버전을 확인합니다.
- 같은 주요 버전의 공식 이미지를 선택하고 임의의 개발용 비밀번호를 지정합니다.
- 호스트에서 사용하지 않는 포트에 연결하고 데이터 볼륨을 별도로 만듭니다.
- 기존 애플리케이션의 접속 문자열만 바꿔 간단한 조회와 저장을 시험합니다.
- 컨테이너를 재시작한 뒤 방금 저장한 데이터가 남아 있는지 확인합니다.
지금 당장 할 행동은 프로젝트 폴더를 수정하는 것이 아니라, 현재 사용 중인 데이터베이스 버전을 한 줄로 기록하는 것입니다. 그다음 동일한 버전의 컨테이너를 15분 동안만 실행해 보세요. 이 작은 실험이면 도커 개발환경이 여러분의 반복 작업을 줄일 도구인지, 불필요한 설정을 더할 뿐인지 직접 판단할 수 있습니다.

- 이전글돌아가는 코드와 믿을 수 있는 코드, 웹개발 테스트의 함정 26.08.28
- 다음글SPA와 서버 중심 렌더링, 웹개발의 무게중심은 어디로 가나 26.08.26
등록된 댓글이 없습니다.
