Nuxt를 사용하다보면 서버사이드에서 axio를 요청하면 쿠키를 전달 할 수 없다는 걸 알게 된다. 브라우저에서 받은 쿠키를 프론트서버에서 API서버로도 전달해야 하는데, 이것을 어떻게 쉽게 해결하는지와 서버사이드와 클라이언트사이드의 코드가 같아질 수 있는 방법을 설명한다.
Nuxt universal mode
Nuxt를 universal 모드로 사용하면 SSR(서버사이드렌더링)을 사용하게 된다.
SSR
페이지 최초 접근시에 다음과 같은 단계들은 서버사이드에서 실행된다.
- nuxtServerInit
- asyncData
- fetch
- middleware
그리고 최초 로딩이 끝나고 이후에 페이지 전환을 할때는 클라이언트 사이드에서 실행된다.
그래서 여기에서 axios를 이용하여 서버로부터 데이터를 받아오는 코드가 있다면, 서버사이드 / 클라이언트사이드에서 호출되는 경우를 모두 고려하여야 한다.
로그인 유지
refreshToken은 쿠키에 accessToken은 nuxt store, 즉 메모리에 저장한다.
페이지 새로고침을 하면 메모리에 저장된 accessToken은 사라지지만,
쿠키에 저장된 refreshToken은 남아있다.
따라서 페이지 새로고침이 되면 refreshToken을 이용하여 accessToken을 가져와서 store에 저장하여야 한다.
nuxtServerInit 에서 이 과정을 처리한다.
axios 사용 (문제 발생)
import axios from 'axios'
async nuxtServerInit ({ commit }, { req }) {
const result = axios.post('/api/token').data
commit('token', result.data)
},
이렇게 하면 될거라 생각할 것이다. 근데 이렇게 하면 안된다.
쿠키에 있는 refreshToken값이 post 요청에 전달이 되지 않는다.
3
3
그림에서 보듯이 브라우저에서 SSR이 이루어지는 프론트엔드 서버로는 refreshToken이 쿠키를 통해 전달이 된다.
하지만 프론트엔드 서버에서 API서버로의 요청에는 이 쿠키값이 들어있지가 않다.
너무나도 당연한 동작이다.
2개의 요청은 독립된 별개의 요청이기 때문이다.
그럼 어떻게 해야 할까? 간단하다.
nuxtServerInit 에서 브라우저로부터 전달된 쿠키값을 API 호출할때 넣어줘야한다.
그런데 nuxtServerInit은 항상 서버사이드에서만 실행이 되지만
asyncData, fecth, middleware는 클라이언트사이드에서 실행이 될수도 있다.
즉 얘네들은 서버사이드와 클라이언트사이드 2가지 경우를 모두 처리해야하는 것이다.
그렇다는건 axios를 이용하여 쿠키정보를 전달해야할 일이 있다면,
서버와 클라이언트 사이드에 따라 분기된 코드를 짜야 한다는 것이다.
이걸 알고나니까 갑자기 Nuxt의 universal 모드를 사용하기가 싫어졌다... 😭😭
그런데 알고보니 nuxt/axios 이처리를 알아서 해주더라😁
nuxt/axios 사용
처음에는 위에 사실을 모르고 가져다가 사용하였다.
그런데 인증정보를 처리하는 과정에서 이게 된다는 사실을 알게 되었다.
nuxt/axios 옵션 중에 proxyHeaders 라는 옵션이 있다. default는 true이다.
이게 바로 내가 아무것을 안했는데도 SSR 상황에서 axios를 호출해도 쿠키정보가 전달이 될 수 있는 이유였다.
proxyHeaders
Default: true
In SSR context, this options sets client requests headers as default headers for the axios requests. This is useful for making requests which need cookie based auth on server side. This also helps making consistent requests in both SSR and Client Side code.
SSR 인경우 클아이언트에서 요청한 헤더정보를 axios 요청에 세팅해준다는 말이다.
그래서 SSR과 클라이언트 사이드의 코드를 일관되게 해준다는 아주 중요한 말이 있다.
nuxt/axios의 github 소스코드를 살펴보면 아래와 같이 이 처리를 해주는 부분이 있다.
의심이 들어서 github 소스코드를 찾아보았다. (의심병..)
<% if (options.proxyHeaders) { %>
// Proxy SSR request headers headers
if (process.server && ctx.req && ctx.req.headers) {
const reqHeaders = { ...ctx.req.headers }
for (const h of <%= serialize(options.proxyHeadersIgnore) %>) {
delete reqHeaders[h]
}
axiosOptions.headers.common = { ...reqHeaders, ...axiosOptions.headers.common }
}
<% } %>
nuxt/axios 플로우
아래와 같이 nuxt/axios를 이용하면
async nuxtServerInit ({ commit }, { req }) {
const token = this.$axios.$post('/api/token')
commit('token', data)
},
아래 그림처럼 SSR 에서 axios 요청을 해도 쿠키값이 API서버로 전달이 되는 것이다.
결론
역시 문서에 답이 있다. 문서를 항상 꼼꼼히 살펴보자.
'개발' 카테고리의 다른 글
Electron 으로 데스크탑 어플리케이션 만들기 기초 (1) | 2023.06.01 |
---|---|
Vue.js 강좌 2. 템플릿 문법 (2) | 2023.05.06 |
Javascript 터치 이벤트 Offset 구하기 (2) | 2023.04.23 |
Gitlab Pages 를 이용하여 무료로 웹사이트 호스팅하기 (3) | 2023.04.21 |
Nuxt.js SSR 모드 PM2 배포시 빌드 문제 (3) | 2023.04.13 |
댓글