로컬에서는 Flask로 실행하고, 배포용으로는 정적 HTML을 docs/에 생성할 수 있는 블로그 예제입니다.
- Flask + Jinja2 템플릿 기반
- Markdown 포스트 자동 로딩
- 검색, 태그 목록, 상세 페이지
- 게시글 CRUD 편집 기능 (웹 인터페이스에서 작성/수정/삭제)
- 프로필/사이드바 위젯
docs/에 정적 HTML 생성 후 GitHub Pages 업로드 가능
이 프로젝트는 Flask 백엔드 개발을 학습하기 위한 교육 자료로 제작되었습니다.
- Flask 라우팅 및 요청 처리
- 파일 I/O 및 Markdown 파싱
- HTML 템플릿 렌더링
- Form 데이터 처리
다음 함수들을 직접 구현해야 합니다. 각 함수의 TODO 주석을 참고하세요.
-
save_post()- 포스트를 마크다운 파일로 저장- 난이도: ⭐ 쉬움
- 핵심: 파일 쓰기, 딕셔너리 조작, 경로 처리
- 힌트:
Path.write_text(),datetime.now(),_build_front_matter()
-
delete_post()- 포스트 파일 삭제- 난이도: ⭐ 매우 쉬움
- 핵심: 파일 존재 여부 확인, 파일 삭제
- 힌트:
Path.exists(),Path.unlink()
-
get_post_raw()- 마크다운 원본 로드- 난이도: ⭐ 쉬움
- 핵심: 파일 읽기, 메타데이터 파싱
- 힌트:
Path.read_text(),_parse_front_matter()
-
admin_posts()- 관리 페이지 (포스트 목록)- 난이도: ⭐ 매우 쉬움
- 핵심: 함수 호출, 템플릿 렌더링
- 힌트:
load_posts(),render_template()
-
admin_create()- 새 포스트 작성- 난이도: ⭐⭐ 보통
- 핵심: GET/POST 처리, 폼 데이터 추출, 유효성 검사
- 힌트:
request.method,request.form.get(),save_post(),redirect()
-
admin_edit()- 포스트 편집- 난이도: ⭐⭐⭐ 어려움
- 핵심: 기존 데이터 로드, 수정된 데이터 저장, slug 변경 처리
- 힌트:
get_post_raw(),delete_post(),save_post(),abort(404)
-
admin_delete()- 포스트 삭제- 난이도: ⭐ 매우 쉬움
- 핵심: 삭제 함수 호출, 리다이렉트
- 힌트:
delete_post(),redirect()
-
파일 저장 함수 (content.py)
# 간단한 것부터 시작 delete_post() # 가장 간단함 get_post_raw() # 파일 읽기 연습 save_post() # 파일 쓰기와 메타데이터 조합
-
라우트 구현 (app.py)
# 기본부터 고급까지 admin_posts() # 기존 코드 사용 (로드만) admin_delete() # 파일 삭제만 admin_create() # 폼 처리 + 파일 저장 admin_edit() # 모든 것을 종합
# 1. 파이썬 실행
python app.py
# 2. 브라우저에서 접속
# 블로그: http://127.0.0.1:5000/
# 관리: http://127.0.0.1:5000/admin
# 3. 각 기능 테스트
# - 포스트 생성 후 목록에 나타나는지 확인
# - 포스트 수정 후 내용이 변경되었는지 확인
# - 포스트 삭제 후 목록에서 사라졌는지 확인
# - 파일 시스템에서 content/posts/ 폴더 확인Python 기본
Path객체: https://docs.python.org/3/library/pathlib.html- 파일 I/O: https://docs.python.org/3/library/io.html
Flask
- 라우팅: https://flask.palletsprojects.com/routing/
- 요청 처리: https://flask.palletsprojects.com/request-handling/
- 리다이렉트: https://flask.palletsprojects.com/api/#flask.redirect
Markdown
- 파싱:
_parse_front_matter()함수 참고 (이미 구현됨) - HTML 변환:
_markdown_to_html()함수 참고 (이미 구현됨)
이 블로그는 정답이 있는 과제가 아니라, 학생들의 아이디어를 얹어보는 실험 공간으로 쓰기 좋습니다. 아래 목록은 "반드시 해야 하는 과제"가 아니라, 시작점일 뿐입니다. 원하는 대로 합치고, 바꾸고, 더 멀리 확장해도 좋습니다.
- 카테고리 추가:
tags처럼category를 하나 더 두고 글을 분류하기 - 프로필 정보 변경:
content/site.json의 이름, 소개, SNS 링크 바꾸기 - 히어로 문구 수정: 메인 페이지 첫 화면의 문구와 버튼 바꾸기
- 색상 테마 변경:
static/css/style.css의:root변수값 바꾸기 - footer 문구 변경: 사이트 하단 저작권/안내 문구 수정하기
- 검색 기능 개선: 제목뿐 아니라 본문까지 검색하기
- 태그 필터 페이지: 특정 태그 글만 따로 보는 페이지 추가하기
- 미리보기 길이 조절: 홈 화면 카드에 본문 일부 미리보기 표시하기
- 초안(draft) 기능: 게시글에
draft: true를 넣으면 목록에서 숨기기 - 정렬 방식 선택: 최신순 / 오래된순 / 제목순 정렬 옵션 추가하기
- 페이지네이션: 글이 많아지면 페이지를 나눠 보여주기
- 이미지 업로드/삽입: 포스트 본문에 이미지 경로를 넣어 미디어 활용하기
- 댓글 기능: 로컬 파일 기반 또는 별도 저장소를 사용한 간단한 댓글 구현
- 좋아요/조회수: 글마다 숫자를 저장하고 화면에 표시하기
- RSS 피드 생성: 블로그 글 목록을 RSS XML로 내보내기
- 코드 하이라이트: Markdown 코드 블록에 구문 강조 적용하기
- 라이트/다크 테마 토글: 버튼으로 테마를 바꾸고 localStorage에 저장하기
학생들이 기능을 고를 때 아래 질문에 답해보면, 자기만의 방향을 잡기 좋습니다.
- 이 블로그가 무슨 블로그였으면 좋겠는가?
- 개발 기록 블로그, 취미 일기, 포트폴리오, 동아리 소식, 공부 노트 등
- 방문자가 들어왔을 때 첫 3초 안에 무엇을 느끼게 하고 싶은가?
- 깔끔함, 개성, 신뢰감, 재미, 전문성, 감성 등
- 글을 읽는 사람이 어떤 행동을 하게 만들고 싶은가?
- 다른 글도 읽기, 검색하기, 태그 탐색하기, 공유하기, 댓글 남기기 등
- 지금 있는 기능 중 무엇을 더 편하게 만들고 싶은가?
- 검색, 글 작성, 태그 보기, 모바일 화면, 다크모드 등
학생들은 아래 항목을 자기 스타일대로 바꿔도 됩니다.
- 사이트 제목과 소개 문구
- 프로필 사진, 이름, 역할, 소개글
- 메인 히어로 문구와 버튼 이름
- 카드 색상, 배경, 타이포그래피, 그림자
- 글 카드 구성 방식(짧게/길게/이미지 포함)
- 관리 페이지의 버튼 배치와 편집기 레이아웃
- 정적 내보내기 결과물의 구조와 파일명
- 내 블로그 정체성 만들기: 각자 다른 테마와 소개 문구로 완전히 다른 분위기 구현하기
- 콘텐츠 중심 블로그: 카드형이 아니라 잡지 스타일, 타임라인 스타일로 바꾸기
- 상호작용 강화: 검색, 필터, 즐겨찾기, 북마크, 공유 버튼 추가하기
- 개인 브랜딩: 프로필, 프로젝트, 연락처, 기술 스택 섹션을 추가해 포트폴리오처럼 만들기
- 커뮤니티 느낌: 댓글, 좋아요, 공지, 배너, 추천 글 같은 요소 넣기
- 기능을 크게 만들기보다 작게 하나씩 바꿔보는 것이 좋습니다.
- 먼저 "무슨 느낌의 블로그를 만들고 싶은지" 한 줄로 적고 시작하면 방향이 선명해집니다.
- 기능을 추가할 때는 보통 아래 파일을 함께 수정합니다.
- 데이터 처리:
blog_site/content.py - 화면 표시:
templates/ - 디자인:
static/css/style.css - 동작 로직:
blog_site/app.py
- 데이터 처리:
- 내가 만들고 싶은 블로그의 분위기를 먼저 정했는가?
- 학생이 직접 수정할 수 있는 기능을 하나 선택했는가?
- 어떤 파일을 수정해야 하는지 이해했는가?
- 기능 추가 후 로컬에서 확인했는가?
- 필요하면
export_site.py로 정적 HTML도 다시 생성했는가?
pip install -r requirements.txtpython app.py기본 접속 주소:
- 블로그:
http://127.0.0.1:5000/ - 관리 페이지:
http://127.0.0.1:5000/admin
http://127.0.0.1:5000/admin접속- "New Post" 클릭해서 새 글 작성
- Edit/Delete로 기존 글 수정/삭제
content/posts/에 .md 파일을 직접 추가해도 됩니다.
---
title: 새 글
slug: new-post
date: 2026-06-05
summary: 한 줄 요약
tags: flask, jinja2
---
# 본문
Markdown 내용 작성.python export_site.py생성 결과는 docs/ 폴더에 저장됩니다.
- 관리 페이지(
/admin,/admin/create등)는 정적 빌드에서 제외됩니다.
docs/폴더를 GitHub 저장소에 포함시킵니다.- GitHub Pages 설정에서 배포 소스를
main branch /docs로 지정합니다. python export_site.py를 다시 실행하면 정적 페이지가 갱신됩니다.
- 사이트 설정 및 프로필:
content/site.json - 템플릿:
templates/(기본, 관리자, 편집기 등) - 스타일:
static/css/style.css - 내보내기 로직:
export_site.py - 게시글 로직:
blog_site/content.py(TODO 주석 참고)