순간을 성실히, 화려함보단 꾸준함을

nginx(reverse proxy) 를 이용하여 cookie samesite 문제 해결하기 본문

나의 개발 메모장

nginx(reverse proxy) 를 이용하여 cookie samesite 문제 해결하기

폭발토끼 2024. 12. 22. 20:23

안녕하세요.

정말 오랜만에 글을 작성해봅니다.

현생에 치여서 블로그 관리를 중단한지 오래됐었네요 ㅎㅎㅎ

 

이번 글은 여러 곳에서 참고하면서 찾아보려고 했지만 관련 정보가 잘 없고 gpt 와 지인분의 도움을 받아 해결했던 문제를 기록으로 남겨보려고 합니다.

 

Cookie 공유 문제입니다.

먼저 cookie 에 대한 간단한 정책은 다른 블로그 및 유투브 영상으로 학습해 오셔야지 됩니다.

https://www.youtube.com/watch?v=Q3YuKipzPbs

위 영상이 정말 잘 설명 잘되어있습니다!

 

cookie 를 발급할때 도메인을 설정할 수 있습니다. spring 에서는 ResponseCookie 를 이용해서 cookie 를 만들때 domain 을 설정할 수 있는데, 이때 domain 을 따로 명시하지 않으면 요청이 온 domain 명으로 자동으로 생성됩니다.

즉, boomrabbit.com 에서 제가 만든 서버로 요청이 와서 cookie 가 발급이 된다면 이 cookie 의 domain 은 boomrabbit.com 이 된다는 뜻입니다.

 

그럼 해당 cookie 는 boomrabbit.com 에서만 유효한 cookie 가 되겠죠??? 혹은 하위도메인 => sub.boomrabbit.com 과 같은 도메인에서 유효하게 됩니다.

 

단, 조건이 붙죠??? 어떨때?? 바로 samesite 의 옵션값이 lax 일때!!!

만약 samesite 옵션이 none 이면 서로 다른 도메인이라고 할지라도 상관없이 쿠키를 공유할 수 있습니다.

그러나 위 같은 상황은 반드시 ssl 인증서를 적용해야지만 된다!! 라고 강제하고 있죠

 

여기까지가 위 영상의 대략적인 설명이었습니다.

 

문제 : samesite = lax 로 cookie 를 어떻게 공유할 수 있을까??

만약에 ssr 방식이 아닌 spa 방식으로 웹개발을 진행하고 있다면 cookie 를 어떻게 공유해야 할까요?

각기 다른 서버에 각 소스가 배포되어 있고, 다른 도메인 명을 가지고 있는 상태에서 cookie 를 공유하려면 무조건 samesite 옵션을 none 으로 설정하고 ssl 인증서를 도입하여 https 통신으로만 적용시켜야 하는 걸까요???

 

현재 제가 개발하고 있는 프로젝트의 구조는 아래와 같습니다.

그림이 좀 조잡하더라도 양해 부탁드립니다 ㅎㅎㅎ

각기 다른 ec2 에 nextjs / jar 파일들이 위치해 있고 실행 되고 있습니다.

당연히 각 서버의 ip 가 다르다보니 cookie 공유가 되지 않겠죠??

두 서버 전부 domain name 은 적용시키지 않고 순수한 ip 로만 api 요청을 보내는 중 입니다.

 

domain 을 하나로 통일 시켜주면서 요청을 보낼 수는 없을까?

현재 문제는 nextjs(10.127.xxx) 에서 다이렉트로 spring boot(10.128.xxx) 로 api 요청을 보낸다는 것 인데요. 그러면 nextjs 에서 백엔드 서버가 아닌 '어딘가' 로 요청을 보내고 그 '어딘가' 에서 대신 백엔드로 요청을 보내는 방식으로 구조를 짠다면 domain 을 일치시켜 줄 수도 있지 않을까? 라고 지인분한테 조언을 들었습니다.

 

더불어 nginx 의 reverse proxy 라는 키워드로 검색을 해보라고 추천을 해주더라구요.

 

https://narup.tistory.com/238#google_vignette

 

[Nginx] 리버스 프록시(Reverse Proxy) 개념 및 사용법

1. 개요 리버스 프록시란? 클라이언트 요청을 대신 받아 내부 서버로 전달해주는 것을 리버스 프록시(Reverse Proxy) 라고 합니다. 저도 사실 프록시라는 개념이 낯설었는데요, 일단 프록시라는 개념

