Conversation
- secure 옵션인 refresh token 쿠키로 인해 설정
- 브라우저 alert 창으로 제공
Mimiminz
left a comment
There was a problem hiding this comment.
에러처리랑 로그인 안했을 시 리다이렉션, 멤버 아이디 가져오는 걸 정리하니까 코드가 훨씬 깔끔해졌네요..!
There was a problem hiding this comment.
이 파일은 ssr 전용 프로필 정보 가져오는 함수인가요?
There was a problem hiding this comment.
아뇨!
이 파일의 목적은 Matcher에 정의된 경로에 접근했을 때,
쿠키에 accessToken과 memberId가 없으면 login 페이지로 이동하는 것입니다.
예를 들어, / 페이지 달라고 nextjs 서버에 요청 들어가기 전에, cookie에 access token과 memberId가 없으면 로그인 페이지로 이동합니다.
| public name = 'ApiError'; | ||
| public statusCode: number; | ||
| public errorCode: string; | ||
| public errorName: string; |
There was a problem hiding this comment.
혹시 여기 name과 errorName이 다른 역할을 하는 건가요?
name은 어떤 곳에 쓰이는 건지 궁금합니당
There was a problem hiding this comment.
name은 저희쪽에서 만든 Error 객체임을 표현하고 싶었고,
errorName은 서버에서 응답값으로 내려줍니다.
middleware.ts
Outdated
| isNumeric(request.cookies.get('memberId')?.value); | ||
|
|
||
| // sign-up 페이지에서 memberId는 null (사용자 이름을 등록해야 memberId 주어짐) | ||
| if (request.url.endsWith('/sign-up')) { |
There was a problem hiding this comment.
혹시 이 부분 request.url.endsWith('/sign-up') 보다
const { pathname } = request.nextUrl; 이런 식처럼 request.nextUrl를 사용하는 건 어떻게 생각하시나용
| export const axiosServerInstance = axios.create({ | ||
| baseURL: `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/`, | ||
| timeout: 10000, | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| withCredentials: true, | ||
| }); |
There was a problem hiding this comment.
서버가 갱신되지 않는 이유....는 정확하지 않지만...
찾아보니 withCredentials: true로는 쿠키가 안 실린다는 것 같습니다..
원래 보통 withCredentials 세팅을 하면 프론트에서 자동으로 쿠키를 첨부해서 서버로 넘겨주지만,
next.js의 SSR의 경우에는 실행되는 위치가 프론트측(브라우저)이 아닌 서버측에서 실행되고 실행 결과를 이용한 완성된 페이지를 프론트로 넘겨주기 때문에 브라우저에 저장되어 있는 쿠키를 알지 못한다고 합니다.
따라서 이 경우에도 refreshToken이 쿠키에 실리지 않아서 백엔드가 인식하지 못해 갱신이 안되는 오류가 아닐까......하는 생각이 듭니다. 🤔
저도 next의 토큰은 잘 몰라서 어렵네요.. 좋은 방법이 있다면 바로 공유하도록 하겠습니다,,
|
영은님 조언대로, middleware에서 access token 유효성 검사를 하였습니다. middleware에서 토큰 재갱신 로직을 짠 이유서버 컴포넌트에서 사용할 axiosServerInstance에서 재갱신 로직을 짜게 된다면, 아래와 같은 flow로 진행됩니다.
하지만, cookies().set은 서버 컴포넌트 측에서 사용할 수 없습니다. server action 또는 route handler에서 사용할 수 있습니다. (공식문서)
axiosServerInstance로 재갱신하는 방법 대신, middleware로 페이지 진입하기 전에 access token이 유효한지 검증하는 방식으로 구현했습니다. middleware에서 재갱신 로직
axiosServerInstance로 요청을 보내기 전에, middleware 쪽에서 access token을 검증합니다. /api/v1/auth/me api는 access token을 통해 memberId를 반환합니다. {
"statusCode": 401,
"timestamp": "2025-08-12T19:56:58.7278032",
"errorCode": "AUTH001",
"errorName": "AUTHENTICATION_FAILED",
"message": "Authentication Failed"
}이 api를 통해 재갱신 로직을 구현하였습니다. refreshAccessToken이 함수는 refresh token으로 access token을 발급하여 반환하는 함수입니다. const refreshAccessToken = async () => {
try {
const refreshToken = await getServerCookie('refresh_token');
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/auth/access-token/refresh`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
cookie: `refresh_token=${refreshToken}`, // 쿠키를 수동으로 전송
},
},
);
const data: { content: { accessToken: string } } = await response.json();
return data.content.accessToken;
} catch (error) {
return null;
}
};저렇게 수동으로 설정해둔 이유는 |
|
백엔드 서버 로컬로 띄워서 access token 유효시간을 2초로 두고 테스트 한 화면입니다. 2025-09-05.3.26.30.mov |
middleware.ts
Outdated
| const res = await axios.get<{ content: number }>( | ||
| `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/v1/auth/me`, | ||
| { | ||
| headers: { | ||
| Authorization: `Bearer ${accessToken}`, | ||
| }, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
공식문서에서 middleware의 경우 Edge Runtime에서 돌며, axios의 경우 내부적으로 환경에 따라 Node.js API를 사용하기 때문에 fetch를 사용하는 게 좋다고 알고 있습니다..!
아래 refreshtoken의 경우는 fetch를 사용한 것 같은데,, 혹시 이 부분은 axios로 한 이유가 있나요?!
There was a problem hiding this comment.
사실 fetch로 해도 되긴 하는데, 에러 응답도 json으로 파싱해야 해서 파싱 과정을 생략하는 axios로 처리했습니다.
공식문서에서 middleware의 경우 Edge Runtime에서 돌며, axios의 경우 내부적으로 환경에 따라 Node.js API를 사용하기 때문에 fetch를 사용하는 게 좋다
요부분은 저도 처음 봤는데요! axios의 경우 내부적으로 환경에 따라 Node.js API를 사용한다는 내용은 공식문서에서 못찾아서, 어디서 확인할 수 있는건지 가이드 부탁드려도 될까요?
There was a problem hiding this comment.
우선, 이 부분은 fetch로 바꿨습니다!
☘️ 작업 내용
1. middleware
nextjs로 들어오는 요청을 가로채는 middleware 기능을 이용해, 사용자가 페이지에 접근할 권한이 없다면 login 페이지로 리다이렉션 해줬습니다.
2. axios instance
유효하지 않은 access token으로 인해 실패한 요청들을 queue에 모아둔 다음, 갱신 성공했으면 queue를 순차적으로 돌면서 재요청합니다.
테스트하기 위해 경도님이 작성해주신 문서보고 로컬에서 백엔드 돌려봐서 테스트하였습니다.
근데, axiosServerInstance는 아직 재갱신이 원활하게 되지 않아, 퇴근 후 다시 확인해야 합니다. 우선 axiosInstance 부분 위주로 리뷰 부탁드립니다 🙇