본문 바로가기

nginx 뒤에 둔 스프링부트에서 클라이언트 IP가 전부 127.0.0.1로 찍힙니다

조회 1 · 댓글 1
모나미153모나미153작성자2026년 8월 26일

스프링부트 3.4(내장 톰캣 10.1) 앱을 같은 서버의 nginx로 리버스 프록시 걸어서 쓰고 있는데, 톰캣 액세스 로그랑 코드에서 request.getRemoteAddr() 찍어보면 전부 127.0.0.1로 나옵니다. 접속 IP별로 통계를 내야 해서 실제 클라이언트 IP가 필요합니다.

nginx location에는 이렇게 넣어놨습니다.

proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

헤더는 잘 넘어오는 것 같은데(컨트롤러에서 X-Forwarded-For 꺼내보면 IP 찍힘) getRemoteAddr는 여전히 127.0.0.1이네요. 헤더에서 직접 꺼내서 쓰는 방법 말고, 톰캣이나 부트 설정으로 해결할 수 있는 방법이 있을까요? 설정 어디에 뭘 넣어야 하는지 궁금합니다.

appsrootappsroot2026년 8월 27일

헤더는 정상적으로 들어오고 있으니 nginx 쪽은 끝난 상태고, 톰캣이 그 헤더를 읽어서 getRemoteAddr() 값을 바꿔주도록 켜주기만 하면 됩니다. 톰캣에는 이 용도로 RemoteIpValve가 있고, 스프링부트는 프로퍼티 한 줄로 그 밸브를 등록해 줍니다. 확인해 보겠습니다.

1. 부트 프로퍼티 한 줄

server.forward-headers-strategy=native

이 값이 native면 부트가 내장 톰캣에 RemoteIpValve를 넣어줍니다. 기본값은 none(클라우드 플랫폼 감지 시에만 native)이라 아무 설정이 없으면 톰캣은 X-Forwarded-For를 무시하고 소켓의 상대 주소, 즉 nginx의 127.0.0.1을 그대로 돌려줍니다. 지금 보시는 현상이 정확히 그 기본 동작입니다.

이렇게 하면 getRemoteAddr()가 X-Forwarded-For의 클라이언트 IP를 돌려주고, getScheme()/isSecure()도 X-Forwarded-Proto를 따라갑니다. 내장 톰캣 액세스 로그의 %a도 같은 값을 쓰기 때문에 로그 통계도 같이 해결됩니다.

2. 헤더 이름과 신뢰 프록시 범위

RemoteIpValve의 기본 헤더가 x-forwarded-for, X-Forwarded-Proto라서 지금 nginx 설정과 그대로 맞습니다. X-Real-IP는 톰캣이 보지 않으니 있어도 무해하고 없어도 됩니다. 바꿔야 할 일이 있으면 아래 프로퍼티로 조정합니다.

server.tomcat.remoteip.remote-ip-header=x-forwarded-for
server.tomcat.remoteip.protocol-header=x-forwarded-proto

한 가지 더 볼 것이 server.tomcat.remoteip.internal-proxies입니다. 밸브는 이 정규식에 맞는 주소에서 온 요청만 프록시로 신뢰하고 헤더를 해석합니다. 기본값에 127.x, 10.x, 192.168.x, 172.16~31.x, 169.254.x가 들어 있어서 지금처럼 nginx가 같은 서버(127.0.0.1)에 있으면 추가 설정 없이 동작합니다. 나중에 nginx나 로드밸런서가 다른 대역의 사설 IP나 공인 IP로 옮겨가면 이 값에 그 주소를 넣어줘야 하고, 반대로 이 값을 비워서 전체를 신뢰하게 두면 클라이언트가 X-Forwarded-For를 위조해 IP를 속일 수 있으니 운영에서는 비우지 마세요.

3. 확인

재시작 후 외부에서 한 번 호출해 보고, 액세스 로그나 getRemoteAddr()에 공인 IP가 찍히면 끝입니다. 만약 코드에서는 바뀌었는데 액세스 로그만 여전히 127.0.0.1이면 server.tomcat.accesslog.request-attributes-enabled=true를 추가하면 됩니다(밸브가 남긴 요청 속성을 액세스 로그가 우선 사용하도록 하는 옵션).

4. 참고

부트 없이 순정 톰캣이라면 server.xml의 Host 안에 <Valve className="org.apache.catalina.valves.RemoteIpValve" /> 한 줄이 같은 역할입니다. 그리고 nginx가 HTTPS를 받고 톰캣으로 http로 넘기는 구성이면 proxy_set_header X-Forwarded-Proto $scheme;도 함께 넣어두는 것이 좋습니다. 리다이렉트 URL이 http로 만들어지는 문제까지 같은 밸브가 잡아줍니다.

공식 문서: Tomcat 10.1 Remote IP Valve, Spring Boot How-to: Embedded Web Servers (Use Behind a Front-end Proxy Server)

로그인 후 답글을 남길 수 있습니다.