총 6개의 엔드포인트를 구현했으며 1.회원가입, 2.로그인, 3.게시물 등록, 4.게시물에 댓글 등록, 5.게시물 '좋아요' 기능 구현, 6.다른 계정 'Follow' 기능 구현 등이 해당 된다. django
를 이용해서 구현하였으며 project
라는 하나의 프로젝트 안에 User
와 Posting
이라는 두 개의 app
으로 이루어져 있다. 각각의 app
의 파일을 보기 전에 project
에 해당하는 파일들을 먼저 살펴보도록 한다.
토큰을 발행하고 확인하는 SECRET_KEY
와 프로젝트의 데이터가 저장될 DB
의 정보를 my_settings.py
에 따로 저장하여 .gitignore
에 추가하여 원격저장소에 해당 정보가 올라가지 않도록 해주었다.
ALLOWED_HOST
는 현재 여러 프론트엔드들이 접속할 수 있도록 모든 주소를 허용해 놓은 것이다. 또한 외부에서도 접속을 허용하게 하는 corsheaders
와 직접 만든 User
와 Posting
을 INSTALLED_APPS
에 추가하여 django
에서 앱을 인식할 수 있게 하였다.
Port
번호 이후에 user
가 보이면 User.urls.py
로, posting
이 보이면 Posting.urls.py
로 가라는 뜻이다.
회원가입 엔드포인트는 회원정보를 DB
에 등록하기 위한 것으로 DB
의 테이블을 어떤 식으로 구성할 지 모델링해야 하고 views.py
를 작성할 때는 어떤 정보가 필수적으로 들어올 지에 대한 것을 정해야한다. 또한 password
나 email
의 형식이 올바르게 들어왔는지 판단해줄 필요가 있으며 각각의 필수적인 것들에 대해 잘못된 요청이 들어왔을 때 적절한 에러메세지를 응답해줘야하며 성공했을 때는 DB
에 저장하고 회원가입에 성공했다는 응답을 보내주어야 한다. 먼저 User/urls.py
를 살펴보자.
from .views import SignUpView, SignInView, FollowPost, FollowGet
위 코드는 각각의 endpoint
에 접근하면 실행될 함수들이다. 이 중 회원가입 엔드포인트로 접근하면 실행될 함수에 해당하는 것은 SignUpView
이다. 회원가입 엔드포인트는 signup
이다. project/urls.py
에서 살펴보았듯 path
함수를 사용했으며 이번에는 다른 urls.py
로 연결하는 것이 아닌 실행될 view
를 연결한다.
이번에 살펴볼 것은 models.py
이다. 실제 DB에 형성될 table
이 class
에 해당되고 각 attribute
는 field
이다. 즉 하나의 column
에 해당한다. email
, password
, name
, phone_number
라는 4개의 column을 선언하였으며, Primary_Key
가 지정되지 않았기 때문에 Django
에서 자동으로 id
라는 column
으로 Primary_Key
에 해당하는 field
를 자동으로 생성해준다.
아래 \_\_str\_\_
함수는 class
의 instance
들을 표현할 때 email field
에 해당하는 값으로 표현하고자 하는 것이다. 해당 함수가 선언되지 않는다면 Primary_Key
에 해당하는 값으로 표현된다. 즉 여기서는 id
값으로 표현된다.
위 코드에 해당하는 것이 회원가입 기능을 구현하는 코드이다. 먼저 엔드포인트에 접근할 때 입력된 정보들을 data
라는 변수에 담는다. 이 data
의 자료구조는 dictionary
에 해당한다.
email
과 password
는 필수적으로 입력되야하는 Key
이기 때문에 들어오지 않는다면 KEY_ERROR
를 반환해주고 phone_number
나 name
은 필수적인 요소는 아니기 때문에 있다면 post_변수
에 저장하고 아니면 빈 값을 저장해준다.
다음에 해당하는 코드는 각각의 입력된 값의 형식이나 중복된 값이 존재하는지를 검사하는 것으로 helper.py
에 따로 함수를 선언 후 import
해서 사용하는 것이다. helper.py
는 다음과 같다.
User/helper.py
순서대로
name
중복,phone_number
중복,password
형식 검사에 해당하는 함수이다.password
형식 검사는 정규표현식을 사용하였다.
post_password = bcrypt.hashpw(post_password.encode('utf-8'), bcrypt.gensalt())
위의 코드는 입력한 패스워드를 암호화하는 작업이다. bcrypt
라이브러리를 사용했으며 이 결과값은 bytes
타입이기 때문에 다음 코드를 살펴보면 DB
에 저장하는 코드인데 decode
후에 저장하는 것을 볼 수 있다. 그 이유는 현재 models.py
를 보면 field
타입이 문자열이기 때문에 bytes
타입이 들어가더라도 문자열로 저장되고 후에 로그인 시에 암호화된 코드를 비교할 때 문제가 생기기 때문에 decode
후에 패스워드를 저장하도록 했다.
그리고 마지막으로 성공적으로 저장이 완료되면 성공했다는 메세지를 status
코드와 함께 보내준다.
로그인 엔드포인트는 위의 User/urls.py
를 참고하면 signin
에 해당하고 SignInView
가 실행되는 함수이다. views.py
에서 해당 코드를 살펴보자.
역시나 들어올 때 입력된 정보들을 data
라는 dictionary
형태의 변수에 담고 각각의 key
가 존재하는지 검사를 진행한다. 로그인 시에 필요한 값은 name
, email
, phone_number
중에 하나 그리고 password
이다. 역시나 필수적인 키가 입력되지 않았을 시 KEY_ERROR
를 반환하게 된다.
그 후 각각의 들어온 키에 해당하는 조건문으로 코드를 구현하였다. 키에 저장된 값을 통해 DB
에 저장된 값을 조회 후 존재하지 않으면 회원가입이 선행되지 않았으므로 에러를 반환하고 존재할 시 DB
에 저장된 암호화된 password
와 입력된 password
를 비교한다. bcrypt.checkpw
는 True/False
로 값을 반환하며 일치할 시 jwt
를 생성하여 토큰을 반환한다.
토큰 생성 시 담게 될 정보는 복호화하여 정보를 확인할 수 있기 때문에 누군지 식별가능하지만 공개되어도 문제 없는 정보를 담아야한다. 그렇기 때문에 다른 DB
나 서비스에서 알아도 다른 값에 해당할 id
를 담는다. 이 때 SECRET_KEY
는 어떤 정보도 상관없다. 나의 경우는 my_settings.py
에 담긴 SECRET_KEY
를 사용하였다. 그렇게 만들어진 token
은 bytes
타입이기 때문에 Json
형식으로 반환할 때 decode
하여 str
형식으로 만들어서 보내주어야 한다. 그래서 decode
하여 응답하였다.
먼저 게시물을 위한 models.py
를 먼저 살펴보자.
게시물 등록에 필요한 field
는 user
, created_at
, img_url
, content
에 해당한다. liked_user
는 후에 설명할 좋아요 기능 구현과 관련해서 필요한 field
값이다. user
의 경우 회원가입과 로그인이 완료된 후에 게시물을 등록할 수 있어야 하므로 기존에 저장된 User
테이블과 연결되어야만 한다. 때문에 ForeignKey
로 연결해주었다. created_at
은 값이 저장될 때 자동으로 저장되도록 하였다. 다음은 posting
app
의 엔드포인트들을 살펴볼 posting/urls.py
를 살펴보자.
게시물 등록에 해당하는 엔드포인트는 post
이다. get
은 게시물을 정보를 요청하는 GET
요청으로 들어왔을 때 처리할 엔드포인트이다.
이제 게시물 등록에 대한 views.py
를 살펴보도록 한다.
이 때 데코레이터 함수가 먼저 실행되도록 하는 것을 살펴볼 수 있는데 이 함수는 로그인 시 발행한 토큰을 확인하는 데코레이터 함수다. 해당 코드를 먼저 살펴보도록 하자.
User/utils.py
먼저 데코레이터 함수 형식은 미리 써놓은 글이 있기 때문에 생략한다.
try-except
로 구문을 묶은 것은 토큰이 유효하지 않은 것이거나 토큰에 담긴 유저의 정보가 나의DB
에서 찾을 수 없는 에러가 발생할 시 처리하기 위한 것이다.보통 토큰은
http
요청에 있어서header
에Authorization
이라는Key
에 담겨 전달되기 때문에 토큰을 해당 위치에서get
하고 토큰을encode
했던 동일한 정보와 방식으로decode
하고 해당 토큰에 담긴user
를DB
에서 찾고 해당user
의 정보를 최종적으로request.user
정보에 담고 후에 실행될 함수를return
에 위치시켜 실행되도록 한다.
이 때 img_url
과 content
는 필수적으로 전달되어야 할 Key
이므로 전달되지 않았을 시 KEY_ERROR
를 반환해준다. 그 후 Post
에 저장을 해준다. 이 때 user
정보는 앞의 데코레이터 함수에서 토큰을 통해 확인한 request.user
를 입력해준다.
그 다음은 GetView
는 등록된 게시물 정보를 요청하는 GET
요청이 들어왔을 경우 처리하는 class
이다. 이 때 post
에 담긴 Post.objects.all()
은 Post
테이블에 담긴 모든 정보를 가져오는 것으로 type
이 QuerySet
이다. Json
형식으로 전달하기 위해서 serializers
를 사용한다.
QuerySet이란?
QuerySet이란 데이터베이스에서 전달 받은 객체의 목록이다.(Django ORM에서 발생한 자료형) 리스트와 구조는 같지만 파이썬 기본 자료구조가 아니기 때문에 파이썬에서 읽고 쓰기 위해서 자료형 변환을 해줘야 한다.
댓글과 연관된 엔드포인트는 commentpost
와 commentget
이다. commentpost
는 댓글 등록, commentget
은 등록된 댓글 정보를 가져오기 위한 엔드포인트이다.
위에서 살펴본 파일의 아랫 부분으로 댓글에 해당하는 모델이다. user
는 어떤 사용자가 댓글을 작성했는지, post
는 어떤 게시물에 달린 댓글인지, commet
는 댓글 내용, created_at
은 댓글이 달린 시점이다.
역시나 토큰을 확인하는 데코레이터 함수가 먼저 실행되고 필수적인 KEY
를 확인한다. 또한 댓글을 달고자 하는 게시물이 존재하는지 먼저 확인한다. 그 후 별 문제가 없다면 해당 게시물에 댓글이 달리도록한다.
get
요청에 대한 함수는 현재 id
가 1
인 게시물의 댓글 정보만 전달되도록 코드를 구현해두었다.
좋아요 기능과 관련된 엔드포인트는 likepost
와 likeget
이다. 해당 정보가 저장되는 모델은 Post
의 liked_user
이다. 즉 좋아요를 누른 user
의 정보가 각 게시물과 연결되는 것이다. views.py
를 살펴보면
전달되는 정보는 post
와 like
이다. user
의 정보는 데코레이터 함수를 통해서 전달 받는다. 이 때 like
에 대한 정보는 0
또는 1
로 전달받도록 하였는데 0
이면 좋아요를 취소한 것이고, 1
이면 좋아요를 누른 것으로 처리하였다.
get
요청을 통한 것은 좋아요 갯수에 대한 것으로 해당 게시물과 연결된 user
의 수를 count
메소드를 통해서 구한 후 전달해준다.
해당 정보가 저장되는 테이블은 User
앱의 models.py
에 구현되어 있으며 해당 필드는 위와 같다. Follow
정보는 Follow
를 하는 것과 당하는 것으로 두 가지 정보가 필요하므로 다른 필드로 구현되어 있다.
Follow
기능 역시 회원가입과 로그인이 선행되어야 하므로 데코레이터 함수를 통해 토큰을 검사한다. 그 후 Follow
하고자 하는 email의 키가 필수적이므로 KEY
검사를 한다. 또한 입력된 email
은 Follow
를 당하는 것이므로 followed_user
에 저장되고 해당 user
의 정보를 User
테이블에서 가져와서 저장한다. following_user
의 경우 Follow
를 하는 주체로 토큰 검사에서 구할 수 있는 request.user
를 통해 저장한다.
이 때 get_or_created
를 통해서 새로운 row
가 생성된 것인지 기존에 존재하는지를 알아낼 수 있는데 기존에 존재하는 값이라면 해당 요청은 Follow
를 취소하는 UnFollow
요청으로 해당 row
를 삭제하도록 한다. 각각의 요청에 대한 응답으로 메세지를 보내주도록 한다.
Follow
의 수에 대한 정보를 얻기위한 get
요청에 대한 기능은 역시나 email
이 필수적으로 입력되어야 하며 이는 로그인한 user
의 것이여도 반드시 들어와야한다. 해당 user
의 following
, followed
정보를 count
를 통해서 수를 반환해준다.