본문 바로가기

PYTHON-BACK

#파이썬 29일차_게시판 만들기1

728x90

Django REST Framework + React.js 게시판 만들기

 

1. 기능 구성


1.1 회원 관련 기능

 

  • 회원 프로필 관리(닉네임, 관심사, 프로필 사진 등)
  • 회원 가입 기능
  • 로그인 기능
  • 프로필 수정하기 기능

1.2 게시글 관련기능

  • 게시글 생성
  • 게시글 1개 가져오기
  • 게시글 목록 가져오기(가져오는 개수 제한하기)
  • 게시글 수정하기
  • 게시글 삭제하기
  • 게시글 좋아요 기능
  • 게시글 필터링(좋아요 누른 글/내가 작성한 글)
  • 게시글 각 기능마다 권한 설정

1.3 댓글 관련 기능

 
  • 댓글 생성
  • 댓글 1개 가져오기
  • 댓글 목록 가져오기
  • 댓글 수정하기
  • 댓글 삭제하기
  • 게시글을 가져올 때 댓글도 가져오게 만들기

 


나만의 추가 기능
 
1.4 알림 관련 기능
 
  • 새로운 알림 기능 : 회원이 좋아요를 받거나 댓글을 받았을 때, 알림을 통해 알려주기.
  • 알림 관리 기능 : 알림 읽음 처리, 알림 삭제 기능
  • 푸시 알림 기능 : 사용자에게 푸시 알림으로 주요 알림 전송 (예: 댓글, 좋아요, 새로운 팔로워 등).

1.5 팔로우/팔로워 기능

  • 팔로우 기능 : 특정 회원을 팔로우하여 그 회원의 게시글과 활동을 피드에서 쉽게 확인할 수 있게 하기
  • 팔로워 목록 보기 : 나를 팔로우한 사람들의 목록 보기
  • 팔로잉 목록 보기 : 내가 팔로우한 사람들의 목록 보기

1.6 메시지/채팅 관련 기능

  • 1 대 1 채팅 기능 : 회원 간의 개인 메시지 주고받기
  • 채팅 알림 기능 : 새로운 메시지 오면 알림을 통해 알려주기
  • 채팅 기록 관리 기능 : 채팅 기록 보기 및 삭제하기

1.7  북마크 / 저장 기능

  • 게시글 저장 기능 : 나중에 다시 보고싶은 게시글 저장해두기
  • 저장한 게시글 목록 보기 : 저장한 게시글들 따로 모아서 몰 수 있는 페이지

1.8 검색 기능

  • 게시글 검색 기능 : 특정 키워드로 게시글 검색하기
  • 회원 검색 기능 : 특정 회원을 검색해서 프로필 및 게시글 보기

1.9 게시글 및 댓글 관리 기능

  • 게시글 / 댓글 신고 기능 : 부적절한 게시글 또는 댓글 신고하기
  • 게시글 / 댓글 차단 기능 : 특정 사용자 게시글이나 댓글을 차단하여 보이지 않게 하기
  • 자동 필터링 및 모니터링 기능 : 욕설이나 스팸성 내용 포함된 게시글이나 댓글을 자동으로 감시하고 차단하는 기능

2. Project Setting

python -m venv bbs
cd bbs
./Scripts/activate
pip install django djangorestframework
django-admin startproject board .
# board/settings.py

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
]

TIME_ZONE = 'Asia/Seoul'

 

3. 모델 구성

3.1 User 모델

 
  • Django 기본 User 모델
    • 회원관리: 서비스를 위한 가장 기본적인 기능
    • User: Django Framework에서 기본 제공하는 모델의 하나
      • 회원관리를 위하여 User 모델을 새롭게 만들어도 되지만 현재 시점에서는 새로운 User 모델이 큰 의미가 없으므로 Django의 User 모델을 사용함
      • django.contrib.auth.models 안에 정의되어 있음
      • django.contrib.auth: 인증 기능을 위해 Django Framework가 미리 만들어둔 모듈
      • settings.py에서 기본으로 등록되어 있음
  • Django 기본 User 모델의 대표적인 필드
    • username: 문자열
      • 흔히 아는 ID가 들어가는 필드
      • ID인만큼 다른 사용자와 겹치면 안됨
      • 필수 항목
    • first_name: 문자열
      • 영문 이름에서 사용되는 이름의 개념
      • 선택 항목
    • last_name: 문자열
      • 영문 이름에서 사용되는 성씨의 개념
      • 선택 항목
    • email: 문자열
      • 회원 이메일 주소
      • 선택 항목
    • password: 문자열
      • 비밀번호
      • 필수 항목
      • 실제로 입력한 비밀번호 문자열을 그대로 저장하지 않고 해시값을 저장함
        • Django에서 비밀번호를 안전하게 보관하는 해시 알고리즘 사용(공식문서 참고할 것)
    • 그외 기타 필드들

