🐈오늘 공부한 것
✔️토큰 개념
서버에 유저 인증 정보를 담고있는 세션과 달리 토큰은 쿠키처럼 클라이언트에 암호화된 인증 정보를 가지도록하여 서버에 부담을 주는 세션의 단점을 보완한 인증 방식이다. 토큰은 암행어사 마패처럼 유저에게 유효한 토큰이 있다면 서버의 특정 정보에 대해서 접근할 수 있는 권한을 부여받는다. 토큰을 발급하면서 권한의 범위를 지정할 수도 있다. 실제로 주고받는 데이터는 암호화된 데이터인데 서버에서 이를 복호화 하기 때문에 키는 노출이 되지 않아 비교적 안전하다. 또한 토큰을 발급해주는 서버가 그 토큰을 꼭 생성하지는 않아도 된다.
✔️JWT
JSON Web Token 의 약자로, 말그대로 JSON 포맷으로 사용자 속성을 적용하는 웹 토큰의 한 종류이다. JWT 는 header, payload, signature 로 구분되는데 각각 아래와 같은 정보를 담고 있다.
- header : 이 토큰의 종류가 무엇인지, 어떤 알고리즘으로 암호화 되는지에 대한 정보
- payload : 유저 정보와 권한의 여부 등 필요한 정보가 담기는 본문, 암호화가 되긴 하지만 민감한 정보는 되도록 담지 않는다.
- signature : header, payload를 base64 방식으로 인코딩한 값과 랜덤 데이터인 salt 값을 조합해 암호화 한 값이다.
JWT 토큰도 인증을 위한 데이터 조각의 일종이기 때문에 어딘가 저장해두고 꺼내써야 할 필요가 있다. 오늘 과제에서는 쿠키를 사용해서 구현했는데, 로컬 스토리지를 사용해서 저장하는 방법도 있다. 참조 블로그
JWT 토큰에는 두 가지 종류가 있는데 하나는 액세스 토큰, 하나는 리프레시 토큰이다. 실제 정보에 접근할 수 있는 권한을 부여하는 토큰은 액세스 토큰이고, 이 액세스 토큰이 만료되었을 때 재발급 여부를 결정하는 토큰이 리프레시 토큰이다. 유효 기간으로 따지자면 액세스 토큰은 보안이 중요하기 때문에 오랜시간 유지 되지 않도록 하는데, 사용자 편의를 위해서 리프레시 토큰을 사용할 수 있다. 다만 리프레시 토큰까지 탈취되면 이를 악의적으로 탈취한 해커가 리프레시 토큰으로 계속 액세스 토큰을 발급받아 데이터에 접근할 수 있기 때문에 편의성 보다 보안이 중요한 사이트에서는 리프레시 토큰을 아예 사용하지 않는 경우도 있다고 한다.
Node.js 상에서 토큰을 구현하기 위해서 jsonwebtoken 이라는 라이브러리와 거기에 속한 sign, verify 라는 메서드를 이용한다. 토큰을 발급하고, 발급된 토큰을 복호화 하기 위해서는 시크릿 키가 필요한데 노출되지 않도록 환경변수 안에서 정의한 후 가져다 쓴다. 이런 발급 과정만 거치면 쿠키를 사용해 토큰을 전달하고 유효성을 검증하여 원하는 데이터를 보내주도록 로직을 짤 수 있다. 리프레시 토큰을 사용한다면 로직을 분기할 때 액세스 토큰은 유효하지 않지만 리프레시 토큰이 유효할 경우 재발급을 하도록 조건을 확인한다. sign으로 만들어진 토큰을 로그인 시에 전달해주고, 토큰과 함께 요청이 들어왔을 때는 verify로 이를 검증한다.
✔️Next.js
노마드 코더의 NextJS 시작하기 강의를 본 후 나름대로 정리한 내용.
SSR
Next.js 의 장점은 리액트 환경에서 SSR 을 쉽게 사용할 수 있도록 기능을 제공한다는 것이다. Next.js 에서 제공하는 getServerSideProps 같은 함수를 사용하면 이 함수 안에 있는 로직은 클라이언트가 아닌 서버에서만 동작하고, app.js 에서 페이지 컴포넌트를 불러올 때 두 번째 인자로 서버에서 실행된 이 함수의 결과값을 받아와서 props로 넘겨주어 클라이언트 측에서 데이터를 조작할 수 있도록 해준다.
기본적인 Next.js 의 동작 방식이 클라이언트의 초기 상태값을 가지고 100% 완벽하지는 않지만 어쨌든 html 파일을 렌더링하도록 서버가 준비를 해주는데, 자바스크립트를 사용해서 렌더링을 하는 예를들어 API등을 사용해 데이터를 받아온 뒤에 모든 페이지가 생성되도록 CSR 방식을 사용할 수도 있지만, 애초에 모든게 완벽하게 준비가 된 html 즉 SSR 방식을 사용하고 싶을 수도 있다. SSR 방식이 검색엔진 최적화에 더 유리하기 때문에... 아래와 같이 활용할 수 있다.
// index.js
// Home 컴포넌트가 받고있는 result라는 props는 아래 getSErverSideProps의 결과물인
// 객체의 props 프로퍼티의 값 results 이다.
export default function Home({results}) { ... }
// getServerSideProps 라는 함수 이름은 반드시 동일하게 사용해야 하고, export 해주어야함.
export async function getServerSideProps() {
const {results} = await (await fetch('http://localhost:3000/api/movie')).json();
return {
props: {results},
};
}
//_app.js
// 처음 페이지가 렌더링 될 때, 첫번째 인자로는 Home 컴포넌트가 들어갈 것이고,
// 두 번째 인자로는 getServerSideProps의 결과값에 해당하는 객체가 들어갈 것이다.
export default function App({Component, pageProps}) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
Dynamic Routes
localhost:3000/movies/all 처럼 하위 경로를 지정하고 싶으면 pages 폴더를 활용하면 된다.
react-router-dom 에서 파라미터를 받을 때 path = '/:category'와 같이 작성해 주었던 것 처럼 Next.js 도 파라미터를 통해 라우팅을 할 수 있도록 지정해줄 수 있다. 위 방법으로 만든 all.js 를 통해 movie/all 과 같이 접근할 수 있다면 아래와 같은 방법으로는 movies/123 과 같이 id를 변수로 하여 접근할 수 있음.
그럼 페이지에서 특정 요소를 클릭하거나 혹은 다른 어떤 트리거가 발생해서 경로를 이동하려면 어떻게 해야할까? 두 가지 방법이 있다.
1. Next.js 의 Link 컴포넌트로 요소를 감싸서 해당 요소를 클릭했을 때 이동할 href 를 설정한다. 이 경우 Link 컴포넌트 안에 요소를 a 태그로 감싸야 하기 때문에 div 같은 블록 요소를 감싸게 되면 웹 표준에 위배된다.
2. Nex.js useRouter 훅을 사용한다. useRouter 훅으로 생성된 오브젝트에는 push 라는 메서드를 적용시킬 수 있는데, 이를 사용하면 현재 경로를 내가 지정한 경로로 변경할 수 있다. onClick 혹은 내가 트리거 하고 싶은 이벤트 핸들러를 생성한 뒤에 아래와 같은 코드로 적용할 수 있다.
const router = useRouter();
const onClick = id => {
router.push(`/movies/${id}`);
};
추가적으로 useRouter 로 생성된 router 객체에서는 query 라는 프로퍼티로 한 경로에서 다른 경로로 정보를 보내주는 역할을 수행할 수 있다. 첫 번째 인자로 router.query 에 들어갈 데이터를 키 : 밸류 형식으로 지정해주고, 두번째 인자로 쿼리가 보이지 않게 - 마스킹할 경로를 전달해주면 됨.
const onClick = (id, title) => {
router.push(
{
pathname: `/movies/${id}`,
query: {
title,
},
},
`/movies/${id}`,
);
};
이렇게되면 온클릭을 통해 이동한 경로에서는 router.query 를 통해 내가 보낸 title에 접근할 수 있게 된다.
Next.js 프레임워크는 리액트 프론트엔드에 관련된 기능 뿐 아니라 서버에 관련된 다양한 기능을 제공하기 때문에 사용법을 잘 익히면 풀스택 프로젝트를 구축하는데 큰 도움이 될 것 같다. 뭔가 되게 통합적이라고 해야되나... url 마스킹 기능 - rewirtes 도 강력한 기능이고 특히 useRouter 훅이 엄청 편리한 것 같다. 라우팅 경로를 만드는 부분이 react-router-dom 보다 직관적이다. 폴더와 파일구조로 한 눈에 볼 수 있어서 엄청 편리하다고 느꼈음.
✔️알고리즘
오늘 푼 두 알고리즘은 map 자료구조를 사용해서 해결할 수 있었다. map 이 좀 가물가물 했는데 has, get 같은 메서드는 Sets 랑 비슷하고 이터레이션도 마찬가지 [key, val] of maps 로 이터레이션 할 수 있다.
🐈더 공부할 것
1. 코플릿 알고리즘, 추가 문제 찾아보기
2. SSR 과 CSR
3. Next.js : rewrite 더 알아보기
🐈오늘의 느낀 점
1. 하루 목표를 두 개 ~ 세 개로 적게 잡으니까 부담도 훨씬 적어지고 시작도 더 빨리 하게 된다. 할 일이 하나만 남았으면 이거 하고 잔다는 마음으로 임하게 됨. 잘게 쪼개고 선택과 집중하는게 중요한 것 같다.
'TIL' 카테고리의 다른 글
[Day 62] 2022-0916: 솔로 프로젝트 프로토타이핑, Next.js 등 (0) | 2022.09.17 |
---|---|
[Day 61] 2022-0915: oAuth 깃허브 인증, Next.js (0) | 2022.09.16 |
[Day 59] 2022-0913: Cookie & Session + 로그인 구현, https, mkcert (0) | 2022.09.13 |
[Day 58] 2022-0912: Next.js (0) | 2022.09.13 |
[Day 57] 2022-0909: Next.js , 알고리즘 (0) | 2022.09.09 |