docker로 올린 내 서비스, 왜 배포 후 로그인이 안 되는 걸까? (session, cookie, path 설정)

2025-01-16

문제 상황

지난 포스팅에서 nginx의 config 파일에 다음 항목을 추가하여 컨텍스트 경로를 처리했다.

server { listen 8087; # 생략 location /api/ { rewrite ^/api(/.*)$ /test-directory-x.x.x$1 break; # 생략 }}

server {
    listen 8087;    
   
    # 생략    
    
    location /api/ {        
	    rewrite ^/api(/.*)$ /test-directory-x.x.x$1 break;
	    
	    # 생략    
	  }
}

이 설정은 "야, 나 프론트인데 **/api/**로 시작하는 경로는 **/test-directory-x.x.x/api/****로 바꿔서 처리할게"**라는 의미였다. 이 작업을 통해 200 응답을 받을 수 있었다.

그런데, 로그인 API를 호출했더니... 200 응답 후, 세션에 저장된 회원 정보를 가져오지 못하고 401 에러를 반환하며 로그인 페이지로 회귀하는 문제가 발생했다.

그렇게 회귀*100 정도 반복되다가 개발자 도구 탭에서 Cookie가 어떻게 남아 있는지를 파악했다.


Response Cookies의 Path 확인!

오마이갓!

세션 쿠키의 path/test-directory-x.x.x/api로 설정된 것을 발견했다.

생각해보면 당연한 일이다. 로그인 API 호출 후, 백엔드에서 로그인 처리가 이루어지고, 세션 정보가 담긴 쿠키가 응답으로 전달되는데, 그 쿠키의 path/test-directory-x.x.x/api로 설정된 것이다.

이제 프론트엔드는 경로를 /api로 변환하여 사용하지만, 백엔드는 여전히 /test-directory-x.x.x/api로 알고 있었기 때문에 문제가 발생했다.


쿠키의 path는 특정 쿠키가 어떤 URL 경로에서만 유효할지를 지정한다. 서버가 쿠키를 전송할 때, 클라이언트는 해당 쿠키를 어떤 URL 경로에 대해 보낼지를 결정한다.


해결 방법

1. nginx의 config 파일을 롤백하여 컨텍스트 경로에 대한 처리를 하지 않도록 한다.

server {
    listen 8087;
 
    # 생략
 
    location /api/ {
        # 생략
    }
}

2. WAR 파일의 명칭을 'ROOT'로 지정한다.

이렇게 하면 WAR 파일은 /usr/local/tomcat/webapps 디렉토리 하위에 ROOT.war로 저장된다.나는 Dockerfile로 이미지를 만들기 때문에, 아래 구문을 추가했다.

# ROOT.war로 이름 변경
RUN mv /usr/local/tomcat/webapps/test-directory-x.x.x.war /usr/local/tomcat/webapps/ROOT.war

3. nginx와 도커 컨테이너를 재구동한다.


결론

이 방법을 통해 로그인도 무사히 완료되었고, 전체 서비스를 사내 온프레미스 서버에 정상적으로 배포할 수 있었다.

다시 한 번 기억하자!

Tomcat에서 WAR 파일을 기본적으로 /webapps 디렉토리에 배포하면, WAR 파일의 이름에 따라 컨텍스트 경로가 자동으로 설정된다.