반응형

Flask 확장으로 게시판 프로젝트 고도화하기

단순한 게시판 웹앱에서 한 단계 더!
Flask 확장 기능으로 편리성과 보안성을 동시에 잡아보세요.

 

 

안녕하세요, Flask 웹 개발을 함께 배워가고 있는 여러분!

오늘은 우리가 지금까지 만들어온 게시판 프로젝트를 더 깔끔하고, 더 안전하게, 더 고급스럽게 만드는 방법을 소개하려 해요.

특히 Flask-WTFFlask-Login 같은 인기 확장 기능을 다루면서, 개발 효율성과 유지 보수성까지 한층 업그레이드할 수 있도록 실습 중심으로 진행할 거예요.

이제 여러분의 게시판이 진짜 '서비스다운' 모습으로 거듭날 준비를 해볼까요? 😎

 

1. Flask-WTF로 폼 처리 개선하기 ✍️

지금까지 우리는 게시글 작성 폼을 HTML로 직접 만들어 사용해왔죠.

그런데 이 방식은 반복 코드가 많고, 검증 처리도 직접 구현해야 해서 번거롭습니다.

그래서 Flask-WTF라는 확장 모듈을 사용하면 폼 관련 작업을 훨씬 더 간단하고 안전하게 처리할 수 있어요.

📌 Flask-WTF란?

Flask-WTF는 WTForms라는 폼 유효성 검사 라이브러리를 Flask에서 쉽게 사용할 수 있도록 도와주는 확장입니다.

입력 필드에 대한 클래스 기반 정의, 자동 CSRF 보호, 내장된 다양한 Validator를 지원하여 폼 처리를 안전하고 일관되게 만들어 줘요.

✔ 설치 및 설정

pip install flask-wtf

설치 후에는 Flask 설정에 SECRET_KEY를 추가해서 CSRF 보호 기능을 켜줘야 합니다.

app.config['SECRET_KEY'] = 'mysecretkey'

🛠 PostForm 클래스 만들기

게시글 작성에 필요한 폼 클래스를 다음과 같이 정의할 수 있어요.

from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField
from wtforms.validators import DataRequired, Length

class PostForm(FlaskForm):
    title = StringField('제목', validators=[DataRequired(), Length(max=100)])
    content = TextAreaField('내용', validators=[DataRequired()])

✅ Flask-WTF의 장점은?

  • HTML 입력 폼을 Python 코드로 간결하게 표현 가능
  • Validator로 유효성 검사를 쉽게 추가할 수 있음
  • CSRF 보호가 자동으로 적용되어 보안성 향상

폼 유효성 검사를 별도로 구현하지 않아도 되고, 입력값이 잘못됐을 때의 메시지도 자동 출력되기 때문에 사용자 경험도 좋아져요.

 

사실 이걸 한 번 적용해보고 나면, 앞으로는 순수 HTML 폼으로 되돌아가기 싫어질지도 몰라요. 🤭

 

 

2. 템플릿에서의 폼 렌더링과 에러 메시지 출력 💡

Flask-WTF를 도입했다면, 템플릿에서도 이제 폼 필드를 직접 출력하는 대신 WTForms의 필드 객체를 사용해 보다 동적으로 표현할 수 있어요.

게다가 오류 메시지를 자동으로 표시할 수 있어서 사용자 친화적인 폼을 아주 쉽게 구현할 수 있답니다.

🧩 기본 템플릿 구조

HTML 코드가 이렇게 바뀝니다.

form.csrf_token은 꼭 포함해야 해요. CSRF 보호를 위한 필수 요소니까요.

 


<form method="POST">{{ form.csrf_token }}
<div>
	{{ form.title.label }}
   	{{ form.title(size=40) }}
    {% for error in form.title.errors %}
       	<span style="color: red;">{{ error }}</span> 
    {% endfor %}
</div>
<div>
	{{ form.content.label }} 
    {{ form.content(rows=10, cols=50) }} 
    {% for error in form.content.errors %} 
    	<span style="color: red;">{{ error }}</span> 
    {% endfor %}
</div>
<button type="submit">작성하기</button>
</form>

기존에 우리가 직접 HTML 인풋을 만들던 방식보다 훨씬 간결하고, 유지보수도 쉬워지죠.

그리고 폼 오류 발생 시 메시지를 바로 보여줄 수 있어서 사용자 입장에서도 훨씬 직관적인 사용 경험을 제공할 수 있어요.

🔍 뷰 함수도 간단하게!

이제 뷰 함수에서는 request.form을 직접 다루는 대신 폼 인스턴스를 생성하고 검증만 하면 됩니다.

@app.route('/board/new', methods=['GET', 'POST'])
def create_post():
    form = PostForm()
    if form.validate_on_submit():
        post = Post(title=form.title.data, content=form.content.data)
        db.session.add(post)
        db.session.commit()
        return redirect(url_for('board.list'))
    return render_template('board_form.html', form=form)

이 코드는 Flask-WTF의 validate_on_submit() 메서드 덕분에 훨씬 간단하고 안전해졌어요.

그리고 form 인스턴스를 템플릿에 넘기기만 하면 끝!

🔧 에러 발생 시 확인 포인트

  • CSRF 토큰을 템플릿에 넣었는지 확인
  • FlaskForm을 상속받았는지 확인
  • SECRET_KEY 설정이 누락되지 않았는지 확인

폼 유효성 검사를 제대로 처리하면 실수로 잘못된 데이터를 넣는 경우도 줄어들고, 사용자도 시스템을 더 신뢰하게 됩니다.

개발자 입장에서도 디버깅 시간이 줄어든다는 거, 진짜 큰 장점이에요! 🙌

 

 

3. Flask-Login으로 사용자 인증 개념 익히기 🔐

이제 게시판 프로젝트가 어느 정도 완성 단계에 이르렀다면, 사용자 인증을 고려할 시점이에요.

왜냐하면, 글을 작성하거나 수정, 삭제할 수 있는 권한을 아무에게나 줄 수는 없으니까요.

