[TIL] 인스타그램 회원가입 구현(views.py)

4802 단어 djangoTILTIL
import json
import re
import bcrypt
import jwt

from django.views       import View
from django.http        import JsonResponse

from user.models        import User
from westagram.settings import SECRET_KEY

class SignUpView(View):
    def post(self, request):
        data               = json.loads(request.body)
        email_check        = re.compile('[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
        phone_number_check = re.compile('^\d{3}-\d{3,4}-\d{4}$')
        password_check     = re.compile('^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$')

        try:
            email        = data['email']
            phone_number = data['phone_number']
            password     = data['password']
            name         = data['name']
            nickname     = data['nickname']

            if User.objects.filter(email=email).exists():
                return JsonResponse({'MESSAGE':'EMAIL_ALREADY_EXIST'}, status=400)

            if not email_check.match(email):
                return JsonResponse({'MESSAGE':'INVALID_EMAIL'}, status=400)

            if User.objects.filter(phone_number=phone_number).exists():
                return JsonResponse({'MESSAGE':'PHONE_NUMBER_ALREADY_EXIST'}, status=400)

            if not phone_number_check.match(phone_number):
                return JsonResponse({'MESSAGE':'INVALID_PHONE_NUMBER'}, status=400)

            if User.objects.filter(nickname=nickname).exists():
                return JsonResponse({'MESSAGE':'NICKNAME_ALREADY_EXIST'}, status=400)

            if not password_check.match(password):
                return JsonResponse({'MESSAGE':'INVALID_PASSWORD'}, status=400)

            salt = bcrypt.gensalt()
            hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)
            hashed_password = hashed_password.decode('utf-8')

            User.objects.create(
                email        = data['email'],
                phone_number = data['phone_number'],
                password     = hashed_password,
                name         = name,
                nickname     = nickname
            )
            return JsonResponse({'MESSAGE':'SUCCESS'}, status=200)

        except KeyError:
            return JsonResponse({'MESSAGE':'KEY_ERROR'}, status=400)

http 요청을 받으면 views.py에서 요청을 처리하고 응답한다.

우선 회원가입을 위해서는 이메일 형식, 비밀번호 형식, 전화번호 형식이 웹사이트가 요구하는 형식이 맞는지 확인해야한다. 그래서 정규표현식을 사용해서 check 변수들을 만들었다. try 안에서 email,phone_number,password,name,nickname 변수들을 선언했으므로 하나라도 정보가 입력되지 않으면 KeyError가 발생한다.

모든 변수들을 다 입력했으면 그 다음부터 에러사항을 하나하나 체크해 나간다.

if User.objects.filter(email=email).exists():
                return JsonResponse({'MESSAGE':'EMAIL_ALREADY_EXIST'}, status=400)

-> 같은 이메일이 데이터 베이스에 이미 존재하면 이메일이 이미 존재한다는 에러 메세지를 보낸다. 여기서 exists()를 사용한 이유는 exists()는 데이터 베이스 안에 정보가 있는지 없는지만 체크하므로 데이터를 가져오지 않는다 (효율성이 좋다)

if not email_check.match(email):
                return JsonResponse({'MESSAGE':'INVALID_EMAIL'}, status=400)

-> 정규표현식을 사용해서 입력한 email이 올바른 형식으로 입력이 되었는지 확인하고 잘못된 형식으로 입력되었으면 에러메세지를 보낸다.

다른 if문들은 전부다 비슷한 의미를 나타내므로 따로 언급하지 않겠다.

이렇게 if 문으로 에러메세지를 보내는데 중복된 email,nickname,phone_number가 없고 원하는 타입 형식으로 제대로 입력이 되었으면 비밀번호 암호화를 시행한다.

bcrypt는 데이터베이스에 유저의 정보를 저장할 때, 비밀번호와 같이 암호화가 필요한 데이터를 쉽게 다룰 수 있도록 해주는 password hashing 라이브러리다.

먼저, 암호화를 위해서는 bcrypt를 설치해야하는데

pip install bcrypt로 설치한후 import bcrypt 한다.

salt = bcrypt.gensalt()

salt를 추가함으로써 암호를 더 복잡하게 만들어준다.
쉽게 말해, 해커들이 해킹하기 더 어렵게 만들어준다.

hashed_password = bcrypt.hashpw(password.encode('utf-8'), salt)

이렇게 hashpw를 사용해서 salt와 함께 encode 시키게 되면 단방향 암호화가 이루어지는데 단방향 암호화란 내가 입력한 비밀번호를 되찾을수 없다. 다시말해, 비밀번호를 까먹으면 그 비밀번호를 찾을수 없다는 뜻이다.

예를들어, 내가 비밀번호를 '1234'로 설정한다면 저 코드로 인해 비밀번호가 데이터베이스에 '1234'로 저장되지 않고

b'$2b$12$4n5NY.agqiRfh.eNlcIJEuFif2gY.m0jIgK4HbwZpJO.FS5U8.vg.' 이렇게 암호화된 비밀번호로 저장된다. 그래서 회원가입할때 유저가 비밀번호를 '1234'를 입력했다는것을 알 수 없다.

hashed_password = hashed_password.decode('utf-8')

encode로 인해서 비밀번호 타입이 'bytes'가 되었는데 데이터베이스에 저장할때는 decode를 한후 'str'타입으로 바꾸고 저장한다.

이렇게 암호화를 시킨후

User.objects.create(
                email        = data['email'],
                phone_number = data['phone_number'],
                password     = hashed_password,
                name         = name,
                nickname     = nickname
            )
            return JsonResponse({'MESSAGE':'SUCCESS'}, status=200)

create문으로 회원가입을 완료한다.

회원가입이 잘 되었다면 {'MESSAGE':'SUCCESS'} 메세지를 리턴하도록 구현했다.

좋은 웹페이지 즐겨찾기