narup.tistory.com

nginx 를 사용한 reverse proxy 의 대한 설명이 담겨 있는 블로그 글 입니다. 참고해주세요!

 

간략하게 말해서 요청을 분기처리 해주는 역할을 수행하는 오픈소스 웹서버입니다. nginx 를 사용하여 api 요청을 보낼때 하나의 도메인으로 통일 시켜 보내줄 수 있습니다.

 

원래는 nextjs 에서 api 요청을 보낼때 백엔드 ip url 로 바로 보냅니다.

(백엔드 ip 는 env 에 담겨져 있습니다)

 

이렇게 되면 nginx 를 거치지 않고 통신이 이루어 지게 됩니다. 따라서 nginx 에서 설정한 domain 으로 요청을 보내게끔 변경해주셔야 되는데 그러면 domain 을 어디서 어떻게 설정하나요?

 

nginx 가 설치되어 있는 서버로 들어가서

/etc/nginx/nginx.conf

위 파일에서 수정해주면 됩니다.

(전 참고로 nginx 를 nextjs 가 설치되어 있는 ec2 서버에 설치하였습니다)

https://longtermsad.tistory.com/11

 

Amazon Linux 2에 nginx 설치

Amazon Linux 2 OS의 EC2에서 nginx 설치하는 방법에 대해서 알아보겠습니다. Amazon Linux 2에서는 yum을 통한 nginx 설치가 지원되지 않습니다. 일반적인 yum 을 통한 설치 시 에러가 발생하는 것을 볼 수 있

longtermsad.tistory.com

대략적으로 위와 같은 그림이 될 것 같습니다.

nextjs 와 spring boot 는 서로 직접적인 통신을 하지 않습니다. 오로지 nginx 를 통해서만 통신을 하게 됩니다.

    server {
        listen       80;
        server_name  도메인명(ex : mydomain.com or 10.127.xxx)
        # domain name 을 구입하지 않았으면 그냥 frontend ip 를 적어주시면 됩니다.(port 는 제외)

        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;

        # Next.js 애플리케이션 프록시
        location / {
        		# 저는 nginx 를 nextjs 와 같은 ec2 에서 설치하였으니 localhost(127.0.0.1) 로 
                # 설정하였습니다.
                # 만약 다른 ec2 에 nginx 를 설치하였으면 nextjs ip or domain name 을 적어주시면 됩니다.
                proxy_pass http://127.0.0.1:3000; # Next.js 서버가 실행 중인 로컬 IP와 포트
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
                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 $scheme;
        }

        # Spring Boot API 프록시
        location /api/ {
        		# 백엔드소스(jar) 이 위치한 ec2 ip 를 10.128.xxx 라고 가정하였으니 
                # 해당 ip 와 port 를 적어주시면 됩니다
                proxy_pass https://10.128.xxxx:8080; # Spring Boot EC2 IP와 포트
                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 $scheme;
        }
        
        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

 

현재 제 프로젝트에는 domain name 을 구입하여 각 서버에 입힌 상태입니다. ssl 까지 입혀져 있는 상태여서 소스를 그대로 캡쳐해서 보여드리기에는 오히려 더 혼란이 올 수 있습니다.

 

domain name 과 ssl 인증서를 입히기 전단계를 최대한 재연해보았습니다.

 

중요한건 위와 같이 nginx 를 설정하였으면 반드시 nginx.conf 파일이 정상적으로 적용이 되었는지

sudo nginx -t
sudo systemctl restart nginx

위 명령어로 확인해주시고 재기동 까지 하셔야 합니다.

 

nextjs 의 모든 요청을 nginx 에서 정의한 domain 으로 통일 시켜주기

이제 모든 요청은 nginx 를 통해서 전송이 되어야 하기 때문에 남은 작업은 nextjs 에서 요청 url 을 nginx 에 정의한 domain 으로 수정하면 됩니다.

    server {
        listen       80;
        server_name  mydomain.com or frontend ip

server_name 에 정의한 값으로요.

 

그리고 브라우저에서도 domain 으로 접속한다음 api 요청을 보내면 서버쪽에서 생성한 cookie 가 정상적으로 저장이 되어있는 것을 확인하실 수 있습니다.

 

감사합니다!!