바로 여기서 Flask-Login이라는 강력한 확장 기능이 등장합니다.

🔑 Flask-Login 소개

Flask-Login은 로그인 상태를 세션에 저장하고, 인증이 필요한 페이지에 접근할 때 로그인 여부를 자동으로 체크해주는 편리한 인증 도구예요.

별도의 UI는 없고, 세션 관리, 현재 사용자 확인, 데코레이터를 이용한 보호 기능에 충실합니다.

🚀 핵심 기능

  • login_user()로 로그인 처리
  • logout_user()로 로그아웃 처리
  • login_required 데코레이터로 특정 라우트 보호

그리고 현재 로그인한 사용자를 확인할 때는 current_user 객체를 사용해요.

User 모델에는 몇 가지 필수 메서드와 속성을 추가해줘야 정상 동작합니다.

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(200), nullable=False)

Flask-Login은 UserMixin 클래스를 상속하면 필요한 메서드들을 자동으로 구현해주기 때문에 아주 편리해요.

물론, 비밀번호는 반드시 해시처리를 해야겠죠?

📝 적용 시나리오

  1. User 모델을 설계하고, 로그인/회원가입 폼을 만들기
  2. 로그인 상태를 세션으로 유지하고, 필요 시 인증 검사하기
  3. 게시글 작성, 수정, 삭제 뷰에 @login_required 추가

이번 강의에서는 시간이 부족하니 직접 구현은 생략하고, 인증 시스템의 구조와 적용 포인트만 개념적으로 익히면 충분합니다.

더 자세히 배우고 싶다면 Flask-Login 공식 문서Flask 튜토리얼의 인증 챕터를 꼭 참고해보세요.

 

중요한 건, 인증은 '기능 추가' 그 이상의 가치가 있다는 거예요.

서비스의 신뢰도와 확장성을 동시에 끌어올려주는 필수 요소니까요. 😊

 

 

4. 게시판 기능 마무리 및 UI 개선 🎨

게시판 기능이 얼추 완성되었죠?

이제는 사용자 경험(UX)을 고려한 마무리 작업을 해볼 차례예요.

그동안 구현했던 CRUD 기능들이 자연스럽게 연결되도록 테스트하고, UI 개선까지 살짝 손대보는 거죠.

💅 Bootstrap으로 UI 다듬기 (선택사항)

Bootstrap은 CSS 프레임워크 중에서도 가장 보편적으로 사용되는 도구예요.

특히 테이블, 폼, 버튼 등 기본 UI 요소들을 빠르게 스타일링할 수 있어서 초보자도 쉽게 적용할 수 있습니다.


  • <table class="table table-hover"> 형태로 목록 페이지 개선
  • form-control, btn btn-primary 등으로 폼 및 버튼 꾸미기

🔁 기능 흐름 점검

다음 시나리오를 한 번 따라가 보세요.

실제 사용자가 프로젝트를 어떻게 사용할지를 기준으로 흐름을 확인하는 거예요.

  1. 새 글 작성 → 제출
  2. 목록 페이지에서 작성한 글 확인
  3. 상세 페이지에서 글 내용 조회
  4. 글 수정 → 다시 확인
  5. 글 삭제 → 목록에서 사라졌는지 확인

🧼 자잘한 버그 및 UX 개선

  • 글이 없을 때 ‘게시글이 없습니다’ 문구 표시
  • 너무 긴 제목은 text-overflow: ellipsis로 잘라내기
  • 삭제 확인 버튼에 JavaScript confirm() 사용

이런 자잘한 디테일들이 모이면, 사용자들은 “오, 이 서비스 되게 잘 만들었네?”라는 느낌을 받게 되죠.

기술력은 기본, 디테일이 완성도를 결정한다는 말, 잊지 마세요. 😉

 

 

5. 전체 기능 점검과 코드 리팩토링 ⚙️

이제 우리가 만든 게시판 프로젝트의 전체 기능을 점검하고, 코드 구조를 한번 깔끔하게 정리해볼 차례입니다.

지금까지는 각 기능을 하나씩 배우고 붙이는 데 집중했다면,

이 단계에서는 전반적인 동작 흐름코드 일관성에 신경 써야 해요.

🧪 시나리오 테스트

실제 사용자가 게시판을 사용할 상황을 가정해서 테스트해보세요.

아래와 같은 항목을 체크리스트로 삼는 것도 좋습니다.

  • 새 글 작성 후 목록 반영 확인
  • 글 상세 페이지에서 제목과 내용 확인
  • 글 수정 및 삭제 후 정상 반영 여부 확인

🧹 코드 정리 (리팩토링)

플라스크 앱의 구조가 깔끔하게 정리되어야 유지보수가 쉬워집니다.

Blueprint로 분리한 파일들을 다음처럼 정리해보세요.

/app
├── __init__.py         # 앱 생성 및 구성
├── models.py           # DB 모델
├── routes.py           # 라우터
├── forms.py            # Flask-WTF 폼 클래스
├── templates/          # HTML 템플릿들
└── static/             # 정적 파일(CSS, JS 등)

이 구조는 규모가 커질 때 유지보수를 훨씬 수월하게 해줘요.

추후 Flask 애플리케이션 팩토리 패턴을 적용하면 더 모듈화된 구조도 가능합니다.

🌐 API 엔드포인트 점검

RESTful API로 구현된 엔드포인트들이 잘 작동하는지도 꼭 확인해봅시다.

프론트엔드뿐 아니라 외부 앱에서도 이 API를 쓸 수 있게 설계한 것이니까요.

  • GET /api/posts → 게시글 목록 반환
  • POST /api/posts → 새 글 등록

만약 CORS 문제로 외부 클라이언트에서 API 호출이 안 된다면,

flask-cors 확장을 설치하고 아래처럼 설정해 주세요.

from flask_cors import CORS
CORS(app)

이제 여러분의 게시판 프로젝트는 기능, 구조, 디자인, API까지 모두 균형 잡힌 상태예요! 🎯

