Spring Boot Relaxed Binding으로 인한 Gateway Connection Refused

Spring Boot의 환경 변수 매핑은 어떻게 돌아가는 걸까?
김주혁's avatar
Nov 19, 2025
Spring Boot Relaxed Binding으로 인한 Gateway Connection Refused
 
Spring Cloud Gateway를 통해 여러 마이크로서비스를 라우팅하는 환경에서 특정 서비스만 연결이 되지 않는 문제가 발생했습니다.
finishConnect(..) failed: Connection refused: CONTAINER-NAME/IP:8080
환경
  • Docker Compose로 구성된 마이크로서비스 아키텍처
  • 모든 서비스가 동일한 Docker 네트워크(spring-network)에 연결
  • 다른 서비스는 정상 작동
  • < CONTAINER-NAME > 만 연결 거부
 
Gateway 설정
cloud: gateway: routes: - id: service uri: http://CONTAINER-NAME:8080 predicates: - Path=/aaa/**
(참고: 실제 Gateway 설정은 Java Config로 구성되어 있지만, 가독성을 위해 yml 형식으로 표현했습니다.)
application.yml 설정
server: port: 8080 address: 0.0.0.0 servlet: context-path: /aaa
 
  1. 먼저 컨테이너 실행을 확인해 보았습니다.
    1. docker ps | grep container-name
      컨테이너는 정상적으로 실행 중이었습니다.
  1. 다음은 Docker Network를 확인해 보았습니다.
    1. docker network inspect spring-network
      Gateway와 < container-name > 모두 동일한 네트워크에 속해 있었습니다.
  1. 설정 비교
    1. 다른 정상 작동하는 서비스들과 설정을 비교했지만, 동일한 구조였습니다.
 

원인 발견


application.yml에는 8080으로 명시되어 있고, Gateway도 8080으로 요청을 보내고 있습니다. 하지만 정말 8080 포트에서 실행되고 있을까요?
docker exec server-dw netstat -tlnp | grep 8080 # 아무것도 출력되지 않음
8080 포트에서 리스닝하지 않고 있었습니다. 이것이 Connection Refused의 원인이었습니다.
 
문제는 docker-compose.yml.env 파일 참조를 통해 해결할 수 있었습니다.
services: spring-dw-server: env_file: - .env `.env` 파일 SERVER_PORT=XXXX
분명 application.yml에는 port: 8080으로 설정되어 있는데, 실제로는 XXXX 포트로 실행되고 있었습니다.
 
docker-compose.yml을 다시 보니 주목해야 할 부분이 있었습니다.
env_file: - .env
.env 파일에서 환경 변수를 주입받고 있었는데, 그 안에 다음과 같은 변수가 있었습니다.
SERVER_PORT=XXXX이 포트 번호로 다시 검색해보니
docker exec server-dw netstat -tlnp | grep XXXX tcp 0 0 :::XXXX :::* LISTEN 1/java
.env의 SERVER_PORT 값으로 서버가 실행되고 있었습니다. 여기서 의문이 생깁니다. 코드 어디에도 SERVER_PORT 환경 변수를 명시적으로 참조하는 부분이 없는데,
 
어떻게 이 값이 적용된 걸까요? 핵심은 Spring Boot의 환경 변수 자동 매핑인 relaxed binding에 있었습니다. Spring Boot는 환경 변수를 프로퍼티로 자동 변환합니다.
 
설정 우선순위:
  1. 환경 변수 (가장 높음)
  1. Java 시스템 프로퍼티
  1. application.yml/properties
  1. 기본값
따라서 다음과 같은 상황이 발생했습니다:
# application.yml (우선순위 낮음) server: port: 8080 # .env → 환경 변수 (우선순위 높음) SERVER_PORT=XXXX # 이 값이 실제로 적용됨
중요한 점은 ${SERVER_PORT}처럼 명시적으로 참조하지 않아도, 환경 변수가 존재하면 자동으로 해당 프로퍼티를 덮어쓴다는 것입니다.

해결


.env 파일에서 불필요한 SERVER_PORT 환경 변수를 제거했습니다.
컨테이너를 재시작하니 정상적으로 8080 포트로 실행되었고, Gateway에서 정상적으로 연결되었습니다.
  1. 환경 변수는 application.yml보다 우선순위가 높습니다
      • Docker 환경에서 유연한 설정을 위한 Spring Boot의 설계 철학입니다
  1. 명시적 참조가 없어도 자동 매핑됩니다
      • SERVER_PORTserver.port로 자동 변환되어 적용됩니다
  1. 디버깅 시 환경 변수를 확인하세요
docker exec <container-name> env | grep SERVER docker logs <container-name> | grep "Tomcat started on port"
  1. 일관된 설정 관리가 중요합니다
    1. 여러 서비스에서 동일한 .env 파일을 공유할 때는 각 서비스별 환경 변수 충돌에 주의해야 합니다
이번 경험을 통해 Spring Boot의 환경 변수 처리 메커니즘을 더 깊이 이해할 수 있었습니다. Spring Boot의 Externalized Configuration 메커니즘, 특히 환경 변수의 자동 매핑과 우선순위 처리 방식에 대해 아는 것이 중요하다고 생각했습니다.
 
사실 표면적으로는 단순한 설정 문제처럼 보였지만, 실제로는 Spring Boot의 기본 원칙과 Docker 컨테이너 환경의 특성이 결합된 문제였습니다. 이러한 기본 동작 원리를 정확히 이해하는 것이 안정적인 인프라 환경을 구성하는 것에 중요하다고 다시 한 번 느꼈습니다.
 
알면 10초면 끝날 일을 모르면 하루가 걸려도 할 수 없는 것이 해결이니까요.
Share article

vlogue