기능 공유 및 에러핸들링

[error] 로그인 안됨 문제 (JWT 쿠키 저장 안됨 (Nest.js)/ SSR (Next.js) )

Fo_rdang 2024. 11. 30. 20:49
반응형

나는 프론트엔드는 Next.js, 

백엔드는 Nest.js로 웹 개발을 진행했다. 

 

풀스택? 을 가능하게 한 AI에게 무한한 감사 인사를 드리고 시작한다. 

요즘 AI에 대한 부정적 인식과는 다르게 나는 AI에 대하여 아주 긍정적 & 낙관적 인식을 가지고 있다. 

'이번 AI 만큼은 삶의 파괴를 가져올 것이다 ' 는 말이 안된다고 생각한다. 

 

지난 두려움을 생각해보자. 

- 산업혁명 (러다이트 운동: 기계가 일자리를 뺏는다는 이유로 기계 파괴)

- 자동차 시대 (말과 마차를 생업으로 삼던 사람들 생계 위협, 도시의 소음과 대기 오염 증가에 대한 우려)

- 인터넷 등장 

- 스마트폰의 보급 

 

변화는 언제나 두렵지만, 늘 반갑다. 

 

초개인화된 사회에서 AI는 더욱이 필요하다. 

각자도생이 된 사회에서 AI는 희망이다.. 

 

그럼에도 AI가 미운가? 그럼 쓰지마라. 

그건 말이 안되는가? 

그럼 감사해하며 AI를 적극적으로 활용하고, 변화를 즐겨보자. 

 

이상황에서 받아들이지 않는 자는 도태의 길을 걸을 뿐이다. 

 

'라며 스스로에게 말했다.'  (남에게 강요안함) 

 

.

.

.

 

Shout out to 'Chat GPT'

 

.

.

.

 

Anyway.... 

 

.

.

.

 

며칠간 배포환경에서 로그인이 안되는 문제를 해결하느라 애를 정말 썼다. 

오늘,,,은 정말 토가 나올 것 같은 기분에,,,

도서관에서 속으로 욕을 하며 코드를 피토하는 심정으로 살펴봤다. (신기하게 속은 울렁거렸으나, 집중도는 점점 높아졌다) 

 

개발환경에서는 로그인 때, 브라우저 쿠키에 JWT가 자동으로 저장이 잘 되는데 

배포환경에서는 저장이 안되고, URL 요청도 안됐다. (네트워크 탭 보면 안찍힘) 

 

나는 nest.js에서 jwt를 관리했기 때문에 주구장창 해당 부분 코드를 계속 바꿔가며.. 배포해보며... test 해봤다. 

결론부터 이야기 하자면 FE 코드의 SSR 문제였는데, 

 

뭐 삽질 덕에 JWT 부분을 좀 완벽히 알게 되었다. (착각이겠지) 

그래서 해당 부분을 정리해서 남들에게 도움이 되고자 한다. (됐으면 좋겠다.) 

 

내가 정리할 것은 두개다. 

1. Nest.js 프로젝트에서 jwt 를 자동으로 생성할 때 확인해야 할 점. (당신의 코드 중 안되는 이유가 이 중 하나일 것) 

2. 나의 Next.js에서의 SSR 문제 해결 

 

.

.

.

 

시작해보자. 

.

.

.

(자세한 설명은 없고, 체크해 볼 만한 소스를 던진다는 느낌) 

01. JWT 쿠키 자동 생성 때 확인해야할 점 (Next.js)

Check01) origin 을 확인하자. 

 

origin 배열 : server에서 허용할 출처(도메인)을 명시한다. 

 

  • http://localhost:3000: 로컬 개발 환경에서 프론트엔드와 백엔드가 통신할 때 허용.
  • https://~~: 배포된 프로덕션 환경의 기본 도메인.
  • https://www.~~~: www가 붙은 도메인도 허용.

 

 

Check02) credentials를 확인하자. 

 

credentials: true 설정을 꼭 해야 한다. 

 

=> 클라이언트가 쿠키를 사용하거나, 인증 토큰을 헤더에 포함해 요청할 때 필요하다. 

 

Check03) 그 외 추가 코드 

 

만약 계속 jwt 이 안된다면 해당 코드도 추가해보자. (아래 전체 코드 붙임) 

 

- methods: 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS'

=> CORS 설정에서 클라이언트가 서버에 요청할 수 있는 HTTP 메서드의 종류를 명시.

 

- allowedHeaders: 'Content-Type, Accept, Authorization'

=> CORS 설정에서 요청 헤더에 대해 허용 가능한 목록을 명시.

 

- OPTIONS 요청 처리

=>  이 미들웨어는 OPTIONS 요청에 적절히 응답하고, 이후 실제 요청(GET, POST 등)을 처리할 수 있도록 함.

 

- 헤더 설정

 

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as cookieParser from 'cookie-parser';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors({
    origin: [
     '각자 쓰기'
    ],
    credentials: true,
    methods: 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS',
    allowedHeaders: 'Content-Type, Accept, Authorization',
  });
  app.use(cookieParser());

  app.use((req, res, next) => {
    if (req.method === 'OPTIONS') {
      res.header('Access-Control-Allow-Origin', req.headers.origin || '');
      res.header(
        'Access-Control-Allow-Methods',
        'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
      );
      res.header(
        'Access-Control-Allow-Headers',
        'Content-Type, Accept, Authorization',
      );
      res.header('Access-Control-Allow-Credentials', 'true');
      return res.status(204).end();
    }
    next();
  });
  await app.listen(4000);
}
bootstrap();

 

 