정말 멋지게 완성됐습니다.

 

 

6. 확장 기능과 보안 적용에 대한 심화 토론 🤔

이번 단계는 약간 자유로운 분위기에서 마무리해보는 시간이에요.

지금까지 우리가 만든 게시판을 바탕으로 앞으로 확장할 수 있는 방향이나 고급 기능에 대한 아이디어를 나눠볼게요.

💬 이런 기능도 추가해보면 어떨까요?

  • 댓글 기능: 각 게시글에 댓글을 달 수 있도록 DB와 템플릿을 확장
  • 검색 기능: 제목 또는 본문에서 키워드를 기반으로 검색
  • 페이지네이션: 게시글이 많아졌을 때 페이지 나누기
  • 파일 업로드: 이미지를 첨부하거나 업로드된 파일 관리 기능

🛡 Flask 보안 확장 소개

사용자 인증을 조금 더 제대로 구현하고 싶다면 Flask-Security 또는 Flask-User 같은 확장도 고려할 수 있어요.

회원 가입, 로그인, 비밀번호 리셋, 이메일 인증 등 흔히 필요한 기능들이 모두 포함되어 있습니다.

🙋‍♀️ 수업 마무리 및 토론 주제

이제 이 프로젝트를 마무리하면서,

다음과 같은 질문을 던져볼 수 있어요:

  • Flask 프로젝트에서 가장 어려웠던 점은 무엇인가요?
  • Flask를 활용한 다른 웹 서비스 아이디어가 있을까요?
  • 확장 기능 중 가장 유용했던 것은 무엇이었나요?

 

이런 질문들을 주제로 서로의 경험을 나누고, 앞으로 어떤 방향으로 발전시킬 수 있을지도 생각해보면 정말 좋은 학습 마무리가 될 거예요.

여기까지 따라오신 여러분, 진심으로 멋졌습니다! 👏👏👏

반응형
반응형

파이썬 REST API 개발 및 활용 완벽 가이드

웹 브라우저 말고도,
모바일 앱이나 외부 시스템에서도 우리 Flask 게시판을 사용할 수 있다면 얼마나 좋을까요?
그 해답은 바로 REST API입니다!

 

 

안녕하세요! 😊

Flask 기반 웹 게시판 프로젝트 여섯째 날입니다.

오늘은 웹 프론트엔드만이 아닌, 외부 클라이언트에서도 사용할 수 있는 REST API 개발을 함께 배워보려고 해요.

예를 들어,

우리가 만든 게시판 기능을 모바일 앱이나 다른 백엔드 서비스에서도 활용하고 싶다면 어떻게 해야 할까요?

그 해답은 바로 Flask를 이용한 RESTful API 구축이에요.

이번 시간에는 REST의 기본 개념부터 시작해 Flask에서 JSON 데이터를 주고받는 API 만들기,

그리고 게시판 CRUD API를 직접 구현해보는 실습까지 차근차근 진행할게요.

어렵지 않아요. 이미 우리가 만든 게시판 로직을 바탕으로 하니까 훨씬 수월하게 느껴질 거예요.

그럼 시작해볼까요?

 

1. RESTful API란 무엇인가요? 🤔

요즘 웹 개발에서 REST API라는 말을 자주 들어보셨을 거예요.

그만큼 백엔드 서비스를 설계할 때 꼭 알아야 할 중요한 개념이죠.

하지만 처음 들었을 땐 뭔가 복잡하고 어려워 보일 수 있어요.

그래서 이번에는 RESTful API의 핵심 개념을 쉽고 간단하게 정리해드릴게요!

REST의 핵심 개념은?

  • Resource(자원): REST는 웹의 모든 것을 자원으로 봅니다. 예를 들어 게시글(post), 사용자(user) 같은 것이죠.
  • URI(Uniform Resource Identifier): 자원을 식별하는 주소입니다. 예: /api/posts
  • HTTP 메서드: 자원에 대한 동작을 정의합니다. 예: GET(조회), POST(생성), PUT/PATCH(수정), DELETE(삭제)

REST API는 왜 이렇게 인기가 많을까요?

REST API가 널리 쓰이는 이유는 간단해요.

간결하고 직관적인 구조 덕분이죠.

복잡한 규약 없이 HTTP의 기본 동작만으로 다양한 클라이언트와 쉽게 통신할 수 있으니까요.

또한, REST API는 다음과 같은 특징들을 가지고 있어요:

  1. 🎯 Stateless(무상태성): 각 요청은 독립적이며, 서버는 이전 요청의 상태를 저장하지 않아요.
  2. 🔄 Cacheable: 응답은 캐싱이 가능하므로 성능을 높일 수 있어요.
  3. 🧩 Uniform Interface: 표준화된 인터페이스 덕분에 다양한 플랫폼에서 사용할 수 있어요.

RESTful API 설계시 고려사항은? 🧐

RESTful하게 API를 설계하기 위해 지켜야 할 몇 가지 규칙이 있어요.

특히 초보자들이 자주 놓치는 부분들을 짚어볼게요.

  • URL은 복수형 명사로: 예를 들어 게시글이면 /api/posts와 같이 작성하는 것이 좋습니다.
  • HTTP 상태 코드 정확히 사용: 예를 들어, 성공은 200, 생성은 201, 오류는 400 또는 404 등으로 클라이언트에게 명확히 알려줘야 해요.
  • JSON 응답은 일관성 있게: 예를 들어 항상 {"id": 1, "title": "...", "content": "..."}와 같은 형식 유지

REST API는 단순히 엔드포인트만 만든다고 되는 게 아니라,

일관성과 예측 가능성을 고려해 설계해야 클라이언트가 편하게 쓸 수 있어요.

이게 바로 진짜 백엔드 개발자의 센스겠죠? 😉

 

 

2. Flask에서 REST API 만들기 🔧

자, 이제 본격적으로 Flask로 REST API를 만들어볼까요?

