-
[5월 1주차-5/7]🧩 Django로 RESTful API 만들기 & 실시간 채팅 앱 구축 (Channels 활용)Why Not SW CAMP 5기/수업 기록 2025. 5. 7. 13:48
✅ 1. RESTful API란?
RESTful API는 웹에서 클라이언트와 서버가 HTTP를 통해 통신할 수 있도록 만든 규칙 기반 구조입니다.
GET, POST, PUT, DELETE 같은 HTTP 메서드로 자원을 주고받으며, 각 요청은 독립적이고 일관된 URL 구조를 가집니다.📌 핵심 개념 정리
- 리소스(Resource): /users/, /posts/3처럼 명사로 된 URL 사용
- HTTP 메서드:
- GET: 조회
- POST: 생성
- PUT / PATCH: 수정
- DELETE: 삭제
- 무상태성(Stateless): 요청은 서로 독립적이며, 서버는 이전 요청 상태를 기억하지 않음
- 표현(Representation): JSON 등을 통해 데이터 표현
- 일관된 URI 구조:
- /users → 전체 사용자
- /users/1/posts → 특정 사용자의 게시글
🛠 2. Django + DRF로 REST API 만들기
🔧 프로젝트 및 앱 생성
python -m venv env/rest .\env\Scripts\activate pip install django djangorestframework django-admin startproject rest cd rest python manage.py startapp restapp
settings.py 수정:
INSTALLED_APPS = [ ... 'rest_framework', 'restapp', ]
📄 모델 작성 (restapp/models.py)
from django.db import models from django.contrib.auth.models import User class Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) update_at = models.DateTimeField(auto_now=True) class Meta: ordering = ['-created_at'] def __str__(self): return self.title
📦 시리얼라이저 작성 (restapp/serializers.py)
from rest_framework import serializers from .models import Post class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = '__all__'
🧠 API View 작성 (restapp/views.py)
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .models import Post from .serializers import PostSerializer class PostListCreateAPIView(APIView): def get(self, request): queryset = Post.objects.all() serializer = PostSerializer(queryset, many=True) return Response(serializer.data) def post(self, request): serializer = PostSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
🌐 URL 설정
restapp/urls.py
from django.urls import path from .views import PostListCreateAPIView urlpatterns = [ path('restapp/', PostListCreateAPIView.as_view(), name='restapp-list-create'), ]
rest/urls.py
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('restapp.urls')), ]
🚀 마이그레이션 및 실행
python manage.py makemigrations python manage.py migrate python manage.py runserver
http://127.0.0.1:8000/api/restapp/ 로 접속해서 API 확인!
💬 3. Django Channels + WebSocket으로 채팅 앱 만들기
📦 의존성 설치
pip install channels channels_redis redis daphne
settings.py
INSTALLED_APPS = [ 'daphne', 'channels', 'chat', ... ] ASGI_APPLICATION = 'chatting.asgi.application' CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('127.0.0.1', 6379)], }, }, }
⚙️ asgi.py 설정
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from chat import routing as chat_routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatting.settings') django_asgi_app = get_asgi_application() application = ProtocolTypeRouter({ "http": django_asgi_app, "websocket": AuthMiddlewareStack( URLRouter( chat_routing.websocket_urlpatterns ) ), })
🧱 모델 (chat/models.py)
from django.db import models from django.contrib.auth.models import User class Room(models.Model): name = models.CharField(max_length=255, unique=True) def __str__(self): return self.name class Message(models.Model): room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name='messages') user = models.ForeignKey(User, on_delete=models.CASCADE) content = models.TextField() timestamp = models.DateTimeField(auto_now_add=True) class Meta: ordering = ('timestamp',) def __str__(self): return f'{self.user.username}: {self.content[:50]}...'
python manage.py makemigrations chat python manage.py migrate
🧠 consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer import json class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = f'chat_{self.room_name}' self.user = self.scope['user'] await self.channel_layer.group_add(self.room_group_name, self.channel_name) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard(self.room_group_name, self.channel_name) async def receive(self, text_data): data = json.loads(text_data) message = data['message'] await self.channel_layer.group_send(self.room_group_name, { 'type': 'chat_message', 'message': message, 'user': self.user.username if self.user.is_authenticated else 'Anonymous', 'timestamp': 'now' }) async def chat_message(self, event): await self.send(text_data=json.dumps({ 'message': event['message'], 'user': event['user'], 'timestamp': event['timestamp'] }))
🌐 routing.py
from django.urls import path from . import consumers websocket_urlpatterns = [ path('ws/chat/<str:room_name>/', consumers.ChatConsumer.as_asgi()), ]
💡 views.py (채팅방 접속용)
from django.shortcuts import render, get_object_or_404 from .models import Room def room(request, room_name): room_obj = get_object_or_404(Room, name=room_name) return render(request, 'chat/room.html', { 'room_name': room_name, 'room': room_obj, 'user': request.user })
💬 room.html
<!DOCTYPE html> <html> <head> <title>Chat Room: {{ room_name }}</title> </head> <body> <h1>Chat Room: {{ room_name }}</h1> <div id="chat-log"></div> <input id="chat-message-input" type="text"> <input id="chat-message-submit" type="button" value="Send"> {{ room_name|json_script:"room-name" }} {{ user.username|json_script:"user-name" }} <script> const roomName = JSON.parse(document.getElementById('room-name').textContent); const userName = JSON.parse(document.getElementById('user-name').textContent); const chatSocket = new WebSocket('ws://' + window.location.host + '/ws/chat/' + roomName + '/'); chatSocket.onmessage = function(e) { const data = JSON.parse(e.data); const message = data.message; const user = data.user; const timestamp = data.timestamp; const chatLog = document.querySelector('#chat-log'); chatLog.innerHTML += `<b>${user}</b>: ${message}<br>`; }; document.querySelector('#chat-message-submit').onclick = function(e) { const input = document.querySelector('#chat-message-input'); const message = input.value; chatSocket.send(JSON.stringify({'message': message})); input.value = ''; }; </script> </body> </html>
✅ 마무리
- Django로 RESTful API와 WebSocket 채팅을 모두 경험
- Channels + Redis로 실시간 처리도 가능하게 됨
- REST API → 기본 HTTP 처리,
WebSocket → 양방향 실시간 통신
'Why Not SW CAMP 5기 > 수업 기록' 카테고리의 다른 글
[5월 1주차-5/9]🌍 Streamlit으로 만드는 CO2 배출량 대시보드 (2) 2025.05.09 [5월 1주차-5/8]🎈 Python으로 웹 대시보드 만들기- Streamlit (1) 2025.05.08 [4월 5주차-4/29~30]🌐 Django로 나만의 로그인 + 이미지 북마크 웹사이트 만들기 (feat. 구글 소셜 로그인까지) (2) 2025.04.30 [4월 5주차-4/28~29]🎯 Django 블로그 프로젝트 (0) 2025.04.29 [4월 4주차-4/24]RubiBlog: Django + Amazon Lightsail 배포기 (0) 2025.04.24