Django - 회원가입view: 기본적인 app (3)

solee·2022년 2월 22일
0

Django

목록 보기
6/12

이전 글인 기본적인 app 시리즈의 3번이다. 회원가입과 로그인 기능을 구현해보려고 한다. gs25 프로젝트로 진행해 보자. gs25의 지점장들이 가입하고, 로그인도 한다는 설정으로 간다.

목표를 간단하게 정리해볼까.

🚩목표

  • httpie로 데이터를 전송해 회원가입을 진행할 수 있다.

  • httpie로 데이터를 전송해 로그인을 진행할 수 있다.

  • 이메일 형식, 비밀번호 유형에 대한 유효성 검사를 통과할 수 있다.




로그인, 회원가입 등을 위한 app을 새로 생성하자.

members 앱이다! settings.py에 앱을 추가해준다.


회원가입 : post 메서드

그리고 urls.py

프로젝트 내에서 앱으로 연결해 주는 urlpattern은 include를 사용해 찾아갈 위치를 설정해 주는 것이다.

http://127.0.0.1:8080/members/1

이런 주소가 있다면 /members까지의 url을 가지고 members.urls로 찾아온 후 남은 /1을 가지고 분류된다. 앱 내부에서 members.urls를 생성해 작성해야 하는데, 앱 내부의 urls에서는 members앱 안의 views를 가지고 찾아 들어간다. 그러면 view를 작성하면 될까? view에서는 models의 클래스(테이블)를 가지고 데이터를 가공하므로 models를 먼저 작성해야 한다.



models.py 작성

내 테이블 안에 어떤 컬럼이 들어갈지 먼저 고민해야 할 것이다.
일단 로그인을 위한 EMAIL과 PASSWORD, 점장의 이름과 어느 지점인지 저장할 NAME과 STORE, 그리고 개점일(가입일)을 위한 CREATED_AT이라는 컬럼을 생성하기로 결정한 후 model을 작성한다.

클래스명은 대문자로 시작하는 단수, 테이블명은 소문자 복수로 작성한다. email은 아이디 대신 사용될 예정이므로 unique=True를 사용해 중복을 허용하지 않는다.

작성했으면 makemigration과 migrate를 통해 데이터베이스에 테이블을 생성한다. 기존에 사용하던 데이터베이스 gs25에 생성할 것인데, 만일 새로운 프로젝트에 시작했다면 데이터베이스가 존재하지 않으므로 데이터베이스 또한 새로 생성해야 한다.

실행시키면, 테이블이 생성된다. mysql에서 제대로 생성되었는지 확인한다.

오케이.




views.py 작성

이제 view를 작성한다. view에서는 데이터를 가공할 것인데, 회원가입 기능에서는 가입에 필요한 정보들을 받아 DB에 삽입할 것이므로 post 메서드가 필요하다.

RegisterView라는 이름으로 view를 상속받는 클래스를 생성하고, 그 안에 def post를 작성한다.

일단 데이터가 들어오는 대로 삽입하는 구문을 짠다면 위와 같다. request로 전해진 json파일을 data에 저장한 후, 해당 파일에서 각각의 컬럼명과 동일한 이름(다를 수도 있다)을 키로 가진 값을 꺼내 컬럼에 대응되는 변수에 할당해 create로 insert한다. 가입일의 경우 auto_now_add로 현재 시간을 자동으로 삽입하므로 적지 않는다.

그럼 아무 데이터를 마구 집어넣으면 될까? 안 된다! 우리가 가입할 때에는 항상 아이디 중복을 확인하고, 비밀번호도 영어와 숫자, 특수문자가 다 필요하다. 또 이메일에서도 형식을 잘 지켜야 한다.

지금은 아주 간단한 야매 정규식을 사용해 데이터를 검증하겠다.
(사실 이거... 프론트에서 해주는 거 아닌가? 아이디 중복 버튼 눌러서 검증하고 비밀번호 해결 안 되면 로그인이나 회원가입 버튼 활성화 안 되고 그런 거...)



🚩검증 목록

  • 이메일 형식(@와 .의 존재 여부 확인)
  • 이메일 중복 확인
  • 비밀번호 형식(영어, 숫자, 특수문자의 존재 여부 확인)
  • 비밀번호 길이(8자 이상)



일단 여러번 사용하는 코드를 짧게 하기 위해 변수에 할당해 준다.

email = data["email"]
password = data["password"]

- 이메일 형식

간단하게 이메일에 @가 들어있는지, .이 들어있는지의 여부만 확인한다. 실제 사이트에서도 단순히 @와 .이 들어있는지만 판단하는 경우를 꽤 봤고 다양한 이메일의 형식을 다 포괄할 수는 없으니(~~@university.ac.kr 등) 이런 방식을 선택했는데, 다만 이 if문을 합치는 방법을 찾지 못했다.

if not re.search("[@]", email) or not re.search("[.]", email):
	return JsonResponse({"results":"EMAIL_ERROR"}, status=400)

import re로 정규식을 가져와 search메서드를 사용해 입력받은 데이터에 "@"라는 특수문자, 또 "."라는 특수문자가 존재하는지 확인하는 것이다. not을 붙여 만일 둘 중 하나라도 없을 경우 email_error 메시지와 함께 400에러를 띄운다.


  • 이메일 중복 확인

