a.k.a 문제 무한발생🔥
1. 회원가입 시 입력받은 emil과 pw를 DB에 저장
2. 로그인 기록을 백엔드 메모리 session(변수)에 저장
3. 아이디(ajkdj-12)를 만들어서 브라우저에 돌려준다
4. 돌려받은 아이디(ajkdj-12)로 다음 요청(createPayment)을 할때 같이 보낸다
❗️문제점 발생 : 사용자가 급증하면 백엔드에 요청이 몰려 데이터 처리가 느려진다
➡️ scale up
을 통해 백엔드서버의 용량(8GB -> 16GB)을 증가시킨다
❗️그래도 문제 발생하면
➡️ scale out
을 통해 백엔드서버를 복사해서 증가시킨다
❗️ 얘도 문제 발생 🤦🏻♀️
세션에 로그인 내역을 저장해놓았는데, 세션은 scale out이 안된다
-> stateful : 백엔드마다 상태를 가짐
(복사를 못함, 수평확장이 안됨)
그래서 내용을 제거하고 db에 저장한다 stateless : 상태없음
session에서 저장했던 로그인 내용이 db로 넘어간다
➡️ 그럼 db에도 무리가 가는거 아닐까?!
➡️ 그럼 db도 여러개로 나눠줄까?
➡️ 데이터 용량이 많아져야한다. 돈이 어마마마~
❗️ 해결방법 : 테이블 파티셔닝
테이블 파티셔닝
1. 수직 파티셔닝
2. 수평 파티셔닝 (샤딩)
어쨌든 db에서 정보를 긁어와야하기 때문에 속도가 느리다 -> memory를 사용하면 빠르지 않을까?
DB에서 data를 긁어오면 시간이 오래걸리기 때문에 1) redis를 이용해 메모리에 저장한다 ➡️ 시간단축
2) 토큰을 받아서 브라우저의 state, cooke, localStorage, sessionStorage 등에 저장한다
1. 로그인 시 DB에서 정보를 확인 후 백엔드에서 객체(로그인만료시간포함)를 만들어낸다.
2. 이를 암호화시켜서 토큰(문자열)을 만든다.
3. 이 토큰을 브라우저에 넘기면 브라우저에서 토큰을 저장한다
❗️ 트랙픽 증가로 백엔드가 늘어남에 따라 백엔드 자체에서 토큰을 복호화(객체로 열어본다)한다.
백엔드👀 ) 아하~ 로그인 만료시간 내에 있으니까 얘는 로그인을 했었구나~
데이터자체가 검증되어있으니 db를 열어보지 않아도 로그인 처리를 할 수 있다.
로그인 인증에 사용되는 토큰을 AccessToken
이라 한다.
이때 객체 형태로 받아오는 JWT 토큰
(Jason Web Token)형식을 사용한다
📌 나중에 배울 refreshToken
: 토큰 만료시간 연장
jwt 사이트
❗️JWT의 문제
암호화를 했지만 누구든지 열어볼 수 있다 (..? 암호화가 맞나?) 이는 보안에 큰 문제가 되기때문에 Payload 아래 verify signature(서명)를 통해 조작을 불가능하게 해놨다.
결론!! 조작은 안되지만 모두가 조회가 가능하다. 중요한 정보 절대 넣으면 안됨!
암호화 방식
양방향 암호화
암호화 ⭕️ 복호화 ⭕️ -> 사용안함
단방향 암호화
암호화 ⭕️ 복호화 ❌ -> Hashing
Authentication 인증 (로그인) - 사용자의 신원 확인
Authorization 인가 (권한 부여) - 액세스 권한 확인
headers
에 Authorization
란 데이터의 값으로 AccessToken
을 담아서 넘겨준다.
해당 서버에서는 이 토큰이 유효하다면 사용자가 로그인을 했다고 판단한 후, 사용자의 인증이 필요한 데이터들을 클라이언트로 보내주게 된다.ex) create, update, createProduct 등
PlayGround - headers
상품등록은 회원인증한 상태에서 실행해야한다
-> accessToken을 http headers에 담아 보낸다Bearer를 안쓰거나 basic을 써도 되는데관례상! 인증을 위한 토큰은 bearer라고 쓰자~
개발자 도구 - headers - request headers
1. headers
모든 로그인 유저는 토큰을 붙이고, 로그인 안한 유저는 토큰을 안붙인다. 이 내용을 모든 페이지(컴포넌트)에 적용한다.
Bearer
는 무시 가능하대서Bearer :
라고 썼더니 에러 발생
멘토님 📌 backend 측에서 Bearer를 시작점으로 잡아버려서 Bearer : 라고 입력하면: ${accessToken}
라고 인식한다!
2. Global State - Context api
📌 state 끌어올리기를 이용해서 props로 넘겨주는 방식은 비효율적이고 코드가 복잡해지기때문에, 모든 페이지/컴포넌트에서 사용할 수 있게 global state에 저장한다
22-01-login
1. state에 저장
2. Login mutation 생성
3. Login 성공하면 accessToken 받기
app.tsx headers에 첨부
1. headers
모든 로그인 유저는 토큰을 붙이고, 로그인 안한 유저는 토큰을 안붙인다. 이 내용을 모든 페이지(컴포넌트)에서 로그인 관련된 http header에 토큰을 붙여서 보낼 수 있다
2. Global State - Context api
api로 받아온 data는 ApolloClientCache에 자동으로 저장된다. accessToken은 직접 저장해줘야하는데 ➡️ Context api를 이용
22-01-login
useContext에서 setAccessToken 뽑아와서 사용하기
22-02-login-success 결과페이지
별도의 검증 필요없이 백엔드에서 알아서 검증해준다~ 신경 안써도 된다