I-deul-of-zoo / wanted-feed-service

(1차 과제) 소셜 미디어 통합 Feed 서비스
0 stars 2 forks source link

(1차 과제) 소셜 미디어 통합 Feed 서비스

목차

개요

본 서비스는 유저 계정의 해시태그(”#dani”) 를 기반으로 인스타그램, 스레드, 페이스북, 트위터 등 복수의 SNS에 게시된 게시물 중 유저의 해시태그가 포함된 게시물들을 하나의 서비스에서 확인할 수 있는 통합 Feed 어플리케이션 입니다.

이를 통해 본 서비스의 고객은 하나의 채널로 유저(”#dani”), 또는 브랜드(”#danishop”) 의 SNS 노출 게시물 및 통계를 확인할 수 있습니다.

유저히스토리

요구사항

개발환경세팅

가상환경: venv

언어 및 프레임워크: Python DjangoREST

데이터 베이스: MySQL


Installation & Run

MySQL DB 세팅

환경 세팅

python -m venv venv
source venv/Scripts/activate  ## 가상환경 실행. git bash기준

pip install -r requirements.txt

python manage.py migrate


ER-Diagram

ER-Diagram

초기 설정 : 데이터


API Documentation

API-Documentation
1. 회원가입 API #### Request ```plain POST /v1/posts/registration ``` - Auth Required: False | Body Parameter | Type | Description | | :------------- | :------- | :---------------------------- | | `username` | `string` | **Required**. 아이디(해시태그) | | `email` | `string` | **Required**. | | `password1` | `string` | **Required**. | | `password1` | `string` | **Required**. | #### Response ```http HTTP 201 Created Allow: POST, OPTIONS Content-Type: application/json Vary: Accept [{ "access": "eyJh...", "refresh": "eyJhbGci...", "user": { "pk": 2, "username": "user2", "email": "user1@gmail.com", "first_name": "", "last_name": "" } } ] ```
2. JWT로그인 API #### Request ```plain POST /v1/auth/login ``` - Auth Required: False | Body Parameter | Type | Description | | :------------- | :------- | :---------------------------- | | `username` | `string` | **Required**. 아이디(해시태그) | | `auth_code` | `string` | **Required**. 승인코드 | #### Response ```http HTTP 200 OK Allow: POST, OPTIONS Content-Type: application/json Vary: Accept { "access": "eyJhbG...." "refresh": "eyJhbG....", "user": { "pk": 1, "username": "testuser", "email": "testuser@email.com", "first_name": "", "last_name": "" } } ```
3. 가입승인(인증코드) API #### Request ```plain POST /v1/auth/code ``` - Auth Required: False | Body Parameter | Type | Description | | :-------- | :------- | :------------------------- | | `username` | `string` | **Required**. 아이디(해시태그) | | `auth_code` | `string` | **Required**. 승인코드 | #### Response ```http HTTP/1.1 200 Content-Type: application/json { "message": "가입승인이 완료되었습니다." } ```
4. 가입승인(재전송) API #### Request ```plain GET /v1/auth/code/ ``` - Auth Required: False #### Response ```http HTTP/1.1 200 Content-Type: application/json { "메일 전송 완료": { "subject": "메일제목", "message": "RD8W2X", "to": [ "test3@test.com" ] } } ```
5. 로그아웃 API #### Request ```plain GET /v1/auth/logout ``` - Auth Required: True | Body Parameter | Type | Description | | :------------- | :------- | :------------------------- | | `username` | `string` | **Required**. 아이디(해시태그) | | `auth_code` | `string` | **Required**. 승인코드 | #### Response ```http HTTP 200 OK Allow: GET, POST, HEAD, OPTIONS Content-Type: application/json Vary: Accept { "detail": "로그아웃되었습니다." } ```
6. 게시물 목록 API #### Request ```plain GET /v1/posts/ example) GET /v1/posts/?hashtag=user2&page_count=5&search=날씨 ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | | Query Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------------- | | `hashtag` | `string` | default: 계정의 username, **정확히 일치** | | `type` | `string` | 미설정시 모두 검색 | | `order_by` | `string` | default: `created_at` (`created_at`, `updated_at`,`like_count`,`share_count`, `view_count`) | | `search_by` | `string` | default: `title,content` (`title`, `content`) | | `search` | `string` | 미설정시 모두 검색, **포함** | | `page_count` | `number` | default: 10 | | `page` | `number` | default: 1 | #### Response ```http HTTP/1.1 200 Content-Type: application/json { "count": 16, "next": "http://127.0.0.1:8000/v1/posts/?hashtag=user2&page=2&page_count=5", "previous": null, "results": [ { "id": 1, "content": "오늘은 날씨가 정말 좋네요! 햇빛이 ...", "content_id": "XyZ4aBcD9e", "type": "facebook", "title": "facebook", "view_count": 1000, "like_count": 500, "share_count": 500, "updated_at": "2023-10-27T00:00:00", "created_at": "2023-10-27T00:00:00", "author": "author_F1" }, { "id": 4, "content": "오늘은 친구들과 함께 영화를 보러 갔...", "content_id": "dV8fGhIu2J", "type": "facebook", "title": "facebook", "view_count": 1000, "like_count": 500, "share_count": 500, "updated_at": "2023-10-30T00:00:00", "created_at": "2023-10-30T00:00:00", "author": "author_F2" }, { "id": 6, "content": "미세먼지도 적고 해도 좋아서 등산했어...", "content_id": "XyZ4aBcD10e", "type": "facebook", "title": "facebook", "view_count": 1000, "like_count": 500, "share_count": 500, "updated_at": "2023-11-01T00:00:00", "created_at": "2023-11-01T00:00:00", "author": "author_F4" }, { "id": 8, "content": "방금 새로운 책을 다 읽었어요. 이 ...", "content_id": "L3mN0oP2iQ", "type": "facebook", "title": "facebook", "view_count": 1000, "like_count": 500, "share_count": 500, "updated_at": "2023-11-03T00:00:00", "created_at": "2023-11-03T00:00:00", "author": "author_F6" }, { "id": 11, "content": "오늘은 날씨가 정말 좋네요! 햇빛이 ...", "content_id": "9pRtYqWxKz", "type": "instagram", "title": "instagram", "view_count": 1000, "like_count": 500, "share_count": 500, "updated_at": "2023-11-06T00:00:00", "created_at": "2023-11-06T00:00:00", "author": "author_I1" } ] } ```
7. 게시물 상세 API #### Request ```plain GET /v1/posts/ EX) GET /v1/posts/1/ ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | #### Response ```http HTTP 200 OK Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS Content-Type: application/json Vary: Accept { "id": 1, "content": "오늘은 날씨가 정말 좋네요! 햇빛이 ...", "content_id": "XyZ4aBcD9e", "type": "facebook", "title": "facebook", "view_count": 1003, "like_count": 501, "share_count": 500, "updated_at": "2023-10-30T22:15:19.275050", "created_at": "2023-10-27T00:00:00", "author": "author_F1" } ```
8. 게시물 좋아요 API #### Request ```plain POST /v1/posts//like EX) POST /v1/posts/1/like ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | #### Response ```http HTTP 200 OK Allow: POST, OPTIONS Content-Type: application/json Vary: Accept { "message": "facebook 게시글에 좋아요 개수가 올라갔습니다.", "like_count": 501 } ```
9. 게시물 좋아요 취소 API (추가기능) #### Request ```plain DELETE /v1/posts//like EX) DELETE /v1/posts/1/like ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | #### Response ```http HTTP 200 OK Allow: POST, DELETE, OPTIONS Content-Type: application/json Vary: Accept { "message": "facebook 게시글에 좋아요 표시가 취소되었습니다.", "like_count": 499 } ```
10. 게시물 공유 API #### Request ```plain POST /v1/posts//share/ ex) /v1/posts/1/share/ ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | | Body Parameter | Type | Description | | :------------- | :------- | :---------------------- | | `content_id` | `string` | **Required**. 게시글 id | | `type` | `string` | **Required**. SNS 타입 | #### Response ```http HTTP/1.1 200 Content-Type: application/json { "message": "공유 성공", "share_count": 525, "sns_type": "facebook", "url": "https://www.facebook.com/share/XyZ4aBcD9e" } ```
11. 통계 API #### Request ```plain GET /v1/posts/statistics/?value=view_count&type=date&hashtag=사용자계정(날씨)' ``` #### Rquest Header | Parameter | Type | Description | | :-------------- | :------- | :-------------------------------------- | | `Authorization` | `string` | **Required**. 'Bearer eyJhbGciOiJIU...' | | `Content-Type` | `string` | **Required**. `application/json` | | Query Parameter | Type | Description | | :-------------- | :------- | :-----------------------------------------| | `hashtag` | `string` | default: 계정의 username, **정확히 일치** | | `type` | `string` | **필수**, (`date`, `hour`) | | `start` | `date` | default: 2023-10-01 과 같이 데이트 형식이며 조회 기준 시작일을 의미합니다. (오늘로 부터 7일전) | | `end` | `date` | default: 2023-10-25 과 같이 데이트 형식이며 조회 기준 시작일을 의미합니다. (오늘 날짜) | `value` | `string` | default: `count` (`count`,`view_count`,`like_count`,`share_count`) | #### Response ```http HTTP/1.1 200 Content-Type: application/json [{ "total": 2000, // 오늘부터 7일전 사이의 모든 게시글 조회수 "count_dict": { // 7일전부터 오늘까지 하루당 총 조회수 "2023-10-23": 0, "2023-10-24": 0, "2023-10-25": 0, "2023-10-26": 0, "2023-10-27": 1000, "2023-10-28": 0, "2023-10-29": 1000 } } ] ```


프로젝트 진행 및 이슈 관리


구현과정(설계 및 의도)

  1. 환경설정

    • 공통의 환경을 구축하는 것이 중요하다고 생각해서 첫 팀 프로젝트인 만큼 환경설정 부분에서 시간 소요가 많았습니다.
    • 아래와 같이 환경설정을 시도했지만 결국 로컬에서 직접 가상환경을 설정해 사용하는 것으로 결정했습니다.

      Poetry 적용한 Docker로 환경설정 > pip 이용한 Docker 환경설정 > 개인 환경설정

    • 결국 Docker는 이용하지 못했지만 다음 프로젝트에는 꼭 도커를 적용한 환경 설정을 성공시킬 수 있는 경험치가 쌓였다고 생각합니다.
  2. RESTful API 설계

    • 요구사항을 파악한 뒤 업무를 어떤 방식으로 나눌지 논의하고 그 기준에 따라 GitHub의 Issue에 등록해서 업무를 구분하고 분배했습니다.


TIL 및 회고


Authors

이름 github주소
강석영 https://github.com/mathtkang
김수현 https://github.com/tneoeo2
오동혁 https://github.com/airhac
유진수 https://github.com/YuJinsoo