"Docker 없어도 되지 않나요?" — 면접관이 듣고 싶은 진짜 대답

TeamGrit·2025년 12월 10일

Interview-Question

목록 보기
6/12
post-thumbnail

안녕하세요, 이력서 기반 면접 준비를 도와드리는 QueryDaily 팀입니다.

"Docker 사용 경험 있으시네요. Docker를 왜 쓰시나요?"
"음... 배포할 때 편해서요?"

혹시 이런 식으로 대답하신 적 있으신가요? 틀린 말은 아니지만, 면접관은 고개를 갸웃거릴 겁니다. "그래서 왜 편한 건데요?"라는 꼬리 질문이 날아오겠죠.

오늘은 Docker를 사용하는 궁극적인 이유에 대해 깊이 있게 알아보겠습니다. "Docker가 없어도 개발과 배포는 됩니다. 하지만 Docker가 해결해주는 문제들을 알면, 왜 이 기술이 현대 개발의 필수가 되었는지 이해하실 수 있을 겁니다."


Docker가 없던 시절, 무엇이 문제였을까?

"제 컴퓨터에서는 잘 되는데요?"

개발자라면 한 번쯤 들어봤거나, 직접 해봤을 이 말. Docker가 해결해주는 가장 고질적인 문제입니다.

Docker가 없던 시절을 상상해볼까요?

1. 개발 환경의 불일치

[팀원 A의 노트북]          [팀원 B의 노트북]          [운영 서버]
- macOS                   - Windows                 - Ubuntu
- Java 11                 - Java 8                  - Java 17
- MySQL 8.0               - MySQL 5.7               - MySQL 8.0
  • 저는 Java 11, 동료는 Java 8이 설치되어 있습니다.
  • 저는 macOS, 동료는 Windows를 씁니다. 운영체제가 달라서 특정 기능이 다르게 동작합니다.
  • 개발 서버, 스테이징 서버, 운영 서버의 환경(라이브러리 버전, 설정 등)이 미세하게 달라서, 개발 환경에서는 잘 되던 코드가 운영 서버에서 오류를 뿜습니다.

2. 복잡한 설치 과정

새로운 팀원이 합류하면 이런 가이드를 따라야 했습니다:

📋 신규 입사자 개발환경 세팅 가이드 (예상 소요 시간: 반나절~하루)

1. Java 11 설치하세요
2. 환경변수 JAVA_HOME 설정하세요
3. MySQL 8.0 설치하고 root 비밀번호 설정하세요
4. MySQL에서 유저 생성하고 권한 부여하세요
5. Redis 설치하고 포트 6379 열어주세요
6. MongoDB 설치하세요
7. application.yml에서 DB 접속 정보 수정하세요
8. ...

⚠️ 한 단계라도 꼬이면 선임 개발자 찾아가세요

이 과정에서 한 단계만 꼬여도 반나절이 그냥 사라졌습니다.


Docker의 해결책: 컨테이너

Docker는 이 문제들을 '컨테이너' 라는 개념으로 해결합니다.

선적 컨테이너의 비유

과거 물류 산업을 생각해보세요:

[과거]
피아노 🎹 → 특수 포장 필요
자동차 🚗 → 별도 운송 방식
과일 🍎 → 냉장 시설 필요
→ 각각 다른 방식으로 운송해야 함

[선적 컨테이너 등장 후]
피아노 🎹 → 📦 컨테이너
자동차 🚗 → 📦 컨테이너
과일 🍎 → 📦 컨테이너
→ 내용물이 무엇이든 '컨테이너'를 배에 싣고 내리면 끝!

Docker도 마찬가지입니다:

# Dockerfile - 우리 애플리케이션을 '박제'하는 레시피
FROM openjdk:11-jdk-slim          # Java 11 환경
COPY target/myapp.jar app.jar     # 우리 애플리케이션
EXPOSE 8080                        # 사용할 포트
ENTRYPOINT ["java", "-jar", "app.jar"]
  • 우리 애플리케이션(Java 코드)
  • 실행에 필요한 환경(Java 11)
  • 각종 라이브러리와 설정

이 모든 것을 하나의 '이미지' 로 박제해서 통째로 상자에 담아버립니다.

