원티드 프리온보딩 코스의 개인 프로젝트 레포지토리입니다.
- 본 과제에서 요구하는 서비스는 SNS(Social Networking Service)입니다.
- 사용자는 본 서비스에 접속하여, 본인의 게시글을 업로드하고 관리(수정/삭제/복구)할 수 있습니다.
- 사용자는 본 서비스에 접속하여, 모든 게시글을 확인하고 좋아요 기능을 사용할 수 있습니다.
Index
Period
Analysis
-
- 유저관리:
- 회원가입
* 이메일을 ID로 사용합니다.
- 유저 로그인 및 인증
* 로그인 성공 시 JWT토큰을 발급받으며, 추후 사용자 인증으로 사용합니다.
- 회원가입
- 게시글:
- 게시글 생성
* 제목, 내용, 해시태그 등을 입력하여 게시글을 생성합니다. * 제목, 내용, 해시태그는 필수사항입니다. * 작성자 정보는 request body에 존재하지 않고 해당 API를 요청한 인증정보에서 추출하여 사용합니다. * 참고로 해시태그는 #으로 시작합니다. (해시태그 입력 형태는 자유롭게 설정가능)
- 게시글 목록
* 모든 사용자(인증/인가에 통과한 유저)는 모든 게시글에 보기권한이 있습니다. * 게시글 목록에는 제목, 작성자, 해시태그, 작성일, 좋아요 수, 조회수 등이 포함됩니다. * 검색/정렬/필터링/페이지네이션 기능은 각각 동작할 뿐만 아니라, 동시에 적용될 수 있어야 합니다. ex) some-url?search=..&order_by=.. (이는 예시이며, 해당변수는 직접 설정할 것) > Ordering(Sorting, 정렬) 사용자는 게시글 목록을 원하는 값으로 정렬할 수 있습니다. 단, 오름차순/내림차순을 모두 선택할 수 있습니다. ex) default: 생성일 //생성일, 좋아요 수, 조회수 중 1개만 선택가능 > Searching(검색) 사용자는 입력한 키워드로 해당 키워드를 포함한 게시글을 조회할 수 있습니다. ex1) some-url?search=후기 >> "후기"가 제목에 포함된 게시글 목록 ex2) "후기" 검색 시 >> 00 방문후기 입니다. (검색 됨) > Filtering(필터링) 사용자는 지정한 키워드로 해당 키워드를 포함한 게시글을 필터링할 수 있습니다. ex1) some-url?hastags=서울 >> “서울" 해시태그를 가진 게시글 목록. ex2) some-url?hastags=서울,맛집 >> “서울" 과 “맛집” 해시태그를 모두 가진 게시글 목록. > Pagination(페이지네이션) 사용자는 1 페이지 당 게시글 수를 조정할 수 있습니다. 단, default 설정은 10개의 게시글로 합니다. ex) some-url?offset=0&limit=10 >> 0번 인덱스 게시글부터 10개의 게시글을 가져옵니다.
- 게시글 상세
* 모든 사용자는 모든 게시글에 보기권한이 있습니다. * 작성자를 포함한 모든 사용자는 본 게시글에 좋아요를 누를 수 있습니다. * 좋아요를 누른 게시글에 다시 좋아요를 누르면, 좋아요는 취소됩니다. * 작성자를 포함한 특정 사용자가 게시글을 상세보기 하면 조회수 1이 증가합니다. (횟수 제한 없음)
- 게시글 수정
* 게시글은 작성자만 수정할 수 있습니다.
- 게시글 삭제
* 게시글은 작성자만 삭제할 수 있습니다.
- 게시글 생성
- 유저관리:
-
- 댓글 기능
- 싫어요/공감 기능
- 조회수가 1인당 1번만 오르도록 제한
- 유저 로그아웃 기능
-
- 본 요구사항에 명시되지 않은 내용은 모두 자유롭게 구상하여 진행해주세요.
- 필수 구현사항에 따라 진행하되, 개인별 완료 가능한 목표만큼 진행해보세요.
Development
-
- 유저관리:
- 회원가입
> 유저 회원가입 기능입니다. * 이메일, 닉네임, 패스워드는 필수값입니다. * 전화번호, 프로필 이미지는 선택값입니다. * 이메일, 닉네임은 중복되지 않습니다. * 패스워드는 반드시 8~20자리의 최소 1개의 소문자, 대문자, 숫자, (숫자키)특수문자로 구성됩니다. * 패스워드는 해싱 후 DB에 저장됩니다.
- 로그인
> 유저 로그인 기능입니다. * DRF-SimpleJwt 라이브리러를 활용했습니다. * 이메일, 패스워드는 필수값입니다. * 입력받은 이메일과 패스워드가 유저 정보와 일치하는지 확인합니다. * 모든 유효성 검사에 통과하면 액세스토큰과 리프레시 토큰을 발급합니다.
- 로그아웃
> 유저 로그아웃 기능입니다. * DRF-SimpleJwt 라이브리러를 활용했습니다. * 리프레시 토큰은 필수값입니다. * 유효한 토큰인지를 확인합니다. * 만료된 토큰인지를 확인합니다. * 모든 유효성 검사에 통과하면 요청받은 리프레시 토큰을 토큰 블랙리스트에 등록합니다. * 단, 기존에 발급된 리프레시 토큰은 모두 사용을 제한합니다.
- 토큰 재발급
> 유저의 토큰을 재발급하는 기능입니다. * DRF-SimpleJwt의 TokenRefreshView 기능을 활용했습니다. * 리프레시 토큰은 필수값입니다. * 유효한 토큰인지를 확인합니다. * 만료된 토큰인지를 확인합니다. * 토큰의 타입을 확인합니다. (오직 리프레시 토큰만 사용가능) * 모든 유효성 검사에 통과하면 요청받은 리프레시 토큰을 기반으로 액세스토큰을 발급합니다. * 단, 리프레시 토큰은 추가로 발급하지 않습니다.
- 회원가입
- 게시글:
- 게시글 목록
> 인증/인가에 통과한 유저는 모든 게시글의 리스트 정보를 조회할 수 있습니다. * 키워드 검색기능(게시글 제목/내용/태그에 해당 키워드가 검색조건으로 사용) * 해시태그 검색기능(다수의 해시태그를 검색조건으로 사용 가능) * 정렬기능(게시글 생성일자/좋아요 수/조회수를 기준으로 오름차순, 내림차순 정렬) * 필터링 기능(현재 게시중인 게시글/삭제된 게시글) * 페이지네이션 기능(사용자가 원하는 게시글 개수를 지정할 수 있음 >> default: 10개)
- 게시글 상세
> 인증/인가에 통과한 유저는 모든 게시글의 상세 정보를 조회할 수 있습니다. * 특정 유저가 게시글을 상세 조회하면 조회수 1이 증가합니다. * 단, 조회수는 ip당 1회만 증가하도록 제한됩니다. * 여기서 클라이언트의 요청이 reverse proxy 서버를 거쳐서 오더라도 클라이언트의 실제 ip를 추출합니다. * 해당 게시글이 존재하는지 확인합니다.
- 게시글 생성
> 인증/인가에 통과한 유저는 게시글을 생성(업로드)할 수 있습니다. * 게시글과 여러개의 해시태그를 함께 생성할 수 있습니다.
- 게시글 수정
> 인증/인가에 통과한 유저는 본인의 게시글을 수정할 수 있습니다. * 해당 게시글이 존재하는지, 본인의 게시글인지를 확인합니다. * 게시글의 제목/내용/태그만 수정할 수 있습니다. * 게시글 수정 시, 다수의 태그를 수정할 수 있습니다.
- 게시글 삭제
> 인증/인가에 통과한 유저는 본인의 게시글을 삭제할 수 있습니다. * 해당 게시글이 존재하는지, 본인의 게시글인지를 확인합니다. * 이미 삭제된 게시글은 다시 삭제할 수 없습니다.
- 게시글 복구
> 인증/인가에 통과한 유저는 본인의 게시글을 복구할 수 있습니다. * 해당 게시글이 존재하는지, 본인의 게시글인지를 확인합니다. * 이미 복구된 게시글은 다시 복구할 수 없습니다.
- 게시글 좋아요
> 인증/인가에 통과한 유저는 모든 게시글에 좋아요를 누르거나 취소할 수 있습니다. * 해당 게시글이 존재하는지 확인합니다.
- 게시글 목록
- 유저관리:
Modeling
API Docs
Deploy
Test
Issue
Guides
-
- 해당 프로젝트를 clone하고, 프로젝트 폴더로 이동합니다.
git clone https://github.com/F5-Refresh/donggyu-sns.git cd project directory
- 가상환경을 만들고, 프로젝트에 필요한 python package를 다운받습니다.
conda create --name project-name python=3.9 conda activate project-name pip install -r requirements.txt
- manage.py 파일과 동일한 위치에서 환경설정 파일을 만듭니다.
ex) .env file ## general ## DEBUG = True ALLOWED_HOSTS = ALLOWED_HOSTS SECRET_KEY = SECRET_KEY ## Docker DB ## MYSQL_TCP_PORT = '3306' MYSQL_DATABASE = MYSQL_DATABASE MYSQL_ROOT_PASSWORD = MYSQL_ROOT_PASSWORD MYSQL_USER = MYSQL_USER MYSQL_PASSWORD = MYSQL_PASSWORD ## AWS RDS ## RDS_HOSTNAME = RDS_HOSTNAME RDS_DB_NAME = RDS_DB_NAME RDS_USERNAME = RDS_USERNAME RDS_PASSWORD = RDS_PASSWORD RDS_PORT = '3306'
- project-name/settings.py에서 DB설정을 적절하게 변경합니다.
Docker로 DB를 구축하는 경우 or AWS RDS로 DB를 구축하는 경우 등 다양한 방법으로 DB를 구축하는 경우에 맞게 DB 설정을 변경합니다. ## Docker DB ## DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : get_env_variable('MYSQL_DATABASE'), 'USER' : 'root', 'PASSWORD': get_env_variable('MYSQL_ROOT_PASSWORD'), 'HOST' : 'localhost', 'PORT' : get_env_variable('MYSQL_TCP_PORT'), } } ''' ## AWS RDS ## DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : get_env_variable('RDS_DB_NAME'), 'USER' : get_env_variable('RDS_USERNAME'), 'PASSWORD': get_env_variable('RDS_PASSWORD'), 'HOST' : get_env_variable('RDS_HOSTNAME'), 'PORT' : get_env_variable('RDS_PORT'), 'OPTIONS' : {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"}, } } '''
- DB의 Table 구조를 최신 modeling에 맞게 설정합니다.
python manage.py migrate
- 개발용 서버를 실행합니다.
python manage.py runserver 0:8000
- 배포용 서버에서 해당 프로젝트를 clone하고, 프로젝트 폴더로 이동합니다.
git clone https://github.com/F5-Refresh/donggyu-sns.git cd project directory
- manage.py 파일과 동일한 위치에서 도커 환경설정 파일을 만듭니다.
ex) .env file ## general ## DEBUG = True ALLOWED_HOSTS = ALLOWED_HOSTS SECRET_KEY = SECRET_KEY ## Docker DB ## MYSQL_TCP_PORT = '3306' MYSQL_DATABASE = MYSQL_DATABASE MYSQL_ROOT_PASSWORD = MYSQL_ROOT_PASSWORD MYSQL_USER = MYSQL_USER MYSQL_PASSWORD = MYSQL_PASSWORD ## AWS RDS ## RDS_HOSTNAME = RDS_HOSTNAME RDS_DB_NAME = RDS_DB_NAME RDS_USERNAME = RDS_USERNAME RDS_PASSWORD = RDS_PASSWORD RDS_PORT = '3306'
- project-name/settings.py에서 DB설정을 적절하게 변경합니다.
Docker로 DB를 구축하는 경우 or AWS RDS로 DB를 구축하는 경우 등 다양한 방법으로 DB를 구축하는 경우에 맞게 DB 설정을 변경합니다. ## Docker DB ## DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : get_env_variable('MYSQL_DATABASE'), 'USER' : 'root', 'PASSWORD': get_env_variable('MYSQL_ROOT_PASSWORD'), 'HOST' : 'db', 'PORT' : get_env_variable('MYSQL_TCP_PORT'), } } ''' ## AWS RDS ## DATABASES = { 'default': { 'ENGINE' : 'django..backends.mysql', 'NAME' : get_env_variable('RDS_DB_NAME'), 'USER' : get_env_variable('RDS_USERNAME'), 'PASSWORD': get_env_variable('RDS_PASSWORD'), 'HOST' : get_env_variable('RDS_HOSTNAME'), 'PORT' : get_env_variable('RDS_PORT'), 'OPTIONS' : {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"}, } } '''
- docker-compose 명령을 사용하여 DB와 Django 서버 컨테이너를 실행시킵니다.
docker-compose -f ./docker-compose.yml up (-d)
Structure
-
📦.github ┣ 📂ISSUE_TEMPLATE ┃ ┗ 📜issue_template.md ┗ 📜pull_request_template.md 📦config ┗ 📂nginx ┃ ┗ 📜nginx.conf 📦core ┣ 📂migrations ┃ ┗ 📜__init__.py ┣ 📂utils ┃ ┣ 📜decorator.py ┃ ┗ 📜get_obj_n_check_err.py ┣ 📜__init__.py ┣ 📜admin.py ┣ 📜apps.py ┣ 📜models.py ┣ 📜tests.py ┗ 📜views.py 📦posts ┣ 📂migrations ┃ ┣ 📜0001_initial.py ┃ ┣ 📜0002_initial.py ┃ ┣ 📜0003_remove_post_tags_post_tags.py ┃ ┣ 📜0004_accessip.py ┃ ┗ 📜__init__.py ┣ 📂tests ┃ ┣ 📜__init__.py ┃ ┣ 📜tests_post_create.py ┃ ┣ 📜tests_post_delete.py ┃ ┣ 📜tests_post_detail.py ┃ ┣ 📜tests_post_like.py ┃ ┣ 📜tests_post_list.py ┃ ┣ 📜tests_post_restore.py ┃ ┗ 📜tests_post_update.py ┣ 📜__init__.py ┣ 📜admin.py ┣ 📜apps.py ┣ 📜models.py ┣ 📜serializers.py ┣ 📜urls.py ┗ 📜views.py 📦sns ┣ 📜__init__.py ┣ 📜asgi.py ┣ 📜settings.py ┣ 📜urls.py ┗ 📜wsgi.py 📦users ┣ 📂migrations ┃ ┣ 📜0001_initial.py ┃ ┗ 📜__init__.py ┣ 📂tests ┃ ┣ 📜__init__.py ┃ ┣ 📜tests_refesh_token.py ┃ ┣ 📜tests_signin.py ┃ ┣ 📜tests_signout.py ┃ ┗ 📜tests_signup.py ┣ 📜__init__.py ┣ 📜admin.py ┣ 📜apps.py ┣ 📜models.py ┣ 📜serializers.py ┣ 📜urls.py ┗ 📜views.py ┣ 📜.env ┣ 📜.gitignore ┣ 📜docker-compose.yml ┣ 📜Dockerfile ┣ 📜manage.py ┣ 📜README.md ┗ 📜requirements.txt