Python/Python 웹프로그래밍

[Flask-②] 파이썬 Flask 라우팅, 요청/응답 처리와 템플릿 렌더링

코딩 코디네이터 2025. 4. 15. 10:00
반응형

파이썬 Flask 라우팅, 요청/응답 처리와 템플릿 렌더링

웹 개발,
단순히 URL에 반응하는 것만으로는 부족하죠.
동적으로 데이터를 받고, 응답을 처리하고,
아름다운 화면까지 보여줘야 진짜 웹 애플리케이션입니다!

 

 

안녕하세요 여러분!

Flask의 기초를 잡은 첫날에 이어, 오늘은 Flask 라우팅의 심화HTTP 요청 및 응답 처리, 그리고 템플릿 렌더링까지 실전 웹 개발에 필요한 핵심 기능들을 배우는 시간을 가져보려고 해요.

특히 Jinja2 템플릿을 활용한 동적 페이지 구현은 처음 보면 살짝 낯설 수 있지만, 익숙해지면 정말 강력한 도구가 된답니다.

또한 클라이언트로부터 전달받는 다양한 형태의 요청 데이터를 처리하는 방법,

그리고 응답의 생성과 상태 관리까지 다뤄볼 예정이에요.

오늘 내용을 잘 익히면, 여러분만의 멋진 웹 인터페이스를 만들 수 있는 기본기를 탄탄히 다질 수 있을 거예요 😊

 

1. Flask 라우팅 심화 🌐

1-1. 동적 경로와 변수

Flask의 가장 강력한 기능 중 하나는 라우트에서 동적 경로를 쉽게 처리할 수 있다는 점이에요.

예를 들어 블로그 글을 클릭했을 때 /posts/3처럼 글 번호를 URL에 포함시키고 싶을 때가 있죠?

그럴 때는 이렇게 작성해요:

@app.route('/posts/<int:post_id>')
def show_post(post_id):
    return f"Post ID: {post_id}"

 

여기서 <int:post_id>는 URL의 일부분을 정수형 변수로 받아와서 파이썬 함수의 인자로 넘기는 역할을 해요.

string, float, path 같은 변환기도 사용할 수 있답니다.

1-2. HTTP 메서드 라우팅

기본적으로 Flask의 라우트는 GET 요청만 처리해요.

그런데 데이터 저장이나 수정이 필요할 때는 POST, PUT, DELETE 같은 메서드를 써야 하겠죠?

@app.route('/submit', methods=['GET', 'POST'])
def submit():
    if request.method == 'POST':
        return 'Form submitted!'
    return 'Submit your form.'

 

이렇게 methods 인자를 사용하면 GET과 POST를 모두 처리할 수 있어요.

사용자 입력을 받는 폼이나 API를 만들 때 필수적인 기능이에요!

1-3. 라우팅 우선순위와 404 처리

라우트가 여러 개 있을 경우, Flask는 위에서 아래로 읽으면서 먼저 일치하는 것을 실행해요.

그래서 더 구체적인 라우트를 먼저 정의하는 것이 좋아요.

또한 정의되지 않은 경로로 사용자가 접속하면 Flask는 기본적으로 404 Not Found 에러 페이지를 보여줘요.

이 페이지도 @app.errorhandler(404) 데코레이터로 커스터마이징할 수 있어요.

@app.errorhandler(404)
def not_found(e):
    return render_template('404.html'), 404

 

사용자 경험을 위한 작은 배려! 에러 페이지도 예쁘게 만들어두면 좋겠죠?

  • 동적 경로는 <타입:변수명> 형식으로 지정
  • methods로 다양한 HTTP 요청 대응
  • 라우트 순서가 중요! 더 구체적인 경로 먼저 정의

 

 

2. HTTP 요청과 응답 처리 📩

2-1. Request 객체 이해하기

Flask에서는 request 객체를 통해 클라이언트로부터 받은 다양한 데이터를 조회할 수 있어요.

이 객체는 flask 모듈에서 자동으로 제공되며, 전역에서 접근 가능합니다.

다음은 주요 속성들입니다:

속성 설명
request.args URL 쿼리스트링 (GET 방식)의 파라미터를 딕셔너리 형태로 반환
request.form 폼 데이터를 조회할 때 사용 (POST 방식)
request.get_json() JSON 형식의 본문 데이터를 파싱하여 반환 (API 제작 시 유용)

예시 코드

from flask import request

@app.route('/search')
def search():
    keyword = request.args.get('q')
    return f"검색어: {keyword}"

2-2. 응답 생성 및 상태코드

Flask에서는 반환값으로 문자열을 주면 자동으로 HTTP 응답이 만들어지지만,

Response 객체를 직접 생성하거나 jsonify를 활용해 JSON 형식으로 응답을 보낼 수도 있어요.

from flask import Response, jsonify

@app.route('/custom')
def custom_response():
    return Response("직접 만든 응답", status=201)

@app.route('/api/data')
def api_data():
    data = {"name": "Flask", "version": 2.0}
    return jsonify(data), 200

 

상태 코드 200(성공), 201(생성됨), 400(잘못된 요청), 404(페이지 없음), 500(서버 에러) 등은 직접 지정할 수 있어요.

