Spring Boot 프로젝트에서 Postman 테스트는 정상적으로 성공했는데, Docker MySQL에 접속해서 확인하니 테이블이 하나도 보이지 않았던 문제를 정리한 글입니다.
커피 주문 프로젝트에서 메뉴 조회, 포인트 충전, 주문 API를 구현한 뒤 Postman으로 테스트를 진행했다.
Postman 결과는 모두 성공이었다.
그래서 당연히 MySQL에도 데이터가 들어갔을 거라고 생각했다.
그런데 Docker MySQL 컨테이너에 접속해서 확인해보니 이상한 결과가 나왔다.
docker exec -it coffee-order-mysql mysql -uroot -p'비밀번호'
MySQL 접속 후 DB 선택:
USE coffee_order;
SHOW TABLES;
결과:
Empty set
분명 Postman에서는 주문이 성공했는데, DB에는 테이블조차 없었다.
심지어 주문 테이블을 조회하면 이런 에러가 발생했다.
SELECT * FROM coffee_orders;
ERROR 1146 (42S02): Table 'coffee_order.coffee_orders' doesn't exist
처음에는 정말 이해가 되지 않았다.
처음에는 아래 문제들을 의심했다.
application.yml에는 아래처럼 설정되어 있었다.
spring:
jpa:
hibernate:
ddl-auto: update
ddl-auto=update라면 애플리케이션 실행 시 Entity를 기준으로 테이블이 생성되어야 한다.
그런데 Docker MySQL에는 테이블이 없었다.
테스트 환경에는 H2를 사용하고 있었기 때문에 혹시 서버가 test profile로 실행 중인지 의심했다.
서버 로그를 확인했다.
No active profile set, falling back to 1 default profile: "default"
test profile은 아니었다.
즉, H2를 보고 있는 것도 아니었다.
application.yml의 datasource 설정도 확인했다.
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/coffee_order
username: root
password: "비밀번호"
겉으로 보기에는 MySQL을 잘 보고 있는 것처럼 보였다.
서버 실행 로그를 자세히 보던 중 이상한 점을 발견했다.
Spring Boot 로그에는 DB 버전이 이렇게 찍혀 있었다.
Database JDBC URL [jdbc:mysql://127.0.0.1:3306/coffee_order?...]
Database version: 9.3
그런데 내가 Docker 컨테이너에 접속했을 때의 MySQL 버전은 이랬다.
Server version: 8.0.46 MySQL Community Server
즉, 두 MySQL의 버전이 달랐다.
여기서 문제의 원인을 알 수 있었다.
결론은 이거였다.
Spring Boot가 보고 있는 MySQL과
내가 docker exec로 확인한 MySQL이 서로 달랐다.
내 프로젝트의 application.yml은 아래 주소를 보고 있었다.
127.0.0.1:3306
그런데 내 로컬 환경에서는 이미 Homebrew MySQL이 3306 포트를 사용하고 있었다.
즉, 실제 구조는 이런 상태였다.
Spring Boot
→ 127.0.0.1:3306
→ Homebrew MySQL 9.3.0
docker exec
→ coffee-order-mysql 컨테이너 내부
→ Docker MySQL 8.0.46
나는 Docker MySQL을 확인하고 있었지만, Spring Boot는 Homebrew MySQL에 데이터를 저장하고 있었다.
Spring Boot가 실제로 바라보는 주소와 동일한 방식으로 MySQL에 접속했다.
mysql -h127.0.0.1 -P3306 -uroot -p'비밀번호'
접속 후 버전을 확인했다.
SELECT VERSION();
결과:
9.3.0
Spring Boot 로그에 찍힌 DB 버전과 같았다.
이제 진짜 애플리케이션이 보고 있는 DB에 들어온 것이다.
DB를 선택하고 테이블을 확인했다.
USE coffee_order;
SHOW TABLES;
결과:
coffee_orders
menus
point_histories
point_wallets
테이블이 정상적으로 보였다.
주문 데이터도 확인했다.
SELECT * FROM coffee_orders;
결과:
id | menu_name | payment_amount | status | user_id
1 | 아메리카노 | 4500 | PAID | 1
2 | 아메리카노 | 4500 | PAID | 1
...
포인트 이력도 정상적으로 들어가 있었다.
SELECT * FROM point_histories;
충전 이력과 사용 이력이 모두 정상적으로 저장되어 있었다.
이번 문제는 코드 문제가 아니라, 내가 확인한 DB와 애플리케이션이 사용하는 DB가 달랐던 문제였다.
그래서 해결 방법은 두 가지 중 하나다.
이 경우 DB 확인 시 docker exec가 아니라 아래 명령어를 사용해야 한다.
mysql -h127.0.0.1 -P3306 -uroot -p
그리고 DB 확인 순서는 다음과 같다.
USE coffee_order;
SHOW TABLES;
SELECT * FROM coffee_orders;
SELECT * FROM point_wallets;
SELECT * FROM point_histories;
Docker MySQL을 사용하고 싶다면 3306 포트를 점유 중인 Homebrew MySQL을 멈추거나, Docker MySQL 포트를 다르게 매핑해야 한다.
예를 들면 Docker MySQL을 3307로 열 수 있다.
ports:
- "3307:3306"
그리고 Spring Boot 설정도 맞춰야 한다.
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3307/coffee_order
중요한 것은 애플리케이션이 접속하는 주소와 내가 확인하는 DB 주소가 같아야 한다는 점이다.
이번 문제를 통해 가장 크게 배운 점은 이것이다.
Postman 성공 = 내가 확인한 DB에 저장됨
이라고 단정하면 안 된다.
반드시 아래를 함께 확인해야 한다.
docker exec로 들어간 DB와 127.0.0.1:3306으로 접속한 DB가 같은지포트 확인은 아래 명령어로 할 수 있다.
lsof -nP -iTCP:3306 -sTCP:LISTEN
이번 문제의 핵심은 단순했다.
Docker MySQL에 데이터가 없는 것이 아니라,
Spring Boot가 Docker MySQL을 보고 있지 않았다.
정리하면 다음과 같다.
| 항목 | 내용 |
|---|---|
| 문제 | Postman은 성공했지만 Docker MySQL에는 테이블이 없었음 |
| 원인 | Spring Boot는 Homebrew MySQL을 보고 있었고, 나는 Docker MySQL을 확인하고 있었음 |
| 단서 | Spring Boot 로그의 DB version은 9.3, Docker MySQL은 8.0.46 |
| 해결 | Spring Boot와 같은 방식으로 MySQL에 접속해서 확인 |
| 배운 점 | 애플리케이션이 보는 DB와 내가 확인하는 DB가 같은지 반드시 확인해야 함 |
이번 경험 덕분에 앞으로 DB 문제를 볼 때는 단순히 SHOW TABLES만 확인하는 것이 아니라,
애플리케이션이 실제로 어디에 연결되어 있는지부터 확인하는 습관을 가지게 되었다.