이메일의 경우 model에 unique=True를 주었다. 이것은 테이블 내에서 해당 컬럼 내 항상 값들이 고유한 것으로, 다시 말하자면 중복을 허용하지 않는다. 그렇기 때문에 따로 중복 확인을 해주지 않아도 자동으로 에러가 발생한다. 이렇게 발생하는 에러는 에러 메시지에서도 확인할 수 있는데, IntegrityError다. try ~ except로 해당 에러를 잡을 수 있다.

IntegrityError를 import하고 메서드 전체를 감싼다.(사실 다 안 감싸고 create만 감싸도 된다) 그리고 에러 메시지를 출력한다.


  • 비밀번호 형식, 길이

이번에는 정말로 길다.

if len(password)<8 or not re.search("[0-9]", password) or not re.search("[a-zA-Z]", password) or not re.search("[^a-zA-Z0-9]", password):
	return JsonResponse({"results":"PASSWORD_ERROR"}, status=400)

앞에서부터 읽어 보면 password의 길이가 8보다 작다면, 혹은 숫자[0-9]가 없거나, 혹은 문자[a-zA-Z]가 없거나, 혹은 숫자도 문자도 아닌 것[^a-zA-Z0-9] 즉, 특수문자가 없을 경우 에러가 발생한다.

개인적으로 동일한 에러를 리턴하기 때문에 if문을 따로 만드는 것보다 조금 길어도 하나로 묶는 게 더 낫지 않나 생각해서 그냥 묶었는데, 79글자 정도로 자른다는 걸 생각하면 나누는 것도 괜찮을 것 같다. 하지만 내 취향엔... 이게 좋으니까.... 나 혼자 작성하는 블로그니까.... 그대로 간다.



members.urls.py 작성

여기까지 작성했으면 이제 불러올 view의 post 메서드가 완성된 것이다.
마지막으로 members앱에 urls.py를 생성한 후 경로를 작성해 준다.


이제 127.0.0.1:8080/members/register에 이메일, 비밀번호, 이름, 지점명을 작성해 보내면 members 테이블에 추가될 것이다.

이렇게 쓰면 헷갈릴 수 있는데, 경로에 적어준 members는 members app으로 연결되도록 잡아 주기 위한 urlpattern으로 다른 값이 될 수 있다.
데이터가 추가되는 members 테이블은 models.py에서 작정한 class Meta의 db_table 값이다.

동일한 이름을 사용할 뿐 다른 데이터를 가지고 있음을 기억해야 한다.




회원가입 결과

입력한 값이 json형태로 정상적으로 등록되고, success를 리턴한다.

데이터는 이전에 실험하느라 입력한 값들이 남아 있다. 시간의 경우 timezone을 설정하지 않았기 때문에 시간대가 맞지 않는다.




회원 목록 : get 메서드

자바 프로젝트와 달라 처음에 가장 헷갈렸던 것이 이 메서드다. get이건 post건 데이터를 넣는 방법이 다를 뿐이라고 생각했는데, 데이터를 보낸다면 post메서드를 사용하고 데이터를 받기만 한다면 get을 사용한다.

간단하게는 post메서드를 작성하면서 혹시 페이지가 연결이 잘 안 된 것 같을 때 get메서드를 껍데기만 작성해 접속되는지 확인하는 용도로 사용할 수 있다.

이렇게만 작성한다면 동일한 페이지로 httpie요청을 보낼 때 아무 데이터 없이 http -v GET 127.0.0.1:8080/members/register로 보내서 message:hello가 출력되는 것을 확인할 수 있다. 또는 그냥 인터넷 주소창에 이 링크를 입력해서 확인할 수도 있다.

이렇게 출력된다면 페이지를 연결하는 url에는 아무 문제가 없다는 뜻이므로 post를 작성하면서 다른 부분을 꼼꼼히 확인할 수 있다.




그럼 이 get메서드를 완성시켜보자. 같은 view에서 아까 삽입한 데이터들을 목록으로 확인할 것이다.(/register라는 urlpattern과는 어울리지 않는다)

get으로는 데이터를 입력받지 않고 회원 목록은 DB 전체를 말하는 것이니 간단하게 간다.

  • members_list에 전체 데이터를 담은 쿼리셋을 할당한다.

  • 빈 리스트 result를 선언한다.

  • members_list로 for문을 돌려 각 객체의 컬럼들을 담은 딕셔너리를 리스트 result에 저장한다.

  • 리스트 result를 리턴한다.

간단하게 작성한 후 실행해 보면 이런 결과가 나온다.

맨 위를 확인하면 리턴받은 json 데이터에서 result라는 리스트를 출력하는데, 그 안에 저장한 각각의 객체들의 데이터가 각각 json형태로 출력되고 있다.

데이터가 중구난방인데, 맨 아래로 가면 아까 삽입한 김미영 점장님의 사랑점을 확인할 수 있다.

완성!





마치며

회원가입을 마쳤다. 로그인은 더더욱 쉽다! 일치하는 데이터가 존재하는지 확인하면 되니까.
다음 글에서는 로그인을 빠르게 해결한 후 회원가입 시 비밀번호를 암호화하여 저장하는 방법과 로그인 시 토큰을 이용해 인가받는 방법에 대해 포스팅하겠다.

profile
DA DA DA

0개의 댓글