4. 회원관리 구현

4.1 회원 인증의 개념

  • 회원 인증 개념 (1): ID/PW를 그대로 담아 보내기 
    • 가장 기본적인 인증 방법
    • Django는 보안을 위하여 회원의 비밀번호를 해시값으로 저장하고 있지만
    • 클라이언트의 입장에서는 그냥 비밀번호를 적어서 보내는 것일 뿐임
    • 인증이 필요할 때마다 ID/PW를 전송해야 하며 중간에서 탈취당할 위험이 높음
    • 보안이 매우 취약한 상태

 

 

  • 회원 인증 개념 (2): 세션 & 쿠키의 사용
    • 세션(Session): 서버쪽에 저장하는 정보
    • 쿠키(Cookies): 클라이언트의 자체적인 저장소
      • 쿠키는 데이터로 구성되긴 하지만 데이터라기보다는 데이터를 저장하는 임시저장소와 같은 역할을 수행함
    • 한 번 로그인을 수행한 후, 로그인 정보를 이용하여 세션에서 발급하는 세션 ID를 보냄으로써 인증을 대체함
    • 클라이언트에서는 세션 ID를 쿠키 저장소에 저장한 후 인증 요청이 있을때마다 세션 ID를 꺼내서 HTTP 헤더에 넣고 전송함
    • 인증이 필요할 때마다 ID/PW를 전송할 필요가 없으므로 정보의 탈취 위험이 줄어들지만 세션 ID를 탈취당할 위험은 여전히 존재함

  • 회원 인증 개념 (3): 토큰 & JWT
    • 세션 & 쿠키 방식과 비슷함
    • 회원 가입 시 서버는 유저에 매칭되는 토큰을 생성하여 클라이언트에 전달하고 클라이언트는 인증 요청 시마다 해당 토큰을 HTTP 헤더에 넣어서 전송함
    • 토큰에는 사용자의 정보가 포함되어 있으므로 서버는 해당 정보를 이용하여 인증을 수행함
    • 토큰은 암호화 방식이 적용되어 있으므로 전송 데이터 패킷을 중간에서 탈취당하더라도 정보가 노출될 가능성은 낮음
    • 암호화에 사용되는 키: settings.py에 등록되어 있는 SECRET_KEY
    • 그러나 토큰 자체를 탈취하여 사용자인척 하는 위험은 여전히 존재함
      • 해결책: 토큰의 유효기간 설정

    • JWT (JSON WEB Token)
      • 사용자 인증을 위해 사용하는 Open Standard(RFC 7519)
      • JSON 포맷을 이용하여 Self-Contained 방식으로 사용자에 대한 정보를 저장하는 Claim 기반의 WEB 토큰
      • 기본 컨셉
        • IdP (Identity Provider)가 사용자의 정보를 담은 내용에 서명하는 것을 통해서 토큰을 생성
        • 유저가 서버에 요청할 때 이 토큰을 사용하며, 이 때 토큰의 무결성(integrity)과 인증성(authenticity)을 보장함
          • 무결성: 정보가 원래의 내용으로 유지되는 것. 즉 정보가 변조되지 않았음을 보장하는 것
          • 인증성: 보낸 사람과 받는 사람이 서로가 맞다고 확인할 수 있는 성질. 정보의 출처를 확인하고 신뢰할 수 있는지 판단하는 과정
        • 유저가 전송하는 데이터를 숨기는 것보다 유저가 전송하는 데이터를 인증하는데 집중하는 방식

 

4.2 Setting

  • 인증을 사용하기 위한 부분 추가
# 앱시작 
python manage.py startapp users
 
# board/settings.py

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',
    'users'
]

# 이부분은 별도로 추가해주어야함.
 
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

