TIL[23일차]로그인!!!!!

남예지·2022년 11월 30일
0

TIL

목록 보기
18/47

중요한 로그인! 로그인은 모든 사이트에 다 있지만 생각보다 깊이가 있는 어려운 문제이다.
예전 방식과 요즘방식을 이해하고 JWT토큰(증표)를 저장하기!

로그인의 역사

회원가입과 로그인은 다르다.
회원가입은 user라는 테이블을 만들고 저장하면 된다. 새로운 게시글을 작성하는 것과 같다.

로그인 1단계

로그인을 하게되면 백앤드에서 해당 유저가 있는지 DB로 요청을 보내서 확인 후 가입이 되어있다면 백앤드 컴퓨터 메모리(세션이라함)에 비밀 키를 저장하고 이 비밀키를 브라우저로 보내준다.

그리고 메모리세션에서 로그인증표를 브라우저로 보낸다.(이를 인증(Authentication) 이라고 한다)
저장할 수 있는 곳은 변수, 로컬스토리지, 세션스토리지, 쿠키 등이 있는데
변수에 저장한다고 했을때, 로그인요청 시 세션에서 증표를 받아오는걸 인증, 로그인인증이 필요할 때마다 인가(Authorization)를 한다.
인가가 필요한 API가 실행될 때마다 증표를 보낸다.(상품등록, 내프로필보기 등)

메모리 세션은 변수처럼 만들어 저장하는 공간
cpu는 작업하는 애(cpu 코어가 많다고 하는데 많을수록 빠르다)
ram은 데이터를 저장하는데 컴퓨터를 끄면 사라진다. 대신 빠르고, 보통 변수를 저장 (세션은 여기 포함)
disk는 데이터를 저장하는데 사라지지 않는대신 느리다.

그런데 이건 옛날방식이다.

이 방식의 문제는
1. 유저의 정보를 다 백엔드 서버로 받다보니 메모리를 많이 쓰게 되어 저장할 곳이 부족한 서버가 터진다던지,
2. 백앤드 컴퓨터가 꺼지면 세션이 날아가기 때문에 로그인이 안된다. 재로그인이 필요하다.
3. stateful(특정 세션이 정보를 가지고 있는 상태) 문제가 있었다.

해결책
1. 메모리를 업그레이드한다. 스케일-업 이라고 한다. ex)램 8기가를 32기가로 업그레이드
하지만 이는 단기적으로 문제를 해결할 수 있을지는 몰라도 데이터가 계속 늘어난다면 계속 업그레이드를 해야하는 한계가 있다.

로그인 2단계

그래서 컴퓨터를 계속 업그레이드 하기보단 복사해서 여러대의 컴퓨터로 백엔드 서버의 부하를 분산하는 방법을 사용하게 됩니다.

해결책
2. 백앤드 컴퓨터 n대를 두고 트레픽을 분산해서 받는다. 스케일-아웃 이라고 한다.
(특정 세션이 정보를 가지고 있는 상태는 stateful이라고 한다. )

하지만 이 방법 또한 문제가 생긴다.

백엔드 컴퓨터를 복사할때는 세션까지 scale out이 안되기때문에 기존의 로그인 정보를 가지고 있던 백엔드 컴퓨터가 아니면, 로그인 정보가 없다.

그럼 DB에 세션 테이블을 만들어 저장해보자. 그럼 백앤드 메모리에 더이상 세션을 저장하지 않아도 되니 stateless 상태가 된다.
하지만 DB로 데이터가 몰리면서 병목현상이 일어난다. 결국 같은 문제가 반복된다.

또한 백엔드 컴퓨터를 복사해도 DB는 하나이기 때문에 결국 DB로 부하가 몰리는 병목현상이 일어납니다.

이를 해결하기 위해 데이터를 쪼개어 저장하게 된다.

수직으로 쪼갠다고 해서 수직 파티셔닝이라고 한다.

수평으로 자르면 수평 파티셔닝이고 이를 샤딩이라고 한다. 일정구간은 DB1 컴퓨터에 저장하고, DB2컴퓨터에 저장하고 이렇게 잘라서 저장한다.
샤딩을 사용했더니 병목현상이 해결되었다.

이렇게 DB에 저장하는데 DB는 컴퓨터를 껏다 켜도 날아가지 않기 때문에 데이터들이 disk에 저장된다.
안전하지만 느리고 우리는 결국 이렇게 disk에 저장된 데이터를 추출해 오는 현상을 DB를 긁는다고(scrapping) 표현한다..
(또 디비 컴퓨터가 더 늘어나기때문에 돈도 많이 들어감)