사실 Flask에서는 별도의 라이브러리 없이도 API를 쉽게 만들 수 있어요.

jsonify() 함수와 request.get_json() 메서드만 잘 활용하면 되거든요.

기본 API 예제

가장 기본적인 API는 이렇습니다.

“/api/hello”에 GET 요청을 보내면 JSON 형식으로 인사 메시지를 돌려주는 간단한 코드예요.

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/api/hello", methods=["GET"])
def hello_api():
    return jsonify(message="안녕하세요! 여기는 Flask REST API입니다.")

 

이렇게 간단한 코드만으로도 API가 완성돼요.

응답은 자동으로 Content-Type: application/json을 포함하므로 별도 설정도 필요 없답니다.

POST 요청 처리 - 클라이언트로부터 JSON 받기

POST 요청은 클라이언트가 서버에 데이터를 보낼 때 사용합니다.

아래처럼 request.get_json()으로 JSON 데이터를 받아 처리할 수 있어요.

from flask import request

@app.route("/api/echo", methods=["POST"])
def echo_api():
    data = request.get_json()
    name = data.get("name", "익명")
    return jsonify(message=f"{name}님, 안녕하세요!")

 

  • request.get_json(): JSON 데이터를 받아서 Python dict로 변환해줘요.
  • jsonify(): dict를 JSON으로 변환해서 응답해줍니다.

 

💡 확장 라이브러리는 쓸까 말까?

Flask는 기본 기능만으로도 API 작성이 가능하지만, 더 복잡한 구조나 반복을 줄이려면 Flask-RESTful 같은 확장을 쓸 수도 있어요.

하지만 지금은 기초 개념을 제대로 익히는 것이 중요하므로, 확장 없이 직접 구현해볼게요.

 

즉, JSON 처리에 필요한 최소한의 도구만으로도 강력한 API를 만들 수 있다는 점!

Flask의 가장 큰 매력이자 초보자에게 추천하는 이유이기도 해요.

 

 

3. JSON 응답 및 요청 처리 방식 📦

REST API에서 데이터를 주고받을 때 가장 흔히 사용하는 형식이 바로 JSON입니다.

Flask에서는 JSON 처리가 매우 간단하면서도 직관적이에요.

이번엔 JSON 응답을 어떻게 만들고, 클라이언트의 JSON 요청 데이터를 어떻게 처리하는지를 정리해볼게요.

1️⃣ JSON 응답 만들기

HTML을 반환하던 일반 웹 뷰와 달리,

API에서는 Python의 딕셔너리 데이터를 JSON 문자열로 변환해서 반환합니다.

Flask에서는 jsonify()를 사용하면 딕셔너리를 자동으로 JSON 형식으로 바꿔주고,

Content-Typeapplication/json으로 지정해줍니다.

from flask import jsonify

@app.route("/api/greet")
def greet():
    return jsonify({
        "status": "success",
        "message": "API가 정상 작동 중입니다."
    })
  • jsonify()는 자동으로 application/json MIME 타입과 200 OK 상태 코드를 설정합니다.

2️⃣ 클라이언트 JSON 요청 처리하기

클라이언트가 보내는 JSON 데이터를 받으려면 request.get_json() 메서드를 사용합니다.

이때 Content-Typeapplication/json으로 설정되어 있어야 해요.

from flask import request

@app.route("/api/submit", methods=["POST"])
def submit_data():
    data = request.get_json()
    name = data.get("name")
    age = data.get("age")
    if not name or not age:
        return jsonify(error="Missing fields"), 400
    return jsonify(message=f"{name}님({age}세), 데이터가 잘 수신되었습니다.")

 

get_json()을 통해 클라이언트의 JSON 요청을 dict로 파싱하고, 데이터 유효성 검사까지 함께 처리할 수 있어요.

3️⃣ 잘못된 요청 처리하기

API는 언제나 올바르지 않은 요청을 고려해야 합니다.

예를 들어

JSON 필드가 빠졌거나 잘못된 값이 들어오면, 클라이언트에게 명확한 메시지와 함께 400 Bad Request를 반환해야 하죠.

 

이런 식으로 API의 응답 일관성을 유지하는 것이 사용자 경험을 높이는 핵심 포인트입니다!

🔓 참고: CORS(Cross-Origin Resource Sharing)

프론트엔드가 다른 도메인(예: React 앱)에서 API를 호출할 경우 CORS 문제가 발생할 수 있어요.

이럴 땐 Flask-CORS 확장을 사용하면 아주 쉽게 해결할 수 있습니다.

# 설치
pip install flask-cors

# 사용 예
from flask_cors import CORS
app = Flask(__name__)
CORS(app)

 

 

4. 게시판 CRUD API 설계 및 구현 📝

이제 본격적으로 게시판 기능을 REST API 형태로 구현해볼 차례입니다.

이전까지는 HTML 페이지를 렌더링해 사용자에게 보여주는 방식이었다면,

이번에는 데이터를 JSON으로 주고받는 API 방식으로 확장합니다.

같은 기능이지만 'API형 백엔드'로 구현한다는 점에서 의미가 커요!

📌 API 엔드포인트 설계

Method URL 설명
POST /api/posts 게시글 생성
GET /api/posts 게시글 목록 조회
GET /api/posts/<id> 게시글 상세 조회
PUT /api/posts/<id> 게시글 수정
DELETE /api/posts/<id> 게시글 삭제

🔨 주요 기능별 구현 예제

1. 게시글 생성 - POST /api/posts

@app.route("/api/posts", methods=["POST"])
def create_post():
    data = request.get_json()
    title = data.get("title")
    content = data.get("content")
    if not title or not content:
        return jsonify(error="필수 입력값 누락"), 400
    new_post = Post(title=title, content=content)
    db.session.add(new_post)
    db.session.commit()
    return jsonify(post_id=new_post.id), 201

2. 게시글 목록 - GET /api/posts

