[t:/]$ 지식_

로그인, 쿠키, 세션

2019/12/30

일하기는 싫고 연말이고 그냥 한 번 적어보는 글. 본 블로그의 모든 글이 항상 그렇듯이 현장에서 주섬주섬 좌출우동 엉망진창으로 체득한 단편을 흩뿌릴 뿐이므로 잘못된 내용과 정의를 어긋난 용어 사용 등이 존재하므로 주의바랍니다. 귀찮아서 그림은 없습니다. 불친절 주의. 약 10분안에 다 쓸 예정이므로 그 정도의 퀄리티만 보장함.

독자 대상

서버-클라-http-웹 개발-기술-용어들을 어느정도 알고 있는 짬통 보유자. 알만한 사람은 다 아는 내용이니까 읽지 말자. 읽고 욕하지 말고.

쿠키란?

서버가 응답할 때 '니 쿠키값으로 뭘 써라'하고 헤더에 박아서 응답하면 브라우저가 그 값을 브라우저가 로컬에 써 둠. 넘의 도메인의 쿠키를 읽거나 하는 것을 허용하지 않으나 수많은 트릭들이 있긴 있음.

쿠키 예제

브라우저 까서 도메인을 입력하고 엔터를 치면 서버야 a 페이지를 줘하고 요청함. 서버는 a를 달라고? 응 줄 께 하고 a에 해당하는 컨텐츠를 전송함. 이 때 내 도메인 troot.co.kr에 대해 mycookie = 333 이라고 헤더에 써둠. 그러면 브라우저가 아 쿠키를 쓰라고? 알았어 하고 mycookie = 333 이라고 브라우저의 저장 공간에 씀. 이 값은 troot.co.kr을 돌아다닐 때만 유효하고 hroot.co.kr 같은 다른 도메인의 페이지에서는 읽을 수 없음.

세션 쿠키란?

쿠키는 유효기간이 있어서 유효기간이 지나면 브라우저가 지움. 서버에서 유효기간을 지났다고 설정해서 보내거나 니 죽어라 하고 보내면 브라우저가 보고 지움. 유효기간을 "세션"이라고 설정해서 보내면 브라우저가 살아있는 동안만 유효한 쿠키가 됨.

로그인을 하면?

클라에서 아이디 암호를 넣고 로그인 해줘! 라고 요청하면 서버가 암호 등을 확인한 다음 어 그래 로그인 처리해줄 께 하고 로그인 했다고 서버에도 기록하고 클라에는 쿠키를 전송함. 예를 들어 아이디 keeptalk에 대해 서버는 333 = { login = keeptalk } 이라고 기록해 두고 login = 333 을 클라에 전송함. 브라우저는 브라우저가 살아있는 동안 (세션) login=333 값을 갖고 있음.

333?

이 때 값 333은 서버 내에서 유일한 값이 되어야 하므로 쫑이 거의 안 나는 해시 함수를 쓰든 블룸필터든 뭐든 해서 (거의) 유일한 키 값으로 만들어 씀.

333이 유일하지 않으면?

사용자 keeptalk와 dawnsea가 같은 로그인 쿠키 값을 갖으면 이 둘을 분간 할 수가 없음. 사용자 클라가 매 요청마다 ID를 전달하지 않기 때문. 뭐 ID를 전달해도 되긴 하는데 ssl 암호화라고 치고 post에 넣으면 안전하다고 볼 순 있는데 인생사 post로만 컨텐츠를 요청하면 욕 얻어먹음. 뭐 get에 body를 넣거나 헤더에 때려박아도 되긴 함.그러나 프레임웤이나 브라우저 상황이 받쳐주진 못함. 브라우저 직접 만들거나 자바스크립트가 누덕누덕 처리하면 되긴 함.

로그인이 유지되려면?

클라가 요청할 때마다 login=333이 서버에 자동으로 전송됨. 서버는 333을 보고 아 얘는 keeptalk로 로그인 중이구나를 파악함. 이 정보를 서버가 들고 있어야 하는데 메모리에 들고 있을 수도 있고, 파일로 저장해도 됨.