4.3 Model

  • Django User 모델에서 활용할 필드 목록
    • username
      • ID로 활용
      • required=True
    • email
      • required=True
    • password
      • required=True
 

4.4 Serializer

 

  • 회원가입 프로세스
    1. 사용자가 정해진 폼에 따라 데이터를 입력함
      • username, email, password, password2
    2. 해당 데이터가 들어오면 ID가 중복되지 않는지, 비밀번호가 너무 짧거나 쉽지는 않은지 검사함
    3. 2단계를 통과했다면 회원을 생성함
    4. 회원 생성이 완료되면 해당 회원에 대한 토큰을 생성함
 
  • Serializer는 요청으로 들어온 데이터를 Django 데이터로 변환하여 저장하는 기능을 수행함
  • 또한 Serializer는 검증(Validation) 기능을 수행하는 역할을 가지고 있음
    • 이번 Serializer에서는 검증기능을 사용하도록 함

 

# users/serializers.py
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password

from rest_framework import serializers
from rest_framework.authtoken.models import Token
from rest_framework.validators import UniqueValidator


# 회원 등록을 위한 부분
class RegisterSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(
        required=True,
        validators=[UniqueValidator(queryset=User.objects.all())],
    )
    password = serializers.CharField(
        write_only=True,
        required=True,
        validators=[validate_password],
    )
    password2 = serializers.CharField(write_only=True, required=True)

# 써야하는 기능들 관리
    class Meta:
        model = User
        fields = ('username', 'password', 'password2', 'email')

# password와 password2 비교, 잘못됐을시 아래 딕셔너리 출력
    def validate(self, data):
        if data['password'] != data['password2']:
            raise serializers.ValidationError(
                {"password": "Password fields didn't match."})

        return data

    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data['username'],
            email=validated_data['email'],
        )

        user.set_password(validated_data['password'])
        user.save()
        token = Token.objects.create(user=user)
        return user

4.5 View

  • Serializer가 복잡해진 대신 View가 간단해짐
  • 회원가입의 경우 회원 생성 기능만 있음(POST)
    • 굳이 ViewSet을 사용해 다른 API 요청을 처리할 필요가 없음
# users/views.py
from django.contrib.auth.models import User
from rest_framework import generics

from .serializers import RegisterSerializer


class RegisterView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = RegisterSerializer

 

4.6 URL

  • 클래스형 뷰를 사용할 것이므로 .as_view()를 사용함
# users/urls.py
from django.urls import path
from .views import RegisterView

urlpatterns = [
    path('register/', RegisterView.as_view()),
]

 

# board/urls.py
from django.urls import path, include
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls')),
]

4.7 Migration & Run Server

 
  • 원래 없었던 파일들을 새로 생성했기 때문에 연결하는 것이 필요
  • Migration
# Migration
python manage.py makemigrations
python manage.py migrate
  • Run Server
python manage.py runserver

 

http://127.0.0.1:8000/users/register/ 로 가서 확인 (제대로 동작하는지)

 

계정추가로 jiung kgw08003@naver.com 1234asdf*

 

관리자 계정을 통해 기능이 제대로 수행되었는지 확인

# Create Super User
python manage.py createsuperuser

http://127.0.0.1:8000/admin/ 으로 들어가 내가 입력한 슈퍼유저 계정으로 확인

 

나의경우 jiungkim kgw08003@gmai.com 1234 로 설정

 

아래와같이 admin 으로 들어와 슈퍼계정 로그인해서  users 를 통해 해당 유저들이 잘 등록되어있는지 알 수 있다.

 

 

Django 프레임워크 (일반 웹 애플리케이션)

  1. Settings - 설정 파일로, 프로젝트의 전반적인 설정을 관리합니다.
  2. Model - 데이터베이스 구조를 정의하는 클래스입니다.
  3. Template - HTML 파일로, 프론트엔드에 데이터를 표시하는 데 사용됩니다.
  4. View - 비즈니스 로직을 처리하고 템플릿에 데이터를 전달합니다.
  5. Urls - URL 패턴과 뷰를 연결하여 특정 URL 요청이 어떤 뷰로 전달될지 결정합니다.

