next-js작동원리 문제해결하기

로그인

로그인이 어려운이유 -> 보안문제, 사용량문제로 많은 부분에서 발전해와 많은 방식이 있고, 우리는 최근 트랜드에 맞춰 보도록 한다.


로그인

  • => 로그인기능 만들기 검색시 => 방식 많음. 우리는 최근 트랜드를 적용핡것이나, 옛날 방법과 최근방법을 학습후, 옛날 방식을 걸러낼 수 있어야함
  • => 비밀번호 : 암호화해서 DB에 저장하고, 복화화할 수 없게함.

비밀번호는 한번 암호화되어 DB에 저장되면, 원본을 알 수 없다(다시 되돌리기 불가)

=> 복호화가 되는경우 잘못만든것(패칭불가) => 비밀번호 관련된것은 백엔드에서 처리

예전에는 비밀번호 찾기시 내 비밀번호를 패칭(조회)해 받아올 수 있었지만,
요즈음에는 새 비밀번호를 만드는 방식으로 바뀌었다.


로그인 처리 과정

회원가입 = 회원등록
로그인 !=== 회원가입

옛날방식
로그인 API요청 -> DB접속해 맞는지 확인 -> 로그인 성공 =>>
벡엔드 컴퓨터에 메모리세션(변수)에 로그인 되어있는지에 대해 저장 -> 세션아이디를 번호로 해서 저장해놓는데, 이 세션아이디를 브라우저로 저장
이 세션 아이디를 벡엔드로 보내며 패치 요청을 하고 벡엔드에서는 해당 세션아이디를 확인 -> DB에서는 해당정보를 가져다준다...

  1. 로그인에서 세션 id만들어오는 과정: 인증 (Authentication)
  2. 이렇게 해당 세션 id를 받아 정보를 받아오는 방식이 인가(Authorization)

브라우저 저장공간
로컬 스토리지,
세션스토리지,
쿠키,


변수

많은 유저들이 사용하게되어 메모리 세션이 부족(메모리 부족). =>
1. 메모리 업그레이드하기(본체뜯고 메모리 올리기) => 스케일 업
2. 같은 컴퓨터를 여러대 구입해 벡엔드 컴퓨터을 여러개 만들어 같은 소스코드를 붙여넣고 똑같이 실행.
-> 이렇게 나눠 접속하게만들어 메모리 적게듬 => 스케일을 옆으로 분산시켰다 라는 의미로 스케일 아웃이라고 불림
=> 로그인했을경우에 해당 로그인 정보를 공유할 수 없어 문제 생김
스테이트 풀상태(세션에 세션 아이디를 가지고있는, 어떤 상태를 가지는 상태를 의미)

  1. 똑같이 테이블로 만들어?? => DB에서 관리하게.=> 스테이트 리스상태(stateless)상태로 만들게됨. (DB에서 관리하기에)!!**
    ====>>>>>> 결국 세션 id를 확인하려면 DB에 가야함 => 병목현상(bottle-neck)현상이 일어남. -

이렇게되면 DB가 병목현상. 그럼
DB를 스케일 아웃 한다면? => 데이터를 저장해야함.=> 모든 데이터 다 모든 컴퓨터에 똑같이 저장해야함....
그외 여러 문제점있음.
따라서 DB의 경우 스케일 아웃이 아니라 스케일 업을 하는 방식을 사용하기도하고, 그외 많은 방식들이 있음.

많이 쓰이는 방식 -> 테이블 자르기
자른다 : 파티셔닝
수직파티셔닝 , 수평 파티셔닝.

수평 파티셔닝으로 테이블을 잘라서 각각의 다른 DB 에 저장해 놓는다(스케일 아웃).=> 분산저장 으로 병목현상이 해결된다. ==> 샤딩 방식 이라고 한다.

브-> 요청 -> 아무벡엔드로 가서 -> 어느 세션 테이블인지 검증후, 해당 테이블이 있는 DB로 이동(벡, DB분산)

DB에 저장된 데이터는 전원을 껏다켜도 없어지지 않음 => 디스크 저장 . 대신얘는 느림. ====> Disk I/O발생

램-> 변수 - 전원 // 삭제됨. 대신 빠름

DB는 디스크에 저장되는것이기에 Disk I/O발생 => 인가할때마다 가야되는데 느림.

그럼 redis라는 곳에 저장 => redis는 메모리에 저장되는것.