로그인 세션 쿠키값을 서버가 알고 있기 위한 문제

메모리에 저장하면? 메모리 부족하면 어쩜? 파일로 저장하면? 작은 쓰레기 파일이 하드 잠식하면 어찌함? DB에 저장하면? 매 호출 마다 DB 콜하고 아 생각만 해도 느리다... 물론 서버가 1대이고 트래픽이 적다면 문제가 안 됨.

서버가 여러 대면?

클라가 1번 서버에 요청하여 1번 서버가 333=keeptalk가 알고 있는 상태임. 이제 클라가 다시 다른 요청을 했는데 이번엔 2번 서버에 붙음. 2번 서버는 로그인 처리를 한 적이 없으므로 333=keeptalk란 사실을 모름. 헐?

L4의 사정

그래서 앞단의 스위치를 특별하게 설정함. 1.2.3.4로 들어오면 1번 서버에만 붙어랑. 1.2.3.5는 2번 서버에만 붙엉~ 이렇게 해 두면 어찌되는가? 1번 서버에서 로그인 한 keeptalk 는 1번 서버에만 붙으므로 333=keeptalk라는 사실을 서버가 항상 알고 있음.

하지만 찜찜한데? 스위치가 RR일 수도 있잖아.

찜찜한 거 맞음. 1번 서버가 뻗어버려서 모든 요청이 이제 2번으로만 가는 상황임. 로그인은 1번에서 했는데 2번으로 요청으로 감. 2번 서버는 333=keeptalk라는 사실을 모름. 사실 트래픽 등등의 사정으로 서버는 RR 설정인 경우가 많음.

DB를 쓰자.

일단 좀 느리겠지만. DB서버를 따로 둬서 해결 할 수 있음. 이제 1번 서버로 오든 2번 서버로 오든 333=keeptalk를 DB에 기록해 둠. 클라에서 요청할 때마다 DB를 들여다보고 333=keeptalk임을 알 수 있음.

느리니까 redis를 쓰자.

DB는 느리자너.. 이제 redis 같은 빠른 메모리 DB를 붙임. redis에다가 333=keeptalk임을 물어보면 됨. TTL 설정으로 자동 정리도 가능. 헤헤헤

브로드 캐스팅 하면 안 되나요?

스프링 같은 데서 그런 방식으로 지원하는 것 같은데.. 실제 어떤지는 모름. 여튼 나 같으면 브로드 캐스팅도 고려해 보겠음. IP에서 브로드캐스팅 방식이 있음. 특정 IP 대역으로 쏘면 그 스윗치에 물려있는 모든 기계가 그 패킷을 동시에 받아먹을 수 있음. 특정 제어 목적의 패킷이나 방송 같은 데서 쓸 수 있음. 보통 서버는 NIC를 여러장 꽂고 있으니까.. 그 중 한 장은 내부 통신용 스위치에 물려두고 브로드 캐스팅으로 333=keeptalk를 저장해! 하고 날리면 모든 서버가 이 정보를 저장하고 있을 순 있음. 이때 문제는 각 서버마다 모든 사용자의 로그인 상태 정보를 저장해야 한다는 것. 따라서 메모리에 저장할 순 없고 하드에 저장할 순 있음. 하지만 파일 갯수 겁나 늘어남. 간단한 파일DB를 쓰면 되긴 할 텐데 여전히 복잡함. 대규모 동접 상황이 아닌 경우라면 간단히 취해볼만한 방식임.

한 편으로 333은 누구냐? 라고 브로드캐스팅 요청을 서버 군체에 하고 누구라도 응답하라고 할 수는 있음. 그러나 아무도 응답하지 않음을 파악할 때 까지 타임아웃으로 처리하거나 모든 서버의 333 나 몰라라는 응답을 받아야 함. 브로드캐스팅 통신의 근원적인 문제점 중 하나.

10분 지남. 황급히 마무리. 끗.









[t:/] is not "technology - root". dawnsea, rss