Django REST Framework (API 개발)

  1. Settings - REST API와 관련된 설정을 관리합니다.
  2. Model - 데이터베이스 구조를 정의하는 클래스입니다.
  3. Serializer - 모델 인스턴스를 JSON과 같은 포맷으로 변환하고, 데이터 검증을 처리합니다.
  4. View - API 엔드포인트의 비즈니스 로직을 처리합니다.
  5. Urls - URL 패턴과 뷰를 연결하여 API 요청이 어떤 뷰로 전달될지 결정합니다.
  6. 기능 or 또다른 모델 - 추가적인 기능이나 모델을 구현하여 API의 확장성을 높입니다.

5. Login 구현

5.1 Serializer

# users/serializers.py

from django.contrib.auth import authenticate

class LoginSerializer(serializers.Serializer):
    username = serializers.CharField(required=True)
    password = serializers.CharField(required=True, write_only=True)

    def validate(self, data):
        user = authenticate(**data)
        if user:
            token = Token.objects.get(user=user)
            return token
        raise serializers.ValidationError(
            {"error": "Unable to log in with provided credentials."})

 

5.2 View

# users/views.py
from django.contrib.auth.models import User
from rest_framework import generics, status
from rest_framework.response import Response

from .serializers import RegisterSerializer, LoginSerializer

