기획자가 알아야하는 데이터 지식 - 서버인증
서비스 기획을 시작하며 서버와의 통신을 처음 접했을 때, 눈 앞이 깜깜했다. 서버를 모르는 기획자, PM은 더 이상 IT환경에서 살아남을 수 없는 세상 (...) 오늘은 기본적으로 알아야 할 데이터를 보내고 받는 서버인증의 기본 개념에 대해 알아보자.
모든 서비스는 사용자의 도입과 함께 시작되고, 그 중심에는 로그인/회원가입이 있다.
클라이언트(사용자) 관점에서 봤을 때는 로그인만 하면 모든 서비스를 이용할 수 있을 것만 같지만, 수 많은 사용자들의 요청 속에서 사용자A와 사용자B의 요청을 정확히 구분해서 데이터를 보내야 하는 서버의 관점에서 보면, 회원인증은 모든 API의 요청에 대해 사용자를 끝도없이 확인해야 하는 작업이다. 만일 정확하지 못하다면.. A의 정보가 B에게 전달되는 최악의 개인정보유출 상황이 발생하기 때문이다. 따라서 클라이언트에서는 사용자가 누구인지 알만한 단서를 여러가지의 방법으로 서버에 보내게 된다.
* 클라이언트는 데이터를 요청하는 주체 (우리가 사용하는 컴퓨터 웹사이트, 스마트폰 어플리케이션 등) 를 의미하며, 서버는 데이터를 제공하는 주체를 의미한다.
그 전에, 우리는 기본적으로 클라이언트와 서버의 통신방식에 대해 알아야 한다.
보통 URL을 사용하면 주소 맨 앞에 http 또는 https가 붙어있는 걸 볼 수 있는데, 이 URL의 가장 첫번째 자리가 바로 "나 이 프로토콜로 통신할거야~"라고 말해주는 자리이고, 일반적인 웹 브라우저에서는 http(s)를 사용한다. 이 HTTP(HyperText Transfer Protocol)는 "우리, 인터넷 상에서 데이터를 주고 받을 때, 서버 ↔ 클라이언트 모델을 사용하자!"는 일종의 약속이다.
* 프로토콜이란, 컴퓨터 사이에서 데이터를 교환하는 방식을 정한 규칙체계이다.
** https는 http에 "s(secure)"이 추가된 버전으로, 보안이 더 강화된 버전의 http라고 보면 된다.
HTTP는 다음과 같은 괘씸한(?) 특징을 가지고 있다.
1. Connectionless, 연결을 유지하지 않음
사용자가 서버에 데이터를 요청하면, 서버는 요청에 맞는 응답을 보내준 다음, 바로 연결을 끊어버린다.
[요청-응답] 을 하나의 건 수로 처리하기 때문에, [요청-응답-요청-응답] 이 불가능하다.
= 쿠키,세션,토큰..이 없는 http는 로그인을 한 후, 마이페이지로 넘어가면 로그인이 해제된다.
2. Stateless, 상태를 저장하지 않음
서버는 사용자의 정보를 저장하지 않기 때문에, 내가 어제 사이트에 접속하고 오늘 또 접속했다고 하더라도, 서버는 나와 어제 통신한 데이터를 전혀 기억하지 못한다.
= 쿠키,세션,토큰..이 없는 http는 어제 장바구니에 담아놓은 상품들이 오늘 다시 로그인하면 사라져있다.
우리는 그래서 인증과 인가를 하려면 토큰, 세션, 쿠키를 이용해야 한다.
HTTP 통신 시 어쩔 수 없는 번거로운 상황들을 해결하기 위해 등장한 것이 바로 이러한 개념들이다.
반복되는 작업은 줄일 수록 좋다.
자주 사용하는 사이트나 앱에 들어갈 때마다 매번 로그인을 해야 한다면 그 서비스를 이용하는 것이 스트레스로 다가올테니! 따라서 이러한 정보들은 한 번 작성하거나 사용한 뒤에는 반복적으로 작업하지 않도록 어딘가에 저장해두는 것이 효율적이다.
즉, 이러한 개념들의 공통점은 클라이언트의 정보를 연속적으로 유지하기 위해 존재한다.
웹 환경에서는 정보를 연속적으로 유지하기 위해 각각의 데이터를 종류와 특성에 맞게 저장하고, 또 저장한 데이터를 재활용하기 위해 여러 방식을 활용한다. 각각의 방식마다 장/단점을 가지고 있기 때문에, 각자 용도에 맞게 적절히 조합하여 사용하는 것이 중요하다. 개념들을 다 모아놓고 하나씩 살피며 비교해보자.
귀신같이 구글 광고는 나한테 필요한 것만 쏙쏙 골라서 관심있는 상품을 노출해주지 않는가? 도저히 돈을 안쓸래야 안쓸 수가 없다. 이러한 알고리즘은 나의 웹 서핑내역과 나의 이전 사이트 검색기록 등이 광고에 활용되는 결과이다. 초록창에 들어가 검색 영역을 누르면 내가 이전에 검색했던 기록들을 찾아볼 수 있는 것도, 내내가 자주보는 웹툰이 목차 상위에 올라와 있는 것도, 어제 설정한 브라우저 다크모드가 오늘도 자동으로 유지되는 것도, 팝업창에서 '오늘 다시보지 않기'를 클릭하면 정말 하루종일 팝업배너가 노출되지 않는 것도 모두 쿠키를 활용한 사례이다.
즉, 쿠키는 어떤 웹 사이트를 방문했을 때 나의 PC 브라우저에 저장되는 조그만 정보 파일 조각이다.
쿠키는 사용자의 PC에 저장되기 때문에 접근 속도가 빠르고, 서버의 자원을 낭비하지 않아 효율적이다.
그렇지만 사용자의 PC에 저장되기 때문에 해킹의 위험이 있고, 브라우저가 종료되어도 자동으로 삭제되지 않기 때문에 보안 측면에서 어느정도의 리스크를 갖는다. 우리는 브라우저의 설정 화면이나 개발자 도구에서 쿠키를 확인하고 수정, 삭제할 수 있다. 다만 나뿐만 아니라 제 3자가 조회하는 것도 가능하기 때문에, 개인정보를 담은 내용이나 보안 상 민감한 정보를 저장하는 것에는 적합하지 않다. 우리 역시 보안을 위해 주기적으로 브라우저의 캐시를 삭제해줘야 하는 이유다.
이러한 이유로 민감성이 높은 정보들은 보통 쿠키에 저장하지 않는다.
A쇼핑몰의 장바구니에는 티셔츠와 청바지가, B사이트의 검색내역에는 치킨이, C사이트 팝업 설정은 7일동안 다시보지 않기의 정보가 저장되어 있는 것. 누군가에게 털려도(?) 괜찮은 정보들이다. 이처럼 쿠키는 남에게 탈취되거나 제 3자에 의해 조작되어도 크게 문제되지 않을 정보만 브라우저에 저장함으로써 웹 사이트 이용을 편리하게 해주기 위해 사용한다.
웹 사이트에 아이디와 비밀번호를 입력한 후 로그인 버튼을 클릭하면 [다은]이의 내 이름으로 로그인이 된다.
또 나는 마이페이지 btn을 클릭해 [다은] 이의 내 정보 화면을 볼 수 있다.
문제는 이와 같은 클릭 하나하나는 서버에게 보내는 익명편지와도 같아서, 서버는 아이디와 비밀번호를 입력해 로그인 버튼을 클릭한 다은이와, 마이페이지 버튼을 클릭한 다은이가 동일한 사람인지 인지할 수 없다는 것이다. 그렇기 때문에 다은이가 사이트에 로그인을 완료했어! 라는 사실을 서버에 인증하지 못하면, 내가 무슨 버튼을 클릭할 때마다 반복해서 아이디와 비밀번호를 서버에 인증해야 하는 번거로움이 발생한다. 이를 방지하기 위해 활용하는 것이 바로 세션이다. 세션은 로그인 후 다른 화면으로 이동해도 로그인을 해제시키지 않고 로그인 상태를 유지시켜 사용자에게 편리한 브라우저 이용경험을 제공한다.
즉, 세션은 일정 기간 사용자의 상태를 일정하게 유지시키는 상태를 의미한다.
* 여기서 일정 기간이란, 로그인부터 로그아웃까지, 혹은 로그인부터 브라우저 종료시점까지를 의미한다.
하나의 브라우저 당 하나의 세션이 생성되기 때문에, 브라우저를 닫아버리면 세션이 종료되어 다음 접속 시에는 다시 로그인을 해야한다. 세션은 서버에서 관리하기 때문에 상대적으로 안전한 상태를 유지할 수 있고, 브라우저를 닫으면 자동으로 삭제되기 때문에 쿠키보다 보안이 좋다.
※ 세션은 어떻게 유지될까?
세션은 사용자가 사이트에 로그인하면 일정 유효기간이 끝날 때까지 ID/PW를 추가적으로 입력하지 않아도 되도록, 사용자가 이미 서버로부터 인증받았음을 증명해준다. 놀이공원에 가면 직원이 티켓의 일부만 찢어 가져가듯, 서버는 로그인에 성공한 사용자에 대해 세션 아이디라는 사본 데이터를 만들어 보관한다.
서버에 저장된 세션 아이디 사본데이터는 쿠키로 저장되어, 사용자가 행하는 이후 요청에 함께 전달된다. 내가 친구목록 버튼을 클릭하면 클라이언트는 서버에 사용자 친구목록 데이터를 요청하고, 서버는 해당 요청에 세션 아이디가 적혀있는지 확인한다. 그 이후 서버가 보관하고 있는 세션 아이디 중 동일한 정보가 있는지 검색하여 사용자를 파악하고, 해당 사용자의 친구 목록을 보내주는 것이다!
요약하면 다음과 같다.
1. 사용자가 서버에 웹페이지를 요청할 때, 쿠키 정보를 함께 보낸다.
2. 서버는 사용자가 전달한 쿠키에 세션ID가 있는 지 확인한다.
3. 세션ID가 존재하면 로그인 상태를 유지해주고, 존재하지 않는다면 ID를 새로 생성해서 DB에 저장한다.
4. 이후, 쿠키에 방금 생성한 세션ID 정보를 함께 넣어서 사용자에게 웹페이지를 돌려준다.
5. 이 쿠키는 요청을 보낸 사용자의 PC에 저장된다.
6. 이후 사용자는 세션ID가 포함된 쿠키를 동봉하여 다른 요청을 보내게 되며, 서버는 세션ID로 사용자를 식별하여 사용자의 상태에 알맞게 데이터를 제공한다.
위에서 살펴본 세션은 서버에 저장된다. 서버는 수많은 사용자의 세션을 저장하고 각각의 사용자에게 요청이 들어올 때마다 세션ID 확인작업을 한다. 문제는 세션ID를 저장하는 저장소 공간이 한정되어 있다는 것이다. 따라서 많은 사람들이 이용하면 이용할 수록 서버에 과부하가 걸려 속도가 느려진다는 단점이 있다.
"세션은 메모리 공간을 너무 많이 차지해. 세션ID 대신 발급해줄만한 것이 없을까?"
서버의 부담을 더어주기 위해 등장한 것이 바로 세션/쿠키보다 보안성도 높고 서버에게도 효율적인 방식인 토큰이다. (세션/쿠키와 함께 모바일과 웹의 인증을 책임지는 대표주자이다.) 토큰은 사용자의 인증 정보를 암호화시킨 것으로, 일종의 출입증 역할을 한다. 사용자가 최초 로그인 시 서버는 세션ID 대신 용량차지가 적은 토큰을 발급해주고, 이후 사용자는 이 토큰을 가지고 다른 웹사이트들도 출입할 수 있게 되는 것이다. 이러한 토큰은 마치 위조 방지장치가 있는 지페와 같아서, 특정 수학적 원리가 적용되어 있어 오직 서버만이 유효한 토큰을 발행할 수 있다.
따라서 토큰을 받아간 사용자가 이를 쿠키로 지정해놓고, 필요할 때마다 이 출입증을 제시하면 서버는 세션저장소에서 세션ID를 확인할 필요 없이 자기가 발급한 토큰임을 알아보고 사용자의 요청을 허가해준다.
즉, 토큰은 특정 서버만이 만들 수 있는 출입증을 발급함으로써 서버에 세션ID를 저장하지 않고도 클라이언트에서 사용자의 로그인 여부를 파악할 수 있는 방식이다.
요약하면 다음과 같다.
1. 사용자가 로그인 시, 서버는 세션ID 대신 토큰을 발급한다.
2. 사용자는 발급된 토큰을 사용자의 PC에 저장한다.
3. 사용자가 토큰과 함께 다른 요청을 보내면, 서버는 사용자의 토큰정보를 검증한 뒤 (복호화 등) 사용자의 권한을 확인하고 요청을 처리한다.
이렇듯 토큰을 사용하면, 서버는 암호화된 토큰을 봉인해제하여 검증만 할 뿐 유저 정보를 저장하지 않기 때문에 메모리 부담이 적다는 강점을 가진다.
물론 토큰도 Http 통신을 할 때, 리스크가 아예 없는 것은 아니다.
토큰 인증방식의 문제점은, 토큰을 제 3자에게 탈취당할 경우의 케이스이다. 따라서 토큰의 유효기간을 어떻게 설정할 것인가?가 보안의 key로 작용한다. 유효기간을 짧게 두면 사용자가 주기적으로 새로운 토근을 발급받아야하는 불편함이 있고, 유효기간을 길게 두면 그만큼 보안에 취약해지기 때문이다.
따라서 "유효기간을 짧게 두면서 사용자의 불편함을 줄이는 방법이 없을까?" 하는 고민이 등장했고, 이를 통해 등장한 대안이 위 로직에 작성하였듯 2가지 종류의 토큰을 사용자에게 발급하는 방식이다.
첫번째는 출입증으로 사용할 Access Token이고, 두번째는 Access Token이 만료되었을 때 인증 상태를 연장해 줄 Refresh Token이다. 보통은 보안을 위해 Access Token의 유효기간을 짧게 설정하고, Refresh Token의 유효기간을 보다 길게 설정해놓는다. Access Token의 유효기간이 만료되면 Refresh Token을 서버에 보냄으로써 새로운 Access Token을 발급받을 수 있다. Refresh Token은 만료 시에만 노출되기 때문에, 해킹을 당할 위험이 적다. Access Token 유효기간이 1시간, Refresh Token 유효기간이 30일이라면, Access Token의 유효기간이 만료되어도 30일 이내에는 얼마든지 재발급이 가능하여 새로 로그인을 하지 않아도 서비스를 이용할 수 있는 것이다.
* 보통 Refresh Token의 유효기간은 2주로 설정하는 것 같다. 이 역시 탈취될 가능성이 있기 때문에 무작정 길게 잡는 것은 보안 상 좋지 않기 때문.
설명에 앞서 캐시가 cash인줄 아는 사람들이 많은데 돈이 아니라 cache다. (나도 오늘 알았당..)
어쨋든, 우리는 매일같이 다양한 플랫폼을 통해 텍스트, 이미지, 동영상 등 대량의 데이터를 서버로부터 전송받는다. 카톡보다 유튜브가 배터리와 데이터 소모량이 빠른 것처럼, 데이터 전송에는 시간뿐만 아니라 비용도소모된다. 그러나 한 번 전송받은 데이터는 저장해 놨다가 다시 사용할 때 꺼내 쓴다면 반복적으로 데이터 전송을 요청할 필요가 없다. 이렇듯 콘텐츠를 반복적으로 사용할 때, 데이터 사용량을 줄이면서 동시에 빠르게 이용할 수 있는 방법이 바로 캐시이다.
우리가 가장 흔하게 접하는 캐시는 브라우저 캐시이다. 캐시 덕분에 사용자는 같은 사이트를 다시 방문하거나, 시청하던 동영상을 멈추고 다시 시청할 때, 로딩 없이 콘텐츠를 이용할 수 있다.
그렇다면 쿠키와 캐시의 차이점은 뭘까?
쿠키와 캐시 모두 정보를 저장하는 기술이지만, 쿠키는 (ID/PW를 자동입력 해주는 등) 사용자의 수고를 덜어주는 데 목적을 두고, 캐시는 데이터 전송량을 줄이고 속도를 높이는 데 목적을 둔다.
앞서 쿠키의 한계점에 대해 언급했듯이, 캐시 역시 매번 데이터를 전송하는 것은 이용자가 많을 수록 서버에 과부하가 걸리며, 이는 곧 사용자 불편으로 이어진다.
이러한 문제를 해결하기 위해 사용하는 것이 CDN이다.
CDN은 콘텐츠 전송 네트워크로, 나는 이전회사에서 영상파일을 URL로 변환하여 열람할 때 CDN 주소를 활용했었는데, 시간과 저장용량을 들여 영상을 다운받지 않고도 빠른 시청이 가능하다는 장점이 있었다. 이처럼 CDN은 여러 개의 서버를 이용해 웹 콘텐츠를 사용자와 가까운 서버에서 전송함으로써 전송 속도를 높인다는 장점을 가진다.
서버가 전 세계 각지에 세워진 CDN 컴퓨터에 데이터를 전달하면, 사용자는 본 서버가 아닌 나와 가까운 캐시서버에서 데이터를 받아오는 것이다. 마치 치킨 체인점이 전국의 주문을 본사에서 전부 처리하지 않고, 각지의 가맹점에서 받는 것과 같다. CDN이라는 것이 세계적으로 유명한 프랜차이즈와 같아서, 전국에 체인점을 깔아서 본사는 부담을 최소화하고, 사용자는 데이터를 빠르고 안정적으로 받아올 수 있는 것이다.
일정 규모 이상의 사용자를 가진 서비스들은 CDN을 사용하여 사용자의 요청을 가까운 서버에서 분산 처리한다. 대량의 데이터를 전송하는 유튜브, 넷플릭스 등와 같은 동영상 서비스에 CDN은 필수다. AWS 역시 전 세계에 캐시 서버를 운영하는 CDN 업체이며, 국내에는 GS네오텍, SK브로드밴드, KT 등이 있다.
간단하게 개념을 짚었지만 하나하나 깊게 파고 들어가면 수만가지의 용어들이 존재한다.
아래는 위 내용들과 관련되어 추가적으로 알고있으면 좋을 개념들.
하나씩 별도의 게시글로 (언젠가) 써내려가 볼 예정이다.
▼ 꼬리에 꼬리를 무는 관련 용어들
* JWT (Json Web Token) : 토큰 기반 인증의 표준. Json 형태로 인증 정보를 담고 있음
* SSO (Single Sign On): 한 번(Single)의 로그인 인증(Sign-on)으로 여러 서비스의 추가적 인증 없이 사용할 수 있는 기술
* LDAP (Lightweigh Directory Access Protocol):사용자의 정보(ID, Password 등)를 중앙집권적으로 관리하는 일종의 주소록 서버
* IdP (Identity Provider, ID공급자): Google이나 Apple 등과 같은 간편 로그인 서비스를 제공하는 회사나 인증 서버를 뜻함. 로그인하려는 서비스에게 인증 정보를 알려주는 역할.
* SAML, OAuth, OIDC: SSO를 위한 표준 친구들
* IAM(Identity Access Mgt., 계정과 접근권한 관리 솔루션), IdM (Identity Mgt., 계정관리), EAM(Enterprise Access mgt., 접근관리)
* ACL (Access Control List, 접근제어목록)