@app.route("/api/posts", methods=["GET"])
def get_posts():
    posts = Post.query.order_by(Post.id.desc()).all()
    result = [post.to_dict() for post in posts]
    return jsonify(posts=result)

 

to_dict()는 모델 클래스에 미리 정의해두어야 합니다.

예: return {"id": self.id, "title": self.title, ...}

3. 게시글 상세조회 - GET /api/posts/<id>

@app.route("/api/posts/<int:post_id>", methods=["GET"])
def get_post(post_id):
    post = Post.query.get(post_id)
    if not post:
        return jsonify(error="존재하지 않는 게시글입니다."), 404
    return jsonify(post=post.to_dict())

4. 게시글 수정 - PUT /api/posts/<id>

@app.route("/api/posts/<int:post_id>", methods=["PUT"])
def update_post(post_id):
    post = Post.query.get(post_id)
    if not post:
        return jsonify(error="해당 게시글 없음"), 404
    data = request.get_json()
    post.title = data.get("title", post.title)
    post.content = data.get("content", post.content)
    db.session.commit()
    return jsonify(message="수정 완료", post=post.to_dict())

5. 게시글 삭제 - DELETE /api/posts/<id>

@app.route("/api/posts/<int:post_id>", methods=["DELETE"])
def delete_post(post_id):
    post = Post.query.get(post_id)
    if not post:
        return jsonify(error="해당 게시글 없음"), 404
    db.session.delete(post)
    db.session.commit()
    return jsonify(message="삭제 완료")

 

 

5. 실습: API 테스트와 사용 예시 🧪

API를 만들었으면 이제는 잘 작동하는지 테스트해봐야겠죠?

우리가 만든 REST API는 브라우저에서는 GET 요청 정도만 직접 확인할 수 있어요.

하지만 POST, PUT, DELETE 같은 요청은 curl이나 Postman 같은 도구로 테스트하는 게 일반적입니다.

🖥 curl 명령어로 API 테스트

  • GET 요청 - 게시글 목록 확인:
    curl -X GET http://localhost:5000/api/posts
  •  
  • POST 요청 - 새 게시글 생성:
    curl -X POST -H "Content-Type: application/json" -d '{"title":"첫 글", "content":"안녕하세요"}' http://localhost:5000/api/posts

🧪 Postman 사용 팁

Postman은 GUI 기반의 API 테스트 도구예요.

HTTP 메서드 선택, 요청 바디 JSON 입력, 응답 확인을 아주 편리하게 할 수 있습니다.

  1. Postman 실행 후 새 요청(Request) 생성
  2. Method: POST, URL: http://localhost:5000/api/posts
  3. Body 탭 → raw → JSON 선택 후 아래 내용 입력: 
  4.  
  5. { "title": "Postman 테스트", "content": "이건 Postman에서 보낸 글이에요." }
  6. Send 버튼 클릭 → 응답 확인!

✅ 예외 케이스 테스트하기

  • 존재하지 않는 게시글을 조회:
    GET /api/posts/99999 → 404 응답 확인
  •  
  • 필수 필드 누락 POST 요청 보내기 → 400 Bad Request 응답 확인

테스트를 반복하면서 우리 API가 얼마나 잘 짜여져 있는지 실감하게 되실 거예요.

오류 메시지도 일관성 있게 만들었다면 더더욱 멋지죠! 😉

 

 

6. 다양한 클라이언트와의 연동 시나리오 📱

지금까지 우리는 Flask 기반 게시판 API를 설계하고 구현하고, 테스트까지 마쳤어요.

이제는 다양한 클라이언트에서 이 API를 어떻게 활용할 수 있을지에 대해 살펴보는 시간입니다.

단순히 웹 브라우저뿐 아니라 모바일 앱, 프론트엔드 자바스크립트, 다른 백엔드 서비스 등과 연동되는 시나리오를 떠올려볼 수 있어요.

🧩 JavaScript에서 AJAX로 API 호출

가장 흔한 연동 방식은 웹 페이지에서 자바스크립트를 이용해 AJAX 방식으로 API를 호출하는 거예요.

예를 들어, HTML 페이지에서 아래처럼 Javascript의 fetch API를 사용할 수 있죠.

fetch("/api/posts")
  .then(response => response.json())
  .then(data => {
    console.log("게시글 목록:", data.posts);
  });

 

이렇게 하면 서버에서 JSON으로 반환한 게시글 목록을 자바스크립트에서 받아와 자유롭게 화면에 뿌릴 수 있어요.

📱 Flutter, React Native 같은 모바일 앱에서 연동

모바일 앱도 마찬가지예요.

백엔드에서 제공한 REST API를 HTTP 통신 모듈 (예: Flutter의 http 패키지, React Native의 axios)로 호출하면 앱에서도 동일하게 게시글을 CRUD할 수 있답니다.

  • Flutter에서는 http.post(), http.get()으로 JSON 데이터를 보내고 받아요.
  • React Native에서는 axios.post(), axios.get() 방식으로 쉽게 연동 가능해요.

🔗 다른 백엔드 시스템과의 연동

우리가 만든 Flask API는 마이크로서비스 구조에서도 활용할 수 있어요.

예를 들어,

사용자 인증은 Django가 담당하고, 게시판 기능은 Flask가 담당하는 식으로 서비스별 역할을 분리해서 통신하는 구조를 만들 수도 있어요.

🚀 실전 팁

  1. API 응답 형식은 항상 일관되게 유지하세요. (예: {"status": "success", "data": ...})
  2. 클라이언트가 다양한 환경에서 호출하는 만큼, CORS 설정은 반드시 고려해야 해요.
  3. API 문서화도 중요합니다! Swagger UI 또는 Postman Collection 등 활용해보세요.

 

이제 우리가 만든 Flask 백엔드는 웹, 앱, 서버 어디서든 활용 가능한 멋진 API 서비스가 되었어요.

여기까지 잘 따라오셨다면 이미 여러분은 초보 탈출 성공! 🎉

 

 

마무리 ✨

