웹 서버 심화

  • 강의 슬라이드 다운로드: click me

  • 실습파일 (.zip) 다운로드: click me

학습 목표

  • Flask 기반 웹 서버를 MTV 패턴으로 구성하고 역할을 이해

  • 환경 설정(config.py)과 앱 초기화(server/__init__.py) 흐름 파악

  • SQLAlchemy 모델 정의와 폼 제출 → DB 저장 라우트 구현 연습

  • Jinja 템플릿으로 입력 폼을 작성하고 렌더링하는 방법 학습

  • run_server.py로 애플리케이션을 실행해 동작을 확인

MTV 패턴

MTV 패턴은 웹 애플리케이션을 구조적으로 나누어 개발하기 위한 아키텍처 패턴으로, Model, Template, View 세 가지 역할로 구성된다.

일반적인 MVC(Model–View–Controller) 패턴과 유사하지만, 웹 프레임워크(특히 Django)에서는 MTV라는 용어를 자주 사용한다.


구성 요소

Model (모델)

  • 데이터와 관련된 모든 것을 담당한다.

  • 데이터베이스 테이블 구조를 정의한다.

  • 레코드를 생성, 조회, 수정, 삭제(CRUD)하는 로직을 포함한다.

  • 예:

    • User, Post, Product 등 도메인 객체

    • Django의 models.py, Flask + SQLAlchemy의 모델 클래스


Template (템플릿)

  • 사용자에게 보여지는 화면(View, UI)을 담당한다.

  • HTML 기반의 템플릿 파일로, 동적으로 데이터를 표시한다.

  • 템플릿 엔진(예: Jinja2, Django Template Language)을 사용하여 변수 출력, 반복, 조건문 등을 처리한다.

  • 예:

    • templates/index.html

    • templates/user_detail.html


View (뷰)

  • 사용자의 요청(Request)을 받고, 응답(Response)을 생성하는 역할을 한다.

  • 비즈니스 로직의 진입 지점으로, 다음과 같은 작업을 수행한다.

    • 요청 파라미터 처리

    • 필요한 Model 호출 (데이터 조회/저장 등)

    • 적절한 Template에 데이터 전달

  • 예:

    • Django의 views.py의 함수/클래스 기반 뷰

    • Flask의 라우트 함수(@app.route 또는 Blueprint의 뷰 함수)


HTML 간단 소개

HTML은 태그(tag)를 이용해 문서 구조를 표현하는 마크업 언어이다. HTML 문서는 트리 구조(Tree Structure)로 구성되며, 가장 상위 루트는 <html> 태그이다.


HTML 문서 구조

<!DOCTYPE html>
<html>
    <head>
        ...
    </head>
    <body>
        ...
    </body>
</html>
구조 설명
<!DOCTYPE html> HTML5 문서임을 선언
<html> HTML 문서의 최상위 루트 노드
<head> 문서 설정 정보(메타데이터) 포함
<body> 실제 화면에 보여지는 콘텐츠 영역

트리 구조 표현 (DOM 구조)

html
├── head
│   ├── meta
│   ├── title
│   ├── link
│   └── script
└── body
    ├── header
    ├── nav
    ├── section
    ├── article
    ├── div
    ├── footer
    ├── script
        ...

head 영역에 들어가는 주요 태그

태그 설명
<meta> 문자 인코딩, SEO, 모바일 설정 등
<title> 웹페이지 제목 (브라우저 탭에 표시됨)
<link> CSS 파일 연결
<script> JavaScript 연결
<style> 내부 CSS 작성

body 영역에서 자주 사용하는 태그

태그 의미
<h1> ~ <h6> 제목(Heading)
<p> 문단(paragraph)
<a> 링크(anchor)
<img> 이미지
<ul> / <ol> / <li> 리스트
<div> 블록 단위 영역
<span> 인라인 영역
<form> 사용자 입력 양식
<input> 데이터 입력 필드
<label> 입력 필드 설명 텍스트,
for-id 연결로 포커스 이동·접근성 향상
<button> 버튼
<table> 표 구조

프로젝트 구조

project/
│
├─ config.py                # 시스템 설정
├─ server/
│      ├─ __init__.py       # 서버 초기화      ├─ models.py         # DB 정의/설정      ├─ views.py          # 라우트 정의      └─ templates/        # 템플릿 저장소           └─ index.html   # 랜딩 페이지
└─ run_server.py            # 서버 구동(시작)

시스템 설정

  • config.py:
# project/config.py
import os

BASE_DIR = os.path.abspath(os.path.dirname(__file__))

class Config:
    SECRET_KEY = "dev-secret-key"
    SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(BASE_DIR, 'hello.db')}"
    SQLALCHEMY_TRACK_MODIFICATIONS = False

서버 초기화

  • __init__.py: Flask 앱을 생성하고 SQLAlchemy DB, Blueprint 뷰를 등록하는 초기화 함수 정의
# project/server/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Config

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)

    db.init_app(app)

    from . import models
    from .views import main
    app.register_blueprint(main)

    with app.app_context():
        db.create_all()

    return app

DB 정의/설정

  • models.py: SQLAlchemy를 사용해 User 테이블의 구조(id, username, email)와 동작을 정의하는 DB 모델
# project/server/models.py
from . import db

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

    def __repr__(self):
        return f"<User {self.username}>"

라우트 정의

  • views.py: GET 요청으로 폼을 표시하고, POST 요청으로 사용자 정보를 DB에 저장한 후 결과를 반환하는 라우트 함수들 정의
python# project/server/views.py
from flask import Blueprint, render_template, request, redirect, url_for
from . import db
from .models import User

main = Blueprint("main", __name__)

@main.route("/", methods=["GET"])
def index():
    return render_template("index.html")

@main.route("/submit", methods=["POST"])
def submit():
    username = request.form.get("username")
    email = request.form.get("email")

    new_user = User(username=username, email=email)
    db.session.add(new_user)
    db.session.commit()

    return redirect(url_for("main.result", username=username, email=email))

@main.route("/result", methods=["GET"])
def result():
    username = request.args.get("username")
    email = request.args.get("email")
    return f"User {username} with email {email} has been added to the database."

랜딩 페이지 작성

  • templates/index.html: username과 email 입력 필드를 가진 HTML 폼으로, submit 버튼 클릭 시 POST 요청을 views의 submit 라우트로 전송
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Form</title>
</head>
<body>
    <h1>Enter your details</h1>
    <form action="{{ url_for('main.submit') }}" method="POST">
        <label for="username">Name:</label><br>
        <input type="text" id="username" name="username" required><br>
        <label for="email">Email:</label><br>
        <input type="email" id="email" name="email" required><br><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

서버 구동 모듈

  • run_server.py: create_app() 함수로 Flask 애플리케이션을 생성하고 포트 8080에서 debug 모드로 서버를 실행
# project/run_server.py
from server import create_app

app = create_app()

if __name__ == "__main__":
    app.run(port=8080, debug=True)

웹 서버 실행

run_server.py 파일을 실행하면 Flask 애플리케이션이 시작되어 http://localhost:8080에서 웹 서버가 실행된다.

python project/run_server.py

# 또는

cd project
python run_server.py

⬆️목차이동