TOP
본문 바로가기
[파이썬 Projects]/<파이썬 웹개발>

[파이썬] FastAPI - 고급 인증: 세션

by 기록자_Recordian 2025. 5. 7.
728x90
반응형
이전 내용
 

[FastAPI] 고급인증: JWT

이전 내용 [FastAPI] 인증과 세션이전 내용 [FastAPI] SQLAlchemy와 CRUD (Depends, db.query)이전 내용 [파이썬] FastAPI - ORM 연동하기(SQLAlchemy)이전 내용 [파이썬] FastAPI - 웹소켓이전 내용 [파이썬] FastAPI - 스트리

puppy-foot-it.tistory.com


고급 인증: 세션

 

HTTP는 자체적으로 상태가 없는(stateless) 프로토콜이라 서버는 클라이언트의 이전 요청을 기억하지 않기 때문에 세션이 등장했다. 클라이언트가 처음 서버에 요청을 보낼 때 서버는 클라이언트에게 고유한 세션 ID를 발급하는데, 이 세션 ID는 쿠키 형태로 클라이언트에 저장된다.

클라이언트가 다시 서버에 요청을 보낼 때마다 이 쿠키를 함께 보내고, 서버는 이 세션 ID를 통해 클라이언트를 식별하고 필요한 정보를 저장하거나 불러온다.

 

FastAPI에서 이전에 인증을 위해 사용했던 JWT와는 유사한 목적을 갖고 있으나, 몇 가지 차이점이 있다.

 

◆ JWT와 세션의 차이

1. 상태 유무 (Statefulness)

 

세션:

  • 상태 정보를 서버 측에 저장하므로 상태가 유지되는 시스템이다.
  • 사용자가 로그인한 상태를 서버에서 관리하여, 서버에서 복원할 수 있다.
  • 서버 측에 클라이언트에 대한 정보를 저장하고 관리해야 하므로 Redis, 데이터베이스 등 추가적인 저장소가 필요하다.

JWT:

  • 상태 정보를 클라이언트 측에 저장하므로 상태가 유지되지 않는 (stateless) 시스템이다.
  • 서버는 클라이언트로부터 받은 토큰을 통해 사용자의 정보를 확인하며, 별도로 상태를 관리할 필요가 없다.
  • 토큰 자체가 모든 정보를 포함하고 있어 서버 측에 별도의 저장소가 필요하지 않다.

2. 보안성 (Security)

 

세션:

  • 서버에서 사용자 정보를 보안적으로 관리하므로 세션 하이재킹의 공격에 대해 어느 정도 보호된다.
  • 일반적으로 서버에서는 추가적인 보안 조치(세션 타임아웃, IP 체크 등)를 취할 수 있다.
  • HTTPS를 사용하면 세션 쿠키가 암호화되어 전송된다.

JWT:

  • JWT는 서명된 토큰이므로 변조를 방지할 수 있지만, 탈취된 경우 악용될 수 있다.
  • 토큰 자체가 정보를 포함하고 있기 때문에 토큰 노출 자체로도 문제가 될 수 있다.
  • 적절한 보안 구성(예: HTTPS, 짧은 만료 시간 설정 등)이 필수적이며, 암호화 알고리즘을 사용하기 때문에 일정 수준의 보안성이 있다.

3. 확장성 (Scalability)

 

세션:

  • 서버 측에 상태 정보를 저장하므로, 여러 서버가 존재하는 경우 일관된 세션 스토리지를 유지하는 것이 복잡할 수 있다.
  • 스케일아웃이 필요할 경우 Redis와 같은 외부 세션 관리 솔루션을 추가해야 할 수도 있다.

JWT:

  • 클라이언트 식별을 위한 정보가 토큰 내에 포함되므로, 서버 간 공유 없이 독립적으로 작동할 수 있다.
  • 높은 확장성을 제공하며, 여러 서버에서 쉽게 사용할 수 있다.

4. 사용성 (Usability)

 

세션:

  • 사용자의 로그인 상태를 쉽게 관리할 수 있으며, 특히 로그인/로그아웃 기능 구현이 간단하다.
  • 한 브라우저에서만 유효하여 다른 브라우저나 장치에서 동일하게 사용할 때 불편할 수 있다.

JWT:

  • 다양한 클라이언트(모바일 앱, 웹 앱 등)에서 동일한 토큰을 사용할 수 있어 유연성이 높다.
  • 만료된 토큰을 처리하고 로그아웃 기능을 구현하는 것이 다소 복잡할 수 있다.

이를 표로 정리하면 아래와 같다.