이번 여섯째 날 학습에서는 우리가 만든 게시판 웹 애플리케이션을 RESTful API로 확장하는 방법을 익혔습니다.

단순히 기능을 구현하는 것에서 한 걸음 더 나아가, 다양한 클라이언트와 연동 가능한 백엔드 서비스로 발전시키는 데 성공했어요.

REST API의 핵심 개념부터 Flask에서의 실제 구현, JSON 데이터 처리 방식, 그리고 Postman과 curl을 통한 실전 테스트까지 모든 과정을 실습하며 직접 체험해보셨을 텐데요, 어떠셨나요?

좀 더 현업 백엔드 개발자처럼 느껴지지 않으셨나요?

 

이제 여러분의 Flask 웹 서비스는 단지 브라우저에서만 동작하는 게 아니라, 앱, JS 프론트, 외부 시스템 등 어디에서든 자유롭게 사용할 수 있는 API 플랫폼이 된 거예요.

다음 시간에는 이 API를 어떻게 응용할 수 있을지, 또 성능 향상이나 인증 같은 고급 기능도 배워보면 좋겠죠?

 

혹시 아직 익숙하지 않은 부분이 있다면, 실습한 코드를 천천히 다시 보면서 정리해보세요.

반복이 최고의 선생님이니까요 😊

다음 단계에서 또 만나요!

반응형
반응형

파이썬과 Flask로 만드는 게시판 CRUD 완벽 가이드 💻🛠️

게시글을 웹에서 직접 작성하고 수정하고 삭제까지?
Flask와 SQLAlchemy만 있으면 가능합니다!
이 글 하나면 게시판 CRUD 구현은 완전 정복할 수 있어요.

 

 

안녕하세요, 여러분 😊

오늘은 Flask 웹 애플리케이션에서 가장 많이 사용되는 기능 중 하나인 CRUD(Create, Read, Update, Delete)를 직접 구현해볼 거예요.

단순히 이론 설명에서 그치는 게 아니라, 실제 웹 브라우저에서 게시글을 작성하고 목록을 보고, 수정하거나 삭제하는 완전한 게시판 시스템을 만들 거예요.

이 과정을 통해 Flask와 ORM(SQLAlchemy)의 활용 방법을 보다 실제적인 방식으로 배워보게 될 거예요.

기초부터 차근차근, 코드 한 줄 한 줄 이해하며 따라올 수 있게 구성했으니, 초보자도 걱정 말고 끝까지 함께 해봐요! 😉

 

1. 게시글 작성 기능 구현 (Create 기능) 📝

웹 게시판에서 가장 먼저 구현할 기능은 게시글 작성입니다.

사용자가 직접 제목과 내용을 입력하고 저장 버튼을 누르면, 해당 내용이 데이터베이스에 저장되고 목록이나 상세 페이지로 이동하게 만들 거예요.

우선 기본적인 흐름을 코드와 함께 살펴볼게요.

① 글 작성 폼 구현

`/board/new` 경로로 GET 요청 시 사용자에게 제목과 내용 입력란을 보여주는 HTML 폼을 렌더링합니다.

아래는 템플릿 예시입니다:

<form method="POST">
  <label>제목</label><br>
  <input type="text" name="title"><br>
  <label>내용</label><br>
  <textarea name="content"></textarea><br>
  <button type="submit">작성하기</button>
</form>

 

CSRF 방지와 보안은 이후 단계에서 `Flask-WTF` 같은 라이브러리를 통해 보완할 예정입니다.

지금은 기본적인 기능 흐름을 먼저 구현해보는 데 집중할게요!

② POST 요청 처리 및 DB 저장

사용자가 작성한 제목과 내용을 받아 `Post` 모델을 통해 DB에 저장합니다.

아래는 Flask 라우트 코드 예시예요:

@app.route('/board/new', methods=['GET', 'POST'])
def create_post():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']

        if not title or not content:
            flash('제목과 내용을 모두 입력해주세요.')
            return redirect(url_for('create_post'))

        post = Post(title=title, content=content)
        db.session.add(post)
        db.session.commit()

        flash('게시글이 작성되었습니다.')
        return redirect(url_for('post_detail', post_id=post.id))

    return render_template('create_post.html')

③ 피드백과 리다이렉트

작성 후에는 목록 페이지 또는 상세 페이지로 이동하며 flash를 통해 사용자에게 피드백 메시지를 전달할 수 있습니다.

템플릿에서 아래와 같이 메시지를 출력할 수 있어요:

{% with messages = get_flashed_messages() %}
  {% if messages %}
    <ul>
    {% for message in messages %}
      <li>{{ message }}</li>
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}

🧪 실습 포인트

  • 제목 또는 내용을 비워서 제출했을 때 적절히 에러 처리가 되는지 확인해보세요.
  • 글 작성 후 DB에 제대로 저장되었는지 SQLAlchemy로 직접 쿼리하거나 목록 페이지에서 확인해보세요.
  • 작성 후 이동된 페이지에서 flash 메시지가 출력되는지 확인해보세요.

여기까지 구현하면 웹을 통해 실제로 글을 작성하고, 그것이 DB에 저장되는 전체 흐름을 직접 체험해볼 수 있어요.

다음은 작성된 글들을 조회해보는 기능, 목록 페이지로 넘어가볼게요!

 

 

2. 게시글 목록 조회 페이지 구현 (Read - 목록) 📋

게시판의 중심이 되는 페이지는 바로 목록 페이지입니다.

작성된 게시글들을 사용자에게 보여주는 역할을 하며, 각 게시글의 제목을 클릭하면 상세 페이지로 이동할 수 있어야 해요.

오늘은 이 목록 페이지를 Flask와 SQLAlchemy로 어떻게 구성할 수 있는지 하나씩 살펴보겠습니다.

① 목록 라우트 구현

/board 경로에서 모든 게시글을 조회할 수 있도록 라우트를 구현합니다.

작성일자를 기준으로 내림차순 정렬해 가장 최신 글이 위로 오도록 할 거예요.