Check04) res.cookie 부분 

 

해당 부분을 100번은 확인해본 것 같은데, 

왜냐하면 개발 환경에서만 안됐기 때문에 환경 변수 부분이 잘못됐나 계속 확인했다. 

 

개발 환경에서는 

- secure: false 

- sameSite :'lax'

이 되게 하였고, 

 

=> 로컬 환경에서는 http 이기 때문에 secure값이 false가 되어야 한다. 

 

배포 환경에서는 

- secure: true

- sameSite:'none'

이 되게 하였다. 

 

=> 프론트와 백엔드 도메인 각각 다르기 때문에 sameSite가 none이 되어야 한다. 

 

 

 

Check05) 환경 변수 파일 체크 

 

아무래도 해당 부분을 놓쳤을 가능성이 크다. 

왜냐하면 env 파일이 깃허브에 올라가지 않게 설정이 되었을 것이다. (.gitignore 파일에 설정되어있음.)

따라서, 

ec2 에 있는 내 프로젝트 에다가 .env 파일을 따로 생성해주자. 

 

sudo nano .env

 

pm2로 재실행할 때 env 업데이트 되게 하는 명령어

 

sudo restart <project-name> --update-env

 

 

Check06) pm2 logs, nginx logs 확인 

해당 jwt 문제인지 내 프로젝트가 실행이 잘 안되고 있는지 확인해봐야 한다. 

 

내 경우에는 프록시는 nginx를 

실행은 pm2를 활용했기 때문에 

 

두개 logs 파일을 들여다봤다. 

 

logs 파일 들여다 볼건 다 들여다 봐야 한다. (각자의 개발 환경에서 생각해보자 어디 파일에 log가 있는가?) 

 

Check07) nginx 파일에 중복으로 헤더 설정 삭제 

 

cors 가 문제인가 싶어서 백엔드 nginx  설정 파일 쪽에도 cors 설정을  추가했었는데, 

이렇게 cors 설정을 nest.js 파일에도 하고 

중복되게 설정하면 문제가 생긴다. 

 

한 곳에만 설정하자.

 

server {
    listen 443 ssl;
    server_name korea-hospital.site;

    location / {
        proxy_pass http://localhost:3000; # Nest.js 백엔드
        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;

        # CORS 설정 <이 부분 이야기 하는 것>
        add_header 'Access-Control-Allow-Origin' 'https://onschoolisreal.site';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept';
    }
}

 

nginx 설정 후에 이것도 확인해봐야 한다.

 

변경한 설정에 문제가 없는지 테스트 명령어 

sudo nginx -t

 

nginx 재시작 명령어 

sudo systemctl reload nginx

 

 

뭐든지 파일 설정 변경하면 적용되도록 해야한다. (자신의 개발 환경에 맞게 생각해보자) 

 

Check08) 프론트 코드 에서 credentials 설정 

 

api 요청하는 부분인데,

credentials: "include"

코드를 넣어줘야 한다. 

 

Check09) 프록시 서버나 로드 밸런서가 있는 경우, 이들이 Set-Cookie 헤더를 차단하거나 수정할 수 있다. 

proxy_pass_header Set-Cookie;  # Set-Cookie 헤더를 클라이언트에 제대로 전달할 수 있도록 추가
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;

 

 

Check10) 해당 api만 안되는게 맞는지? 

 

로그인(jwt 저장)만 안되고 있는게 맞는가? 

다른 api 들은 잘 작동되고 있는지 (fe -be 통신 확인) 

확인해보자. 

 

나는 결국 이 check10 에서 정답을 찾았다.

해당 api 만 안되는게 맞는지 확인하기 위해서 코드를 수정하는 과정에서 답을 찾았다.

 

회원가입 요청은 된거 맞으니까, 로그인만 안되는거라 확신했었다. 

 

다른 페이지는 배포 환경에서 못들어가봤는데

그 이유는 로그인 jwt 이 없으면 접근하지 못하게 막아놨기 때문이다.

 

check 8까지 반복 시도한 후, 결국 난 지쳐 나가 떨어져....

전체적으로 코드를 확인하기로 했다. 

 

페이지에 접근하지 못하게 한 코드를 모두 주석처리 했다.

 

그랬더니 웬걸? 로그인 jwt 되더라. 

jwt 관련 코드 문제도 아니였고, 프론트-백엔드 api 통신 문제도 아니였고,,, 

 

페이지 접근 권한 코드가 문제였던 황당한 ,,, 문제가 원인이였다. 

 

.

.

.

.

.

 

여기까지가 Nest.js에서 jwt 관련 고민해 볼 소스였다. 

 

(이제 완전히 다른 주제임)

 

이제는 왜 내 프론트 코드 (Next.js) 가 문제였는지 알아보자. 

이건 안궁금해하실 것 같고,,,

내가 잘 이해가 안가서 정리하면서 이해해보기로 하자. 

 

.

.

.

 

이제 나가주세요 (next.js ssr 를 한번 생각해볼 사람은 남아주세요)

 

.

.

.

 

02. Next.js에서의 SSR 문제 해결

해당 부분 코드가 문제였다. 

 

login 페이지에 진입할 때 SSR 방식으로 loginAuthentication 함수를 실행했다. 

 

 

 

/auth/login 요청이 발생하기도 전에 페이지 접근이 차단되었을 가능성이 크다. 

특히, loginAuthentication 함수에서 jwt 토큰이 존재하는 경우, 

로그인 페이지(/login) 에 접근하지 못하고 리다이렉트가 발생한다. 

 

 

 

 

 

 

 

 

반응형