특징 세션 (Session)  JWT (JSON Web Token)
상태 유무 - 상태 정보를 서버 측에 저장 (상태 유지)
- 추가 저장소 필요 (Redis, DB 등)
- 상태 정보를 클라이언트 측에 저장 (무상태)
- 별도의 저장소 필요 없음
보안성  - 세션 하이재킹 공격에 대한 보호 실현
- 추가적인 보안 조치 가능 (타임아웃, IP 체크 등)
- HTTPS로 안전하게 전송
- 서명된 토큰으로 변조 방지
- 탈취 시 악용 가능성 존재
- 적절한 보안 구성이 필요
확장성  - 여러 서버에서 일관된 세션 스토리지 유지 어려움
- 스케일아웃 시 외부 솔루션 필요 (Redis 등)
- 높은 확장성 제공
- 여러 서버에서 독립적으로 작동 가능
사용성 - 로그인 상태 관리가 용이
- 다른 브라우저나 장치에서 유효성 문제
- 다양한 클라이언트에서 동일한 토큰 사용 가능
- 만료 처리 및 로그아웃 구현 복잡성

 


FastAPI와 Starlette

 

FastAPI는 Starlette 위에 구축된 고급 웹 프레임워크로, 비동기 웹 애플리케이션을 신속하게 개발할 수 있고,  강력한 기능과 유연성을 바탕으로 설계되어, 고성능 RESTful API 개발에 최적화되었다.

Starlette는 ASGI(Asynchronous Server Gateway Interface) 기반의 웹 프레임워크로, 비동기 웹 애플리케이션을 위한 간단하면서도 확장 가능한 툴킷이다. Starlette의 경량성과 비동기 처리 기능 덕분에 FastAPI를 통해 개발자들은 빠르고 효율적인 웹 애플리케이션을 구축할 수 있다.

 

[FastAPI와 Starlette의 관계]

 

1. 구조와 디자인

 

Starlette:

  • ASGI 기반의 웹 프레임워크로, 비동기 웹 애플리케이션을 위한 경량화된 툴킷이다.
  • 라우팅, 미들웨어, 응답 생성 등 기본적인 웹 애플리케이션 기능을 제공한다.
  • HTTP와 WebSocket 프로토콜을 모두 지원하여 다양한 애플리케이션에 적합하다.

FastAPI:

  • Starlette 위에 구축된 프레임워크로, RESTful API를 보다 쉽고 우아하게 설계할 수 있도록 지원한다.
  • Starlette의 기본 기능을 확장하여 데이터 유효성 검사, 문서화, 경로 및 쿼리 매개변수 처리를 지원한다.

2. 기능상 차별화

  • FastAPI는 Starlette의 기본 기능을 기반으로 추가적으로 Pydantic을 사용하여 데이터 모델링과 유효성 검사를 통합한다. 이로 인해 요청 데이터의 검증 및 자동화된 문서화가 가능해져 API 개발의 생산성이 높아진다.
  • FastAPI는 OpenAPI를 자동으로 생성하여 API의 문서화 작업을 간소화하고, 이를 통해 Frontend 개발자와의 협업이 용이해진다.

3. 비동기 처리

  • FastAPI는 ASGI를 지원하여 비동기 처리를 자연스럽게 활용할 수 있다.
  • Starlette의 비동기 기능을 상속받아 데이터베이스와의 비동기 연결을 통해 성능을 최적화하며, 이러한 특징은 높은 동시성을 요구하는 애플리케이션에서 특히 유리하다.

4. 미들웨어와 라우팅

  • FastAPI는 Starlette의 미들웨어와 라우터를 활용하여 HTTP 요청 처리 및 응답 생성 시 다양한 기능을 제공한다.
  • 사용자 정의 미들웨어를 쉽게 추가할 수 있으며, 라우팅 시스템을 통해 RESTful API를 효율적으로 구성할 수 있다.

세션 관리
SessionMiddleware


Starlette는 세션 관리를 위한 SessionMiddleware 라는 미들웨어를 제공하며, SessionMiddleware를 FastAPI 애플리케이션에 추가하면 FastAPI 기반의 웹 애플리케이션에서도 세션을 쉽게 관리할 수 있다.

※ 미들웨어: 요청과 응답을 중간에서 처리하는 컴포넌트. 로깅, 인증, 세션 관리 등 다양한 기능 수행.

 

FastAPI에서 SessionMiddleware을 사용하기 위해서는 SessionMiddleware를 애플리케이션에 추가하면 된다. 추가 후에는 각 요청 객체에서 session 속성을 통해 세션 데이터 접근할 수 있다.

from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware
import os

app = FastAPI()

# 실무에서는 환경 변수를 활용하여 secret_key를 관리
SECRET_KEY = os.environ.get("SECRET_KEY")
app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)

 

이렇게 한 후에는 각 라우트 함수에서 Request 객체를 통해 세션에 데이터를 저장하거나 읽을 수 있다.

@app.post("/set/")
async def set_session(request: Request):
    request.session["username"] = "test_user"
    return {"message": "Session value set"}

@app.get("/get/")
async def get_session(request: Request):
    username = request.session.get("username", "Guest")
    return {"username": username}

 

