jdbc:mysql://localhost:3306vsjdbc:mysql://mysql:3306같은
DbConfig.java를 쓰는데 어떤 상황에서 어떤 주소를 써야 하는지 이해하는 것이 이 프로젝트의 핵심 설정 포인트입니다.
이 프로젝트에는 MySQL에 접속하는 경우가 두 가지 있습니다.
┌─────────────────────────────────────────────────────────────┐
│ 실행 환경 1: Docker (실제 애플리케이션 구동) │
│ 실행 환경 2: Unit Test (JUnit 테스트 직접 실행) │
└─────────────────────────────────────────────────────────────┘
각 환경에서 MySQL의 네트워크 위치가 다릅니다. 이것이 JDBC URL 호스트 부분이 달라지는 이유입니다.
┌─────────────────────────────────────────────────────────┐
│ Docker 내부 네트워크 │
│ │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ spring-mvc- │ │ spring-mvc-mysql │ │
│ │ tomcat │ │ (컨테이너 이름) │ │
│ │ │ │ │ │
│ │ Spring MVC App │──────►│ MySQL 9.1 │ │
│ │ (WAR 배포) │ │ port: 3306 │ │
│ │ │ │ │ │
│ └──────────────────┘ └──────────────────────┘ │
│ 호스트명: tomcat 호스트명: mysql │
│ │
└─────────────────────────────────────────────────────────┘
▲
│ docker-compose.yml이 이 네트워크를 자동 생성
Docker Compose는 같은 docker-compose.yml 안에 정의된 서비스들을
자동으로 같은 가상 네트워크에 연결합니다.
이 네트워크 안에서는 **서비스 이름이 곧 호스트명(DNS)**이 됩니다.
# docker-compose.yml
services:
mysql: # ← 이 이름이 네트워크 내 호스트명이 됨
image: mysql:9.1
...
tomcat:
image: tomcat:11.0-jdk21
... # tomcat 컨테이너는 "mysql" 이라는 이름으로 MySQL에 접근따라서 Tomcat 컨테이너 안의 Spring 앱이 MySQL에 접속할 때:
jdbc:mysql://mysql:3306/productdb
↑
Docker 내부 DNS 이름 (서비스명)
"localhost"가 아님!
┌────────────────────────────────────────────────┐
│ Tomcat 컨테이너 내부에서 localhost = Tomcat │
│ │
│ localhost:3306 → Tomcat 컨테이너 자신의 3306 │
│ MySQL이 없음 → 연결 실패 ❌ │
└────────────────────────────────────────────────┘
Tomcat 컨테이너 안에서 localhost는 Tomcat 컨테이너 자신을 가리킵니다.
MySQL은 별도 컨테이너이므로 localhost로는 절대 접근할 수 없습니다.
┌──────────────────────────────────────────────────────────┐
│ 개발 PC (호스트 머신) │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ IntelliJ IDEA (JVM 프로세스) │ │
│ │ │ │
│ │ JUnit Test ──────────────────────────────────► │ │
│ │ EntityRelationshipTest │ │
│ │ ProductRepositoryTest DbConfig.java │ │
│ │ (DataSource) │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ │ localhost:3306 │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Docker 컨테이너 (spring-mvc-mysql) │ │
│ │ │ │
│ │ MySQL 9.1 │ │
│ │ 포트 바인딩: 호스트 3306 → 컨테이너 3306 │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────┘
JUnit 테스트는 IntelliJ 안에서 직접 실행됩니다. 즉, 테스트 코드는 Docker 컨테이너 안이 아닌 개발 PC(호스트) 위에서 돌아갑니다.
MySQL 컨테이너는 docker-compose.yml에서 포트를 바인딩했습니다:
# docker-compose.yml
mysql:
ports:
- "3306:3306" # 호스트 3306 → 컨테이너 3306 으로 포워딩따라서 호스트(개발 PC)에서 localhost:3306으로 접근하면
Docker가 자동으로 MySQL 컨테이너의 3306으로 연결해 줍니다.
jdbc:mysql://localhost:3306/productdb
↑
개발 PC 자신 = Docker 포트 바인딩을 통해 MySQL 접근 가능
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
구분 Docker 실행 Unit Test 실행
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
실행 주체 Tomcat 컨테이너 IntelliJ (개발 PC)
네트워크 Docker 내부 네트워크 호스트 네트워크
MySQL 위치 같은 네트워크의 컨테이너 포트 바인딩된 컨테이너
호스트명 mysql (서비스명 = DNS) localhost
JDBC URL mysql://mysql:3306 mysql://localhost:3306
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
현재 DbConfig.java는 localhost로 설정되어 있습니다.
// DbConfig.java
ds.setUrl("jdbc:mysql://localhost:3306/productdb" + ...);┌────────────────────────────────────────────────────────────┐
│ Unit Test (IntelliJ) │
│ localhost:3306 → Docker 포트 바인딩 → MySQL ✅ │
└────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Docker (Tomcat 컨테이너) │
│ localhost:3306 → Tomcat 자신의 3306 → MySQL 없음 ❌ │
│ │
│ → Tomcat 컨테이너에서는 localhost가 동작하지 않음! │
└────────────────────────────────────────────────────────────┘
현재 프로젝트는 Unit Test 중심으로 구성되어 있으므로
localhost를 사용합니다. Tomcat 컨테이너로 실제 배포까지 하려면mysql로 변경하거나 환경별로 설정을 분리해야 합니다.
실제 프로젝트에서는 환경에 따라 JDBC URL이 자동으로 바뀌도록 구성합니다.
// DbConfig.java
String dbHost = System.getenv("DB_HOST") != null
? System.getenv("DB_HOST")
: "localhost"; // 환경 변수 없으면 localhost (테스트용)
ds.setUrl("jdbc:mysql://" + dbHost + ":3306/productdb");# docker-compose.yml
tomcat:
environment:
DB_HOST: mysql # Docker 환경에서는 mysql로 설정 Unit Test → DB_HOST 없음 → localhost 사용
Docker → DB_HOST=mysql → mysql 사용
# application-local.yml (Unit Test / 로컬 개발)
spring.datasource.url: jdbc:mysql://localhost:3306/productdb
# application-docker.yml (Docker 배포)
spring.datasource.url: jdbc:mysql://mysql:3306/productdb 질문: "왜 JDBC URL 호스트가 환경마다 다른가?"
답: 네트워크 관점에서 MySQL의 위치가 다르기 때문입니다.
Unit Test (개발 PC에서 직접 실행)
└─ 개발 PC의 localhost:3306
└─ Docker 포트 바인딩(3306→3306)으로 MySQL 접근
Docker (Tomcat 컨테이너 안에서 실행)
└─ Docker 내부 DNS: mysql:3306
└─ 같은 Compose 네트워크 안의 MySQL 컨테이너 직접 접근
(localhost는 Tomcat 컨테이너 자신이므로 사용 불가)