26장: 웹 개발 심화

파이썬은 다양한 웹 개발 프레임워크를 제공하여 복잡한 웹 애플리케이션을 쉽게 구축할 수 있게 합니다. 이 장에서는 `Flask`와 `Django`를 사용한 웹 개발의 심화 내용을 다룹니다. 또한 RESTful API와 웹 소켓을 구현하는 방법도 소개합니다.


#### 26.1 Flask 심화


`Flask`는 소규모 프로젝트에 적합한 간단하고 유연한 웹 프레임워크입니다. 이 섹션에서는 `Flask`를 사용한 고급 웹 개발 기법을 다룹니다.


##### 26.1.1 블루프린트


블루프린트(Blueprint)는 `Flask` 애플리케이션을 모듈화하는 방법입니다.


```python

# users.py

from flask import Blueprint, render_template


users_bp = Blueprint('users', __name__, template_folder='templates')


@users_bp.route('/users')

def list_users():

    return render_template('users.html')


# app.py

from flask import Flask

from users import users_bp


app = Flask(__name__)

app.register_blueprint(users_bp)


if __name__ == '__main__':

    app.run(debug=True)

```


##### 26.1.2 데이터베이스 연결


`Flask-SQLAlchemy`를 사용하여 데이터베이스와 상호작용할 수 있습니다.


```sh

pip install flask-sqlalchemy

```


```python

from flask import Flask

from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'

db = SQLAlchemy(app)


class User(db.Model):

    id = db.Column(db.Integer, primary_key=True)

    name = db.Column(db.String(80), nullable=False)


@app.route('/add_user/<name>')

def add_user(name):

    user = User(name=name)

    db.session.add(user)

    db.session.commit()

    return f'User {name} added'


if __name__ == '__main__':

    db.create_all()

    app.run(debug=True)

```


##### 26.1.3 사용자 인증


`Flask-Login`을 사용하여 사용자 인증을 구현할 수 있습니다.


```sh

pip install flask-login

```


```python

from flask import Flask, render_template, redirect, url_for, request

from flask_sqlalchemy import SQLAlchemy

from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required


app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'

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

db = SQLAlchemy(app)

login_manager = LoginManager(app)


class User(UserMixin, db.Model):

    id = db.Column(db.Integer, primary_key=True)

    username = db.Column(db.String(80), nullable=False)

    password = db.Column(db.String(80), nullable=False)


@login_manager.user_loader

def load_user(user_id):

    return User.query.get(int(user_id))


@app.route('/login', methods=['GET', 'POST'])

def login():

    if request.method == 'POST':

        username = request.form['username']

        password = request.form['password']

        user = User.query.filter_by(username=username, password=password).first()

        if user:

            login_user(user)

            return redirect(url_for('dashboard'))

    return render_template('login.html')


@app.route('/dashboard')

@login_required

def dashboard():

    return 'Welcome to your dashboard!'


@app.route('/logout')

@login_required

def logout():

    logout_user()

    return redirect(url_for('login'))


if __name__ == '__main__':

    db.create_all()

    app.run(debug=True)

```


#### 26.2 Django 심화


`Django`는 강력하고 기능이 풍부한 웹 프레임워크로, 대규모 프로젝트에 적합합니다. 이 섹션에서는 `Django`를 사용한 고급 웹 개발 기법을 다룹니다.


##### 26.2.1 사용자 정의 모델 매니저


사용자 정의 모델 매니저를 사용하여 모델 쿼리를 커스터마이징할 수 있습니다.


```python

# models.py

from django.db import models


class CustomManager(models.Manager):

    def get_queryset(self):

        return super().get_queryset().filter(is_active=True)


class User(models.Model):

    name = models.CharField(max_length=100)

    is_active = models.BooleanField(default=True)


    objects = CustomManager()

    all_objects = models.Manager()

```


##### 26.2.2 신호


신호(Signals)를 사용하여 특정 이벤트에 대해 자동으로 작업을 수행할 수 있습니다.


```python

# models.py

from django.db.models.signals import post_save

from django.dispatch import receiver


class User(models.Model):

    name = models.CharField(max_length=100)


@receiver(post_save, sender=User)

def post_save_user(sender, instance, created, **kwargs):

    if created:

        print(f'New user created: {instance.name}')

```


##### 26.2.3 사용자 인증과 권한


`Django`의 내장 인증 시스템을 사용하여 사용자 인증과 권한을 관리할 수 있습니다.


