생각보다 렌더링이 더 많이 되는 문제들
일부만 렌더링 될 것이라 예상한 곳이, 전체가 리렌더링 되는 경우
간단히 레이아웃을 그림으로 표현하면 아래와 같다.
TodoMain은 리덕스 스토어에 있는 값을 받아와서 각각의 TodoItem으로 내용과, 함수들을 전달하는 구조이다.
함수들 중에는 할 일의 완료 여부를 체크하는 toggle
함수가 있다.
toggle
함수를 실행하면 서버에 TodoItem 상태를 업데이트하고, 그 결과를 받아와 스토어에 반영한다.
스토어가 업데이트 되면, 결과를 반영하기 위해 컴포넌트가 리렌더링된다.
TodoMain이 값을 가져오는 것이므로, TodoMain 컴포넌트만 리렌더링 되면 될텐데 화면 전체가 리렌더링 되는 문제가 생겼다.
const TodoMain = () =>{
...
return (
<Layout>
<Header/>
<Sidebar/>
<TodoMain/>
</Layout>
)
}
문제점은? TodoMain 컴포넌트 내부에 레이아웃이 모두 들어있던 문제였다. 간단하게 다음과 같이 해결했다.
const TodoMain = () =>{
...
return <TodoMain/>
}
const TodoMainPage = () =>{
...
return (
<Layout> // Layout 내부에 Header와 Sidebar를 포함시켰다.
<TodoMain/>
</Layout>
)
}
이렇게 하면 문제 TodoMain에서 값을 업데이트 하더라도, Layout에는 전혀 영향을 미치지 않는다.
JWT 토큰 전략
'JWT 토큰을 어디에 저장할 것인가' 에 관한 문제는 많은 사람들이 부딪히는 문제인 듯 하다.
선택지가 많은 것은 아니고, cookie
혹은 localStorage
정도가 되겠다.
나는 localStorage에는 저장하고 싶지 않아서, 쿠키에만 토큰을 저장하기로 결정했다.
처음에는 단순히 access token만 발급받아서 서버에 요청을 할 때 헤더에 붙이는 방식만 사용했다.
그러나 새로고침을 하거나, 유효 기간이 끝나면 로그인을 다시해야했고, 특히 새로고침을 했을 때 많이 귀찮더라 (중요).
그래서 refresh token도 같이 사용하기로 했다. 시나리오는 다음과 같았다.
우선 클라이언트에서 로그인을 성공하면, 서버에서는 cookie에 refresh token을, body에 access token을 전달한다.
클라이언트에서는 결과를 받아, 다음과 같은 함수를 실행하여 헤더에 access token을 설정한다.
export const setAuthToken = (accessToken) => {
axios.defaults.headers.common["Authorization"] = `Bearer ${accessToken}`;
};
이렇게 하면, 이 이후에 모든 요청에 대해 access token을 같이 실어서 보내게 된다.
또한 새로고침을 하게 되면, header에 있는 access token은 사라지게 되는데, 새로 access token을 발급 받기 위해서 refresh token을 서버로 보내게 된다. 이러한 작업을 수행하기 위해 최상단 컴포넌트에 useEffect를 이용하여 요청을 시도했다.
const App = () =>{
//
useEffect(() =>{
axios.get('/auth/silent-signin')
},[])
return ...
}
서버에서 받은 refresh token이 올바른 토큰이라면, 새롭게 access token을 만들어서 클라이언트로 전달할 것이고,
그렇지 않다면 로그인 페이지로 리다이렉션하도록 만들어놨다.
여기서 추가적으로 겪은 두 가지 문제점이 있다.
얘도 비동기 처리를 해야 하는데, 리액트 컴포넌트 내부에서 곧바로 요청을 날려도 되는걸까?
결론적으로 saga를 사용해서 처리하긴 했다. saga가 어떻게 돌아가는지 흐름을 이해하기는 좋은데, 추가하기 위해서 꽤나 많은 코드들이 필요하다. 다른 선택지는 없을까 고민했던 하루.
nestJS 어느 부분에서 예외처리를 해줄 것인가? Guard? filter? custom strategy?
nestJS는 많이 안 써봐서 그런지... 여러 문서들 읽어보니까 다들 다양한 방법을 소개시켜주었다.
분명 내가 문제인게 확실하긴 한데, Guard나, custom strategy를 이용하려고 하면 token을 verify하는 것까지는 문제가 없었다.
문제는 refresh token이 만료되었을 때, 다시 클라이언트쪽으로 값을 돌려주어야 하는데, response 객체를 찾을 수가 없었다.
그래서 그냥, 컨트롤러 / 서비스 단에서 처리하는 것으로 마무리 했다.
다음주에 인턴 면접도 있고, 신입 포지션으로 몇 군데 넣어볼 예정이라 했던 내용들을 정리하고 있다.
정말 짜스는 파면 팔 수록 어렵다는 걸 다시 한 번 느낀다.
강연같은 경우에는, 정말 재밌어서 넋 놓고 봤는데, 유익한 내용들이라 따로 정리 해볼 예정이다.
기능적인 구현은 웬만해서 다 했다. 이제 더 나은 코드를 만들기 위해서 더 노력할 뿐 🤔