---
# System prepended metadata

title: 로그인
tags: [subject]

---

---
tags: subject
---

# 로그인

로그인, 로그인은 모든 서비스의 만들때 접하는 첫번째 관문이다.
**"로그인 구현"** 이라고 검색하면 수많은 정보가 나온다. cookie-session, jwt, OAuth... 그래서 그게 어떻게 되는건데? 이 글은 로그인 과정을 구현하면서 만나는 과정들을 일련의 과정으로 나열해보았다.

### 가장 처음에 만나는 것은?

네이버에 접속한다. 그러면 id와 password를 치고 login버튼을 누른다. 와 로그인 완료~
당연히 이게 시작이 아니지. 먼저 회원가입을 해야한다. 회원가입은 User를 DB에 저장하는 과정이다. server는 로그인을 했을 때 user가 보낸 id, password를 DB의 id와 password와 일치하는지 검증한다. 단순하게 생각해보자. 우리가 어떤 정보(id, password)를 검증 하는 가장 쉬운법이 뭘까? 당연히 `==`이다. 

```javascript
if ('받은_ID' == 'DB_ID' && '받은_password' == 'DB_password') return 'login success!'
```

그런데 서버는 비밀번호를 그대로 저장하지 않는다. 비밀번호는 항상 '암호화' 되어 저장된다. 왜? 일단 관리자는 모든 DB를 볼 수 있다. 그렇다면 관리자는 개인의 비밀번호를 알게 된다. 당연히 보안문제이다. 즉 로그인 서비스를 구현하려면 회원가입을 만들어야 하고 비밀번호를 어떻게 암호화 하는지 알아야 한다.

### 비밀번호 암호화에 대하여

일반적으로 hashing이 활용된다. 해싱에 대한 내용은 적기보단 [링크](https://st-lab.tistory.com/100)를 참고하자. 

### 이제 로그인은?

이제 유저는 로그인을 할 준비(회원가입)를 마쳤다. id와 password를 보냈고 server에서 검증 완료! 물론 우리는 이 안에서 일어난 과정을 알아햐 한다. 로그인은 인증(Authentication)과정이다. 인가(Authorization)와 차이를 잘 알아둬야 한다만 일단 생략하자. 어찌됬건 server는 client가 보낸 ip, password를 확인하여 client가 서비스에 가입된 유저임을 확인했다.

그럼 이게 끝일까? 앞으로도 클라이언트는 수많은 요청을 할테고 그때마다 인증을 할것인가? 뭐 안될건 없다. 매번 요청 헤더에 id, password를 넣어서 보내면 된다... 만약 그렇게만 했다면 로그인인을 만들때 고민할 필요가 별로 없겠지. 일단 이렇게 되면 server가 매번 DB와 대조하여 검증을 시도하므로 비효율적이다. 그리고 header에 그대로 보내므로 요청을 한번이라도 요청을 탈취당하게 되면 모든 정보를 다 털리게 된다. 따라서 이러한 인증과정을 간단히 축소하고 보안적으로 만들 필요성이 있다. 이때부터 검색하면 나오는 **Session/cookie 방식**, 이나 **JWT**가 요구되는 것이다.

### Session / Cookie 방식

매번 인증하기 보단 `session`에 유저가 로그인했다는 사실을 저장하고 client에겐 session에 본인이 로그인했다는 사실을 알려주는 'key'를 준 후 매칭때 마다 'key'를 보내주는 방식이다. 이 key가 `session ID`이고 client는 앞으로 모든 요청헤더에 이 값을 함께 보내게 된다.

server는 요청에 함께온 `session ID`로 `session`에서 정보를 찾고 이 client는 로그인 했구나!를 판단하는 것이다. 이때 client가 `session ID`를 담아두는 공간이 `cookie`이다.

따라서 client는 앞으로 모든 요청에 `session ID`를 같이 보내는 기능을 가지고 있어야 하고, 반대로 server는 `session ID`를 받아 인가를 하는 기능이 있어야 한다.

### JWT

**Session / Cookie 방식**은 서버에 session저장을 계속 하므로 resource사용이 많아진다. 그 해결점으로 나온것이 token방식이고 현 token방식의 웹표준이 **JWT**이다. token방식에선 로그인시에 server는 client에게 `session ID`대신 `token`을 준다. client는 요청헤더에 token을 같이 담아 보낸다. 응? 그렇다. 사실 client에선 **session / cookie**나 **JWT**나 그게 그거다. 뭐 저장소가 어디냐 라던가 저장용량이 다르다거나 하는 것은 있지만 client 입장에선 딱히 생각할게 없다.

하지만 Server입장에선 완전 다르다. 앞서 말했듯이 token은 resource사용이 많은 것을 해결해준다고 했다. 그러니까 저장을 안한다. token은 발급하고 해석하는 과정만 존재하고 저장할 필요성이 없다(서비스에 따라 저장하는 경우도 있는 듯한데, 왜인지 아직 모르겠다. 더 조사해보겠다)

따라서 client는 앞으로 모든 요청에 `token`를 같이 보내는 기능을 가지고 있어야 하고, 반대로 server는 `token`를 받아 해석, 인가를 하는 기능이 있어야 한다.

### 로그인 된 후에는?

위에 언급했듯이 앞으로 client는 요청마다 token이건 session ID건 본인이 로그인했다는 걸 인증할 수 있는 정보를 계속 같이 보낸다. 서버는 매번 이를 확인하여 평생 자원을 보내준다. 평생? 당근 아니다. 어느날 보면 로그인이 풀려있고 다시 로그인하는 경우가 생긴다.

session방식에선 session이 만료되는 시점이 존재한다. server 입장에선 session을 무한정 유지하는 것은 자원 부담이 너무 크다. 따라서 일정 시간동안 동작이 없으면 만료시켜 session을 삭제할 수도 있고, 일정 시간이 지난 후, 혹은 브라우저가 종료될때까지 라던가 다양한 방식으로 session의 만료 기한을 설정할 수 있다.

token은 JWT문서를 보면 알겠지만 expire이라는 만료 기한이 payload에 기록된다. 이러한 부분이 일괄적으로 기록되어져야 한다.

### SNS Login과 착각

SNS Login, OAuth2.0이니 뭐니하는건 일단 다 제쳐두고 가장 큰 착각을 한번 고쳐보자. SNS Login은 새로운 방식이 아니다. 그냥 SNS의 서버로부터 client의 정보를 가져와 간단히 login을 구현할 뿐 만약 서비스의 server가 존재한다면 그거대로 따로 인가서비스를 만들어야 하는 점이다. 계속 sns server에 인가를 요청해도되고 자체 인가를 위한 형태로 서비스를 해도 된다. 그건 자유지만 예를 들어 우리 42의 API를 보자. 느리다. 그냥 느리다. 인가 한번당 1 ~ 2초가 걸린다. 그 이야기는 client가 server에 요청을 날릴 때 마다 최소 1 ~ 2초의 딜레이가 인가 때문에 생기게 된다.

SNS로 회원가입을 만들게 되면 session이던 DB건 SNS서버로부터 날아온 token을 저장한다. server는 token을 저장안하는거 아니었나? 왜냐하면 지금은 우리 server가 SNS server의 client니까 저장을 하고 앞으로 SNS server에 요청이 필요할 때마다 요청헤더에 담아 보내야 하는것이다.
