2025. 2. 6. 11:43ㆍNetwork 공부
1. TCP는 Stateful(상태 유지)
TCP(Transmission Control Protocol)는 Stateful하다
- TCP는 연결형 프로토콜로, 클라이언트와 서버 간의 연결을 유지하면서 데이터를 주고받는다.
- 3-Way Handshake(3방향 핸드셰이크) 를 사용하여 연결을 설정한 후 데이터를 주고받고, 4-Way Handshake(4방향 핸드셰이크) 로 연결을 종료합니다.
TCP의 Stateful 동작 방식
- 클라이언트가 서버와 연결을 설정 (3-Way Handshake)
- 데이터 전송 시 연결 유지 (State 유지)
- 서버가 데이터 패킷을 재전송할 수도 있음 (State를 기억함)
- 연결 종료 (4-Way Handshake)
💡 TCP는 현재 연결 상태(Connection State)를 기억하고 관리하는 프로토콜이므로 Stateful하다!
2. HTTP는 Stateless(무상태)
- HTTP는 TCP 위에서 동작하지만 Stateless한 프로토콜이다.
HTTP는 Request-Response(요청-응답) 기반 프로토콜로,
요청을 보낼 때마다 새로운 연결을 생성하고 응답을 받은 후 연결을 끊어버립니다.
서버는 이전 요청의 상태를 기억하지 않음.
따라서, 각 HTTP 요청은 독립적이고 서버는 이전 요청과 관계없이 새로운 요청으로 처리함.
- HTTP의 Stateless 동작 방식
- 클라이언트가 서버에 HTTP 요청을 보냄 (GET /index.html)
- 서버가 응답을 반환하고 연결을 종료함 (HTTP 200 OK)
- 클라이언트가 다시 요청을 보내면, 서버는 이전 요청을 기억하지 못하고 새로운 요청으로 처리함.
HTTP는 매 요청마다 새로운 연결을 생성하고, 상태를 유지하지 않으므로 Stateless하다!
TCP의 Stateful vs. HTTP의 Stateless 차이점
연결형 (Connection-Oriented) | 비연결형(Connectionless-like) | |
연결 유지 여부 | 3-Way Handshake로 연결 설정 후 상태 유지 | 요청-응답이 끝나면 연결 종료 |
데이터 전송 방식 | 데이터 패킷이 순서대로 전송되고 재전송 가능 | 요청과 응답이 독립적으로 동작 |
서버가 상태를 기억하는가? | 예 (클라이언트와 연결 유지) | 아니요 (각 요청을 독립적으로 처리) |
HTTP는 TCP의 연결을 사용하지만, TCP처럼 "연결을 유지하는" 방식이 아니라, "요청-응답 후 연결을 끊어버리는" 방식이기 때문에 Stateless하다고 한다!
4. HTTP가 완전한 Stateless인가?
아니다!
기본적으로 HTTP는 Stateless이지만, 쿠키, 세션, JWT, OAuth 같은 기술을 사용하면 Stateful하게 동작할 수도 있다.
예를 들어, 세션(Session) 을 사용하면 서버가 클라이언트의 상태를 유지할 수 있다.
하지만, 이는 HTTP 자체가 Stateful해지는 것이 아니라, 부가적인 기술을 사용하여 상태를 유지하는 것다.
HTTP는 기본적으로 Stateless이지만, 개발자가 쿠키나 세션 등을 사용하면 Stateful한 동작을 구현할 수도 있다!
- TCP는 Stateful → 연결을 유지하면서 상태를 기억하는 프로토콜.
- HTTP는 Stateless → 요청-응답이 독립적으로 처리되며, 서버는 상태를 기억하지 않음.
- HTTP는 TCP 위에서 동작하지만, TCP처럼 연결을 유지하지 않으므로 Stateless하다.
- 쿠키, 세션 등을 사용하면 HTTP도 Stateful한 동작을 구현할 수 있음.
HTTP 는 그러면 왜 기본적으로 Staeless 하고 쿠키나 Session 이라는 추가적인 기능을 사용해서 Stateful 한 특징을 가지는 것일까?
HTTP가 기본적으로 Stateless한 이유
HTTP는 각 요청이 독립적이기 때문에, 서버는 이전 요청의 정보를 기억하지 않음.
사용자가 로그인하더라도, 다음 요청에서는 로그인 상태를 유지하지 못함.
이를 해결하기 위해 쿠키(Cookie)나 세션(Session)을 사용하여 상태를 유지(Stateful)하는 방식이 필요함.
1. 쿠키(Cookie)를 사용한 Stateful 동작
쿠키란?
- 쿠키는 클라이언트(브라우저)에 저장되는 작은 데이터 조각.
- 서버가 클라이언트에게 상태를 저장하도록 요청할 수 있음.
- 이후 클라이언트는 HTTP 요청을 보낼 때마다 쿠키를 함께 전송하여, 서버가 사용자의 상태를 유지하도록 함.
2. 쿠키의 저장과 작동 방식
쿠키는 HTTP 응답 시 서버가 클라이언트(주로 브라우저)에게 특정 데이터를 저장하도록 요청하고 클라이언트가 HTTP 요청을 보낼 때마다 해당 쿠키를 함께 전송하는 방식으로 동작한다.
1) Set Cookie
클라이언트가 로그인 등의 요청을 보냈을 때 서버는 응답 Header 에 Set-Cookie 를 포함하여 쿠키를 저장하도록 요청한다.
클라이언트가 로그인 시도:
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
username=admin&password=1234
로그인이 성공하면 서브는 Set-Cookie Header 를 통해 쿠키를 브라우저에 저장하도록 요청한다
서버 응답 (쿠키 설정)
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure
Content-Type: text/html
<html>로그인 성공!</html>
쿠키 옵션 설명
- session_id=abc123 → session_id라는 쿠키에 abc123 값을 저장
- Path=/ → 이 쿠키는 / 경로 이하에서 모든 요청에 포함됨
- HttpOnly → JavaScript에서 접근할 수 없도록 보호됨
- Secure → HTTPS 환경에서만 전송됨
2) 이후 요청 시 쿠키 전송을 통한 (State 유지)
클라이언트가 서버로 요청을 보낼 때마다 저장된 session_id 쿠키를 포함하여 전송한다.
사용자가 로그인 후 /dsahboard 페이지를 요청하면:
GET /dashboard HTTP/1.1
Host: example.com
Cookie: session_id=abc123
서버는 session_id = abc123 을 확인하여 로그인된 사용자 정보를 유지한다
HTTP/1.1 200 OK
Content-Type: text/html
<html>대시보드 페이지</html>
3) 쿠키 만료 및 삭제
쿠키는 설정된 시간이 지나면 자동으로 만료된다. 혹은 서버가 쿠키를 삭제 할 수 있다.
쿠키 만료 설정 (Expires or Max-Age)
ex) 1시간 후에 만료되는 쿠키 설정
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; Max-Age=3600
쿠키 삭제
로그아웃 시 쿠키를 삭제하려면 Expires 를 과거 날짜로 설정하면 된다.
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; Expires=Thu, 01 Jan 1970 00:00:00 GMT
이렇게 현재 시간보다 Expires 시간이 과거이면 브라우저는 해당 쿠키를 삭제하게 된다.
+ JavaScript 에서 쿠키 사용 (document.cookie)
1) 의 session_id 설정에서 HttpOnly 라는 설정이 있었는 데 이 속성이 포함되지 않는 경우 JavaScripts 에서도 쿠키에 접근 할 수 있다. 하지만 session_id 는 기본적으로 보안상 중요한 정보이기 때문에 HttpOnly 속성을 설정하여 JavaScript 에서 접근 할수 없도록 하는 것이 좋다쿠키 설정
document.cookie = "user=admin; path=/";
쿠키 읽기
console.log(document.cookie); // "user=admin"
쿠키 삭제
document.cookie = "user=admin; expires=Thu, 01 Jan 1970 00:00:00 GMT";
1. 세션 (Session)
세션이란?
- 서버 측에서 클라이언트의 정보를 유지하는 방식
- 서버가 클라리언트별로 세션 ID 를 생성하여 서버에 저장하고 클라이언트는 해당 세션 ID 를 쿠키로 저장하여 서버와 통신한다.
- 세션 ID 만 유지하면 서버는 클라이언트의 정보를 Stateful 한 상태로 유지할 수 있기 때문에 쿠키보다 보안성이 높다. 그래서 일반적으로 ( 쿠키에는 민감한 정보가 저장되지 않는다.)
2. 세션을 이용한 Stateful 과정
1) 클라이언트의 로그인 요청
POST /login HTTP/1.1
Host: example.com
Content-Type: application/json
{
"username": "user123",
"password": "password"
}
POST /login HTTP/1.1 -> HTTP Method (요청 방식)으로 데이터를 서버로 전송할 때 사용된다. (로그인, 데이터 저장 그리고 회원 가입 등등)
/login -> 요청을 보낼 서버의 경로 (EndPoint, API address), 로그인 처리를 담당하는 서버의 URL
POST /login 은 서버의 /login 경로로 로그인 요청을 보낸다는 의미
HTTP/1.1 -> HTTP 프로토콜 버전
Host: example.com -> Host Header는 요청을 처리할 서버의 주소(Domain) 을 의미
ex) google.com, amazon.com, naver.com, tistory.com
Content-Type: application/json -> Content -Type Header 는 요청하는 데이터 형식을 의미한다.
application / json 은 json 형식의 데이터를 전송한다는 것을 의미하며, 위의 json data 는 user 의 id 와 pw 이다.
그래서 결국 Content-Type: application/json 이 설정된 상태에서 서버의 /login 경로로 전송된다.
위 내용은 로그인 API 에 내 계정 정보를 보내서 인증을 시도하는 단계인 것이다.
2. 서버 응답 (세션 ID 설정)
HTTP/1.1 200 OK
Set-Cookie: session_id=xyz789; Path=/; HttpOnly
session_id=xyz789 -> session_id 를 클라이언트에 저장
Path = / -> 해당 쿠키는 사이트 전체에서 사용 가능 이라는 의미
HttpOnly -> http 만 접근하도록 설정 (보안 강화)
3. 사용자 정보를 서버에 저장
서버는 session_id 와 함께 로그인한 사용자의 정보를 session storage 에 저장한다.
session_storage = {
"xyz789": {
"user_id": 123,
"username": "user123"
}
}
4. 클라이언트가 이후 요청을 보낼 때 마다 쿠키를 자동으로 포함시킴
사용자가 로그인 상태에서 dashboard 페이지를 요청하면 브라우저는 자동으로 session_id 를 쿠키에 포함하여 요청을 서버로 보낸다.
GET /dashboard HTTP/1.1
Host: example.com
Cookie: session_id=xyz789
5. 서버는 session_id 를 확인하여 해당 사용자의 로그인 상태를 유지한다.
- 서버 세션 확인 코드 예제 (Python Flask)
def get_user_from_session(session_id):
return session_storage.get(session_id, None)
session_id = "xyz789"
user = get_user_from_session(session_id)
if user:
print(f"Welcome, {user['username']}!") # "Welcome, user123!"
else:
print("Session expired. Please log in again.")
- 서버 응답 ( 로그인된 사용자에게 대시보드 페이지 제공)
HTTP/1.1 200 OK
Content-Type: text/html
<html>대시보드 페이지</html>
6. 세션 만료 및 삭제
세션은 일정 시간이 지나면 만료되거나 사용자가 로그아웃하면 삭제된다.
1) 세션 자동 만료 설정
일반적으로 세션은 비활성 시간이 일정 시간을 초과하면 만료된다.
- 세션 만료 시간 설정
from flask import Flask, session
from datetime import timedelta
app = Flask(__name__)
app.secret_key = "super_secret_key"
app.permanent_session_lifetime = timedelta(minutes=30)
permanent_session_lifetime = timedelta(minutes=30)
-> 세션이 30분 후 자동 만료
- 사용자가 로그아웃하면 세션 삭제
사용자가 로그아웃하면 서버는 해당 session _ id 를 제거하고 만료된 세션을 클라이언트에 전달한다.
HTTP/1.1 200 OK
Set-Cookie: session_id=xyz789; Path=/; HttpOnly; Expires=Thu, 01 Jan 1970 00:00:00 GMT
+ 세션 이외에도 JWT(JSON Web Token) 을 사용해서 Stateful 한 상태로 만들 수 있다.
JWT 는 세션 보다 확장성이 좋지만 클라이언트에게 토큰을 할당해 사용자의 정보를 확인하기 떄문에 토큰이 탈취되면서 발생하는 보안 문제가 있다.
그래서 확장성이 매우 중요한 경우에는 고려할 수 있다.
1. HTTP는 왜 기본적으로 Stateless인가? 그리고 쿠키/세션을 통해 Stateful하게 만드는 이유는 무엇일까?
1) 서버 부하 감소 (Scalability)
Http 가 stateless 하면 기본적으로 서버는 클라이언트의 이전 요청을 기억할 필요가 없어짐.
각 요청이 독립적으로 처리되면서 다중 사용자 요청을 쉽게 처리할 수 있게 된다.
요청마다 서버가 클라이언트의 상태를 기억해야한다면 서버의 메모리와 리소스 부담이 증가할 것이다.
2) 클라이언트와 서버의 독립성 유지
Http 는 클라이언트와 서버를 독립적으로 설계할 수 있게 만들어졌다.
서버는 어떤 클라이언트의 요청인지 알 필요 없이 해당 요청의 작업만 처리하게 되고 이렇게 하면
서버의 구현이 단순해지고 유지보수가 쉬워진다.
3) 네트워크의 안정성 증가
Stateless 모델에서는 서버가 다운되어도 요청이 독립적이기 때문에 큰 문제가 발생하지 않는다.
하지만 Stateful 한 경우에는 서버가 다운될 경우
기존의 연결된 세션이 모두 날아가기 때문에 문제가 발생한다.
ex) 온라인 쇼핑몰에서 일부 서버가 다운되어도 사용자의 요청은 독립적이기 때문에 다른 서버가 사용자의 요청을 받아서 처리할 수 있음
2. 쿠키 & 세선의 필요성
이런 Http 에 쿠키와 세션을 사용해서 Stateful 하게 만들어야 하는 이유는 무엇일까?
기본적으로 Http 가 Stateless 하더라도
웹 서비스에서는 사용자의 상태 (ex: 로그인, 장바구니, 설정 등)을 유지해하는 경우가 있다.
이를 위해서 쿠키와 세션을 통해 사용자의 상태를 저장하고 유지하는 것이다.
1) 로그인 상태 유지
사용자가 로그인할 때마다 ID/PW 를 계속 입력하지 않게 하기 쿠키를 사용해서
자동 로그인 기능 등을 제공하는
2) 사용자 맞춤 환경
사용자가 설정한 다크 모드, 언어 설정 등을 저장하고 싶을 때 쿠키를 사용하여 해당 사용자 설정에 대한 정보를 유지
'Network 공부' 카테고리의 다른 글
State Inspection Table (0) | 2025.02.10 |
---|---|
VyOS(Firewalld) (0) | 2025.02.06 |
Multi Process vs Multi Thread (0) | 2025.02.05 |
Synchronous vs Asynchronous ( 동기 vs 비동기 ) 방식 (0) | 2025.02.05 |
ACL (Access Control List) (0) | 2025.02.05 |