https://github.com/codestates-seb/seb45_main_026
๐งโ๐ป ํจ๊ป ์ฑ์ฅํ๊ธฐ ์ํ ์ ํ, Prometheus
https://github.com/codestates-seb/seb45_main_026
Last synced: about 1 year ago
JSON representation
๐งโ๐ป ํจ๊ป ์ฑ์ฅํ๊ธฐ ์ํ ์ ํ, Prometheus
- Host: GitHub
- URL: https://github.com/codestates-seb/seb45_main_026
- Owner: codestates-seb
- License: mit
- Created: 2023-08-18T04:20:05.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-03-27T07:25:23.000Z (about 2 years ago)
- Last Synced: 2025-04-13T01:45:46.146Z (about 1 year ago)
- Language: Java
- Homepage: https://www.itprometheus.net/
- Size: 18.5 MB
- Stars: 15
- Watchers: 3
- Forks: 6
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Team. OppenHeimer
IT ๊ต์ก ์คํ ํ๋ซํผ
๐งโ๐ป ํจ๊ป ์ฑ์ฅํ๊ธฐ ์ํ ์ ํ, Prometheus
ํ๋ก์ ํธ ๊ธฐ๊ฐ: 2023.08.24 ~ 2023.09.22
## ๐ ๋ฐฐํฌ์ฃผ์ : [PROMETHEUS](https://www.itprometheus.net)
- ๊ฒ์คํธ์ฉ ID/PW : guest@gmail.com / 1q2w3e4r!
- ๋ง์์ ๋์ ๋ค๋ฉด โญ ๋ถํ๋๋ฆฝ๋๋ค! ใ
ใ
## ๐ซ ์๊ฐ
> ๐ง ๋ถ๋ด์์ด IT ๊ต์ก ๋์์์ ๋ณด๊ณ ์ฌ๋ฆด ์ ์๋ ๊ณต๊ฐ์ด ์์๊น?
> ๊ฐ๋ฒผ์ด ๋ง์์ผ๋ก ๋ณผ ์ ์๋ IT ์์์ด ์์์ผ๋ฉด ์ข๊ฒ ๋ค..
- ์ด๋ค ์๊ฒฉ ์กฐ๊ฑด์ด๋ ์ฌ์ฌ ์์ด ์์ ๋ง์ IT ๋
ธํ์ฐ๋ฅผ ๊ฐํธํ๊ฒ ์ฐ๊ณ ์ฌ๋ฆด ์ ์์ต๋๋ค.
- ๐ธ ๋ฌด๋ฃ ์์, ๋ฆฌ์๋ ์ ๋ฆฝ๊น์ง ๋ค์ํ ํํ์ด ์์ด์.
- ๊ตฌ๋
, ์นดํ
๊ณ ๋ฆฌ ๋ฑ์ผ๋ก ์์ ์๊ฒ ์๋ง์ ์์์ ์ฐพ์ผ์ธ์!
---
# ๐ [๋ชฉ์ฐจ](#index)
- [ํ์ ์๊ฐ](#team)
- [๊ธฐ์ ์คํ](#tech)
- [Idea](#idea)
- [๊ฐ๋ฐ ๋ฌธ์](#document)
- [์ํคํ
์ฒ](#architecture)
- [ERD](#erd)
- [์๋น์ค ํ์ด์ง](#outputs)
- [[FE] ์/์ด๋ป๊ฒ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋์?](#whyfe)
- [[BE] ์/์ด๋ป๊ฒ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋์?](#whybe)
- [ํ
์คํธ/๋ชจ๋ํฐ๋ง](#test)
- [ํ๊ณ ](#retrospection)
# ๐จโ๐จโ๐งโ๐ง ํ์ ์๊ฐ
|[๊นํ๋ฆผ](https://github.com/HyerimKimm)|[๋ฐฉ์นํ](https://github.com/BangSeung)|[์ด์ข
๋ฒ](https://github.com/JB0129)|[๊นํธ๋น](https://github.com/hobeen-kim)|[๊น์ง์](https://github.com/oksu01)|[ํจ์์ค](https://github.com/da9dac)|
|:---:|:---:|:---:|:---:|:---:|:---:|
|||||||
|FE ๋ถํ์ฅ|FE|FE|BE ํ์ฅ|BE|BE|
FE ๋ด๋น ํํธ (๐ Click)
+ **๊นํ๋ฆผ(๋ถํ์ฅ)**
- ์ฌ์ฉ์ ์ธ์ฆ, OAuth, ํ์์ ๋ณด ๊ด๋ฆฌ ๊ธฐ๋ฅ ๊ตฌํ
- ๊ฒฐ์ ๋ชฉ๋ก, ๋ฆฌ์๋ ๋ชฉ๋ก ๋ฌดํ์คํฌ๋กค ์ ์ฉ
- React hook form ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ
- ์์ ํ์ด์ง ๊ตฌํ
- ํด๋ฆฐ ์ฝ๋๋ฅผ ๊ณ ๋ คํ Custom hook, ์ฌํ์ฉ ์ปดํฌ๋ํธ ๊ตฌํ, API ๋ก์ง ๋ถ๋ฆฌ
- ๋์์ธ ์์คํ
, storybook ์ ์ฉ
- ํด๋ผ์ด์ธํธ ๋ฐฐํฌ ๊ด๋ฆฌ
+ **๋ฐฉ์นํ**
- ์์ ํํฐ๊ธฐ๋ฅ ๊ตฌํ
- ๊ฒ์๊ธฐ๋ฅ ๋ฐ ์๋์์ฑ ๊ตฌํ
- ๊ฐ์ ๋ฐ ์ฑ๋ ๋ชฉ๋ก ์ ๋ฐ ๊ตฌํ ๋ฐ ๋ฌดํ์คํฌ๋กค ์ ์ฉ
- ์ฑ๋ํ์ด์ง ๊ตฌํ
+ **์ด์ข
๋ฒ**
- S3 Presign-url๋ฅผ ํตํ ์ด๋ฏธ์ง ๋ฐ ๋์์ ์
๋ก๋
- ๊ฐ์ ๋ฌธ์ CRD
- ์ฅ๋ฐ๊ตฌ๋ ๋ฆฌ์คํธ CRUD
- TossPayment ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ
- React-Player ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ, ์ปค์คํ
์ปจํธ๋กค๋ฌ ๊ตฌํ, 1๋ถ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
- ๋ฆฌ๋ทฐ CRUD, ํํฐ ๊ธฐ๋ฅ, Pagination
- ๋ด ๊ฐ์ ํ์ฑํ/๋นํ์ฑํ ๊ธฐ๋ฅ
BE ๋ด๋น ํํธ (๐ Click)
+ **๊นํธ๋น(ํ์ฅ)**
- AWS ์ํคํ
์ฒ ์ค๊ณ ๋ฐ ํ๊ฒฝ ๊ตฌ์ถ
- Git Actions CI/CD ๊ตฌ์ถ
- Logging ๋ฐ Cloudwatch ๋ชจ๋ํฐ๋ง
- API Rest docs ๋ฌธ์ํ
- ๋น๋์ค ๊ด๋ จ ๊ธฐ๋ฅ, ์ฃผ๋ฌธ/๊ฒฐ์ ๊ธฐ๋ฅ, ์ฑ๋ ๊ณต์ง์ฌํญ ๊ธฐ๋ฅ
+ **๊น์ง์**
- ์ฑ๋ ๊ธฐ๋ฅ
- T๋น๋์ค ๋ฆฌ๋ทฐ ๊ธฐ๋ฅ
- ํตํฉ ํ
์คํธ(์ฑ๋, ๋ฆฌ๋ทฐ, ๊ณต์ง์ฌํญ)
+ **ํจ์์ค**
- ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์
, OAuth (์ธ์ฆ ๋ฐ ์ธ๊ฐ ๊ธฐ๋ฅ) ๊ธฐ๋ฅ
- ํ์ ์ ๋ณด ๊ด๋ จ CRUD ๊ธฐ๋ฅ
- API Rest docs ๋ฌธ์ํ
- ํตํฉ ํ
์คํธ(ํ์, ๋น๋์ค, ์ธ์ฆ, ์ฃผ๋ฌธ)
### Front-end

### Back-end


### Dev-Ops & Tool

์์ด๋์ด ํ์ธ (๐ Click)
์ ํฌ๋ ๊ธฐ์กด ๊ต์ก ๋์์ ํ๋ซํผ์ ๋ฌธ์ ์ ์ผ๋ก ์์ฐ์์ ๊ตฌ๋งค์์ ์ญํ ์ด ๋๋ ์ง๊ณ ์ฝ๊ฒ ์์ฐ์๊ฐ ๋ ์ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ์ต๋๋ค. ํ๋งค๋ฅผ ์ํ ๊ต์ก ์์์ ์
๋ก๋ํ๊ธฐ ์ํด์๋ ์ผ์ ์ฌ์ฌ๋ฅผ ํต๊ณผํด์ผ ํ๊ฑฐ๋, ์์ง์ ๋์์์ ์ฌ๋ฌ ๊ฐ ์ฐ์ ํ ํ๋์ ๊ฐ์๋ก ๋ฌถ์ด์ผ ํ๋ ๋ฑ ์์ฐ์๋ก ์ง์
ํ๊ธฐ ์ํ ์ฅ๋ฒฝ์ด ๋์์ต๋๋ค.
๋ฐ๋ผ์ ์ด๋ฅผ ํด๊ฒฐํ๊ณ ๋๊ตฌ๋ ์์ฐ์์ด์ ์๋น์๊ฐ ๋ ์ ์๋๋ก IT ๊ต์ก ์คํ ํ๋ซํผ์ ์ ๊ณตํ๊ธฐ ์ํด ์๋น์ค๋ฅผ ๊ธฐํํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฌด๋ฃ ๋์์ ์
๋ก๋, ๋ฆฌ๋ทฐ ์์ฑ, ๋ฌธ์ ํ๊ธฐ ๋ฑ์ ํ๋์ผ๋ก ์ฝ๊ฒ ๋ฆฌ์๋๋ฅผ ์ ๋ฆฝํ๊ณ ํ์ฉํ ์ ์๋๋ก ์ ๋ํ์ฌ ํ๋ซํผ์ ์ด์ฉ์ด ์ ์ํ๋ ์ ์๋๋ก ํ์์ต๋๋ค.
- ์ฌ์ฉ์ ์๊ตฌ์ฌํญ ์ ์์ ๋ฐ๋ก๊ฐ๊ธฐ โ [์๊ตฌ์ฌํญ ์ ์์ ํ์ผ](https://1drv.ms/x/s!AjqmbzT14UKwi0P6wFF3pjN1tkgw?e=mchNti)
- API ๋ช
์ธ์ ๋ฐ๋ก๊ฐ๊ธฐ โ [API ๋ช
์ธ์ (restDocs)](https://api.itprometheus.net)
- Figma ๋ฐ๋ก๊ฐ๊ธฐ โ [Figma](https://www.figma.com/file/PXVOZwRkw6LmWof1HUL2q1/%ED%94%84%EB%A1%9C%EB%A9%94%ED%85%8C%EC%9A%B0%EC%8A%A4-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%ED%99%94%EB%A9%B4-%EC%84%A4%EA%B3%84%EC%84%9C?type=design&node-id=0-1&mode=design&t=FxvRqxuBDV44mvy0-0)
- Storybook ๋ฐฐํฌ ๋งํฌ ๋ฐ๋ก๊ฐ๊ธฐ โ [Storybook](https://6509249be693180105e6fcc7-tgkycquvac.chromatic.com/?path=/docs/configure-your-project--docs)
- ๊ฐ๋ฐ์ ํ
์คํธ ๋ฌธ์ ๋ฐ๋ก๊ฐ๊ธฐ โ [๊ฐ๋ฐ์ ํ
์คํธ ํ์ผ](https://1drv.ms/x/s!AjqmbzT14UKwi0404Ht2GZMTb-oD?e=Djm5VW)
ERD ๋ณด๊ธฐ (๐ Click)
์ํคํ
์ฒ ์์ธ ํ์ธ (๐ Click)

### ์น ํด๋ผ์ด์ธํธ
- S3 ๋ฒํท์ ์น ์๋ฒ ๋ฐฐํฌ
- CloudFront ์ Route53 ์ ํตํด ๋ผ์ฐํ
, HTTPS ์๋ฒ ๊ตฌ์ถ, ์ ์ ํ์ผ ์บ์ฑ
### ์ ํ๋ฆฌ์ผ์ด์
์๋ฒ
- private subnet ์ ์ธ๋ถ์ ๊ฒฉ๋ฆฌํ์ฌ ๋ฐฐํฌ, NAT instance ๋ก ์์๋ฐ์ด๋ ํต์
- Load Balancer ์ Auto Scaling Group ์ผ๋ก ํธ๋ํฝ ๋ถ์ฐ, ๊ฐ์ฉ์ฑ ํ๋ณด
### ๋ฐ์ดํฐ ๋ฒ ์ด์ค
- RDS(MySQL) ์ด์คํ ๊ตฌ์ฑ, Redis Cluster ๊ตฌ์ถ
### CloudWatch
- API, DB ์๋ต ์๊ฐ ํ์ธ
- ์๋ฌ ๋ก๊ทธ ๋ก๊น
- ASG ๋ฉ๋ชจ๋ฆฌ ๋ฐ CPU, ๊ฐ ์์ฒญ๋ณ ์๋ต ์๊ฐ ๋ชจ๋ํฐ๋ง[๋์๋ณด๋ ๋ฐ๋ก๊ฐ๊ธฐ](https://cloudwatch.amazonaws.com/dashboard.html?dashboard=prometheus-dashboard&context=eyJSIjoidXMtZWFzdC0xIiwiRCI6ImN3LWRiLTU4OTc5NDU0NjI0NCIsIlUiOiJ1cy1lYXN0LTFfUXd0TzZvdWxRIiwiQyI6IjEyZ2E2M2NrNDZzMHBudTZqZTI4c25tamZ2IiwiSSI6InVzLWVhc3QtMTo4YTAyZDc0YS0zOTVjLTQxOGYtYjQzMS0wODQwODdlMGZhYzciLCJNIjoiUHVibGljIn0%3D&start=PT1H&end=null)
### ์ ์ ๋ฆฌ์์ค ํ์ผ
- ํด๋ผ์ด์ธํธ๊ฐ ์ง์ s3 ๋ฒํท์ ์
๋ก๋ (presignedUrl ํ์ฉ)
- CloudFront ๋ก ํ์ผ ์บ์ฑ
์๋น์ค ํ์ด์ง ํ์ธ (๐ Click)
|์์ ํ์ด์ง|๋ก๊ทธ์ธ ํ์ด์ง|
|------|---|
|
|
|
|ํ์๊ฐ์
ํ์ด์ง|๋น๋ฐ๋ฒํธ ์ฐพ๊ธฐ ํ์ด์ง|
|------|---|
|
|
|
|๊ฐ์ ๋ชฉ๋ก ํ์ด์ง|๊ฐ์ ์์ธ ํ์ด์ง|
|------|---|
|
|
|
|๋ฌธ์ ํ๊ธฐ ํ์ด์ง|์ฅ๋ฐ๊ตฌ๋ ํ์ด์ง|
|------|---|
|
|
|
|๊ฐ์ ์
๋ก๋ ํ์ด์ง|๋ฌธ์ ์
๋ก๋ ํ์ด์ง|
|------|---|
|
|
|
|์ฑ๋ ์ ๋ณด ํ์ด์ง|๊ตฌ๋
๋ชฉ๋ก ํ์ด์ง|
|------|---|
|
|
|
|๋ฆฌ์๋ ์กฐํ ํ์ด์ง|๊ฒฐ์ ๋ด์ญ ํ์ด์ง|
|------|---|
|
|
|
|์ ์ฐ๋ด์ญ ํ์ด์ง|์์ฒญ๊ธฐ๋ก ํ์ด์ง|
|------|----|
|
|
|
|๊ด๋ฆฌ์์ฉ - ์ ๊ณ ๋ ๋น๋์ค ๋ชฉ๋ก|๊ด๋ฆฌ์์ฉ - ์ ๊ณ ๋น๋์ค ์์ธ|
|------|----|
|
|
|
# โจ [FE] ์/์ด๋ป๊ฒ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋์?
FE ๊ธฐ์ ์์ธ ์ค๋ช
ํ์ธ (๐ Click)
## React Hook Form

๋๋ฌด ๋ง์ input state๊ด๋ฆฌ๋ก ์ธํ ์ฝ๋์ ๊ฐ๋
์ฑ ์ ํ์ ์ฆ์ ํ๋ฉด ์ฌ๋๋๋ง์ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์ฉํ์ต๋๋ค.
React Hook Form ์ input ์
๋ ฅ๊ฐ์ ref ํ์์ผ๋ก ์ ์ดํ์ฌ ํ๋ฉด์ ์ฌ๋๋๋ง์ ์ต์ํํ๊ณ ,
```register```, ```handleSubmit```, ```formState```, ```useWatch``` ๋ฑ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ
๋ณต์กํ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋๋ก ๋์์ค๋๋ค.
## Custom Hook

๋ฐ๋ณต ์ฌ์ฉ๋๋ ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด Custom Hook์ ์์ฑํ์ต๋๋ค.
Refresh Token์ ์ด์ฉํ Authorization ํ ํฐ ์ฌ๋ฐ๊ธ ๋ก์ง ์ฌํ์ฉ
```useLogout```, ```useLongPress``` ```useConfirm``` ๋ฑ์ ๋ก์ง์ ์ฌํ์ฉ ํ๊ธฐ ์ํด ์ฌ์ฉํ์ต๋๋ค.
## react-intersection-observer

๋ฌดํ ์คํฌ๋กค์ ๊ตฌํํ๊ธฐ ์ํด์ ์ฌ์ฉํ์ต๋๋ค.
styled-component๋ฅผ ์ฌ์ฉํ ์ด๋ฒ ํ๋ก์ ํธ์์ ```useRef```๋ ```addEventListener```๋ฑ์ ๋ฐ๋ก ์ค์ ํ ํ์ ์์ด ```useInView```๋ก ๊ฐํธํ๊ฒ ์คํฌ๋กค ๋ฐ๋ฅ ๊ฐ์ง ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค.
## Redux Toolkit with Persistent

๋ก๊ทธ์ธ ์ ๋ณด, ์ ์ ์ ๋ณด, ๋คํฌ๋ชจ๋ ๋ฑ UI ์ค์ ์ ๋ณด, ์ฅ๋ฐ๊ตฌ๋ ์ ๋ณด, ์ฌ์ ๋น๋์ค ์ ๋ณด ๋ฑ์ ์ ์ญ ์ํ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด์ Redux Toolkit์ ์ฌ์ฉํ์ต๋๋ค. Redux Toolkit์ ์ฌ์ฉํ๋ฉด Redux์์ action ์์ฑ์ ๋ฐ๋ก ์์ฑํด์ฃผ์ง ์์๋ ๋๋ค๋ ์ฅ์ ์ด ์์ผ๋ฉฐ, ```redux-persist```์ ์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํฉํ์ฌ ์ํ๋ ์ํ ์ ๋ณด๋ง ๋ก์ปฌ์คํ ๋ฆฌ์ง์ ์๋์ผ๋ก ์ ์ฅ๋๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
## react-player

๊ธฐ์กด์ video ํ๊ทธ์์์ ๊ธฐ๋ฅ๋ค์ ์ข ๋ ์ฝ๊ฒ ์์ฑ๋ค์ ์ ๊ทผํ ์ ์์ด์, ์ปค์คํ
์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค ๋ react-player์ ๋ด์ฅ๋ ๋ฉ์๋๋ค์ ์ฌ์ฉํด ๊ธฐ์กด๋ณด๋ค ๊ฐํธํ๊ณ ๋น ๋ฅด๊ฒ ์์
์ด ๊ฐ๋ฅํฉ๋๋ค.
## Storybook & Figma Token
| ๋คํฌ๋ชจ๋/๋ผ์ดํธ๋ชจ๋ switch | storybook |
|-------------|---------|
|
|
|
๐๐ป storybook chromatic ๋ฐฐํฌ ๋งํฌ ๋ฐ๋ก๊ฐ๊ธฐ
์ ์ฒด ํ๋ฉด ๋์์ธ์ ํต์ผ์ฑ์ ์งํค๊ณ ๋คํฌ๋ชจ๋ ๋ฑ ์ ์ฒด UI ์ค์ ์ ๋ณ๊ฒฝํ๊ธฐ ์ํด์ Figma Token์ ์ ์ฉํ์์ผ๋ฉฐ,
์ฌ์ฌ์ฉํ ์ปดํฌ๋ํธ์ ๋์์ธ์ ํ์ธํ๋ฉฐ ์ฌ์ฉํ ์ ์๋๋ก Storybook์ ์ ์ฉํ์ต๋๋ค.
## CSS keyframes

๋ฉ์ธํ์ด์ง์ Viewport ์ ๋๋ฉ์ด์
๊ณผ ๋กค๋ง ๋ฐฐ๋, ์ฌ์ด๋๋ฐ ๋์์ธ์ ์ํด์ styled-component์ keyframes๋ฅผ ์ ์ฉํ์ฌ ์ ๋๋ฉ์ด์
์ ๊ตฌํํ์ต๋๋ค.
## react-flicking

๋ฉ์ธํ์ด์ง ๋ ๋ฒ์งธ ํ์ด์ง์ ์ฌ๋ผ์ด๋ ๋ฐฐ๋๋ฅผ ๋ง๋ค๊ธฐ ์ํด์ react-flicking UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ฉํ์ต๋๋ค.
# โจ [BE] ์/์ด๋ป๊ฒ ์ด ๊ธฐ์ ์ ์ฌ์ฉํ๋์?
BE ๊ธฐ์ ์์ธ ์ค๋ช
ํ์ธ (๐ Click)
## API ๋ฌธ์ํ
| ๋ฌธ์ ๋ฉ์ธ ํ์ด์ง | API์ ๋ฐ๋ฅธ ์์ธ ํ์ด์ง |
|-----|-----|
|
|
|
Swagger ๋ ๊ฐ๋จํ๊ณ ๋น ๋ฅด๊ฒ ํด๋ผ์ด์ธํธ์๊ฒ API ๋ฌธ์๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋ฌธ์๊ฐ ์ค์ API์ ๋ค๋ฅด๊ฑฐ๋ ์ฑ๋ฅ์ ๋ณด์ฅ ๋ฐ์ง ๋ชปํฉ๋๋ค.
๋ฐ๋ผ์ ์ด๋ฒ ํ๋ก์ ํธ์์๋ ๊ฒ์ฆ๋ API ์ ์ ๊ณต๊ณผ ๊น๋ํ API ๋ก์ง ์์ฑ์ ์ํด Spring Rest Docs๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
## OAuth
| ํด๋ผ์ด์ธํธ | ์๋ฒ |
|-----|---------|
|
|
|
๋ก์ปฌ ๋กํฌ์ธ ์ธ์๋ ๊ฐํธํ ์ธ์ฆ ๋ฐฉ์ ์ ๊ณต์ ์ํด
๊ตฌ๊ธ, ์นด์นด์ค, ๊นํ๋ธ ๋ก๊ทธ์ธ์ ์ ์ฉํ์ต๋๋ค.
๊ธฐ์กด์ ํด๋ผ์ด์ธํธ๊ฐ OAuth ๋ก๊ทธ์ธ์ ์์ฒญํ๋ฉด ์ธ์ฆ์ ์ํ ๋ฆฌ๋ค์ด๋ ํธ URI๋ฅผ ์ฃผ์์ง๋ง ํด๋ผ์ด์ธํธ์๊ฒ ๋ฏธ๋ฆฌ URI๋ฅผ ์ ๊ณตํ์ฌ ๋ฐ๋ก ์ธ๊ฐ ์ฝ๋๋ฅผ ์ ๋ฌ ๋ฐ์ ์ค๊ฐ์ ๋ฆฌ๋ค์ด๋ ํธ ํ๋ ๊ณผ์ ์ ์๋ตํ์ต๋๋ค.
## ์ด๋ฉ์ผ ์ธ์ฆ & Redis
| ์ด๋ฉ์ผ ์ ์ก ๋ฐ ์ธ์ฆ | ์ธ์ฆ๋ ๊ฒฝ์ฐ |
|-------------|---------|
|
|
|
์ผ์์ ์ผ๋ก ์ธ์ฆ๊ณผ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์ํด
ํค, ๊ฐ ํํ์ ๋น์ ํ ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ธ Redis ๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
์ฌ์ฉ์์ ์ด๋ฉ์ผ์ ํค๋ก ํ๊ณ ์ธ์ฆ ์ํ๋ฅผ ๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ํ์ ์ธ์ฆ ์ฝ๋ ๋ฑ์ผ๋ก ์ธ์ฆ์ ์ฑ๊ณตํ ๊ฒฝ์ฐ ์ธ์ฆ ์ํ๋ฅผ ๋ฐ๊พธ๋ ์์ผ๋ก ์ผ์์ ์ธ ์ธ์ฆ์ด ํ์ํ ๊ฒฝ์ฐ์ ์ ์ฉํ์ต๋๋ค.
## ๊ฒ์๊ธฐ๋ฅ (Mysql fulltext)
| ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ ๋ฐ ์ธ๋ฑ์ฑ | Full-Text Search |
|-------------|---------|
|
|
|
๊ธฐ์กด์ LIKE๋ฌธ์ ์ฟผ๋ฆฌ๋ ๋ฌธ์์ด ํจํด ๋งค์นญ์ ์ํํ์ฌ ๋์ฉ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฒฝ์ฐ์ ์ฑ๋ฅ์ด ๋จ์ด์ง ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ํ
์คํธ ๊ฒ์์ ํนํ ๋๊ณ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ MySQL์ Full-Text ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํด์ ๊ฒ์ ๊ธฐ๋ฅ์ ๊ตฌํํ์ต๋๋ค.
ํ๊ธ ๊ฒ์์๋ ๋ฌธ์ ๊ฐ ์๋ n-gram parser๋ฅผ ์ฌ์ฉํ์ฌ ํ ํฐ์ ๊ฐ์ 1๋ก ์ค์ ํด ์ธ๋ฑ์ฑ์ ํ๊ธฐ ๋๋ฌธ์ ์ต์ ํ ๊ธ์์ ํค์๋๋ก๋ ๊ฒ์์ ์ํํ ์ ์๊ฒ ํ์ต๋๋ค.
## Querydsl
๊ธฐ๋ณธ์ ์ธ CRUD ๋ Spring Data JPA ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํด์ฃผ๋ CRUD ๋ฉ์๋ ๋ฐ ์ฟผ๋ฆฌ ๋ฉ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ต๋๋ค. ํ์ง๋ง GET ์์ฒญ์์ ์ํ๋ ์กฐ๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ธฐ ์ํด์๋ ์ฌ๋ฌ ์กฐ๊ฑด์ด ํ์ํฉ๋๋ค. ์ด๋ ์ฟผ๋ฆฌ๋ฌธ์ด ๋ณต์กํด์ง๊ธฐ ๋๋ฌธ์ JPQL ์ด๋ Native Query ๋ฅผ ์ฌ์ฉํด์ผ ํ๊ฒ ๋๋๋ฐ, ์ฟผ๋ฆฌ๋ฌธ์ด ๊ธธ์ด์ง ๊ฒฝ์ฐ ์คํ๋ ๋ฌธ๋ฒ์ ์ธ ์ค๋ฅ ๋ฑ ํด๋จผ ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ ์ ์ฟผ๋ฆฌ๊ฐ ์๋ ์ด์ ๋ฐํ์ ์์ ์ ์ค๋ฅ๋ฅผ ์ ์ ์๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Querydsl ์ ๋ถ๋ถ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์๋์ ๊ฐ์ ์ด์ ์ด ์์์ต๋๋ค.
- Querydsl ์ ์ปดํ์ผ ์์ ์ ํ์
์ ๊ฒ์ฌํ๊ธฐ ๋๋ฌธ์, ์๋ชป๋ ํ๋๋ช
์ด๋ ๋ฐ์ดํฐ ์ ํ ์ฌ์ฉ๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฐ์งํ ์ ์์ต๋๋ค.
- ๋ณต์กํ ์กฐ๊ฑด์ ๊ธฐ๋ฐ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋์ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋์ผํ ๋ฉ์๋ ๋ด์์ ๋ค์ํ ์กฐ๊ฑด ๋ฐ ํํฐ๋ฅผ ์ ์ฉํ ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
- Querydsl์ ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ๊ฐ ์ค์ ์ฟผ๋ฆฌ๋ฌธ์ฒ๋ผ ์์ฑ๋๊ธฐ ๋๋ฌธ์ ๊ฐ๋
์ฑ์ด ์ข์ต๋๋ค.
## git actions / Docker
### Job ๋ถ๋ฆฌ
์ด๊ธฐ git actions ๋ ํ๋์ Job ์์ ๋ชจ๋ ๊ณผ์ ์ ๋ค ์ฒ๋ฆฌํ์ต๋๋ค. ํ์ง๋ง ํ
์คํธ๊ฐ ๋ฌด๊ฑฐ์์ง๊ณ ๊ทธ์ ๋ฐ๋ผ ๋น๋ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ฉด์ ํ
์คํธ์ ๋น๋๋ฅผ ๋ถ๋ฆฌํด์ผ๊ฒ ๋ค๋ ํ๋จ์ด ๋ค์์ต๋๋ค. git actions ์ Job ์ ๋ณ๋ ฌ๋ก ์คํ๋๊ธฐ ๋๋ฌธ์ test ๋ฅผ ํฌ๊ฒ 4๊ฐ(testA, testB, testC, buildTest) ๋ก ๋๋๊ณ ๊ฐ๊ฐ ์คํ์์ผฐ์ต๋๋ค. ๋น๋ ์์ API ๋ฌธ์ํ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ControllerTest ๋ ๋น๋ Job ์์ ํ๋๋ก ํ์ต๋๋ค. ์ดํ ๋ชจ๋ ํ
์คํธ์ ๋น๋๊ฐ ์๋ฃ๋๋ฉด cd Job ์ด ์คํ๋ฉ๋๋ค. ํด๋น Job ์์ ๋์ปค๋ฅผ push ํ๊ณ EC2 ์์ ๋์ปค ์ด๋ฏธ์ง๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์ ๋ฐฐํฌํ๋ ๊ณผ์ ์ด ์ด๋ฃจ์ด์ง๋๋ค.
### Caching
`build.gradle` ํ์ผ์ ์์ฃผ ๋ณ๊ฒฝ๋์ง ์๊ธฐ ๋๋ฌธ์ `actions/cache@v2` ์ ํตํด ์์กด์ฑ์ ์บ์ฑํด์ฃผ์ด์ ํ
์คํธ ๋ฐ ๋น๋ ์๊ฐ์ ๋จ์ถ์์ผ์ฃผ์์ต๋๋ค. ๋์ปค ์ด๋ฏธ์ง ์บ์ฑ์ด๋ ๋ ์ด์ด ์บ์ฑ์ ์คํ๋ ค ์บ์ฑ์ ํ๊ธฐ ์ํด ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ค๊ณ ์ ์ฅํ๋ ๊ณผ์ ์ด ์๊ฐ์ด ๋ ๊ฑธ๋ ค์ ์๋ตํ์ต๋๋ค.
### Docker Image ์ต์ ํ
๋ฉํฐ ์คํ
์ด์ง๋ฅผ ์๊ฐํ์ผ๋ ์ด๋ฏธ git actions ์ Job ์์ ๋น๋์ ๋ฐฐํฌ๊ฐ ๋ถ๋ฆฌ๋๊ธฐ ๋๋ฌธ์ ๋ฉํฐ ์คํ
์ด์ง ๋น๋๋ ํ์ง ์์์ต๋๋ค. ๋์ ๋์ปค ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ค์ด๊ธฐ ์ํด base-image ๋ฅผ `openjdk:11-jre-slim` ๋ก ๋ณ๊ฒฝํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ `build.gradle` ์์ ๋ถํ์ํ dependency ๋ฅผ ์ ๊ฑฐํ์ต๋๋ค.
### ๊ฒฐ๊ณผ
๊ฒฐ๊ณผ์ ์ผ๋ก CICD ๊ณผ์ ์ ํ๊ท 3๋ถ 20์ด์์ 2๋ถ์ผ๋ก ์ค์๊ณ , ์ด๋ฏธ์ง ํฌ๊ธฐ๋ 731MB ์์ 296MB ๋ก 60% ์ค์์ต๋๋ค.
๋น๋ ์ต์ ํ ์์ธ ๋ด์ฉ ํ์ธ โ [CI/CD](https://hobeen-kim.github.io/devops/Docker-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94/)
## ๋ก๊ทธ ๋ฐ ๋ชจ๋ํฐ๋ง
ec2 ๋ฐฐํฌ ์ดํ ์ต์ด ๋ช ๋ฒ์ GET ์์ฒญ์ 1000ms ์ด์์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค๋ ๊ฑธ ํ์ธํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐฐํฌ ํ๊ฒฝ๊ณผ ๋ก์ปฌ ํ๊ฒฝ๋ ๋ถ๋ช
ํ ์ฐจ์ด๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ด๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋์ง๋ ๋ชจ๋ํฐ๋ง์ด ๊ฐ๋ฅํด์ผ ํ์ต๋๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ ๋ก๊ทธ ์ ๋ต์ ์ธ์ ์ต๋๋ค.
### ๋ก๊ทธ ์ ๋ต
- API ํธ์ถ ์ ์์๋๋ ์๊ฐ
- Repository ํด๋์ค ํธ์ถ ์ ์์๋๋ ์๊ฐ
- ๋น์ฆ๋์ค ์์ธ๋ฅผ ์ ์ธํ ๋ชจ๋ Exception
### ๋ก๊ทธ ํ์ธ
๋ก๊ทธ๋ logBack ์ ์ฌ์ฉํ์ต๋๋ค. `@Slf4j` ์ด๋
ธํ
์ด์
์ผ๋ก ์ ์ฉํ ์ ์๊ณ , ๋ก๊ทธ๋ฅผ ํ์ผ๋ก ๋จ๊ธฐ๋ ๊ฒ ๊ฐ๋จํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ํ ์คํ๋ง ๋ถํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก SLF4J๋ฅผ ์ฌ์ฉํ๊ณ Logback์ ๊ทธ ๊ตฌํ์ฒด๋ก ์ ํํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์คํ๋ง ๋ด๋ถ์์ ์์์น ๋ชปํ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋๋ ํจ๊ป ๋ก๊ทธ๊ฐ ๋จ๋๋ค๋ ์ฅ์ ๋ ์์ต๋๋ค.
API ๋ก๊ทธ๋ `MDCLoggingFilter` ์์, Data ์ ๊ทผ ๋ก๊ทธ๋ `RepositoryLoggingAop` ์์, ์๋ฌ ๋ก๊ทธ๋ `GlobalExceptionHandler` ์์ ๋จ๊ฒผ์ต๋๋ค. `log.info` ํน์ `log.error` ๊ฐ ๋ฐ์ํ๋ฉด logs ํด๋์ `.log` ํ์ผ๋ก ๊ธฐ๋ก๋ฉ๋๋ค. ํด๋น ๋ก๊ทธ๋ ec2 ์์ cloudwatch agent ์ ์ํด ์์ง๋์ด log group ์ ๊ธฐ๋ก๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ metric ์ ํตํด ํ์ฑํ ํ ํ์ํ ๊ฐ์ ๋์๋ณด๋์ ํ์ํ์ต๋๋ค.
[๋์๋ณด๋ ๋ฐ๋ก๊ฐ๊ธฐ](https://cloudwatch.amazonaws.com/dashboard.html?dashboard=prometheus-dashboard&context=eyJSIjoidXMtZWFzdC0xIiwiRCI6ImN3LWRiLTU4OTc5NDU0NjI0NCIsIlUiOiJ1cy1lYXN0LTFfUXd0TzZvdWxRIiwiQyI6IjEyZ2E2M2NrNDZzMHBudTZqZTI4c25tamZ2IiwiSSI6InVzLWVhc3QtMTo4YTAyZDc0YS0zOTVjLTQxOGYtYjQzMS0wODQwODdlMGZhYzciLCJNIjoiUHVibGljIn0%3D&start=PT1H&end=null)
ํนํ ๋์๋ณด๋๋ฅผ ํตํด GET ์์ฒญ์ ์๋ต ์๊ฐ ์ง์ฐ์ ๋ฐฐํฌ ์๋ง๋ค ๋ฐ์ํ๋ค๋ ๊ฑธ ์ ์ ์์๊ณ ์๋์ warm up ์ ํ๊ฒ ๋๋ ์ด์ ๊ฐ ๋์์ต๋๋ค.
## JVM warm up
warmup ์ ํ๊ฒ ๋ ์ด์ ๋ ์ ๊ทธ๋ํ์ ๊ฐ์ด ํน์ ์์ฒญ์์ 1000ms ์ด์์ ๋ ์ดํด์๋ฅผ ๋ฐ๊ฒฌํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ฒ์์๋ GET ์์ฒญ์์ ์ฟผ๋ฆฌ๋ฌธ์ ์กฐ๊ฑด์ด ๋ง์ด ๊ฑธ๋ ค์์ด์ ๊ทธ๋ฐ๊ฐ ์๊ฐํ์ง๋ง ์ค์ ๋ก DB ์์ ์ฟผ๋ฆฌ๋ฌธ ์คํ ์์ฒด๋ 10ms ์ด ์ฑ ๋์ง ์์์ต๋๋ค. ๋ก๊ทธ๋ฅผ ํตํด ํ์ธํด๋ณธ ๊ฒฐ๊ณผ ์คํ๋ ค ์ ํ๋ฆฌ์ผ์ด์
๋ก์ง์ ์คํํ๋ ๋ฐ ๋๋ถ๋ถ์ ์๊ฐ์ด ์์๋์์ต๋๋ค. ๋ฐ๋ผ์ JVM ์ JIT(Just-in-Time) ์ผ๋ก ์ธํด ์ปดํ์ผ์ด ์ค์๊ฐ์ผ๋ก ๋๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํ์ต๋๋ค. ๊ทธ ์ด์ ๋ ์ต์ด ๋ช ๊ฐ์ ์์ฒญ ์ดํ์๋ ์ ์์ ์ธ ์๋ต ์๊ฐ์ ๋ฐํํ๊ธฐ ๋๋ฌธ์
๋๋ค.
์ฒ์์๋ ์ ํ๋ฆฌ์ผ์ด์
์ด ์คํ๋๋ฉด์ localhost:8080 ์ผ๋ก GET ์์ฃผ์ ๋ฉ์ธ API ๋ฅผ ํธ์ถํ๋ฉด์ warm up ๊ณผ์ ์ ์คํํ์ต๋๋ค. ํ์ง๋ง warm up ๊ณผ์ ์ด 3๋ถ ์ด์ ์์๋๋ฉด์ ๋ฉ์ธ ๋ก์ง ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ฐฉํฅ์ผ๋ก ๋ฐ๊พธ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์คํ๋ง์ ํํฐ ๋ถ๋ถ๋ warm up ํ๊ธฐ ์ํด `WarmupController` ๋ฅผ ๋ง๋ค์ด ํด๋น API ๋ฅผ ํจ๊ป ํธ์ถํด์ฃผ์์ต๋๋ค. ์๋๋ warmup ์ ํ๋ ํด๋์ค์
๋๋ค.
```java
public class WarmupApi implements ApplicationListener {
...
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (warmup ์ด ๋์ง ์์๋ค๋ฉด) {
;
request("http://localhost:8080/warmup"); //WarmupController ํธ์ถ
methodWarmup(); //๋ฉ์๋ ๋จ์ warmup ์ํ
warmupState.setWarmupCompleted(true); //warmup ์ ์๋ฃ ์ํ๋ก ๋ณ๊ฒฝ
}
}
private void methodWarmup() {
videoMethodWarmup();
channelMethodWarmup();
memberMethodWarmup();
}
...
}
```
ํด๋น ๊ณผ์ ์ ์๋ฃํ๋ฉด ์ต์ด ์์ฒญ ์์๋ ํ๊ท ์ ์ธ ์๋ต ์๊ฐ (200ms ~ 400ms) ์ผ๋ก ์์ฒญ์ด ๋๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
warm up ์์ธ ๋ด์ฉ ํ์ธ โ [warm up](https://hobeen-kim.github.io/java/JAVA-JIT-%EC%B5%9C%EC%A0%81%ED%99%94)
ํ
์คํธ/๋ชจ๋ํฐ๋ง ํ์ธ (๐ Click)
## ๊ฐ๋ฐ์ ํ
์คํธ
๊ฐ๋ฐ์ ํ
์คํธ๋ ์๊ตฌ์ฌํญ ๊ธฐ๋ฐ์ผ๋ก ํ
์คํธ๋ฅผ ์งํํ์ต๋๋ค. ์๊ตฌ์ฌํญ์๋ ์์ง๋ง ํ์ํ ๋ด์ฉ์ด๋ ์์ด๋์ด๋ ์คํฌ๋ผ์ ํตํด ํ
์คํธ ๋ฌธ์์ ์ถ๊ฐํ์ต๋๋ค. ๊ฐ๋ฐ๋ถํฐ ๋ฐฐํฌ๊น์ง ์ ๊ธฐ์ ์ผ๋ก ํ
์คํธ๋ฅผ ์งํํ์ผ๋ฉฐ ํ
์คํธ ํต๊ณผ๋ฅผ ์ค์ฌ์ผ๋ก ๊ธฐ๋ฅ ๊ฐ๋ฐ์ ํ์์ต๋๋ค.
- ๊ฐ๋ฐ์ ํ
์คํธ ๋ฌธ์ ๋ฐ๋ก๊ฐ๊ธฐ โ [๊ฐ๋ฐ์ ํ
์คํธ ํ์ผ](https://1drv.ms/x/s!AjqmbzT14UKwi0404Ht2GZMTb-oD?e=Djm5VW)
## BE ๋จ์ ๋ฐ ํตํฉํ
์คํธ

BE JAVA ์ ํ๋ฆฌ์ผ์ด์
์์ ์ด 800 ๊ฐ์ ๋จ์ ๋ฐ ํตํฉํ
์คํธ๋ฅผ ์งํํ์ต๋๋ค. ๋จ์ ํ
์คํธ์ ๋์์ Controller, Service, Repository, Entity ์ ๋ชจ๋ public ๋ฉ์๋์
๋๋ค. ์ค์ ์ ๊ธฐ๋ฅ ๋์ ์ฌ๋ถ์ ์ฃ์ง ์ผ์ด์ค์์ ์ ์์ ์ธ ์์ธ๋ฅผ ๋์ง๋์ง ์์ต๋๋ค. ํตํฉํ
์คํธ๋ ์ฃผ์ด์ง ์กฐ๊ฑด์์ mockMvc ๋ฅผ ํ์ฉํด API ๋ฅผ ํธ์ถํ์ ๋ ๊ธฐ๋๋๋ ์๋ต๊ฐ๊ณผ DB CRUD ๊ฐ ๋๋์ง ํ์ธํ์ต๋๋ค.
ํ๊ณ ํ์ธ (๐ Click)
- [๊นํ๋ฆผ](https://velog.io/@hyerimkimm/๋ฉ์ธ-ํ๋ก์ ํธ-ํ๊ณ )
- [๋ฐฉ์นํ](https://velog.io/@luna1328/%EB%A9%94%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0-lc2prhgg)
- [์ด์ข
๋ฒ](https://dunggu.tistory.com/66)
- [๊นํธ๋น](https://hobeen-kim.github.io/review/Review-%EC%B2%AB-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0/)
- [๊น์ง์](https://www.notion.so/jiina/19b6722eb48d431f8059e22dc3eb8167)
- [ํจ์์ค](https://da9dac.tistory.com/157)