느리고, 돈이 많이 드는 문제를 해결하기위한 방법으로 Redis라는 메모리에 저장하는 메모리기반 데이터베이스가 있다. Redis는 메모리에 저장하기 때문에 디스크 보다 빠릅니다.
껏다 키면 사라지지만 빠른게 장점이다.

데이터베이스는 디스크에 저장하고 가져온다. 이를 Disk input/output 즉 DISK I/O라고 한다..

로그인 3단계

최신방법이 하나 더 있는데 Redis까지 안가도 되는 방법
개발자들이 radis를 사용 안해도 되는 방법을 찾았다.
디비에서 받은 데이터를 백앤드에서 객체로 만든 후 암호화해서 로그인증표로 넘겨주면 브라우저에서 저장해놨다가 인가가 필요할 때마다 사용한다.
이 암호화를 푸는 방법은 복호화라고 한다. 그럼 인가 시 복호화 해서 디비에 정보를 요청해서 받는다.

json 로그인토큰을 json web token 이라 하고 이를 줄이면 JWT토큰이라 한다.

깊은보안은 radis와 jwt토큰을 같이 쓰기도 한다.


실습

실습은 1. 회원가입, 2. 증표받아오기, 3. 증표를 사용해서 내정보요청해보기(인가), 4. 내정보 가져오기 로 진행해보자!

백앤드 10 graphql에서 진행

createUser에서 회원가입하고
loginUser에서 로그인하면

Encoded : 암호화된
Decoded : 복호화된(암호를 푸는 것)
페이로드는 내가 저장하고 싶은 데이터가 들어온다.
lat은 날짜를 초로 보여준다.
시그니처는 비밀번호라고 알면된다.

JWT특징은 암호화는 했지만 누구든지 볼 수 있다는 것이다. 그래서 백앤드에서는 중요한 데이터는 JWT 토큰에 저장해서는 안된다.
그럼 암호화는 무슨 의미가 있나요?
누구든 열람은 할 수 있어도 조작은 불가능하다. 토큰을 요청보냈을 때 조작이 되었는지 검증하는 로직이 백앤드에 들어가있기 때문에 비밀번호가 있어야 사용이 가능하다. (시그니처 필요)

인증 토큰(증표)을 header에 같이 보낸다. Authorization이라는 이름으로 추가해준다.
보통 관례상 앞쪽에 뭘 붙이는데 이건 백앤드와 상의하면 된다.
보통 Bearer를 붙인다.

refreshToken이라고 로그인을 1시간마다 하지 않고도 보안을 높일 수 있는 방법이 있다. 뒤에 배운다.

Storage

브라우저 저장소
local storage는 키벨류처럼저장
sesstion storage도 키벨류처럼 저장
안에 들어있는 정보를 불러올 수 잇다.
콜솔에서 localStorage.getItem("qqq") 하면 qqq의 값이 나온다.
sessionStorage.getItem
데이터를 저장할수도 있다.
localstorage.setItem("qqq", "훈이")

local storage는 껏다 켜도 남아있지만 session storage는 껏다 키면 사라짐. 변수는 새로고침만 해도 사라짐(새로운걸 다시 받아와서 기존것이 새로고침된다.)

쿠키도 브라우저 저장소인데 이름, 값, 기간, 보안 강화 등의 내용을 가지고 있다.
백앤드와 브라우저 간에 데이터 주고받는 통로라 한다.
백앤드요청할때 쿠키가 딸려 들어가거나 백앤드에서 쿠키에 정보를 담아 보낼수도 있다.
쿠키도 콘솔에서 불러올 수 있다.
document.cookie


비밀번호는 fetch할 수 없다. 암호화해서 저장하게 되는데 암호화는 양방향, 단방향 2가지 방법이 있다.

단방향 암호화를 hash라고 한다. 그래서 hashing했다고 한다.
경우의 수가 많다.
그런데 이것도 문제가 해커가 997이 나오는 경우의수를 다 대입해보면서 결국 찾아낼 수 있게 되었다.
이를 무차별 대입공격이라 한다.(Brute Force Attack)

요즘은 hash를 그냥하는게 아니라 임의의 문자열을 더해서 한다.이를 salt라 한다. 완전히 다른 결과값이 나오게 한다.
그 결과를 또 hash하게 되면 레인보우테이블을 만들 수 없어 보안성이 높다.
hash결과를 또 hash하는 걸 키 스트레칭이라고 한다.

하.. 오늘 너무 많은 내용이 들어왔다.
복습하자

profile
총총

0개의 댓글