2-3. 쿠키와 세션

사용자 상태를 유지하려면 쿠키세션을 사용해야 해요.

Flask에서는 request.cookies로 쿠키를 읽고, response.set_cookie로 저장할 수 있어요.

세션은 session 객체를 사용해 딕셔너리처럼 데이터를 저장할 수 있어요.

이를 통해 로그인 상태를 유지하거나, 특정 사용자에게 맞춤 정보를 제공할 수 있죠.

from flask import session

@app.route('/set_session')
def set_session():
    session['username'] = 'python_user'
    return '세션 저장 완료!'

@app.route('/get_session')
def get_session():
    return f"저장된 사용자: {session.get('username')}"

 

세션은 내부적으로 쿠키를 사용하긴 하지만, 암호화되어 안전하고 편리하게 데이터를 저장할 수 있어요.

단, 세션을 사용하려면 app.secret_key를 설정해줘야 한답니다.

 

 

3. 템플릿 렌더링과 Jinja2 🧩

3-1. Jinja2 기본 문법

Flask는 Jinja2라는 템플릿 엔진을 기본으로 사용합니다.

Python 코드를 HTML 안에 자연스럽게 녹여서 동적인 웹페이지를 만들 수 있게 해주죠!

 

기본 문법은 아래와 같아요:

  • {{ 변수 }} : 파이썬 변수 출력
  • {% if 조건 %}, {% for 요소 in 리스트 %} : 제어문

예시 코드 (템플릿)

<ul>
  {% for user in users %}
    <li>{{ user }}</li>
  {% endfor %}
</ul>

3-2. render_template 사용법

템플릿 파일은 Flask 프로젝트의 templates 폴더 안에 두어야 하고, 이를 불러오려면 render_template 함수를 사용합니다.

from flask import render_template

@app.route('/hello')
def hello():
    return render_template('hello.html', name='Flask')

 

이렇게 하면 templates/hello.html을 찾아서 {{ name }} 부분에 'Flask'를 출력하게 돼요.

 

 

3-3. 템플릿 상속과 레이아웃 구성

Jinja2는 템플릿 상속을 지원해서, 공통된 레이아웃을 base.html에 작성하고 다른 템플릿에서 상속받을 수 있어요.

예를 들어:


<body>
  <header><h1>My Site</h1></header>
  {% block content %}{% endblock %}
</body>


{% extends "base.html" %}
{% block content %}
  <p>Hello, {{ name }}!</p>
{% endblock %}

 

이 구조 덕분에 중복을 줄이고, 각 페이지에 필요한 콘텐츠만 작성하면 되니까 유지보수도 훨씬 쉬워지죠!

3-4. 템플릿에서 동적 콘텐츠 출력

템플릿은 단순히 정적인 HTML을 보여주는 게 아니라,

Python 쪽에서 넘긴 데이터를 받아서 동적으로 리스트를 출력하거나 조건 분기를 적용할 수도 있어요.

@app.route('/posts')
def post_list():
    posts = ['첫 번째 글', '두 번째 글', '세 번째 글']
    return render_template('posts.html', posts=posts)

 

템플릿(posts.html)에서는 아래처럼 반복문을 사용해서 출력할 수 있죠:

<ul>
  {% for post in posts %}
    <li>{{ post }}</li>
  {% endfor %}
</ul>

 

정말 마법 같죠?

Flask와 Jinja2만 있으면 동적 웹 페이지를 어렵지 않게 만들 수 있답니다 ✨

 

 

4. 정적 파일 제공 🎨

4-1. static 디렉토리의 역할

웹페이지가 동작하려면 CSS, 이미지, JavaScript 같은 정적 파일이 꼭 필요하죠.

Flask에서는 static/ 폴더를 통해 이 정적 리소스를 제공해요.

 

예를 들어

static/style.css라는 파일이 있다면,

템플릿에서 아래처럼 불러올 수 있어요:

<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

 

url_for('static', filename='파일명')은 Flask에서 정적 파일의 URL을 안전하게 생성해주는 방법이에요.

경로를 직접 쓰는 것보다 이 방식이 훨씬 안전하답니다.

4-2. 정적 파일 구성 예시

프로젝트 내 디렉토리 구성 예시는 아래와 같아요:

project/
│
├── app.py
├── static/
│   ├── style.css
│   └── logo.png
└── templates/
    └── index.html

 

템플릿 안에서 이 파일들을 다음과 같이 불러올 수 있어요:

<img src="{{ url_for('static', filename='logo.png') }}" alt="로고">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

4-3. 간단한 스타일링 실습

style.css를 만들어 아주 간단한 배경색과 폰트를 설정해볼게요.

/* static/style.css */
body {
  background-color: #f9f9f9;
  font-family: 'Noto Sans KR', sans-serif;
}
h1 {
  color: #1b6ca8;
}

 

그리고 템플릿에서 해당 CSS를 로딩하면 웹페이지에 기본 스타일이 적용돼요.

이렇게 하면 프로젝트에 디자인적인 생명이 불어넣어지죠!

TIP 💡

