특정 페이지(ex. 글작성, 메인) 에 대해 로그인 후에만 접근 가능하도록 하려면 해당 페이지 접속 시 토큰값을 검증하고 값 유무에 따라 권한분기 처리를 해 줘야 함
이를 위해 HOC 방식을 사용하여 각 페이지의 컴포넌트를 인수로 받아서 토큰 값이 있다면 정상적으로 전달받은 컴포넌트 자체를 return 하도록 HOC 방식을 적용
AuthLogin 이란 함수를 만든 후 내부에서 Component를 인수로 받은 후, localStorage에서 토큰값을 꺼내서 해당 컴포넌트를 return 하는 newComponent 함수를 작성
결과적으로 토큰값이 존재한다면 이 newComponent 함수가 return되게 됨
이 때 return 하는 Component는 사실 Component 함수에 props를 인수로 넣어서 해당 함수를 실행한 결과값인 JSX문을 return하게 되는 것
UseEffect 안에 로직을 작성한 이유, useRouter 객체 사용 위치
Next는 SSR 방식으로 서버에서 우선 렌더링 되는 과정을 거치는 데 이 때 localStorage는 브라우저 환경에서만 동작하는 코드로 서버에서 인식을 못해 오류가 발생하기 때문에 useEffect로 마운트 후에 실행되도록 작성
기본적으로 react 에서는 router 같은 hooks를 컴포넌트 구성요소 내에서 사용할 것을 제시 (Server 측 오류 방지), 따라서 newComponent 컴포넌트 형식 내부에서 router 객체를 가져와서 사용하도록 정의
토큰 값을 받아서 이를 이용해 jwt 토큰 발행 시 입력했던 payload 값을 반환 받고, 이를 이용해 DB 에서 유저정보가 있는지를 체크
이를 위해 우선 authController
를 따로 만들어 줌
authController
에서 위와 같이 요청 header 에서 보내진 토큰 값을 tokenString 변수에 담음
이후 replace 메서드로 인식표로 함께 보내진 Bearer 를 제외한 순수 토큰 값만 필터링
이 토큰 값과 환경변수에 저장해 둔 SecretKey 를 토대로 jwt 토큰에 저장한 값을 추출
verif 메서드의 세 번째 인수로 콜백함수를 받아서 검증 실패(error), 성공(payload) 에 대한 응답을 받아볼 수 있음
이 때 추출 성공 시 받는 Payload 에서 앞서 토큰 발행 시 설정했던 회원가입 정보의 id값을 req 객체 내 새로운 key 에 값으로 저장
이 후 next 메서드로 다음 함수가 실행되도록 넘겨 줌
+a) jwt 토큰 검증으로 추출한 payload._id값
jwt.sign
메서드의 첫 번째 인수로 넣어 준 값임을 확인 가능+a)authenticate Controller 에서 받은 id 값으로 User.findById(id) 해서 유저 정보까지 찾아보면 안되는가?
물론 payload 로 받은 id 값으로 바로 find 메서드를 이용해 유저 정보를 찾고 이값을 response 응답으로 보내 줄 수도 있음
그러나 이 경우 authenticate 함수의 정체성이 흔들림. 함수는 가능한 한 가지 일만 수행하도록 작성해야 이후 유지보수 측면에서도 효율적인데 id값으로 유저정보를 찾는 로직은 토큰 값으로 유효한 토큰인지를 체크하는 로직과는 관련성이 없는 별개의 로직이기에 따로 함수로 분리하는 편이 좋음
상위 파일로 돌아와서, 앞의 next() 가 호출되면 해당 메서드가 위치한 authenticate
함수가 종료되고 router 메서드 내 다음 인수에 위치한 getUser
함수가 실행되게 됨
즉 next 는 현재 함수를 종료하고, 연결된 순서에 따라 다음 함수가 실행되도록 해 주는 것
위 코드처럼 router 로 API 경로와 함수를 정의할 때 함수는 여러 개를 정의할 수 있음, 그리고 이 각 함수는 next 메서드로 순차적으로 실행되게 됨
다음으로 실행되는 getUser 에서 보면 앞서 authenticate
함수에서 req 객체의 새로운 key 에 담아두었던 id 값을 구조분해할당으로 가져옴
이 id 값으로 user 정보를 찾은 다음 응답으로 보내 줌
로그인 후 들어갈 수 있는 페이지(토큰 값 존재)의 경우 먼저 HOC 방식에 따라 Auth 를 체크하는 함수로 해당 컴포넌트를 넘김
이후 localStorage 에 저장된 토큰 값을 꺼냄
토큰 값이 있고, 접근하려는 페이지가 로그인 페이지인 경우 이미 로그인 한 상태임으로 main 페이지로 routing
토큰 값이 없고, 접근하려는 페이지가 로그인 외의 페이지이면 로그인 페이지로 routing
그 외에 토큰값이 존재한다면 getUser
메서드 실행하여 관련된 user 정보를 요청으로 받아서 result 변수에 저장
axios 인스턴스 설정에 default 로 headers 에 localStorage에서 토큰 값을 꺼내서 담아 보내도록 설정
이 설정을 토대로 위의 Auth 처리 과정에서 토큰 값을 체크하고, /user/me
로 요청을 보낼 때 headers에 기본적으로 localStorage에 저장된 토큰값을 담아 보내서 정상적으로 검증을 통과하고 결과값을 받아오게 되는 것
window!== 'undefined'
는 Next의 특성상 SSR 과정에서 렌더링 오류 발생을 방지하기 위해 넣음
+a) 전역 상태관리와 토큰을 통한 유저정보 요청은 최상위 app.js 에서
위의 코드는 현재 accessToken 유무를 판별해서 분기를 나누고, 정상적인 토큰일 경우 이 토큰값을 통해 user 정보까지 받아오고 있음
Auth 는 토큰 유무에 따라 분기를 나누는 역할만 할 필요가 있음 (함수는 한 가지의 일만!)
따라서 recoil 같은 전역 상태관리 라이브러리로 accessToken을 전역에 저장하고, app.js
에서는 이 토큰으로 user 정보를 요청하여 받아온 다음 해당 user 정보도 전역에 저장하여 auth 컴포넌트에서는 이 user 데이터의 유무로 분기를 나누도록 리팩토링 할 필요성이 있음 (props drilling 방지)