인가를 해야하는 api.
로그인을 하고 , => 회원정보가 맞으면 세션아이디를 받아 DB에 저장하는데 DB 는 디스크IO 발생하기에 느려서 redis에 저장하고 -> 이 세션 id를 브라우저로 보내 ->브라우저에서 저장=>
인가가 필요한 api들은 DB접속 해서 해당 세션 id를 검증해야하는데, 이 인가를 redis로 빼서 사용하면 빠름.

현재 가장 많이 사용되는 방법

redis에도 저장하지 않기

인가를 redis에도 가지 않게하기.
어떻게??

세션아이디를 redis에 저장하지 않고 객체에 저장. -> 이것을 암호화해서 세션 id로 사용=>

브라우저로 돌려줌 =====> 브라우저에서는 이것을 저장해서 인가시 이 세션아이디인 변수를 보내주고, 벡엔드에서 복호화, DB에서꺼내 데이터 가져다줌.

이런 암호화한것을 토큰이라고하고 =>(객체로만들었기에 )JSON Web Token이라고 함 즉, 객체를웹상에서 사용할 수 있게 만들었다고해 JWT라고하고, 지금은 JWT를 접근용으로 사용할 것이기에 접근토큰 (accessToken) 이라고 할 수 있다.

==> 아주 간단한 서비스시에는 redis없이 위와같이 가능하지만, 추가정보 등을 저장하거나 규모 커지면 redis를 사용하기도함.

토큰을 받아오는것 : 인증
받아온것을 가지고 복호화해서.. api에 접근 가능하도록 한것이 : 인가


JWT의 문제점 :
일단 플레이 그라운드에서 실습하고 로그인을 하여 토큰을 받아오니 패치시 아래 HTTP HEADERS에

{
  "Authorization": "Bearer 발급받은accessToken"
}

이렇게 Bearer뒤에 추가하니 패치가 가능했는데,
jwt.io라는 사이트에서 이 토큰을 넣으니 복호화가 가능했다.
따라서 토큰 유효시간이 있어야한다.
현재는 1시간..

JWT토큰은 누구든지 다 볼 수 있다. 따라서 중요한 정보는 절대 저장하지 말아야하고, 아주 최소화된 사이즈로만 만들어져야한다.
만약 이 토큰이 조작될경우 비밀번호를 넣어야하기에 벡엔드에서는 조작여부를 판단해 막야주어야한다.

로그인시 토큰 받아오면 그 부분을 헤더에 저장 필요!!
그럼 이것토큰을 어디에 저장??

브라우저 자체에 저장소


로컬, 세션, 쿠키

셋다 객체

로컬: 브라우져 껐다가켜도 살아있음.
세션: 브라우저 껐다가 키면 사라져있음.
로컬 스토리지와 세션스토리지는 벡엔드와는 관련없음

쿠키: aPi요청시 함께 전송됨. 변수에 담아 처리하지 않아도됨.(서버와 긴밀하게 협업)
HTTPOnly가 true면 자바스크립트(document.cookie)로 꺼내올 수 없다.
(보안)


가장 안전하게 accessToken저장하기 => 변수에 저장(state에)
모든 페이지에서 필요!!(모든 컴포넌트에 필요)

따라서 글로벌 state를 사용!!


복호화 못하는 암호화 사용하기.

brute force attack => 무자비 공격 => 단방향으로 암호화를 하는데(해시를 한다.) 복호화 어렵게 해놓으나, 해커가 무자비로 공격을 가한다면 ....

현재는 복호화못하게 임의의 문자열을 추가하여 저장한다.

단방향암호화(해시) => 복호화 못함.
그러나 레인보우 테이블이라고 무자비 공격을 가하면 언젠가는 뚫림

따라서 원래의 비밀번호에 + 임의문자열해서 해시하고, 계속 반복하면 헤커도 복호화가 어려울것.


accessToken 글로벌 스테이트에 저장해 어디에 불러와도 사용이 가능하게 처리하였다.
그런데 이 글로벌 스테이트를 매번 accessToken이 필요한곳에 요청해주는것은 귀찮은 일이다.
그래서 아폴로 세팅 부분에 header라는것을 추가하고 해당 부분에 이 변수에 저장한 accessToken이 Bearer 뒷부분에 들어가는 토큰 부분이라 이렇게 추가해준다면 매번 gqlapi를 요청시마다 같이 날라가게된다.

그런데 문제가있다 => 변수 (state)에 저장했기에 화면을 다시 리랜더링하면 날라가버린다.(새로고침시 html, css,js 다 다시 받아오는것.다시 초기값으로 나옴 - > 먼저 html을 그리면서 src,css,js 를 다시 받아 그려줌. 따라서 모든 안의 데이터는 초기화된것.(실제로는 초기화되어 다시 받아옴))

0개의 댓글