@app.post("/set/") 라우트

  • HTTP POST 메서드를 사용하는 /set/ 경로
  • Request 객체를 인자로 받아 session 속성을 통해 세션에 username 이라는 키와 그 값으로 "test_user" 라는 값을 저장
  • async 키워드는 비동기 I/O 작업을 위함

  • 클라이언트가 /set/ 엔드포인트에 POST 요청 보냄
  • FastAPI 애플리케이션은 이 요청을 받고 set_session() 함수 호출
  • set_session() 함수 내에서 request.session["username'] = "test_user" 코드가 실행되면서, 세션에 "username"키와 "test_user" 값 저장
  • 함수는 {"message": "Session value set"}을 반환하여 클라이언트에게 세션이 성공적으로 설정되었다는 것을 알림.

@app.get("/get/") 라우트

  • HTTP GET 메서드를 사용하는 /get/ 경로
  • 세션에서 username 키의 값을 가져와 반환하며, 만약 키가 없으면 "Guest" 반환

  • 클라이언트가 /get/ 엔드포인트에 GET 요청 보냄
  • 이때 -b cookies.txt 옵션을 통해 이전에 저장한 쿠키(세션 정보)가 요청에 포함
  • FastAPI 애플리이션은 이 요청을 받고 get_session() 함수 호출
  • Get_session() 함수 내에서 username = request.session.get("username", "Guest") 코드가 실행된다. 이 코드는 세션에서 "username" 키 값을 찾아 username 변수에 저장하고, 만약 키가 없으면 "Guest" 저장
  • FastAPI 애플리케이션은 {"username": "test_user"} 라는 응답 반환 (세션에 저장된 "username"의 값을 응답으로 반환)

 

항목 설명 예시 값
Name (이름) 쿠키의 이름. 주로 세션이나 로그인된 사용자를 식별할 때 사용. session
Value (값) 쿠키에 저장된 실제 데이터. 암호화된 문자열 (예: 세션 ID, 토큰 등) eyJ1c2VybmFt... 
Domain (도메인) 이 쿠키를 사용할 수 있는 웹사이트 도메인.
이 도메인에서만 이 쿠키를 읽고 쓰기 가능.
127.0.0.1 (로컬 테스트용 주소)
Path (경로) 쿠키가 적용되는 웹사이트 경로.
/는 사이트 전체를 의미
/
Expires (만료 시각)  쿠키가 언제 만료되어 삭제될지를 나타냄.
이 시각이 지나면 자동으로 쿠키가 사라짐.
2025년 5월 21일 수요일
HttpOnly  true이면 자바스크립트에서 이 쿠키에 접근 불가. 보안 목적(예: XSS 방지)에 사용 true
Secure  true이면 HTTPS(보안 연결)로만 쿠키가 전송됨. 
HTTP에서는 전송되지 않음.
 false (테스트 중이므로 비활성화됨)

 

실제 웹 환경에서는 웹 브라우저 내에서 cookies.txt 파일을 통해 세션 정보를 확인할 수 있고, 이곳의 정보를 관리한다.

from fastapi import FastAPI, Request, HTTPException
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()

# session 미들웨어 추가
app.add_middleware(SessionMiddleware, secret_key="my_secret_key")

@app.post("/login/")
async def login(request: Request, username: str, password: str):
    # 실제로는 데이터베이스에서 사용자 인증을 수행해야 함
    if username != "test_user" or password != "1234":
        raise HTTPException(status_code=401, detail="Invalid credentials")
    else:
        # 세션에 사용자 정보 저장
        request.session["username"] = username
        return {"message": "Logged in successfully"}
    
@app.get("/dashboard/")
async def dashboard(request: Request):
    # 세션에서 사용자 정보 가져오기
    username = request.session.get("username")
    if not username:
        raise HTTPException(status_code=401, detail="Not authenticated")
    return {"message": f"Welcome to the dashboard, {username}!"}

 

 

[테스트]

1. 로그인 테스트

로그인 엔드포인트(/login/)에서 사용자명과 패스워드를 입력받아, 유효한 경우 세션에 사용자명 저장하고 로그인 성공 메시지 출력

 

2. 대시보드 접근 테스트

대시보드 엔드포인트(/dashboard/) 세션에서 사용자명을 조회하여, 로그인된 사용자만 접근하도록 하고, 로그인 성공 시 성공 메시지 출력

 


[참고]

가장 빠른 풀스택을 위한 플라스크 & FastAPI


다음 내용

 

[FastAPI] 비동기 처리 (asynchronous processing)

이전 내용 [FastAPI] 고급 인증: 세션이전 내용 [FastAPI] 고급인증: JWT이전 내용 [FastAPI] 인증과 세션이전 내용 [FastAPI] SQLAlchemy와 CRUD (Depends, db.query)이전 내용 [파이썬] FastAPI - ORM 연동하기(SQLAlchemy)이

puppy-foot-it.tistory.com

 

728x90
반응형