Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/1-blue/deprecated-blequotes
๐ฌ ์ํ / ๋๋ผ๋ง / ๋์ ๋ช
๋์ฌ๋ฅผ ์์ฑํ๋ ๊ฐ๋จํ ์ฌ์ดํธ ๐ฌ
https://github.com/1-blue/deprecated-blequotes
aws-s3 express prisma react redux-toolkit tailwindcss typescript
Last synced: 1 day ago
JSON representation
๐ฌ ์ํ / ๋๋ผ๋ง / ๋์ ๋ช ๋์ฌ๋ฅผ ์์ฑํ๋ ๊ฐ๋จํ ์ฌ์ดํธ ๐ฌ
- Host: GitHub
- URL: https://github.com/1-blue/deprecated-blequotes
- Owner: 1-blue
- Created: 2022-12-07T01:23:34.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2023-06-05T01:33:01.000Z (over 1 year ago)
- Last Synced: 2024-11-10T07:25:58.215Z (about 2 months ago)
- Topics: aws-s3, express, prisma, react, redux-toolkit, tailwindcss, typescript
- Language: TypeScript
- Homepage: https://jslog.co.kr
- Size: 1.36 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ๐ถ ๋ช ๋์ฌ ์ปค๋ฎค๋ํฐ
์ํ / ๋๋ผ๋ง / ๋์์ ๋ช ๋์ฌ๋ฅผ ๊ฐ๋จํ๊ฒ ์์ฑํ๋ ์ปค๋ฎค๋ํฐ์ ๋๋ค.
๐งโ๐ป ์ฌ์ฉํ ๊ธฐ์ ๐งโ๐ป
๐จ ์ฌ์ฉ ํด ๐จ
# ๐น๏ธ ๊ตฌํ ๊ธฐ๋ฅ
1. [`Movie DB API`](https://developers.themoviedb.org/3)๋ฅผ ์ด์ฉํ ์ํ ๋ฐ ๋๋ผ๋ง๋ค์ ๊ฐ์ข ์ ๋ณด ํจ์น ๋ฐ ๊ฒ์
2. [`Kakao Book API`](https://developers.kakao.com/docs/latest/ko/daum-search/dev-guide#search-book)๋ฅผ ์ด์ฉํ ๋์ ๊ฒ์
3. `Image Carousel` ( `react-slick` ์ฌ์ฉ )
4. ๋ช ๋์ฌ ๋ฑ๋ก ๊ธฐ๋ฅ ( [`AWS-S3`์ `presignedURL`](https://1-blue.github.io/posts/AWS-S3-presignedURL)๋ฅผ ์ด์ฉํ ์ด๋ฏธ์ง ๋ฑ๋ก )
5. ๋ช ๋์ฌ์ ์ข์์ ๋ฐ ์ซ์ด์ ๊ธฐ๋ฅ
6. ์ํ / ๋๋ผ๋ง / ๋์ ๊ฒ์ ๊ธฐ๋ฅ ( [`Debouncing`](https://1-blue.github.io/posts/%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81-%EB%A9%94%EB%AA%A8%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98/#%EF%B8%8F-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1--debouncing-) ์ฌ์ฉ )
7. ๋ฌดํ ์คํฌ๋กค๋ง ( [`IntersectionObserver API`](https://1-blue.github.io/posts/Intersection-Observer-API) ์ฌ์ฉ )
8. [`Redux-ToolKit`](https://1-blue.github.io/posts/Redux-Toolkit)์ ์ด์ฉํ ์ ์ญ ์ํ ๊ด๋ฆฌ
9. [`Prisma`](https://1-blue.github.io/posts/prisma)๋ฅผ ์ด์ฉํ `DB`๊ด๋ฆฌ ๋ฐ ๋ฐ์ดํฐ ๊ด๋ฆฌ
10. [AWS-EC2 + nginx + certbot์ ์ด์ฉํ ๋ฐฐํฌ](https://1-blue.github.io/posts/deploy)# ๐ ์ ์ ํ๊ฒฝ
1. OS: `Window11`
2. editor: `VSCode`, `Sourcetree` ( + `Notion`, `Figma` )
3. terminal: `git bash`
4. Database: `Mysql`
6. vcs: `Git` / `GitHub`
7. Front: `React.js`
8. Back: `Node`์ `Express`
9. ์ด๋ฏธ์ง ์ ์ฅ์: `AWS S3`
10. ๋ฐฐํฌ: `AWS-EC2`# ๐ ๊ฐ์ด๋๋ผ์ธ
## ๐ ํ๋ก ํธ ์๋
### 0๏ธโฃ ์ข ์์ฑ ์ค์น
```bash
npm install
```### 1๏ธโฃ ํ๊ฒฝ ๋ณ์ ๋ฑ๋ก
```
# ์๋ฒ URL ( ์ํฉ์ ๋ง๊ฒ ์์ )
REACT_APP_API_URL=http://localhost:3050# "MovieDB" ์ด๋ฏธ์ง URL
REACT_APP_MOVIE_IMAGE_URL=https://image.tmdb.org/t/p/w500
```### 2๏ธโฃ ํ ์คํธ ์คํ
```bash
npm start
```### 3๏ธโฃ ๋น๋
```bash
npm run build
```## ๐ ๋ฐฑ์๋
### 0๏ธโฃ ์ข ์์ฑ ์ค์น
```bash
cd backend
npm install
```### 1๏ธโฃ ํ๊ฒฝ ๋ณ์ ๋ฑ๋ก
```
# ํ๊ฒฝ ๋ณ์
NODE_ENV=development# "Prisma"์์ "Mysql" ์ฐ๊ฒฐ์ ์ํ
DATABASE_URL="mysql://<์ ์ ์ด๋ฆ>:<๋น๋ฐ๋ฒํธ>@localhost:3306/"# "MovieDB" ์์ฒญ ๊ด๋ จ
MOVIE_DB_API_URL=https://api.themoviedb.org/3
MOVIE_DB_API_KEY=# "Kakao Book" ์์ฒญ ๊ด๋ จ
KAKAO_API_URL=https://dapi.kakao.com
KAKAO_API_KEY=# "AWS-S3" ๊ด๋ จ
AWS_BUCKET=<๋ฒํท๋ช >
AWS_REGION=<์ฌ์ฉ์ง์ญ๋ช >
AWS_ACCESS_KEY=
AWS_ACCESS_SECRET_KEY=
```### 2๏ธโฃ ํ ์คํธ ์คํ
```bash
npm run dev
```### 3๏ธโฃ prisma ๋ช ๋ น์ด
```bash
# ๊ฐ์ง ๋ฐ์ดํฐ ๋ฑ๋ก
npx prisma seed# ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ด๊ธฐํ
npx prisma migrate dev# ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ด๊ธฐํ ๋ฐ ๊ฐ์ง ๋ฐ์ดํฐ ๋ฑ๋ก
npx prisma migrate reset
```# โ๏ธ ํ๋ก์ ํธ์ ๊ด๋ จ๋ ํฌ์คํธ๋ค
1. [`Redux`](https://1-blue.github.io/posts/Redux/)
2. [`React` ์คํฌ๋กค ๋ฐฉํฅ ์ฐพ๊ธฐ](https://1-blue.github.io/posts/React-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EB%B0%A9%ED%96%A5/)
3. [`React-Router-Dom`์ `replace`](https://1-blue.github.io/posts/React-Router-Dom/)
4. [`AWS-S3` - `presignedURL` ์ฌ์ฉ ๋ฐฉ๋ฒ](https://1-blue.github.io/posts/AWS-S3-presignedURL/)
5. [`Node.js` + `TypeScript` ์ธํ ๋ฐฉ๋ฒ](https://1-blue.github.io/posts/Setting-NodeJs/)
6. [`IntersectionObserver API`์ ๋ฌดํ ์คํฌ๋กค๋ง](https://1-blue.github.io/posts/Intersection-Observer-API/)
7. [`Debouncing`๊ณผ ์ฌ์ฉ ์์](https://1-blue.github.io/posts/%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81-%EB%A9%94%EB%AA%A8%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98/#%EF%B8%8F-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8B%B1--debouncing-)
8. [`prisma` ์ฌ์ฉ๋ฒ ์ ๋ฆฌ](https://1-blue.github.io/posts/prisma/)
9. [`Redux-ToolKit` + `TypeScript` + `React` ์ฌ์ฉ ๋ฐฉ๋ฒ](https://1-blue.github.io/posts/Redux-Toolkit/)
10. [`blequotes` ๋ง๋ฌด๋ฆฌ ํฌ์คํธ](https://1-blue.github.io/posts/bleqoutes-%EB%A7%88%EB%AC%B4%EB%A6%AC/)# ๐ธ ์คํ ์์
## 0๏ธโฃ ๋ฐ์ํ ๋ ์ด์์ 1## 1๏ธโฃ ๋ฐ์ํ ๋ ์ด์์ 2
## 2๏ธโฃ ๋ฌดํ ์คํฌ๋กค๋ง
## 3๏ธโฃ ์ค์ผ๋ ํค UI
## 4๏ธโฃ ๊ฒ์
## 5๏ธโฃ ๊ฒ์๊ธ ์์ฑ
# ๐ค API
```ts
type ApiType = "axios" | "prisma" | "unknown";// ์ฑ๊ณต ์ response ํ์
type ApiResponse = {
meta: { ok: boolean; type?: ApiType };
data: { message: string } & T;
};// 500 ์คํจ ์ response ํ์
type ApiErrorResponse = ApiResponse<{}>;
```## 0๏ธโฃ Movie
```ts
// ์์ฒญํ ์ํ ์นดํ ๊ณ ๋ฆฌ ( ์ธ๊ธฐ, ํ์ฌ ์์ ๋ฑ )
type MovieCategory = "popular" | "top_rated" | "now_playing";// ์ํ ์ธ์ด
type MovieLanguage = "ko-kr" | "en-us";// ์ํ ํ์
type Movie = {
adult: boolean;
backdrop_path: string;
genre_ids: number[];
id: number;
original_language: string;
original_title: string;
overview: string;
popularity: number;
poster_path: string;
release_date: string;
title: string;
video: false;
vote_average: number;
vote_count: number;
};// ์ํ ์์ธ ํ์
type DetailMovie = {
adult: boolean;
backdrop_path: string;
belongs_to_collection: {
id: number;
name: string;
poster_path: string;
backdrop_path: string;
};
budget: number;
genres: {
id: number;
name: string;
}[];
homepage: string;
id: number;
imdb_id: string;
original_language: string;
original_title: string;
overview: string;
popularity: number;
poster_path: string;
production_companies: {
id: number;
logo_path: string;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
release_date: string;
revenue: number;
runtime: number;
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
title: string;
video: boolean;
vote_average: number;
vote_count: number;
};
```### 1. ์ธ๊ธฐ / ์ต์ / ๊พธ์คํ ์ธ๊ธฐ ์ํ๋ค ์์ฒญ
`GET` - `api/movie`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type FetchMoviesRequest = {
category: MovieCategory;
language?: MovieLanguage;
};
```+ `response`
```ts
type FetchMoviesResponse = ApiResponse<{ movies: Movie[] }>
```### 2. ์ํ ๊ฒ์ ์์ฒญ
`GET` - `api/movie/search`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SearchMoviesRequest = {
title: string;
language?: MovieLanguage;
};
```+ `response`
```ts
type SearchMoviesResponse = ApiResponse<{ movies: Movie[] }>
```### 3. ์ํ ์ถ์ฒ ๊ฒ์์ด๋ค ์์ฒญ
`GET` - `api/movie/suggested`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SuggestMoviesRequest = {
keyword: string;
language?: MovieLanguage;
};
```+ `response`
```ts
type SearchMoviesResponse = ApiResponse<{ titles: string[] }>
```### 4. ์ ์ฌ ์ํ๋ค ์์ฒญ
`GET` - `api/movie/similar`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SimilarMoviesRequest = {
movieIdx: string; // "Movie DB"์์ ์ ๊ณตํ ์๋ณ์
language?: MovieLanguage;
};
```+ `response`
```ts
type SimilarMoviesResponse = ApiResponse<{ movies: Movie[] }>
```### 5. ํน์ ์ํ ์์ธ ์ ๋ณด ์์ฒญ
`GET` - `api/movie/detail`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type DetailMovieRequest = {
movieIdx: string; // "Movie DB"์์ ์ ๊ณตํ ์๋ณ์
language?: MovieLanguage;
};
```+ `response`
```ts
type DetailMovieResponse = ApiResponse<{ movie: DetailMovie }>
```## 1๏ธโฃ Drama
```ts
// ์์ฒญํ ๋๋ผ๋ง ์นดํ ๊ณ ๋ฆฌ ( ์ธ๊ธฐ, ํ์ฌ ์์ ๋ฑ )
type DramaCategory = "popular" | "top_rated" | "on_the_air";// ๋๋ผ๋ง ์ธ์ด
type DramaLanguage = "ko-kr" | "en-us";// ๋๋ผ๋ง ํ์
type Drama = {
backdrop_path: string;
first_air_date: string;
genre_ids: number[];
id: number;
name: string;
origin_country: string[];
original_language: string;
original_name: string;
overview: string;
popularity: number;
poster_path: string;
vote_average: number;
vote_count: number;
};// ๋๋ผ๋ง ์์ธ ํ์
type DetailDrama = {
adult: boolean;
backdrop_path: string;
created_by: {
id: number;
credit_id: string;
name: string;
gender: number;
profile_path: string | null;
}[];
episode_run_time: number[];
first_air_date: string;
genres: {
id: number;
name: string;
}[];
homepage: string;
id: number;
in_production: boolean;
languages: string[];
last_air_date: string;
last_episode_to_air: {
air_date: string;
episode_number: number;
id: number;
name: string;
overview: string;
production_code: string;
runtime: number;
season_number: number;
show_id: number;
still_path: string;
vote_average: number;
vote_count: number;
};
name: string;
next_episode_to_air: null | string;
networks: {
id: number;
name: string;
logo_path: string;
origin_country: string;
}[];
number_of_episodes: number;
number_of_seasons: number;
origin_country: string[];
original_language: string;
original_name: string;
overview: string;
popularity: number;
poster_path: string;
production_companies: {
id: number;
logo_path: null | string;
name: string;
origin_country: string;
}[];
production_countries: {
iso_3166_1: string;
name: string;
}[];
seasons: {
air_date: string;
episode_count: number;
id: number;
name: string;
overview: string;
poster_path: string;
season_number: number;
}[];
spoken_languages: {
english_name: string;
iso_639_1: string;
name: string;
}[];
status: string;
tagline: string;
type: string;
vote_average: number;
vote_count: number;
}
```### 1. ์ธ๊ธฐ / ์ต์ / ๊พธ์คํ ์ธ๊ธฐ ๋๋ผ๋ง๋ค ์์ฒญ
`GET` - `api/drama`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type FetchDramasRequest = {
category: DramaCategory;
language?: DramaLanguage;
};
```+ `response`
```ts
type DetailBookResponse = ApiResponse<{ dramas: Drama[] }>
```### 2. ๋๋ผ๋ง ๊ฒ์ ์์ฒญ
`GET` - `api/drama/search`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SearchDramasRequest = {
title: string;
language?: DramaLanguage;
};
```+ `response`
```ts
type SearchDramasResponse = ApiResponse<{ dramas: Drama[] }>
```### 3. ๋๋ผ๋ง ์ถ์ฒ ๊ฒ์์ด๋ค ์์ฒญ
`GET` - `api/drama/suggested`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SuggestDramasRequest = {
keyword: string;
language?: DramaLanguage;
};
```+ `response`
```ts
type SuggestDramasResponse = ApiResponse<{ titles: string[] }>
```### 4. ์ ์ฌ ๋๋ผ๋ง๋ค ์์ฒญ
`GET` - `api/drama/similar`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SimilarDramasRequest = {
dramaIdx: string; // "Movie DB"์์ ์ ๊ณตํ ์๋ณ์
language?: DramaLanguage;
};
```+ `response`
```ts
type SimilarDramasResponse = ApiResponse<{ dramas: Drama[] }>
```### 5. ํน์ ๋๋ผ๋ง ์์ ์ ๋ณด ์์ฒญ
`GET` - `api/drama/detail`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type DetailDramaRequest = {
dramaIdx: string; // "Movie DB"์์ ์ ๊ณตํ ์๋ณ์
language?: DramaLanguage;
};
```+ `response`
```ts
type DetailDramaResponse = ApiResponse<{ drama: DetailDrama }>
```## 2๏ธโฃ Book
```ts
// ๋์ ํ์
type Book = {
authors: string[];
contents: string;
datetime: string;
isbn: string;
price: number;
publisher: string;
sale_price: number;
status: string;
thumbnail: string;
title: string;
translators: string[];
url: string;
};
```### 1. ํน์ ๋์ ๊ฒ์ ์์ฒญ
`GET` - `api/book/search`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SearchBooksRequest = {
title: string;
};
```+ `response`
```ts
type SearchBooksResponse = ApiResponse<{ books: Book[] }>
```### 2. ๋์ ์ถ์ฒ ๊ฒ์์ด๋ค ์์ฒญ
`GET` - `api/book/suggested`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SuggestedBooksRequest = {
keyword: string;
};
```+ `response`
```ts
type SuggestedBooksResponse = ApiResponse<{ titles: string[] }>
```### 3. ํน์ ๋์์ ์ ์ฌํ ๋์๋ค ์์ฒญ
`GET` - `api/book/similar`
( ์ ์ ๊ธฐ์ค์ผ๋ก ์ ์ฌ ๋์ ๊ฒ์ )+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type SimilarBooksRequest = {
author: string;
};
```+ `response`
```ts
type SimilarBooksResponse = ApiResponse<{ books: Book[] }>
```### 4. ํน์ ๋์์ ์์ธ ์ ๋ณด ์์ฒญ
`GET` - `api/book/detail`+ `Status Code`
1. `200`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type DetailBookRequest = {
bookIdx: string; // "Movie DB"์์ ์ฌ์ฉํ๋ ์๋ณ์
};
```+ `response`
```ts
type DetailBookResponse = ApiResponse<{ book: Book }>
```## 3๏ธโฃ Image
### 1. S3์ presignedURL ์์ฒญ
`GET` - `api/image`+ `Status Code`
1. `201`: ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type FetchPresignedURLRequest = {
name: string;
};
```+ `response`
```ts
type FetchPresignedURLResponse = ApiResponse<{ preSignedURL: string }>
```## 4๏ธโฃ Post
```ts
export const PostCategory: {
MOVIE: 'MOVIE',
DRAMA: 'DRAMA',
BOOK: 'BOOK'
};// ๊ฒ์๊ธ ์นดํ ๊ณ ๋ฆฌ ( ์ํ, ๋๋ผ๋ง, ๋์ )
export type PostCategory = (typeof PostCategory)[keyof typeof PostCategory]// ๊ฒ์๊ธ๋ค ์ ๋ ฌ ๊ธฐ์ค
type PostSortBy = "popular" | "latest";// ๊ฒ์๊ธ
type Post = {
id: number
idx: string
title: string
category: PostCategory
speech: string
like: number
hate: number
updatedAt: Date
time: string | null
episode: number | null
page: number | null
thumbnail: string
}
```+ `take`: ์์ฒญํ ๊ฐ์
+ `lastId`: ์ต๊ทผ์ ์์ฒญํ ๋ง์ง๋ง ๊ฒ์๊ธ์ ์๋ณ์ ( ์ด ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์๋ตํ ๊ฒ์๊ธ์ ๊ฒฐ์ )### 1. ๊ฒ์๊ธ ์์ฑ ์์ฒญ
`POST` - `api/post`+ `Status Code`
1. `201`: ๊ฒ์๊ธ ์์ฑ ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type CreatePostRequest = {
idx: string;
title: string;
category: PostCategory;
speech: string;
thumbnail: string;// ์ํ / ๋๋ผ๋ง ์ฉ
time?: string;// ๋๋ผ๋ง ์ฉ
episode?: number;// ๋์ ์ฉ
page?: number;
};
```+ `response`
```ts
type CreatePostResponse = ApiResponse<{}>
```### 2. ๊ฒ์๊ธ๋ค ๊ฐ์ ธ์ค๊ธฐ ์์ฒญ
`GET` - `api/post`+ `Status Code`
1. `200`: ๊ฒ์๊ธ๋ค ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type GetPostsRequest = {
category: "ALL" | PostCategory;
sortBy: PostSortBy;
take: number;
lastId: number;
};
```+ `response`
```ts
type GetPostsResponse = ApiResponse<{
take: number; // ๋ง์ง๋ง ๊ฒ์๊ธ์ธ์ง ํ๋จํ๊ธฐ ์ํด ๋ณด๋
category: "ALL" | PostCategory;
posts: Post[];
}>
```### 3. ํน์ ๊ฒ์๊ธ ์ข์์/์ซ์ด์ ์์ฒญ
`POST` - `api/post/like`+ `Status Code`
1. `200`: ์ข์์/์ซ์ด์ ์ฑ๊ณต
2. `404`: ์กด์ฌํ์ง ์์ ๊ฒ์๊ธ์ ์์ฒญํจ
3. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type UpdateLikeOrHateRequest = {
id: number;
already: boolean; // ์ด๋ฏธ ์ข์์/์ซ์ด์๋ฅผ ๋๋ ๋์ง ์ฌ๋ถ
isLike: boolean; // ์ข์์๋ฅผ ๋๋ ๋์ง / ์ซ์ด์๋ฅผ ๋๋ ๋์ง
isDuplication: boolean; // ์ข์์๋ฅผ ๋๋ฅธ ์ํ์์ ๋ค์ ์ข์์ / ์ซ์ด์๋ฅผ ๋๋ฅธ ์ํ์์ ๋ค์ ์ซ์ด์๋ฅผ ๋๋ ๋์ง
}
```+ `response`
```ts
type GetPostsResponse = ApiResponse<{ resultPost?: Post }>
```### 4. ํน์ ๋์์ ๊ฒ์๊ธ๋ค ์์ฒญ
`GET` - `api/post/:idx`+ `Status Code`
1. `200`: ์ข์์/์ซ์ด์ ์ฑ๊ณต
2. `500`: ์๋ฒ ๋ฌธ์ ์คํจ+ `request`
```ts
type GetPostsOfTargetRequest = {
idx: string;
sortBy: PostSortBy;
take: number;
lastId: number;
}
```+ `response`
```ts
type GetPostsOfTargetResponse = ApiResponse<{
take: number; // ๋ง์ง๋ง ๊ฒ์๊ธ์ธ์ง ํ๋จํ๊ธฐ ์ํด ๋ณด๋
posts: Post[];
}>
```