class LoginView(generics. CreateAPIView ): 
    serializer_class = LoginSerializer

    def post(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        token = serializer.validated_data
        return Response({"token": token.key}, status=status.HTTP_200_OK)

 

5.3 URL

# users/urls.py
from django.urls import path
from .views import RegisterView, LoginView

urlpatterns = [
    path('register/', RegisterView.as_view()),
    path('login/', LoginView.as_view()),
]

 

5.4 실행

python manage.py runserver

http://127.0.0.1:8000/users/login/

 

로그인하면 토큰 잘 넘어오는것을 알수 있다.

 

 

지금까지 작업한 내용을 정리\

주요 기능

  • 게시판 글 관리: 게시글 생성, 수정, 삭제, 목록 보기, 좋아요 기능 등.
  • 회원 정보 관리: 회원 가입, 로그인, 프로필 수정, 인증, 회원 정보 확인 등.
  • 댓글 관리: 댓글 생성, 수정, 삭제, 목록 보기, 게시글과 함께 댓글 표시 등.

회원 정보 및 인증 시스템 구현 과정

  1. 독립적인 회원 정보 관리: 회원 정보는 게시판이나 댓글과 독립적으로 관리되며, Django의 기본 User 모델을 사용합니다.
  2. Model 생성:
    • Django의 기본 User 모델을 사용하여 회원 정보를 관리합니다.
    • 추가적인 인증 관련 모델이나 프로필 모델이 필요하면 추가로 정의할 수 있습니다.
  3. Serializer 작성:
    • Django REST Framework(DRF)의 Serializer를 이용해 User 모델의 데이터를 JSON 포맷으로 변환합니다.
    • 예를 들어, 회원 가입을 위한 RegisterSerializer, 로그인 처리를 위한 LoginSerializer 등을 작성합니다.
  4. View 작성:
    • DRF의 View를 작성하여 회원 가입, 로그인, 프로필 조회 및 수정 등의 기능을 구현합니다.
    • 예를 들어, RegisterView, LoginView 등을 구현합니다.
  5. URL 설정:
    • Django의 urls.py 파일에서 회원 관련 뷰(View)와 URL을 연결합니다.
    • 예를 들어, /users/register/, /users/login/ 등의 엔드포인트를 설정합니다.
  6. 마이그레이션 및 서버 실행:
    • 모든 모델과 설정이 완료된 후, python manage.py makemigrations 및 python manage.py migrate 명령어를 사용해 데이터베이스에 변경 사항을 반영합니다.
    • python manage.py runserver 명령어로 개발 서버를 실행합니다.
  7. 회원 가입 테스트:
    • 회원 가입이 잘 되는지 확인하기 위해 /users/register/ 엔드포인트로 POST 요청을 보냅니다.
    • Django 관리자 페이지에 접속하기 위해 superuser를 생성합니다.
    • 관리자 페이지에서 회원 정보가 올바르게 저장되었는지 확인합니다.
  8. 로그인 기능 구현 및 테스트:
    • LoginSerializer와 LoginView를 작성하여 로그인 기능을 구현합니다.
    • 로그인 요청에 성공하면, 토큰을 발급하여 이후 요청에 사용합니다.
  9. 토큰 인증:
    • 발급된 토큰을 이용해 사용자가 인증된 상태로 다른 API 엔드포인트에 접근할 수 있는지 확인합니다.

6. User 모델의 확장

 

  • 프로젝트에서 사용하는 회원 모델
    • username: 아이디(CharField, primary=True)
    • email: 이메일 주소(EmailField)
    • password: 비밀번호(CharField)
    • 위 까지는 user에 넣음
    • 아래는 projile 에 넣음
    • nickname: 닉네임(CharField)
    • position: 직종(CharField)
    • subjects: 관심사(CharField)
    • image: 프로필 이미지(ImageField)

Profile 모델

 

profile에 들어갈 4가지 model에 넣어주기

# user/models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver


# Create your models here.
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nickname = models.CharField(max_length=128)
    position = models.CharField(max_length=128)
    subjects = models.CharField(max_length=128)
    image = models.ImageField(upload_to='profile/', default='default.png')


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
 
 pip install Pillow 로 이미지 처리를 위한 사전 다운로드
 
 

모델이 변경되었으므로, 다시 migration 해주어야함

# Migration
python manage.py makemigrations
python manage.py migrate
python manage.py runserver

 

4.5 이미지를 위한 사전 처리

#board/settings.py

import os

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
  • URL
# board/urls.py
from django.urls import path, include
from django.contrib import admin

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

 

  • Serializer
# user/serializers.py
from .models import Profile


class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ("nickname", "position", "subjects")
        # extra_kwargs = {"image": {"required": False, "allow_null": True}}
  • View + 기본 Permission
# users/views.py
from .serializers import RegisterSerializer, LoginSerializer, ProfileSerializer
from .models import Profile

class ProfileView(generics.CreateAPIView):
    queryset = Profile.object.all()
    serializer_class = ProfileSerializer
# users/ permissions.py

from rest_framework import permissions

class CustomReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

User 모델의 확장

프로젝트에서 사용하는 회원(User) 모델을 확장하여 기본적인 회원 정보와 추가적인 프로필 정보를 함께 관리할 수 있도록 설정했습니다. User 모델에는 아이디(username), 이메일(email), 비밀번호(password)가 포함되고, 별도의 Profile 모델을 통해 추가적인 사용자 정보를 관리합니다.

User 모델과 Profile 모델의 설계

  • User 모델: Django의 기본 User 모델을 사용하며, 주요 필드로는 username, email, password를 포함합니다.
  • Profile 모델: 사용자와 연결된 추가 정보인 nickname, position, subjects, image 필드를 포함합니다. Profile 모델은 User 모델과 OneToOne 관계로 연결되어 있습니다.

이미지 처리 라이브러리 설치

  • 이미지를 다루기 위해 Pillow 라이브러리를 설치했습니다.

데이터베이스 마이그레이션

  • Profile 모델을 추가한 후, 데이터베이스 스키마를 업데이트하기 위해 마이그레이션을 수행했습니다.

. 미디어 파일 설정

  • 사용자가 업로드한 이미지를 처리하기 위해 Django 설정 파일에 미디어 파일 처리를 위한 설정을 추가했습니다.

URL 설정

  • 미디어 파일이 올바르게 제공될 수 있도록 URL 설정 파일에 정적 파일 및 미디어 파일 관련 설정을 추가했습니다.

Serializer 작성

  • Profile 모델 데이터를 JSON으로 변환하고, API 응답으로 반환하기 위해 ProfileSerializer를 작성했습니다.

View와 Permission 설정

  • 프로필 정보를 생성하거나 조회할 수 있는 API 뷰를 작성하고, 기본적인 접근 권한 설정을 추가했습니다.

사용자 권한을 제어하기 위해 커스텀 Permission 클래스를 작성했습니다.

728x90

'PYTHON-BACK' 카테고리의 다른 글

#파이썬 31일차_게시판 만들기3  (0) 2024.08.16
#파이썬 30일차_게시판 만들기2  (0) 2024.08.14
#파이썬 28일차_MYSQL5  (0) 2024.08.12
#파이썬 27일차_MYSQL4  (0) 2024.08.09
#파이썬 27일차_MYSQL4  (0) 2024.08.08