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 책을 참조하였습니다.
댓글
댓글 쓰기