본문 바로가기

프로젝트/Techfork

[26/01/23] 오늘의 개발 일지 - baseUrl 문제 해결 및 쿠키 도메인 에러 해결

오늘은 카카오 OAuth2 로그인을 연동하던 중 트러블 슈팅이 있었습니다.

 

로컬에서는 잘 되던 로그인이

배포 환경에서 제대로 진행되지 않았고, Nginx 리버스 프록시와 관련이 있을거라고 짐작을 하였습니다.

 

저희 서비스는 Cloudflare와 Nginx를 통해 HTTPS를 구현하였고, 구조는 아래와 같습니다.


🏗️ 전체 아키텍처

사용자 브라우저
       ↓ HTTPS (443)
   Cloudflare (SSL 종료)
       ↓ HTTP (80)
     Nginx (리버스 프록시)
       ↓ HTTP (8080)
   Spring Boot

 


🔧 Nginx 리버스 프록시 설정

upstream springapp {
    server 127.0.0.1:8080 fail_timeout=0;
}

server {
    listen 80;
    server_name techfork.shop www.techfork.shop api.techfork.shop;

    # Cloudflare Real IP 설정
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;
    real_ip_header CF-Connecting-IP;

    location / {
        proxy_pass http://springapp;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;  # Cloudflare 환경에서는 https 고정
    }
}

Nginx 설정은 terraform 코드로 위와 같이 되어있는데요. 차근차근 살펴보겠습니다.

 

각 설정의 의미

설정 역할

upstream 백엔드 서버 그룹 정의, fail_timeout=0은 실패해도 바로 재시도
listen 80 HTTP 80 포트 수신 (Cloudflare가 SSL 종료하므로)
set_real_ip_from Cloudflare IP 대역 신뢰 설정
real_ip_header CF-Connecting-IP Cloudflare 헤더에서 실제 클라이언트 IP 추출
proxy_set_header Host 원본 요청의 Host 헤더 전달
proxy_set_header X-Forwarded-Proto 원본 프로토콜 정보 전달 (HTTPS)

위와 같이 설정이 되어 있었는데 불구하고 문제가 생겼던 것입니다.

무엇이 문제였을까요?

 


🚨 문제 1: redirect_uri가 localhost로 생성됨

증상

  • OAuth2 로그인 후 콜백에서 멈춤
  • 카카오 개발자 콘솔에서 "redirect_uri 불일치" 에러

원인

Spring Security OAuth2 설정에서 {baseUrl} 플레이스홀더를 사용할 때:

spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"

{baseUrl}은 Spring이 인식하는 자신의 주소로 치환됩니다.

Spring Boot는 자기 앞에 프록시가 있는지 모르기 때문에:

# Spring이 인식하는 자신의 주소
http://localhost:8080

# 실제 외부에서 접근하는 주소  
https://api.techfork.shop

결과적으로 잘못된 redirect_uri가 생성됩니다:

# ❌ 잘못 생성된 redirect_uri
http://localhost:8080/login/oauth2/code/kakao

# ✅ 올바른 redirect_uri
https://api.techfork.shop/login/oauth2/code/kakao

 

그럼 어떻게 해결했을까요?

 

해결

application.yml에 추가:

server:
  forward-headers-strategy: native

 

forward-headers-strategy란?

리버스 프록시 뒤에서 원본 요청 정보를 인식하게 해주는 설정입니다.

Nginx가 전달하는 헤더들:

proxy_set_header X-Forwarded-Proto https;   # 원본 프로토콜
proxy_set_header X-Forwarded-Host $host;    # 원본 호스트
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  # 클라이언트 IP

Spring Boot는 기본적으로 이 헤더들을 무시합니다 (보안상 이유).

forward-headers-strategy: native 설정은 Spring에게 "이 헤더들 신뢰해도 돼, 사용해"라고 알려주는 것입니다.

설정값 동작

none X-Forwarded 헤더 무시 (기본값)
native 서블릿 컨테이너(Tomcat)가 처리
framework Spring Framework가 처리

 

