일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 쉬운 문제
- Algorithm
- 타입스크립트
- 레벨 1
- socket
- 그래프
- javascript
- 프로그래머스
- 가천대
- 타입 챌린지
- 알고리즘
- 자바스크립트
- 크롤링
- 백준
- 소켓
- typescript
- Crawling
- 프로그래머스 레벨 2
- dfs
- HTTP 완벽 가이드
- 문자열
- HTTP
- BFS
- 수학
- dp
- type challenge
- TCP
- ip
- Nestjs
- Node.js
- Today
- Total
kakasoo
[HTTP] 18. 클라이언트 식별과 쿠키 본문
웹 서버는 서로 다른 수천 개의 클라이언트와 동시에 통신한다. 서버는 모든 요청을 처리할 뿐만 아니라, 특정 클라이언트를 추적해야 할 수도 있다. 이 장은 서버가 통신 대상을 식별하는 기술에 대해 설명한다.
11.1 개별 접촉
HTTP는 익명으로 사용한다. 또한 연결에 대한 정보를 가지지 않으며 매 요청이 일회성에 독립적이다. 즉 무상태성을 지닌다. 다만 웹 서버는, 이런 HTTP 속에서도 약간의 정보를 이용할 수가 있다.
현대의 웹 사이트들은 개인화된 서비스를 제공하고 싶어 한다. 네트워크로 연결된 사용자에 대해 더 많은 것을 알고 싶어하고 사용자의 정보를 저장해두려고 한다.
개별 인사
개개인에게 맞춰져 있는 것 같은 느낌을 주기 위해 사용자에게 특화된 환영 메시지나 페이지를 만든다.
사용자 맞춤 추천
고객의 흥미가 무엇인지 학습해서 고객이 좋아할 것을 예상하여 보여줄 수 있다.
저장된 사용자 정보
신용카드와 같이 복잡한 정보를 사용자가 매번 입력하는 것은 불편할 수 있기 때문에, 이런 정보를 미리 저장해두는 것도 가능하다.
세션 추적
HTTP 트랜잭션은 상태가 없다. 각 요청은 독립적이다. 그렇지만 장바구니와 같은 기능을 생각해볼 때, 사용자가 누구인지를 추적하는 것은 필요하다. 따라서 사용자를 식별할 기술이 필요하다.
다만, HTTP 자체에서는 사용자를 식별하는 기능이 풍부하지 않다. 따라서 초기 웹 사이트 설계자들을 그들만의 기술을 개발했다.
- 사용자 식별 관련 정보를 전달하는 HTTP 헤더들
- 클라이언트 IP 주소 추적으로 알아낸 IP 주소로 사용자를 식별
- 사용자 로그인 인증을 통한 사용자 식별
- URL에 식별자를 포함하는 기술인 뚱뚱한(fat) URL
- 식별 정보를 지속해서 유지하는 강력하면서도 효율적인 기술인 쿠키
자세한 내용은 이후 설명한다.
11.2 HTTP 헤더
사용자에 대한 정보를 전달하는, HTTP의 자체적인 방법이 7가지가 있다.
- From
- User-Agent
- Referer
- Authorization
- Client-ip
- X-Forwarded-For
- Cookie
From 헤더는 사용자의 이메일 주소를 포함한다. 이상적으로는 각 사용자가 서로 다른 이메일 주소를 가지므로 From 헤더로 사용자를 모두 식별할 수 있겠다.
하지만 악의적인 서버가 이메일 주소를 모아서 스팸 메일을 발송하는 문제가 있어서, From 헤더를 보내는 브라우저는 많지 않다. (사용자를 보호하기 위한 브라우저의 대책이라고 볼 수 있겠다.)
실제로 로봇이나 스파이더는 데이터를 수집하는 과정에서 웹 사이트에게 문제를 일으켰을 때 항의 메일을 보낼 수 있도록 하기 위해 From 헤더에 이메일을 기술하곤 한다.
User-Agent 헤더는 사용자가 쓰고 있는 브라우저의 이름과 버전 정보, 어떤 경우에는 운영체제에 대한 정보까지 포함하여 서버에게 알려준다.
다만 이는 사용자의 환경을 알아내 콘텐츠를 최적화하는 데에는 도움을 주지만, 특정 사용자를 식별하는 데에는 도움을 줄 수 없다.
Referer 헤더는 사용자가 현재 페이지로 유입하게 한 웹 페이지의 URL을 가리킨다. 이는 사용자를 식별할 수는 없지만 사용자의 취향을 알아내는 데에 좋은 정보이다.
11.3 클라이언트 IP 주소
초기 웹 선구자들은 사용자 식별에 클라이언트의 IP를 직접 사용하려고 했다. 보통 IP 주소는 HTTP 헤더에 없지만, 웹 서버는 HTTP 요청을 보내는 반대쪽 TCP 커넥션의 IP 주소를 알아낼 수 있다.
(참고로 이것은 node.js에서도 가능하다.)
다만 클라이언트 IP 주소를 가져오는 것은 약점이 있다.
- 사용자가 아니라 컴퓨터를 가리킨다. 따라서 특정인을 알 수는 없다.
- 많은 인터넷 서비스 제공자는 사용자에게 동적으로 IP를 할당한다. 따라서 매번 IP 주소가 변경될 테니 IP 주소로는 아무 정보를 얻을 수 없다.
- 보안을 강화하기 위해 많은 사용자는 애초에 IP 주소를 주지 않으려고 한다.
- 중간에 프락시가 있는 경우에는 알 수 없다. 프락시 중에는 알려주는 것도 있긴 하나 모든 프락시가 그런 것은 아니다.
따라서 이 방식은 완벽하지 못하다.
11.4 사용자 로그인
웹 서버는 명시적으로 사용자 이름과 비밀번호를 요구할 수 있다. 웹 사이트 로그인이 더 쉽도록 HTTP는 WWW-Authenticate와 Authorization 헤더를 사용해 웹 사이트에 이름을 전달하는 체계를 가지고 있다.
한 번 로그인하면, 브라우저는 사이트로 보내는 모든 요청에 이 로그인 정보를 함께 보내므로 웹 서버는 그 로그인 정보를 항상 확인할 수 있다.
사용자가 로그인 전에 요청을 보낸다면 401 Login Required 응답 코드를 보낼 수 있다.
한 번 로그인이 된 후부터는 어떤 요청이든 사용자의 정보를 같이 보내면 된다. 다만 사용자가 각 사이트마다 로그인하는 것은 번거롭고, 특정 사이트의 ID가 이미 선점된 상태면 사용자에게 불편을 초래한다.
11.5 뚱뚱한 URL
어떤 웹 사이트는 URI마다 버전을 기술하여 사용자를 식별하고 추적하였다. 보통, URL은 URL 경로의 처음이나 끝에 어떤 상태 정보를 추가해 확장한다.
사용자의 상태 정보를 포함하고 있는 URL을 뚱뚱한 URL이라고 한다. 괜찮은 방법이지만, 아래와 같은 문제가 발생한다.
- 못생긴 URL
- 공유하면 안 되는 URL
- 캐시를 사용할 수 없음 (매번 경로에 따라 다르게 URL이 나올 것이다.)
- 서버 부하 가중 (경로에 따라 다른 HTML을 그려야 한다.)
- 이탈 (사용자가 해당 HTML로 돌아오고 싶다면 동일한 경로를 기억해두고 다시(!?) 접근해야 한다.)
- 세션 간 지속성의 부재
- 위와 같은 이유로, 로그아웃 시 사용자는 모든 정보를 잃는다.
11.6 쿠키
쿠키는 가장 널리 사용되는 방식이다. 쿠키는 앞서 말한 기술들의 문제점들로부터는 자유롭지만, 쿠키만으로 하기 힘든 일이 있어 앞의 기술과 섞어서 사용되기도 한다.
쿠키는 모든 브라우저에서 동작한다. 쿠키는 매우 중요한 기술일 뿐만 아니라, 새로운 HTTP 헤더를 정의하므로 더 자세히 볼 필요가 있다.
대부분의 캐시나 브라우저는 내용물을 캐싱하지 않는다.
11.6.1 쿠키의 타입
쿠키는 세션 쿠키와 지속 쿠키 두 가지 타입으로 나누곤 한다. 세션 쿠키는 사용자가 사이트를 탐색할 때 관련된 설정을 저장하는 임시적인 쿠키다. 브라우저를 닫으면 사라지는 종류의 쿠키이다.
지속 쿠키는 삭제되지 않고 오래 유지된다. 지속 쿠키는 디스크에 저장되어 브라우저를 닫거나 컴퓨터를 재시작하더라도 남아있다.
지속 쿠키는 사용자가 주기적으로 방문하는 사이트 정보, 로그인 정보를 유지한다. 세션 쿠키와 지속 쿠키의 다른 점은 파기되는 시점 뿐이다.
11.6.2 쿠키는 어떻게 동작하는가
쿠키는 서버가 사용자에게 붙인 스티커와 같다고 한다. 웹 사이트는 사용자가 방문 시 바로 그 스티커를 읽을 수 있다. 처음에 사용자가 웹 사이트에 방문할 때에는 당연히 이런 스티커가 없다.
웹 서버는 사용자가 다시 돌아왔을 때 해당 유저를 파악하기 위해 유일한 값을 쿠키에 할당한다. 쿠키는 임의의 이름 형태의 리스트를 가진다.
그 리스트는 Set-Cookie 혹은 Set-Cookie2 (확장 헤더)같은 HTTP 응답 헤더에 기술되어 사용자에게 전달한다.
서버가 사용자 추적 용도로 생성한 단순 식별 번호만을 포함하곤 한다. 하지만 쿠키는 사실 어떤 정보든 담을 수 있다. 필요에 따라서는 더 구체적인 정보를 담기도 한다. (전화번호나 이름 등)
11.6.3 쿠키 상자 : 클라이언트 측 상태
쿠키의 기본 발상은 브라우저가 정보를 저장하고 사용자가 그 서버에 접근할 때마다 그 정보를 같이 전달하게 하는 것이다.
브라우저는 쿠키 정보를 저장할 책임이 있는데, 이 시스템을 '클라이언트 측 상태' 라고 한다. 쿠키 명세에서 이것의 공식적인 이름은 'HTTP 상태 관리체계 (HTTP State Management Mechanism)'이다.
브라우저마다 방식이 상이하니 참고 바람.
11.6.4 사이트마다 각기 다른 쿠키
브라우저에 쿠키가 잔뜩 쌓일 수도 있다. 하지만, 그렇다고 해서 사이트에 들어갈 때 브라우저가 모든 쿠키를 다 보내는 것은 아니다. 보통은 두 개에서 세 개 정도의 쿠키만을 보낸다.
당연하지만 모든 쿠키를 보내게 된다면 성능에 문제가 생길 수 있다. 쿠키는 대부분 서버에 특화된 이름/값 쌍을 가지고 있다. 따라서 이것으로 해당 사이트에 맞는 쿠키만 보내면 되는 것이다.
또 다른 문제로는, 쿠키에는 사용자의 정보가 담겨 있는데, 관련없는 사이트에 정보를 보내는 것은 개인정보 문제를 일으킨다.
쿠키 Domain 속성
서버는 쿠키를 생성할 때 Set-Cookie 응답 헤더에 Domain 속성을 기술해서 어떤 사이트가 그 쿠키를 읽을 수 있는지 제어할 수 있다.
쿠키 pATH 속성
웹 사이트의 일부에만 쿠키를 적용할 수도 있다. URL 경로의 앞부분을 가리키는 Path 속성을 기술해서 해당 경로에 속하는 페이지에만 쿠키를 전달한다.
11.6.5 쿠키 구성 요소
현재 사용되는 쿠키 명세에는 Version 0 쿠키와 Version 1 쿠키가 있다. Version 1 쿠키는 Version 0 쿠키의 확장으로, 널리 쓰이지는 않는다. (2011년에 폐기 당했다.)
두 버전 모두 HTTP/1.1 명세의 일부로 기술되어 있지는 않다.
11.6.6 Version 0 쿠키
Version 0 Set-Cookie 헤더
Set-Cookie 헤더는 쿠키의 이름과 값을 가진다. 이는 쿠키 옵션 속성들에 세미콜론으로 이어 기술하다.
Set-Cookie : name=value [; exprires=date] [; path=path] [; domain=domain] [; secure]
Cookie: name1=value1 [; name2=value2] ....
Version 0 Cookie 헤더
클라이언트가 서버에 요청을 보낼 때는 Domain, Path, Secure 필터들이 현재 요청하려고 하는 사이트들에 들어맞으면서 아직 파기되지 않은 쿠키들을 함께 보낸다.
11.6.7 Version 1 Cookie에 대한 설명들은 생략한다.
11.6.8 쿠키와 세션 추적 : 생략
11.6.9 쿠키와 캐싱
쿠키 트랜잭션과 관련된 문서를 캐싱하는 것은 주의해야 한다. 이전 사용자의 쿠키가 다른 사용자에게 할당되거나, 누군가의 개인 정보가 다른 이에게 노출되는 상황이 일어날 수 있다.
쿠키와 캐싱에 대한 규칙은 잘 정리되어 있지 않다. 다음은 캐시를 다루는 기본적인 원칙이다.
캐시되지 말아야 할 문서가 있다면 표시하라
문서를 캐시하면 될지 안될지는 문서의 소유자가 가장 잘 안다. 문서가 만약 Set-Cookie 헤더를 제외하고 캐시를 해도 될 경우라면 명시적으로 Cache-Cnotrol: no-cache="Set-Cookie"를 표시한다.
또한 캐시를 해도 되는 문서에 Cache-Control: public을 사용하면 웹의 대역폭을 더 절약시켜준다.
Set-Cookie 헤더를 캐시하는 것에 유의하라
응답이 Set-Cookie 헤더를 가지고 있으면 본문은 캐시할 수 있지만, 이 역시 주의해야 한다. 같은 Set-Cookie 헤더를 여러 사용자에게 보내면 사용자 추적에 실패할 것이기 때문이다.
어떤 캐시는 응답을 저장하기 전에 Set-Cookie 헤더를 제거하기 때문에 그 캐시 데이터를 받는 클라이언트는 Set-Cookie 헤더 정보가 없는 데이터를 받게 되어 문제가 생길 수 있다.
캐시는 모든 요청마다 Set-Cookie 헤더 값을 기술하여 이 문제를 해결할 수 있다.
Cookie 헤더를 가지고 있는 요청을 주의하라
요청이 Cookie 헤더와 함께 오면 콘텐츠가 개인 정보를 가지고 있을 수도 있다는 힌트가 된다. 개인 정보는 캐시되지 않도록 표시되어 있어야 하지만, 그렇지 않을 수도 있다.
11.6.10 쿠키, 보안, 그리고 개인 정보
쿠키를 사용하지 않도록 비활성화할 수 있고, 로그 분석 같은 다른 방법으로 대체하는 것도 가능하므로 그 자체가 보안성으로 엄청나게 위험한 것은 아니다.
사실 DB에 개인정보를 저장하고 해당 데이터의 키 값을 쿠키에 저장하는 방식을 표준으로 하면 클라이언트와 서버 사이에 예민한 데이터가 오가는 것을 줄일 수 있다.
'프로그래밍 > HTTP' 카테고리의 다른 글
[HTTP] 20. 보안 HTTP (0) | 2021.01.31 |
---|---|
[HTTP] 19. 기본 인증 (0) | 2021.01.31 |
[HTTP] 17. 캐시(2) (0) | 2020.12.06 |
[HTTP] 16. 캐시(1) (0) | 2020.12.05 |
[HTTP] 15. 프락시 (0) | 2020.11.30 |