Flask에서 HTTP 요청 및 응답 제어와 세션 관리

요청 생명주기

Flask 애플리케이션은 클라이언트 요청이 들어오면 WSGI 서버를 거쳐 전역 훅, 라우팅, 뷰 함수를 실행하고 다시 역순으로 응답을 반환하는 구조를 갖는다.

요청 객체 (Request)

Flask의 request 객체는 현재 요청에 대한 모든 정보를 담고 있다. from flask import request로 가져올 수 있으며, 내부적으로 Werkzeug의 Request 클래스를 기반으로 한다. 주요 속성은 다음과 같다.

속성설명타입
data요청 본문을 바이트 문자열로 제공. Form, JSON 등으로 해석되지 않는 원시 데이터를 담음bytes
formHTML 폼 데이터ImmutableMultiDict
args쿼리 문자열 파라미터ImmutableMultiDict
cookies클라이언트가 보낸 쿠키Dict
headers요청 헤더ImmutableMultiDict
methodHTTP 메서드 (GET, POST 등)str
url요청 URL 전체str
files업로드된 파일 목록ImmutableMultiDict
jsonJSON 형식의 요청 본문dict

요청 데이터 추출

다음 예제는 다양한 요청 데이터를 읽는 방법을 보여준다. GETDELETE는 본문이 없으므로 POST, PUT, PATCH만 허용했다.

from flask import Flask, request
from pathlib import Path

app = Flask(__name__)
app.config['DEBUG'] = True

@app.route('/api/data', methods=['POST', 'PUT', 'PATCH'])
def handle_data():
    # 원시 본문 (XML, 바이너리 등)
    raw_body = request.data

    # 폼 데이터
    user_name = request.form.get('name')
    user_age = request.form.get('age')

    # JSON 요청
    if request.is_json:
        payload = request.json
        username = payload.get('username')

    # 파일 업로드 (multipart/form-data)
    uploaded = request.files.get('avatar')
    if uploaded:
        save_path = Path(__file__).parent / 'uploads' / uploaded.filename
        uploaded.save(save_path)

    # 헤더 정보
    host = request.headers.get('Host')
    custom_token = request.headers.get('X-Auth-Token')

    # 클라이언트 정보
    user_agent = request.user_agent
    remote_ip = request.remote_addr
    server_info = request.server

    # 요청 메서드와 URL
    method = request.method
    full_url = request.url
    url_path = request.path

    return '데이터 처리 완료'

응답 생성

Flask는 HTML, JSON, 리다이렉트 등 다양한 응답을 지원한다. 뷰 함수가 문자열을 반환하면 Flask가 자동으로 Response 객체로 변환한다.

HTML 응답

from flask import Flask, make_response, Response

app = Flask(__name__)

@app.route('/')
def home():
    # 기본 HTML 반환
    return '<h1>환영합니다</h1>', 200, {'X-Custom-Header': 'flask'}

@app.route('/explicit')
def explicit():
    resp = make_response('<p>명시적 응답</p>', 201)
    resp.headers['X-Info'] = 'custom'
    return resp

JSON 응답

jsonify()를 사용하면 리스트, 딕셔너리 등 복합 데이터를 JSON으로 직렬화할 수 있다. Decimal 같은 타입도 자동 처리된다.

from flask import Flask, jsonify
from decimal import Decimal

app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False

@app.route('/api/users')
def get_users():
    users = [
        {'id': 1, 'name': 'alice', 'score': Decimal('98.5')},
        {'id': 2, 'name': 'bob', 'score': Decimal('87.2')}
    ]
    return jsonify(users)

리다이렉트

리다이렉트는 redirect() 함수로 간편하게 처리할 수 있다. 내부적으로 Location 헤더와 상태 코드를 설정한 Response를 반환한다.

from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route('/old')
def old_page():
    # 외부 사이트로 영구 이동 (301)
    return redirect('https://example.com', 301)

@app.route('/profile')
def profile():
    return '프로필 페이지'

@app.route('/login')
def login():
    # 내부 엔드포인트로 임시 이동 (302)
    return redirect(url_for('profile'))

@app.route('/item/')
def item_detail(item_id):
    return f'아이템 {item_id}'

@app.route('/goto-item')
def goto_item():
    # 동적 URL 생성 후 리다이렉트
    target_url = url_for('item_detail', item_id=42)
    return redirect(target_url)

사용자 정의 상태 코드와 헤더

@app.route('/custom')
def custom_response():
    body = '생성됨'
    status = 201
    headers = {'X-API-Version': '1.2'}
    return body, status, headers

HTTP 세션 제어

HTTP는 무상태 프로토콜이므로 사용자 상태를 유지하기 위해 쿠키와 세션을 사용한다.

쿠키 (Cookie)

쿠키는 서버가 생성하여 클라이언트에 저장하는 작은 텍스트 데이터다. response.set_cookie()로 설정하며, max_age를 지정하지 않으면 세션 쿠키(브라우저 종료 시 삭제)가 된다.

from flask import Flask, request, make_response

app = Flask(__name__)

@app.route('/cookie/set')
def set_cookie():
    resp = make_response('쿠키 설정')
    resp.set_cookie('user_id', 'abc123', max_age=3600)  # 1시간 유효
    resp.set_cookie('theme', 'dark')                     # 세션 쿠키
    return resp

@app.route('/cookie/get')
def get_cookie():
    uid = request.cookies.get('user_id')
    theme = request.cookies.get('theme', 'light')
    return f'사용자: {uid}, 테마: {theme}'

@app.route('/cookie/delete')
def delete_cookie():
    resp = make_response('쿠키 삭제')
    resp.set_cookie('user_id', '', max_age=0)
    resp.set_cookie('theme', '', max_age=0)
    return resp

세션 (Session)

Flask의 세션은 기본적으로 클라이언트 쿠키에 암호화되어 저장된다. SECRET_KEY 설정이 필수이며, session 객체를 통해 딕셔너리처럼 사용한다.

from flask import Flask, session

app = Flask(__name__)
app.secret_key = 'your-secret-key-here'

@app.route('/session/set')
def set_session():
    session['username'] = 'alice'
    session['cart'] = ['item1', 'item2']
    return '세션 저장됨'

@app.route('/session/get')
def get_session():
    user = session.get('username', 'guest')
    cart = session.get('cart', [])
    return f'{user}님의 장바구니: {cart}'

@app.route('/session/delete')
def delete_session():
    session.pop('username', None)
    session.pop('cart', None)
    return '세션 삭제됨'

세션 데이터는 쿠키에 저장되므로 쿠키가 클라이언트에서 삭제되면 세션도 사용할 수 없다. 대규모 서비스에서는 Flask-Session 확장을 통해 Redis나 데이터베이스에 저장하는 것이 일반적이다.

태그: flask HTTP Request Response cookie

9월 3일 12:52에 게시됨