@app.route('/board')
def post_list():
    posts = Post.query.order_by(Post.created_at.desc()).all()
    return render_template('post_list.html', posts=posts)

② 템플릿에서 게시글 목록 출력

게시글 데이터를 HTML에서 반복문을 통해 출력합니다.

게시글 제목을 클릭하면 상세 페이지로 이동하도록 링크를 걸어주세요.

<h2>게시글 목록</h2>
<ul>
  {% for post in posts %}
    <li>
      <a href="{{ url_for('post_detail', post_id=post.id) }}">{{ post.title }}</a>
      ({{ post.created_at.strftime('%Y-%m-%d %H:%M') }})
    </li>
  {% else %}
    <li>작성된 게시글이 없습니다.</li>
  {% endfor %}
</ul>

 

작성일이 보이도록 strftime을 활용해 날짜 포맷을 지정하는 것도 사용자 편의에 도움이 돼요.

③ (선택) 페이지네이션 기능 소개

글이 많아졌을 경우 모든 글을 한 페이지에 보여주는 것은 비효율적이에요.

이럴 땐 페이지네이션을 도입할 수 있습니다.

Flask-SQLAlchemy에서는 아래와 같이 페이지당 몇 개의 게시글을 보여줄지 설정할 수 있어요:

@app.route('/board')
def post_list():
    page = request.args.get('page', 1, type=int)
    posts = Post.query.order_by(Post.created_at.desc()).paginate(page=page, per_page=10)
    return render_template('post_list.html', posts=posts.items, pagination=posts)

 

실습에서는 구현하지 않아도 되지만, 프로젝트가 커질 경우 꼭 필요한 기능이에요.

Flask-Paginate 확장도 한 번 찾아보세요!

🧪 실습 포인트

  • 게시글 여러 개를 작성한 뒤, 최신 순으로 잘 정렬되는지 확인해보세요.
  • 게시글 제목을 클릭했을 때 해당 글의 상세 페이지로 잘 이동되는지 확인해보세요.
  • 아무 글도 없을 때 ‘게시글이 없습니다’ 문구가 표시되는지도 테스트해보세요.

이제 목록 페이지도 완성되었네요!

다음은 하나의 게시글을 눌렀을 때 나오는 상세 보기와 수정 기능을 구현해볼 차례입니다. 💪

 

 

3. 게시글 상세 보기 및 수정 기능 구현 (Read/Update) ✏️

게시글 목록에서 사용자가 특정 게시글을 클릭했을 때, 그 게시글의 내용을 보여주는 상세 보기 페이지와, 이후 수정할 수 있는 기능까지 구현해볼 거예요.

이 단계에서는 동적 라우팅, 데이터 조회, 그리고 POST 기반 수정 처리를 중심으로 배워보겠습니다.

① 게시글 상세 보기 페이지 구현

사용자가 게시글 제목을 클릭하면 /board/<post_id> 경로로 이동하도록 구현합니다.

이때 post_id를 기준으로 해당 게시글을 데이터베이스에서 조회해 보여줍니다.

@app.route('/board/<int:post_id>')
def post_detail(post_id):
    post = Post.query.get_or_404(post_id)
    return render_template('post_detail.html', post=post)

 

get_or_404()는 ID에 해당하는 데이터가 없을 경우 자동으로 404 에러를 반환해주기 때문에 안전한 처리 방식입니다.

② 수정 폼 페이지 구현

게시글 상세 페이지에서 ‘수정’ 버튼을 누르면 /board/<post_id>/edit 경로로 이동합니다.

이 경로에서는 기존 게시글 데이터를 폼의 초기값으로 미리 넣어 보여줍니다.

@app.route('/board/<int:post_id>/edit', methods=['GET', 'POST'])
def edit_post(post_id):
    post = Post.query.get_or_404(post_id)
    if request.method == 'POST':
        post.title = request.form['title']
        post.content = request.form['content']

        if not post.title or not post.content:
            flash('빈 칸 없이 입력해주세요.')
            return redirect(url_for('edit_post', post_id=post.id))

        db.session.commit()
        flash('게시글이 수정되었습니다.')
        return redirect(url_for('post_detail', post_id=post.id))

    return render_template('edit_post.html', post=post)

 

POST 요청 시 사용자가 입력한 값으로 기존 객체의 속성을 업데이트하고, db.session.commit()으로 저장합니다.

③ 수정 폼 템플릿 예시

<form method="POST">
  <label>제목</label><br>
  <input type="text" name="title" value="{{ post.title }}"><br>
  <label>내용</label><br>
  <textarea name="content">{{ post.content }}</textarea><br>
  <button type="submit">수정하기</button>
</form>

🧪 실습 포인트

  • 존재하지 않는 게시글 ID로 상세 페이지나 수정 페이지에 접근했을 때 404 오류가 잘 출력되는지 확인해보세요.
  • 수정 후 변경 사항이 목록 페이지나 상세 페이지에 즉시 반영되는지 확인해보세요.
  • 빈 입력값에 대한 처리와 사용자 피드백 메시지가 적절히 작동하는지 체크해보세요.

게시글 수정까지 완료했으니, 이제 남은 마지막 핵심 기능은 삭제입니다!

다음 단계에서는 게시글 삭제 처리 및 후속 처리까지 깔끔하게 구현해볼게요.

 

 

4. 게시글 삭제 기능 구현 (Delete) 🗑️

이제 게시글을 삭제하는 기능을 구현해볼 차례예요.

사용자 인터페이스에서 삭제 버튼을 클릭하면 해당 게시글이 실제로 데이터베이스에서 제거되고, 목록 페이지로 되돌아가게 만들 거예요.

삭제 전 확인 메시지를 띄우는 방법도 함께 알아봅시다.

① 삭제 버튼 추가하기

게시글 상세 페이지나 수정 페이지에서 삭제 버튼을 추가해 사용자가 클릭할 수 있도록 합니다.

아래는 HTML 폼을 사용한 간단한 예시예요:

