Web/Django-python

Django에서 mysql 이용하여 로그인, 회원가입 기능 만들기

컨테이너간 연동이 끝났으니, 이제 웹 페이지에서 데이터베이스를 실제로 활용해볼 차례.

장고에서 디비를 사용할때는 모델, 뷰, 템플릿 , URL 파일 정도만 건드려주면 된다.

models.py

class User(models.Model):
    user_id = models.CharField(max_length=20)
    email = models.CharField(max_length=20)
    password = models.CharField(max_length=20)

일단 모델 생성부터. User라는 테이블을 생성하여 내용을 정의하는데, 이 방식은 장고 튜토리얼에도 나와있는 기존 장고에서 디비를 사용하는 방식과 동일하다.

 

PHP로 웹 개발을 할때 사용하는 MYSQL을 생각하면 복잡한 쿼리문의 반복밖에 떠오르지 않는데, 장고를 사용하면 쿼리문을 사용할 필요가 거의 없는것 같다. )다만 디비에 연결해서 사용할 일은 있을테니 기본적인 쿼리 정도는 익혀놓는게 맞다. )

views.py

from .models import User
@csrf_exempt
def signup(request):
    template_name = 'login.html'
    data = request.POST
    if User.objects.filter(user_id= data['id']).exists():
        context = {
            "result" : "이미 존재하는 아이디입니다."
        }
        return HttpResponse(json.dumps(context),content_type="application/json")
    else :
        User.objects.create(
            user_id = data['id'] , 
            email = data['email'] ,
            password = data['password'],
        ).save()
        context = {
            "result" : "회원가입 성공"
        }
        return HttpResponse(json.dumps(context),content_type="application/json")

@csrf_exempt
def loginCheck(request):
    template_name = 'login.html'
    request.session['loginOk'] = False
    try:
        data = request.POST
        inputId = data['id']
        inputPassword = data['password']

    except (KeyError,inputId == "",inputPassword == "") :
        context = {
            "uid" : "empty",
            "upass" : "empty",
        }
        return render(request,template_name,context)
    else : 
        if User.objects.filter(user_id= inputId).exists():
            getUser = User.objects.get(user_id = inputId)
            if getUser.password == inputPassword : 
                request.session['loginOk'] = True
                context = {
                    "result" : "로그인 성공"
                }
            else :
                request.session['loginOk'] = False
                context = {
                    "result" : "비밀번호가 틀렸습니다"
                }
        else :
            request.session['loginOk'] = False
            context = {
                "result" : "존재하지 않는 id입니다"
            }
        return HttpResponse(json.dumps(context),content_type="application/json")

세션에 대한 내용도 저번에 정리해뒀으니, 지금은 데이터베이스 관련 내용만 보면 된다.

.models 에서 User 모델을 임포트하고, User.objects 의 형태로 해당 테이블을 사용한다.

 

테이블에서 값을 가져올때는 getUser = User.objects.get(user_id = 입력값) 와 같은 형태로 , 해당 테이블의 어트리뷰트(속성값) 에서 내가 입력한 값과 일치하는 값이 있으면 그 튜플 전체를 가져와 getUser라는 클래스형태 객체로 사용할 수 있게 만든다.

 

가져온 객체는 if getUser.password == inputPassword : 와 같은 형태로 간단하게 사용이 가능하다. 확실히 PHP에서 값을 가져오는 방식과 비교하면 엄청나게 간편한걸 알 수 있다.

 

어떤 속성의 특정 값이 그 테이블에 존재하는지 여부도 미리 정의된 함수들을 통해 간단하게 찾아낼 수 있다. if User.objects.filter(user_id= inputId).exists(): 의 형태로 입력한 ID값이 회원가입 되어있는 아이디인지를 찾아내었다.

 

* 다만 ,실제 환경에서 개발을 진행할 때에는 절대로 비밀번호를 평문으로 저장하면 안된다. 정보통신망법에서 정의한 기준에 따라 비밀번호는 일방향 암호화저장, 즉 해쉬함수를 이용해 변형하여 저장해야 하고, 값을 검증할 시에도 입력값을 해쉬하여 저장된 값과 비교하여 검증하도록 코드를 작성해야한다. 실제 서비스에서 이러한 조건을 지키지 않으면 보안사고 발생 위험이 매우 높아지므로 주의하자. 

 

login.html

$('#signupSend').on('click',function(event) {
    var formData = $('#signupForm').serialize();
    $.ajax({
        cache : false,
        url : "{% url 'login:signup' %}" ,
        type : 'POST',
        data : formData,
        success : function(data){
            var res = data['result'];
            var uid = data['uid'];
            console.log(uid);
            alert(res);
        },
        error : function(xhr,status,)
        {
            alert("통신 실패");
        },
    });
})

$('#loginButton').on('click',function(event){

    var formData = $('#loginForm').serialize();
    $.ajax({
        cache : false,
        url : "{% url 'login:loginCheck' %}" ,
        type : 'POST',
        data : formData,
        success : function(data){
            var res = data['result']
            alert(res);
        },
        error : function(xhr,status,)
        {
            alert("통신 실패");
        },
    });
});

서버사이드 코드가 간략화 되었으니, 클라이언트 사이드 코드도 간단하게 작성된다.

 

ajax로 작성한 형태이긴 하지만 , 복잡한 분기문이나 태그의 사용 없이 데이터 전송/수신 형태로 함수가 간단하게 정의되는걸 알 수 있다. 그저 보내는 값/받는값의 형식과 이름정도만 맞춰주면 크게 무리 없이 동작 구현이 가능하다.

 

또, URL을 하드코딩할 필요 없이 정의된 URL 패턴에 맞춰 적어주기만 하면 장고에서 자동으로 url을 지정하여 연결해주는 기능을 제공한다.

urls.py

#login/ulrs.py
from django.urls import path

from . import views

app_name ='login'
urlpatterns = [
    path('login/',views.login,name='login'),
    path('base/',views.base,name='base'),
    path('loginCheck/',views.loginCheck,name='loginCheck'),
    path('loginOk/',views.loginOk,name='loginOk'),
    path('signup/',views.signup,name='signup')
]

새로운 view를 추가하였으니 URL패턴 추가는 당연히 해줘야한다.

 

테스트 해보니 로그인, 중복가입, 비밀번호 오류, 아이디 오류 등 모든 기능이 문제없이 잘 동작하는게 확인된다.

여기까지 장고를 사용하며 웹페이지를 개발해보고 느낀게, 확실히 PHP/HTML을 이용한 개발보다 개념과 구조는 조금 복잡할 지 몰라도, 코드를 작성하며 개발하는데 걸리는 시간은 훨씬 단축되는게 맞는것 같다.

 

조금 어려운 개념을 익히는게 힘들지, 그 다음부터는 기존 방식에 비해 매우매우 편하게 코드를 작성하고 데이터베이스를 가지고 놀 수 있는게 장고를 이용한 개발의 큰 장점인것 같다. URL 패턴이 있으니 ajax를 이용한 동적 페이지 개발이 쉬운건 덤이다. 아마 이는 MVC 패턴을 이용하는 대부분 프레임워크의 장점인것 같기도 하다.