```python

# views.py

from django.shortcuts import render, redirect

from django.contrib.auth import authenticate, login, logout

from django.contrib.auth.decorators import login_required


def user_login(request):

    if request.method == 'POST':

        username = request.POST['username']

        password = request.POST['password']

        user = authenticate(request, username=username, password=password)

        if user is not None:

            login(request, user)

            return redirect('dashboard')

    return render(request, 'login.html')


@login_required

def dashboard(request):

    return render(request, 'dashboard.html')


def user_logout(request):

    logout(request)

    return redirect('login')

```


#### 26.3 RESTful API


RESTful API는 웹 애플리케이션 간에 데이터를 주고받는 방법으로 널리 사용됩니다. `Flask`와 `Django REST framework`를 사용하여 RESTful API를 구현할 수 있습니다.


##### 26.3.1 Flask를 사용한 RESTful API


`Flask`와 `Flask-RESTful`을 사용하여 RESTful API를 구현할 수 있습니다.


```sh

pip install flask-restful

```


```python

from flask import Flask

from flask_restful import Resource, Api


app = Flask(__name__)

api = Api(app)


class HelloWorld(Resource):

    def get(self):

        return {'hello': 'world'}


api.add_resource(HelloWorld, '/')


if __name__ == '__main__':

    app.run(debug=True)

```


##### 26.3.2 Django REST framework를 사용한 RESTful API


`Django REST framework`는 Django에서 RESTful API를 쉽게 구현할 수 있게 해줍니다. 먼저 `djangorestframework`를 설치해야 합니다.


```sh

pip install djangorestframework

```


```python

# settings.py

INSTALLED_APPS = [

    ...

    'rest_framework',

]


# serializers.py

from rest_framework import serializers

from .models import User


class UserSerializer(serializers.ModelSerializer):

    class Meta:

        model = User

        fields = ['id', 'name']


# views.py

from rest_framework import generics

from .models import User

from .serializers import UserSerializer


class UserListCreate(generics.ListCreateAPIView):

    queryset = User.objects.all()

    serializer_class = UserSerializer


# urls.py

from django.urls import path

from .views import UserListCreate


urlpatterns = [

    path('users/', UserListCreate.as_view(), name='user-list-create'),

]

```


#### 26.4 웹 소켓


웹 소켓(WebSocket)은 실시간 양방향 통신을 가능하게 하는 프로토콜입니다. `Flask-SocketIO`와 `Django Channels`를 사용하여 웹 소켓을 구현할 수 있습니다.


##### 26.4.1 Flask-SocketIO


`Flask-SocketIO`를 사용하여 실시간 통신을 구현할 수 있습니다.


```sh

pip install flask-socketio

```


```python

from flask import Flask, render_template

from flask_socketio import SocketIO, send


app = Flask(__name__)

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

socketio = SocketIO(app)


@app.route('/')

def index():

    return render_template('index.html')


@socketio.on('message')

def handleMessage(msg):

    print(f'Message: {msg}')

    send(msg, broadcast=True)


if __name__ == '__main__':

    socketio.run(app, debug=True)

```


##### 26.4.2 Django Channels


`Django Channels`를 사용하여 실시간 통신을 구현할 수 있습니다.


```sh

pip install channels

```


```python

# settings.py

INSTALLED_APPS = [

    ...

    'channels',

]


ASGI_APPLICATION = 'myproject.asgi.application'


# asgi.py

import os

from django.core.asgi import get_asgi_application

from channels.routing import ProtocolTypeRouter, URLRouter

from channels.auth import AuthMiddlewareStack

from myapp import routing


os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')


application = ProtocolTypeRouter({

    "http": get_asgi_application(),

    "websocket": AuthMiddlewareStack(

        URLRouter(

            routing.websocket_urlpatterns

        )

    ),

})


# routing.py

from django.urls import path

from . import consumers


websocket_urlpatterns = [

    path('ws/chat/', consumers.Chat


Consumer.as_asgi()),

]


# consumers.py

import json

from channels.generic.websocket import WebsocketConsumer


class ChatConsumer(WebsocketConsumer):

    def connect(self):

        self.accept()


    def disconnect(self, close_code):

        pass


    def receive(self, text_data):

        text_data_json = json.loads(text_data)

        message = text_data_json['message']


        self.send(text_data=json.dumps({

            'message': message

        }))

```


이상으로, 파이썬을 사용한 웹 개발의 심화 내용을 다루었습니다. 웹 애플리케이션을 더 복잡하고 확장 가능하게 만들기 위해 이러한 고급 기능들을 활용해 보세요. 추가로 알고 싶은 내용이나 질문이 있으시면 댓글로 남겨주세요!


---


이 글의 내용은 GoalKicker.com의 Python Notes for Professionals 책을 참조하였습니다.

댓글