💡 핵심 포인트: Docker 이미지는 내 애플리케이션 코드뿐만 아니라, 그 코드가 돌아가기 위해 필요한 모든 것(OS, 라이브러리, 설정 등)을 하나의 패키지로 '박제'합니다. 단순히 오류를 최소화하는 것을 넘어, 환경을 100% 동일하게 보장해주는 거죠.


이미지는 한 번 만들면 절대 수정하지 않는다 (Immutable)

Docker를 처음 배우면 자연스럽게 드는 의문이 있습니다.

"이미지를 변경하는 시점은 언제인가요?"

여기서 아주 중요한 원칙이 있습니다.

"이미지는 한번 만들면 절대 수정하지 않는다(Immutable)"

'변경'하는 것이 아니라, 항상 '새로운 버전의 이미지를 만든다' 라고 생각해야 합니다.

새로운 이미지를 만드는 시점

1. 애플리케이션 코드가 변경되었을 때 (가장 흔한 경우)

버그를 수정하거나 새로운 기능을 추가하면, 새로운 버전의 코드가 반영된 이미지가 필요합니다.

[워크플로우]
1. 개발자가 코드를 수정하고 git push
2. CI 서버(Jenkins 등)가 이를 감지하고 프로젝트 빌드 (새로운 .jar 생성)
3. 새로운 .jar 파일을 포함시켜 새로운 Docker 이미지 빌드
4. 새 이미지에 my-app:1.1.0 같은 새로운 버전 태그를 붙여서 배포

2. 의존성(라이브러리)이 변경되었을 때

build.gradle 파일에 새로운 라이브러리를 추가하거나, 기존 라이브러리(예: Spring Boot)의 버전을 올렸을 때입니다. 새로운 라이브러리가 포함된 환경을 만들어야 하므로, 새로운 이미지를 만들어야 합니다.

3. 기반 환경(Base Image)이 변경되었을 때

# Dockerfile의 첫 줄 = 베이스 이미지
FROM openjdk:11-jre-slim   # ← 이 부분!

베이스 이미지에 중요한 보안 패치가 적용되거나, Java 11에서 Java 17로 런타임 버전을 통째로 올리고 싶을 때, 베이스 이미지를 변경하고 우리 앱 이미지를 새로 빌드해야 합니다.

왜 수정하면 안 될까?

❌ 잘못된 방법
$ docker exec -it my-container bash
# 컨테이너 안에서 직접 파일 수정...
# 문제 발생 시 "뭘 수정했더라?" 추적 불가 😱

✅ 올바른 방법
$ docker build -t my-app:1.0.1 .
$ docker stop my-container
$ docker run my-app:1.0.1
# 문제 발생 시 이전 버전으로 즉시 롤백 가능 👍

기존에 실행 중인 컨테이너에 접속해서 무언가를 수정하는 것은 절대 금물입니다:

  • 문제가 생겼을 때 추적하기가 매우 어려워집니다
  • Docker의 가장 큰 장점인 '환경의 일관성'을 스스로 깨버리는 행위입니다

이러한 개발 방식을 "불변 인프라(Immutable Infrastructure)" 라고 부릅니다. 서버 환경을 직접 수정하지 않고, 문제가 생기면 그냥 새 이미지로 만든 컨테이너로 교체해버리는 개념이죠.


.jar 파일과 이미지 버전 관리

왜 .jar 파일로 배포하나요?

.jar (Java Archive) 파일은 자바 애플리케이션을 위한 '실행 가능한 이삿짐 박스' 라고 생각하시면 됩니다.

.jar 파일 안에는 다음과 같은 것들이 모두 들어있습니다:

📦 my-app.jar
├── 컴파일된 내 코드 (.class 파일들)
├── 모든 외부 라이브러리 (Spring Boot, JPA 등)
└── 설정 파일 및 리소스 (application.yml 등)

핵심은 '이 파일 하나만 있으면 어디서든 실행 가능하다'는 점입니다.

Java가 설치된 어떤 컴퓨터(서버)로든 이 .jar 파일 하나만 옮겨서 실행하면 됩니다:

java -jar my-app.jar

그래서 Dockerfile에서도 이런 흐름으로 사용됩니다:

# 1. Java가 설치된 리눅스 환경을 준비
FROM openjdk:11-jre-slim