<form method="POST" action="{{ url_for('delete_post', post_id=post.id) }}" 
      onsubmit="return confirm('정말 삭제하시겠습니까?');">
  <button type="submit">삭제하기</button>
</form>

 

자바스크립트의 confirm() 함수로 간단한 삭제 확인창도 띄워줍니다.

이렇게 하면 실수로 삭제하는 것을 방지할 수 있어요.

② Flask 라우트에서 삭제 처리

삭제 처리는 POST 방식으로 요청을 받아 처리하는 것이 일반적입니다.

아래는 Flask에서 삭제를 처리하는 라우트 예시입니다.

@app.route('/board/<int:post_id>/delete', methods=['POST'])
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    db.session.delete(post)
    db.session.commit()
    flash('게시글이 삭제되었습니다.')
    return redirect(url_for('post_list'))

 

get_or_404()를 통해 유효하지 않은 접근은 방지하고, 삭제 후에는 목록 페이지로 리다이렉트하며 플래시 메시지로 피드백을 줍니다.

③ 삭제 후 상태 확인

삭제가 완료되면 목록 페이지에서 해당 글이 사라져야 하고,

삭제된 게시글의 상세 주소로 접근할 경우 404 오류가 발생해야 해요.

이를 통해 삭제가 확실히 이루어졌는지 확인할 수 있습니다.

🧪 실습 포인트

  • 게시글 삭제 시 confirm 창이 잘 뜨는지 확인해보세요.
  • 삭제 후 목록 페이지에서 해당 글이 사라지는지 확인해보세요.
  • 삭제된 게시글 URL에 다시 접근했을 때 404 페이지가 나오는지도 꼭 확인해보세요.

이제 CRUD의 마지막 조각까지 완성되었습니다!

다음 단계에서는 전체 흐름을 다시 정리하고, CRUD를 어떻게 확장할 수 있을지에 대한 인사이트도 함께 나눠볼게요. 😊

 

 

5. CRUD 전체 사이클 정리 및 테스트 💡

지금까지 우리는 Flask와 SQLAlchemy를 활용해 게시판 CRUD 기능을 하나하나 구현해봤어요.

작성(Create), 조회(Read), 수정(Update), 삭제(Delete)까지 모든 사이클을 직접 경험하면서 웹 애플리케이션의 기본기를 탄탄하게 익혔습니다.

이 섹션에서는 전체 흐름을 다시 정리해보고, 실습 시 꼭 확인해야 할 테스트 항목들도 체크해볼게요.

① CRUD 사이클 요약 정리

기능 라우팅 설명
작성 (Create) /board/new 폼을 통해 게시글 생성, DB에 저장
조회 (Read - 목록) /board 모든 게시글을 리스트로 조회
조회 (Read - 상세) /board/<id> 단일 게시글을 ID로 조회
수정 (Update) /board/<id>/edit 기존 글을 수정하여 업데이트
삭제 (Delete) /board/<id>/delete 해당 게시글을 DB에서 삭제

② 전체 기능 테스트 체크리스트 ✅

  • 글 작성 시 제목과 내용이 비어 있으면 경고 메시지가 표시되는가?
  • 목록에서 최신 글이 가장 위에 오는가?
  • 상세 페이지에서 제목, 내용, 작성 시간이 제대로 보이는가?
  • 수정 시 기존 내용이 폼에 미리 채워지고, 수정 후 정상 반영되는가?
  • 삭제 후 목록에서 글이 사라지고, 삭제된 글 URL 접근 시 404가 나오는가?

③ 다음 단계 미리 보기 👀

CRUD 기능은 웹 애플리케이션의 핵심 기초라고 할 수 있어요.

이후에는 이 기능들을 REST API 형태로 제공하거나, JavaScript를 활용해 비동기로 처리하는 등 다양한 확장으로 이어질 수 있어요. 예를 들어:

  • 게시판을 API 형태로 만들어 React, Vue 같은 프론트엔드 프레임워크와 연동하기
  • JWT 로그인 기능과 결합해 작성자 인증/권한 부여 기능 추가하기
  • 댓글 기능, 파일 첨부 기능 등 게시판 고도화

이번 CRUD 구현이 단순한 끝이 아니라, 앞으로 나아갈 가능성의 출발점이라는 걸 꼭 기억해 주세요!

 

 

6. 마무리 및 다음 단계 안내 🚀

여기까지 따라오신 여러분 정말 수고 많으셨습니다! 👏

Flask와 SQLAlchemy를 사용한 게시판 CRUD 기능 구현을 하나하나 직접 해보며, 웹 애플리케이션 개발의 핵심 흐름을 완전히 익히셨을 거예요.

처음에는 생소했던 라우팅, 폼 데이터 처리, 데이터베이스 모델, 커밋과 쿼리 등 다양한 개념이 이제는 자연스럽게 느껴지실 겁니다.

이 CRUD 구현 경험은 이후의 모든 웹 개발 여정에 있어서 든든한 뼈대가 되어줄 거예요.

 

이번 실습을 통해 익힌 기술은 단순한 기능 구현을 넘어서, 실제 서비스를 만들고 유지보수하는 데에도 큰 도움이 됩니다.

 

그리고 여기서 끝이 아니에요!

다음 단계에서는 이 CRUD 기능들을 RESTful API로 전환하고, 프론트엔드와 연결하거나, 인증 기능을 넣는 방법도 배울 수 있어요.

웹 개발자로서 한 단계 더 도약할 수 있는 기반이 다져진 거죠. 😎

 

꼭 한 번 CRUD 기능을 자신만의 프로젝트에 적용해보세요.

예를 들어,

  • 나만의 블로그 만들기
  • 간단한 TODO 앱이나 일기장 만들기
  • Flask와 React를 연동한 게시판 프로젝트 도전하기

앞으로도 꾸준히 연습하고 발전해 나가면, 어떤 웹 서비스도 직접 만들 수 있게 될 거예요.

우리는 이제 시작입니다! 😄

반응형

+ Recent posts