Bootstrap이나 Tailwind 같은 외부 CSS 프레임워크도 정적 파일로 함께 사용하거나 CDN 링크로 불러와서 템플릿에 간단히 적용할 수 있어요!

 

 

5. 라우트 및 템플릿 실습 페이지 만들기 🛠️

5-1. 여러 페이지 연결하기

Flask에서 여러 웹페이지를 만드는 방법은 정말 간단해요!

각 페이지마다 라우트템플릿을 하나씩 연결하면 끝입니다.

예를 들어 메인 페이지와 소개 페이지를 만들어 서로 링크로 연결해보죠.

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/about')
def about():
    return render_template('about.html')

 

템플릿에서는 url_for을 활용해서 내부 링크를 쉽게 만들 수 있어요 👇

<a href="{{ url_for('index') }}">홈으로</a>
<a href="{{ url_for('about') }}">소개 페이지</a>

5-2. 동적 데이터 출력 실습

이번에는 파이썬 리스트를 만들어 템플릿에 넘겨보고,

Jinja2의 반복문을 사용해 동적으로 내용을 출력해볼 거예요.

마치 실제 게시판처럼요!

@app.route('/posts')
def posts():
    post_list = [
        {'title': '첫 번째 글', 'author': '홍길동'},
        {'title': '두 번째 글', 'author': '이몽룡'},
        {'title': '세 번째 글', 'author': '성춘향'}
    ]
    return render_template('posts.html', posts=post_list)

 

posts.html에서는 이렇게 리스트를 테이블로 출력할 수 있어요:

<table border="1">
  <tr><th>제목</th><th>작성자</th></tr>
  {% for post in posts %}
    <tr>
      <td>{{ post.title }}</td>
      <td>{{ post.author }}</td>
    </tr>
  {% endfor %}
</table>

5-3. 실습 마무리 및 팁

이제 여러분은 라우팅을 설정하고, HTML 템플릿을 렌더링하고, 동적 데이터를 출력하는 전 과정을 경험해보셨어요.

이걸 바탕으로 나중에는 사용자 로그인, 댓글 작성, 데이터베이스 연동 같은 고급 기능도 훨씬 수월하게 이해할 수 있어요.

 

항상 시작은 작게, 그러나 제대로! 지금 만든 코드들도 훌륭한 출발점이 될 수 있어요.

  • 여러 라우트로 페이지 구성하기
  • Jinja2 반복문으로 리스트 출력하기
  • 정적 링크와 템플릿 상속으로 구조화하기

 

 

6. 폼 입력과 데이터 처리 실습 ✍️

6-1. HTML 폼 만들기

사용자의 입력을 서버에 전달하려면 이 필요하겠죠.

HTML에서는 <form> 태그를 사용하고, Flask는 이를 POST 방식으로 받아 처리할 수 있어요.

<form action="/contact" method="POST">
  이름: <input type="text" name="name"><br>
  메세지: <textarea name="message"></textarea><br>
  <input type="submit" value="전송">
</form>

6-2. POST 요청 처리하기

Flask에서는 request.form을 사용해서 사용자가 입력한 데이터를 받아올 수 있어요.

그리고 조건문으로 GET인지 POST인지 구분해서 처리하면 돼요!

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form['name']
        message = request.form['message']
        return render_template('result.html', name=name, message=message)
    return render_template('contact.html')

 

result.html에서는 이렇게 입력값을 출력할 수 있어요:

<p>{{ name }}님이 보내신 메세지입니다.</p>
<blockquote>{{ message }}</blockquote>

6-3. 폼 처리 요약과 유의점

  • GET 요청은 주로 폼을 보여줄 때 사용
  • POST 요청은 실제 입력 데이터를 서버로 보낼 때 사용
  • request.form을 통해 데이터를 추출하고 응답에 활용

지금은 단순히 입력값을 받아 출력하는 수준이지만,

나중엔 이 데이터를 DB에 저장하거나 이메일로 전송할 수도 있답니다!

실습 결과 요약 📝

기능 설명
폼 렌더링 GET 요청 시 contact.html 렌더링
데이터 수신 POST 요청 시 사용자의 입력값을 추출
결과 출력 result.html에서 입력값을 표시

 

마무리 ✨

이번 시간에는 Flask의 핵심 기능 중 하나인 라우팅요청/응답 처리,

그리고 템플릿 렌더링까지 웹 애플리케이션을 구성하는 기본 요소들을 차근차근 살펴봤어요.

단순히 URL을 연결하는 것에서 그치지 않고, 사용자의 요청을 읽고 응답을 생성하며, 템플릿을 통해 멋진 동적 페이지까지 만들어낸 경험은 정말 인상적이었을 거예요 😊

 

이제 여러분은 단순한 Flask 앱이 아니라, 실제 사용자와 상호작용할 수 있는 인터페이스 중심의 웹 서비스를 만들 수 있는 준비가 되셨습니다.

아직 데이터베이스나 사용자 인증 같은 내용은 남아있지만, 오늘 배운 내용을 기반으로 앞으로의 실습도 훨씬 수월하게 진행될 거예요. 😄

 

반응형