# 2. 잘 만들어진 .jar 파일을 환경 안으로 복사
COPY build/libs/*.jar app.jar

# 3. 컨테이너가 시작될 때 .jar 파일 실행
ENTRYPOINT ["java", "-jar", "/app.jar"]

빌드할 때마다 새로운 버전의 이미지를 만드나요?

네, 정확합니다!

앞서 이야기한 '불변성(Immutability)' 원칙이 여기서 다시 등장합니다.

새로운 .jar 파일 = 애플리케이션의 새로운 버전 = 새로운 Docker 이미지

새로운 .jar 파일이 만들어졌다는 것은, 새로운 버전의 애플리케이션을 배포해야 한다는 의미입니다. 이를 위해 항상 새로운 Docker 이미지를 만듭니다.

<# 버전 1.0 배포
docker build -t my-app:1.0 .

# 코드 수정 후 버전 1.1 배포
docker build -t my-app:1.1 .

# 또 수정 후 버전 1.2 배포
docker build -t my-app:1.2 .

이전에 사용하던 이미지는 어떻게 되나요?

새로운 이미지를 계속 만들면 이전 이미지들은 다 어디로 갈까요?

결론: 이전 이미지는 '이미지 저장소(Registry)'에 그대로 남아있습니다.

[이미지 저장소 (Docker Hub, AWS ECR 등)]
├── my-app:1.0  ← 첫 번째 버전 (삭제되지 않음)
├── my-app:1.1  ← 두 번째 버전 (삭제되지 않음)
├── my-app:1.2  ← 세 번째 버전 (현재 운영 중)
└── my-app:latest ← 가장 최신 버전을 가리킴

왜 남겨두나요?

빠른 롤백(Rollback): 만약 1.2 버전에 심각한 버그가 발견되면, 급하게 1.1 버전 이미지로 다시 배포해서 빠르게 서비스를 원상복구 시킬 수 있습니다.

# 버그 발견! 이전 버전으로 긴급 롤백
docker pull my-app:1.1
docker run my-app:1.1
# 서비스 정상화 완료 (몇 분 안에!)

그럼 이미지가 무한히 쌓이나요?

아닙니다. 대부분의 이미지 저장소는 정리 정책(Cleanup Policy) 을 설정할 수 있습니다:

정책 예시설명
최신 N개만 유지"최신 20개 이미지만 남기고 나머지는 삭제"
기간 기반 삭제"만들어진 지 90일이 지난 이미지는 삭제"
태그 기반 보호"v1.0, v2.0 처럼 중요한 버전 태그는 삭제하지 않음"

정리 정책은 어떻게 적용하나요?

이 기능은 Docker 자체가 아니라, 이미지를 저장하는 '이미지 저장소(Registry)' 가 제공합니다. AWS ECR, Docker Hub, Google GCR, Harbor 등 대부분의 저장소에서 비슷한 기능을 제공합니다.

AWS ECR을 예로 들면, "수명 주기 정책(Lifecycle Policy)" 이라고 부릅니다.

예시 1: 최신 10개만 유지하기

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "최신 이미지 10개만 유지",
      "selection": {
        "tagStatus": "tagged",
        "tagPrefixList": ["v"],
        "countType": "imageCountMoreThan",
        "countNumber": 10
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}

v로 시작하는 태그를 가진 이미지가 11개 이상이 되면, 가장 오래된 이미지부터 자동 삭제하여 항상 10개를 유지합니다.

예시 2: 30일 지난 이미지 삭제하기

{
  "rules": [
    {
      "rulePriority": 1,
      "description": "30일 지난 이미지 삭제",
      "selection": {
        "tagStatus": "any",
        "countType": "sinceImagePushed",
        "countUnit": "days",
        "countNumber": 30
      },
      "action": {
        "type": "expire"
      }
    }
  ]
}

어떤 이미지든 만들어진 지 30일이 지나면 자동으로 삭제합니다.

이처럼 팀의 운영 전략에 맞춰 다양한 규칙을 조합할 수 있습니다:

  • "feature 브랜치 이미지는 3일 뒤 삭제"
  • "release 태그가 붙은 이미지는 영구 보존"

이전 이미지는 '자동으로 사라지지 않고, 정해진 규칙에 따라 관리된다' 고 이해하시면 됩니다.


Docker가 가져다 주는 것들

1. 환경 통일 — "내 컴퓨터에선 됐는데..." 원천 차단

[개발자 A 노트북]     [개발자 B 노트북]     [운영 서버]
      ↓                    ↓                  ↓
   Docker               Docker              Docker
      ↓                    ↓                  ↓
  [동일한 이미지]      [동일한 이미지]     [동일한 이미지]
      ↓                    ↓                  ↓
  100% 동일한 환경    100% 동일한 환경    100% 동일한 환경

이제 개발자는 자기 컴퓨터에 Java나 Redis를 직접 설치할 필요가 없습니다. Docker만 설치되어 있다면, 이 '이미지'를 가져와 실행하기만 하면 됩니다.

# Redis 설치? 이거면 끝
docker run -d -p 6379:6379 redis

# MySQL 설치? 이것도 끝
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 mysql:8.0

2. 신속한 구성 — 반나절 → 5분

기억하시나요? 신규 입사자 세팅 가이드...

Docker가 있으면 이렇게 바뀝니다:

# docker-compose.yml
version: '3'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 1234
      MYSQL_DATABASE: myapp

  redis:
    image: redis:latest
# 신규 입사자 개발환경 세팅 가이드 (소요 시간: 5분)
# 1. Docker 설치
# 2. 아래 명령어 실행
docker-compose up -d

# 끝! ☕ 커피 한 잔 마시고 오세요

3. 안정적인 배포 — 배포 변수 최소화

[기존 배포]
소스 코드 → 빌드 → 운영 서버에서 실행
           ↑
    "서버 환경이 달라서 오류 발생 가능"

[Docker 배포]
소스 코드 → 빌드 → 이미지 생성 → 어디서든 동일하게 실행
                      ↑
         "환경까지 통째로 포장했으니 변수 없음"

VM(가상 머신)과 Docker의 차이

"환경을 통일한다는 건 VM도 할 수 있지 않나요?"

맞습니다. 하지만 결정적인 차이가 있습니다.

[가상 머신 (VM)]
┌─────────────────────────────┐
│         App A              │
│    Guest OS (Ubuntu)       │  ← OS 전체를 가상화 (무거움)
│    Hypervisor              │
├─────────────────────────────┤
│         App B              │
│    Guest OS (CentOS)       │  ← 또 다른 OS 전체
│    Hypervisor              │
├─────────────────────────────┤
│       Host OS              │
│       Hardware             │
└─────────────────────────────┘

[Docker 컨테이너]
┌─────────────────────────────┐
│   App A  │  App B  │  App C │
│ Container│Container│Container│  ← 앱 + 필요한 라이브러리만
├─────────────────────────────┤
│       Docker Engine        │
├─────────────────────────────┤
│       Host OS              │
│       Hardware             │
└─────────────────────────────┘
구분VMDocker
가상화 수준OS 전체애플리케이션 레벨
시작 시간수 분수 초
용량수 GB수십~수백 MB
리소스 사용높음낮음
이식성낮음높음

Docker는 Host OS의 커널을 공유하기 때문에 훨씬 가볍고 빠릅니다.


면접 예상 질문

Q1. "Docker를 왜 사용하나요?"

핵심 포인트: 환경 일치, 빠른 구성, 안정적 배포 세 가지를 언급하세요.

"Docker를 사용하면 개발, 테스트, 운영 환경을 완전히 일치시킬 수 있습니다. '제 컴퓨터에서는 되는데요' 같은 문제를 원천 차단하고, 새로운 팀원도 docker-compose up 한 번으로 전체 개발 환경을 구성할 수 있습니다."

Q2. "Docker와 VM의 차이점은?"

핵심 포인트: 가상화 수준의 차이를 설명하세요.

"VM은 하드웨어 레벨에서 OS 전체를 가상화하지만, Docker는 OS 커널을 공유하면서 애플리케이션 레벨에서 격리합니다. 그래서 Docker 컨테이너는 VM보다 훨씬 가볍고, 시작도 수 초 만에 됩니다."

Q3. "Docker 이미지와 컨테이너의 차이는?"

핵심 포인트: 클래스와 인스턴스의 관계로 비유하세요.

"이미지는 애플리케이션 실행에 필요한 모든 것을 담은 '템플릿'이고, 컨테이너는 그 이미지를 실행한 '인스턴스'입니다. 객체지향에서 클래스와 객체의 관계와 비슷합니다. 하나의 이미지로 여러 개의 컨테이너를 실행할 수 있습니다."

Q4. "이미지를 변경(업데이트)하는 시점은 언제인가요?"

핵심 포인트: '변경'이 아니라 '새로 만든다'는 점을 강조하세요.

"Docker 이미지는 불변(Immutable)이 원칙입니다. 기존 이미지를 수정하는 것이 아니라, 새로운 버전의 이미지를 만듭니다. 주로 애플리케이션 코드가 변경되었을 때, 의존성 라이브러리가 변경되었을 때, 베이스 이미지에 보안 패치가 적용되었을 때 새 이미지를 빌드합니다."

Q5. "실행 중인 컨테이너에 직접 접속해서 수정해도 되나요?"

핵심 포인트: 절대 안 된다는 점과 그 이유를 명확히 설명하세요.

"절대 금물입니다. 컨테이너에 직접 접속해서 수정하면, 문제 발생 시 무엇을 수정했는지 추적이 어렵고, Docker의 가장 큰 장점인 환경 일관성을 스스로 깨버리는 행위입니다. 대신 새 이미지를 빌드하고 컨테이너를 교체하는 '불변 인프라(Immutable Infrastructure)' 방식을 따라야 합니다."

Q6. "이전 버전 이미지는 어떻게 관리하나요?"

핵심 포인트: 롤백을 위해 보관하고, 정리 정책으로 관리한다는 점을 설명하세요.

"이전 버전 이미지는 이미지 저장소(Registry)에 그대로 보관합니다. 배포 후 문제가 발생하면 이전 버전으로 빠르게 롤백할 수 있기 때문입니다. 다만 무한히 쌓이면 비용이 발생하므로, '최신 N개만 유지' 또는 '90일 지난 이미지 삭제' 같은 정리 정책(Cleanup Policy)을 설정해서 관리합니다."

Q7. "Docker를 사용하면서 겪었던 어려움은?"

답변 팁: 실제 경험을 바탕으로 말씀하시되, 해결 과정까지 함께 설명하세요.

예: "초기에 이미지 용량 관리가 어려웠습니다. 멀티스테이지 빌드를 적용하고, .dockerignore를 활용해서 불필요한 파일을 제외하니 이미지 크기를 1GB에서 200MB로 줄일 수 있었습니다."


정리

Docker를 사용하는 궁극적인 이유:

  1. 환경 통일 — 개발, 테스트, 운영 환경을 일치시켜 환경 차이로 인한 문제 원천 차단
  2. 신속한 구성 — 명령어 한 번으로 전체 개발 환경을 몇 분 안에 구성
  3. 안정적인 배포 — 잘 동작하는 이미지를 그대로 배포하므로 변수 최소화
  4. 리소스 효율 — VM 대비 가볍고 빠른 컨테이너 기술

"Docker 없어도 되지 않나요?"라는 질문에 이제 자신 있게 대답할 수 있으시겠죠?

"됩니다. 하지만 Docker가 해결해주는 문제들을 생각하면, 안 쓸 이유가 없습니다."


면접에서 Docker 관련 질문이 나온다면, 단순히 "편해서요"가 아닌 구체적인 문제와 해결책을 말씀하실 수 있어야 합니다. 여러분의 이력서에 적힌 'Docker 사용 경험'에서 어떤 꼬리 질문이 나올 수 있을까요? QueryDaily 에서 미리 연습해보세요.


👉 팀그릿 더 알아보기


#Docker #컨테이너 #DevOps #백엔드면접 #QueryDaily

profile
우리는 당신의 가능성을 믿는 사람들입니다. '되는 사람'이 되는 방법을 이야기합니다.

2개의 댓글

comment-user-thumbnail
2025년 12월 15일

좋은 글 잘 봤습니다~

답글 달기
comment-user-thumbnail
2025년 12월 23일

좋은 글 감사합니다! 이해가 쏙쏙 되네요!

답글 달기