OAuth2 로그인 흐름 비교

❌ forward-headers-strategy 설정 없을 때:

1. 사용자가 카카오 로그인 클릭
2. Spring이 카카오로 리다이렉트
   → redirect_uri=http://localhost:8080/login/oauth2/code/kakao
3. 카카오 로그인 성공
4. 카카오가 http://localhost:8080/... 으로 리다이렉트 시도
5. ❌ 실패 (localhost는 카카오 서버에서 접근 불가)

✅ forward-headers-strategy 설정 후:

1. 사용자가 카카오 로그인 클릭
2. Spring이 X-Forwarded-* 헤더를 읽어서 실제 주소 파악
3. Spring이 카카오로 리다이렉트
   → redirect_uri=https://api.techfork.shop/login/oauth2/code/kakao
4. 카카오 로그인 성공
5. 카카오가 https://api.techfork.shop/... 으로 리다이렉트
6. ✅ 성공!

 

 

설정 후 Spring이 인식하는 값 변화

// 설정 전
request.getScheme()      → "http"
request.getServerName()  → "localhost"
request.getServerPort()  → 8080

// 설정 후
request.getScheme()      → "https"
request.getServerName()  → "api.techfork.shop"
request.getServerPort()  → 443

 

디버깅 팁

실제로 어떤 redirect_uri가 생성되는지 확인하려면:

방법 1: 로그 레벨 조정

logging:
  level:
    org.springframework.security.oauth2: DEBUG

방법 2: 브라우저 개발자 도구

Network 탭에서 카카오로 가는 요청의 URL을 확인:

https://kauth.kakao.com/oauth/authorize?
  client_id=xxx&
  redirect_uri=여기를_확인&
  response_type=code

 


🚨 문제 2: 쿠키 도메인 에러

증상

java.lang.IllegalArgumentException: An invalid domain [.techfork.shop] was specified for this cookie

OAuth2 로그인 성공 후 쿠키 설정 단계에서 에러가 발생했습니다.

 

원인

RFC 6265 표준에서는 쿠키 도메인 앞에 점(.)을 붙이면 안 된다고 합니다.

// ❌ 잘못된 코드
cookie.setDomain(".techfork.shop");

// ✅ 올바른 코드  
cookie.setDomain("techfork.shop");

 

쿠키 도메인 동작 원리

설정값 적용 범위

techfork.shop techfork.shop, api.techfork.shop, www.techfork.shop 전부
api.techfork.shop api.techfork.shop만

점 없이 설정해도 서브도메인 전체에서 쿠키 공유가 가능합니다!

 

예전 방식 vs 현재 방식

# RFC 2109 (구버전) - 점 필요했음
.techfork.shop → 서브도메인 포함

# RFC 6265 (현재) - 점 없이
techfork.shop → 서브도메인 자동 포함

Tomcat 최신 버전은 RFC 6265를 따르기 때문에 앞에 점 붙이면 에러가 납니다.

 

해결

환경변수 수정:

# ❌ 잘못된 설정
SERVER_DOMAIN=.techfork.shop

# ✅ 올바른 설정
SERVER_DOMAIN=techfork.shop

또는 CookieUtil 코드 수정:

// ❌ 점을 붙이는 코드가 있다면 제거
cookie.setDomain("." + domain);

// ✅ 그대로 사용
cookie.setDomain(domain);

 

✅ 최종 체크리스트

Spring Boot 설정 (application.yml)

server:
  forward-headers-strategy: native
  domain: ${SERVER_DOMAIN:localhost}

spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"

 

Nginx 설정

location / {
    proxy_pass http://springapp;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;  # Cloudflare 환경
}

 


📝 요약

문제 원인 해결

redirect_uri가 localhost Spring이 프록시 뒤 주소를 모름 forward-headers-strategy: native
쿠키 도메인 에러 RFC 6265에서 점(.) 금지 SERVER_DOMAIN=techfork.shop