Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/git-marvel/commit-guardians-client

๐Ÿ… ์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ๋ฅผ ์ ์ˆ˜๋กœ, ๋ฑƒ์ง€๋กœ ์ž๋ž‘ํ•˜์„ธ์š”! Show off your commit quality with scores and a badge!
https://github.com/git-marvel/commit-guardians-client

firebase-storage github-api javascript react repository-badge zustand

Last synced: 15 days ago
JSON representation

๐Ÿ… ์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ๋ฅผ ์ ์ˆ˜๋กœ, ๋ฑƒ์ง€๋กœ ์ž๋ž‘ํ•˜์„ธ์š”! Show off your commit quality with scores and a badge!

Awesome Lists containing this project

README

        

# Commit Guardians

## ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

![project_intro.png](assets/readme/project_intro.png)


## ๋ชฉ์ฐจ


## ํ”„๋กœ์ ํŠธ ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ

๊ฐœ๋ฐœ์ž์˜ ์ผ์ƒ์€ ์ฝ”๋“œ๋งŒ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ **โ€˜๊ธฐ๋กโ€™์„ ๋‚จ๊ธฐ๊ณ  ๊ณต์œ ํ•˜๋Š” ๊ณผ์ •๊นŒ์ง€๋„ ํฌํ•จ**๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ํŒ€ ํ”„๋กœ์ ํŠธ๋‚˜ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์˜คํ”ˆ์†Œ์Šค์—์„œ๋„ **์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€**๋Š” ์ž‘์—… ํ๋ฆ„์„ ์ดํ•ดํ•˜๊ณ  ์ง€๋‚œ ์ž‘์—…์„ ๋˜๋Œ์•„๋ณด๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ ๋งฅ๋ฝ์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ์— ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ปค๋ฐ‹๋ฉ”์‹œ์ง€๋Š” ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์š”์•ฝํ•ด์ค„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, โ€˜์™œโ€™ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฝ”๋“œ๋ฆฌ๋ทฐ๋‚˜ ๋””๋ฒ„๊น…์„ ํ•  ๋•Œ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š” ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์ปค๋ฐ‹ ํƒ€์ž…์— ๋”ฐ๋ผ ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์–ด์„œ ์ž‘์—… ๋‹จ์œ„๋ฅผ ์ž˜๊ฒŒ ์ชผ๊ฐœ์–ด ์ปค๋ฐ‹์„ ํ•˜๋Š” ๊ฒƒ์€ ํ˜‘์—…์— ์žˆ์–ด์„œ ์ข‹์€ ์Šต๊ด€์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— **์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€์— ๋”ฐ๋ฅธ ์ฝ”๋“œ ์ˆ˜์ •์ด ์„œ๋กœ ์ผ์น˜ํ•ด์•ผ** ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์ข‹์€ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์˜ ๋‚ด์šฉ์€ **์˜๋ฏธ์žˆ๋Š” ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ์“ฐ๋Š” ๊ฒƒ**์ด๋ฉฐ, ์ตœ๋Œ€ํ•œ ๋…ผ๋ฆฌ์ ์ธ ๋‹จ์œ„๋กœ diff (๋ณ€๊ฒฝ์‚ฌํ•ญ)๋ฅผ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋…ผ๋ฆฌ ๋‹จ์œ„๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ปค๋ฐ‹์„ ํ•˜๋Š” ๊ฒƒ์ด ๊ฐœ๋ณ„ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์œผ๋กœ ๋˜๋Œ๋ฆฌ๊ธฐ ํŽธํ•˜๊ณ  ์–ด๋Š ๋ถ€๋ถ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฌ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์ˆ˜์›”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ผผ๊ผผํ•œ ์ปค๋ฐ‹๋“ค์ด ๋ชจ์—ฌ์„œ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์šฉ์ดํ•˜๊ณ  ํ˜‘์—…ํ•˜๊ธฐ ์ข‹์€ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ธฐ์ดˆ๊ฐ€ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด, **ํ˜„์žฌ ๊นƒํ—™ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ ์ปค๋ฐ‹๋“ค์€ ๊ณผ์—ฐ ๊ฑด๊ฐ•ํ•œ ์ƒํƒœ์ผ๊นŒ์š”?**

์ด ์งˆ๋ฌธ์—์„œ ์‹œ์ž‘๋œ Commit Guardians ํŒ€ ํ”„๋กœ์ ํŠธ๋Š”, **์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์™€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๊ฐ„์˜ ์ผ์น˜์„ฑ์„ ์ ๊ฒ€ํ•˜๊ณ , ๋ณด๋‹ค ๋‚˜์€ ์ปค๋ฐ‹ ๋ฌธํ™”๋ฅผ ํ˜•์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅ**ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


## ๊ธฐ๋Šฅ

### 1. ๋ฉ”์ธ ํŽ˜์ด์ง€

![home_mock.gif](assets/readme/home_mock.gif)

![home_login.gif](assets/readme/home_login.gif)

**1-1. github ๋กœ๊ทธ์ธ**

- github ๋กœ๊ทธ์ธ ์‹œ ์‚ฌ์šฉ์ž์˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ url์ž…๋ ฅ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
- ๋กœ๊ทธ์ธ ์ „์—๋Š” ์˜ˆ์‹œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋กœ ์„œ๋น„์Šค๋ฅผ ๋ฏธ๋ฆฌ ์ด์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**1-2. ์„œ๋น„์Šค ์ด์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธํ•˜๊ธฐ**

- ํ—ค๋”์˜ ์ขŒ์ธก ์ƒ๋‹จ ๋ถ€๋ถ„์—๋Š” Github API์˜ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
Github์˜ Commit์„ ํ™•์ธํ•ด์•ผํ•˜๋Š” ์„œ๋น„์Šค ํŠน์„ฑ ์ƒ Github API status์— ๋”ฐ๋ผ ์„œ๋น„์Šค ์ด์šฉ์„ ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์–ด์„œ Github API status๊ฐ€ ์ •์ƒ์ธ ๊ฒฝ์šฐ์—๋งŒ URL ์ž…๋ ฅ(์ปค๋ฐ‹ ๋ถ„์„)์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
- Github API status ๋ฒ„ํŠผ ์„ ํƒ ์‹œ [https://www.githubstatus.com/](https://www.githubstatus.com/) ๋กœ ์ด๋™ํ•˜์—ฌ ์ƒ์„ธ ๋‚ด์—ญ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**1-3. ํ˜„์žฌ ๋Œ€์‘ ๊ฐ€๋Šฅํ•œ Commit Type ํ™•์ธํ•˜๊ธฐ**

- `remove` `docs` `style` `test`
- ๋กœ๊ณ  ์ƒ๋‹จ์—๋Š” ํ˜„์žฌ Commit Guardians์—์„œ ๋ถ„์„ํ•˜๊ณ  ์žˆ๋Š” 4๊ฐœ์˜ Commit Type์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**1-4. ์ปค๋ฐ‹ ๋ถ„์„ ์‹œ์ž‘ํ•˜๊ธฐ**

- ๋งจ ์ฒ˜์Œ ๋ณด์ด๋Š” ํ™”๋ฉด์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ commit์„ ๋ถ„์„๋ฐ›๊ณ  ์‹ถ์€ Github Repository์˜ URL์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- URL ์ž…๋ ฅ ํ›„ Enterํ‚ค or Check the Quality ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ปค๋ฐ‹ ๋ถ„์„์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- ์บ๋ฆญํ„ฐ์˜ ์„ค๋ช…์„ ํ†ตํ•ด default branch์˜ Commit์„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‚ด์šฉ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.


## 2. ์ปค๋ฐ‹ ๋ฑƒ์ง€ ํŽ˜์ด์ง€

![badge_readme.png](assets/readme/badge_readme.gif)
![b_review_faq.png](assets/readme/b_review_faq.gif)

๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ ์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ ๋ถ„์„์ด ๋๋‚œ ํ›„ ๋ณด์—ฌ์ง€๋Š” ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.

**2-1. ์ ์ˆ˜์— ๋”ฐ๋ฅธ ๋ฑƒ์ง€ ์ฐจ๋ณ„ํ™”**

- ์‚ฌ์šฉ์ž์˜ ์ ์ˆ˜์— ๋”ฐ๋ผ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฑƒ์ง€๊ฐ€ ์ฃผ์–ด์ง€๋ฉฐ 4๊ฐœ์˜ ๋ฑƒ์ง€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ ์ˆ˜ ๊ตฌ๊ฐ„์€ 80์  ์ด์ƒ, 50์  ์ด์ƒ, 30์  ์ด์ƒ, 30์  ๋ฏธ๋งŒ ์œผ๋กœ ์ฑ„์ ๋ฉ๋‹ˆ๋‹ค.
- `Copy your Badge` ๋ฒ„ํŠผ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž์˜ GitHub repository README ์— ๋ฑƒ์ง€๋ฅผ ๋ถ™์—ฌ๋„ฃ๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” html ํƒœ๊ทธ๋ฅผ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**2-2. Commit ํ†ต๊ณ„ ๊ทธ๋ž˜ํ”„**

- Pie chart
- ์ค‘์•™์—” ๊ฒ€์‚ฌํ•œ ์ปค๋ฐ‹์˜ ์ด ๊ฐœ์ˆ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- ๊ฒ€์‚ฌํ•œ ์ปค๋ฐ‹๋“ค์„ ์ปค๋ฐ‹ ํƒ€์ž…๋ณ„๋กœ ๋ถ„๋ฅ˜ํ•˜์—ฌ ๋น„์œจ์„ ๋‚˜ํƒ€๋ƒˆ์Šต๋‹ˆ๋‹ค.
- Bar Chart
- ๊ฐ€์žฅ ๋งŽ์ด ๊ธฐ์—ฌํ•œ ์ƒ์œ„ 3๋ช…์„ ์„ ์ •ํ•˜์—ฌ ๊ฐ์ž์˜ ์ปค๋ฐ‹์„ ์ปค๋ฐ‹ ํƒ€์ž…๋ณ„๋กœ ๋ถ„๋ฅ˜ํ•ด ๋‚˜ํƒ€๋ƒˆ์Šต๋‹ˆ๋‹ค.

**2-3. ์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ ์ตœ์ข… ์ ์ˆ˜**

- 100์  ๋งŒ์ ์„ ๊ธฐ์ค€์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ์ ์ˆ˜๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- `View All Results` ๋ฒ„ํŠผ์„ ํ†ตํ•ด ์ปค๋ฐ‹ ๋ถ„์„ ๊ฒฐ๊ณผ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ๊ฐ์˜ ์ปค๋ฐ‹ ๋งˆ๋‹ค์˜ ์ ์ˆ˜๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**2-4. FAQ**

- ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํ˜•์‹์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- Commit Guardians ์—์„œ ํ™•์ธํ•˜๋Š” ์ปค๋ฐ‹ ํƒ€์ž…๊ณผ ์ฑ„์  ๋ฐฉ์‹์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

**2-5. ์‚ฌ์šฉ์ž์™€์˜ ์†Œํ†ต์„ ์œ„ํ•œ ์ด๋ฉ”์ผ์ฃผ์†Œ์™€ GitHub ๋งํฌ**

- ํ‘ธํ„ฐ์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ Commit Guardians ์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์ œ์•ˆํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฉ”์ผ ์ฃผ์†Œ์™€ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์˜ GitHub ๋งํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.


## 3. ์ปค๋ฐ‹ ๋ถ„์„ ๊ฒฐ๊ณผ ํŽ˜์ด์ง€

![scoreboard.png](assets/readme/scoreboard.gif)

์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ๋ฅผ ๋ถ„์„ํ•œ ๊ฐ ์ปค๋ฐ‹์— ๋Œ€ํ•œ ์ƒ์„ธ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

- GitHub Owner์™€ Repository ์ด๋ฆ„

- ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํ˜•์‹๋ณ„๋กœ ๋ถ„๋ฅ˜๋œ ๋น„์œจ

1. Prefix Style
2. Simple Text
3. Template Based Style

- ๊ฐ ์ปค๋ฐ‹์˜ ์ •๋ณด
- COMMIT MESSAGE : ์„ ํƒ ์‹œ ํ•ด๋‹น ์ปค๋ฐ‹์˜ GitHub ํŽ˜์ด์ง€๊ฐ€ ์—ด๋ฆฝ๋‹ˆ๋‹ค.
- CHANGES : ๋ณ€๊ฒฝ๋œ ํŒŒ์ผ ๊ฐฏ์ˆ˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, -/+ ์˜ ๋ฌถ์Œ์„ Change ๋กœ ์ •์˜ํ•˜์—ฌ ๋ง‰๋Œ€๊ทธ๋ž˜ํ”„๋ฅผ ํ†ตํ•ด ์ผ์น˜์œจ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- DATE : ๋กœ์ปฌ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
- SHA : ์ „์ฒด SHA ๊ฐ’์„ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ 7์ž๋ฆฌ๋งŒ ๋ณต์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


## ๊ธฐ์ˆ ์Šคํƒ

| ์—ญํ•  | ์ข…๋ฅ˜ |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Library | ![React](https://img.shields.io/badge/React-61DAFB?style=for-the-badge&logo=React&logoColor=white) |
| Bundler | ![VITE](https://img.shields.io/badge/VITE-f88afc?style=for-the-badge&logo=Vite&logoColor=white) |
| Programming Language | ![JavaScript](https://img.shields.io/badge/JavaScript-FFD93E.svg?style=for-the-badge&logo=JavaScript&logoColor=white) |
| Styling | ![tailwindcss](https://img.shields.io/badge/tailwindcss-61DAFB?style=for-the-badge&logo=tailwindcss&logoColor=white) |
| Data Fetching | ![Axios](https://img.shields.io/badge/Axios-5A29E4?style=for-the-badge&logo=Axios&logoColor=white) |
| State Management | ![zustand](https://img.shields.io/badge/zustand-FF4154?style=for-the-badge&logo=zustand&logoColor=white) |
| Formatting | ![ESLint](https://img.shields.io/badge/ESLint-4B3263?style=for-the-badge&logo=eslint&logoColor=white) ![Prettier](https://img.shields.io/badge/Prettier-F7B93E?style=for-the-badge&logo=prettier&logoColor=white) |
| Package Manager | ![npm](https://img.shields.io/badge/npm-2C8EBB?style=for-the-badge&logo=npm&logoColor=white) |
| Version Control | ![Git](https://img.shields.io/badge/git-%23F05033.svg?style=for-the-badge&logo=git&logoColor=white) ![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white) |

GitHub ์ด์šฉ์ž์˜ ๋Œ€๋ถ€๋ถ„์ด PC๋ฅผ ํ†ตํ•œ ์›น ๋ธŒ๋ผ์šฐ์ € ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, REACT๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์›น ํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, Axios๋ฅผ ํ™œ์šฉํ•˜์—ฌ GitHub API์™€์˜ ๋งŽ์€ ํ†ต์‹ ์„ ์›ํ™œํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ๋ฐ ๊ด€๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

### ์ฃผ์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฆฌ

- `diff-match-patch` : ๊ตฌ๊ธ€์˜ Neil Fraser๊ฐ€ ๊ฐœ๋ฐœํ•œ ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ํ…์ŠคํŠธ์˜ ์ฐจ์ด์ (diffs)์„ ๊ณ„์‚ฐํ•˜๊ณ  ํŒจ์น˜๋ฅผ ์ƒ์„ฑ ๋ฐ ์ ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋Ÿ‰์˜ ์ปค๋ฐ‹์„ ์ •ํ™•ํ•˜๊ณ  ๋น ๋ฅด๊ฒŒ ๋ถ„์„ํ•˜์—ฌ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

- `idb-keyval` : IndexedDB๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒฝ๋Ÿ‰ ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, key-value ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ์กฐํšŒ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. zustand ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ๋ธŒ๋ผ์šฐ์ €์˜ IndexedDB์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด ๋Œ€๋Ÿ‰์˜ ์ƒํƒœ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ , ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.


## Git Commit ์ปจ๋ฒค์…˜

**- Commit Type**

```
type: title

body
```


**- Commit ๋ฉ”์‹œ์ง€ ์ข…๋ฅ˜ ์„ค๋ช…**

| ์ œ๋ชฉ | ๋‚ด์šฉ |
| -------- | ---------------------------------------- |
| feat | ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| fix | ๋ฒ„๊ทธ ์ˆ˜์ •์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| chore | ๋นŒ๋“œ ์ˆ˜์ •์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| docs | ๋ฌธ์„œ ์ˆ˜์ •์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| style | ์ฝ”๋“œ ์Šคํƒ€์ผ ํ˜น์€ ํฌ๋งท ๋“ฑ์— ๊ด€ํ•œ ์ปค๋ฐ‹ |
| refactor | ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| design | css ๋””์ž์ธ ๊ด€๋ จ์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| test | ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€, ์‚ญ์ œ, ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์ปค๋ฐ‹ |
| remove | ๋ถˆํ•„์š”ํ•œ ํŒŒ์ผ์ด๋‚˜ ๋กœ์ง ์‚ญ์ œ์— ๊ด€ํ•œ ์ปค๋ฐ‹ |




# ๐Ÿค” ๊ณ ๋ฏผํ•œ ๋ถ€๋ถ„

## 1. ์ปค๋ฐ‹ ํƒ€์ž… ํ•„ํ„ฐ๋ง

์ข‹์€ ์ปค๋ฐ‹์ธ์ง€๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ์ปค๋ฐ‹์˜ ๋ฉ”์‹œ์ง€์™€ ์‹ค์ œ ๋ณ€๊ฒฝ ๋‚ด์šฉ์˜ ๋งฅ๋ฝ์ด ์ผ์น˜ํ•œ์ง€ ๊ฒ€์‚ฌ๊ฐ€ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์— โ€œtest: ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ˆ˜์ •โ€ ์ด๋ผ๊ณ  ์ ํ˜€์žˆ์œผ๋‚˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ์—” ํ•ด๋‹น ๋‚ด์šฉ๊ณผ ๊ด€๋ จ ์—†๋Š” ๋ถ€๋ถ„์ด ํฌํ•จ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ปค๋ฐ‹์˜ ์งˆ์„ ๋‚ฎ์ถ˜๋‹ค๊ณ  ํŒ๋‹จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Problem

**์ปค๋ฐ‹ ๋ถ„์„์„ ์œ„ํ•œ ๊ธฐ์ค€ ์„ค์ •์— ๋Œ€ํ•œ ์–ด๋ ค์›€**

1. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํ˜•์‹์˜ ๋น„์ผ๊ด€์„ฑ

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ์ปจ๋ฒค์…˜์ด ์กด์žฌํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ทœ์น™์„ ์ ์šฉํ•˜๊ฑฐ๋‚˜ ์ปจ๋ฒค์…˜์„ ๊ฐ•์ œํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๊ณ  ๋™์ผํ•œ ์ปค๋ฐ‹ ํƒ€์ž…์ด์–ด๋„ ์ž‘์„ฑ์ž์˜ ์Šคํƒ€์ผ์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€ ํ˜•์‹์ด ๋‹ฌ๋ž์Šต๋‹ˆ๋‹ค.

2. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์™€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋‚ด์šฉ ๊ฐ„์˜ ๋ชจํ˜ธํ•œ ๊ธฐ์ค€

์˜ˆ๋ฅผ ๋“ค์–ด, ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํƒ€์ž…์ด โ€œfixโ€ ์ด๊ณ  CSS ๊ด€๋ จ UI ๋ณ€๊ฒฝ์ด ๋œ ๊ฒฝ์šฐ์—๋Š” โ€œfixโ€ ์ธ์ง€ โ€œdesignโ€์ธ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ธฐ์ค€์ด ๋ชจํ˜ธํ–ˆ์Šต๋‹ˆ๋‹ค. โ€œrefactorโ€, โ€œfeatโ€ ๋“ฑ์˜ ๊ฒฝ์šฐ์—๋„ ํ•ด๋‹น ์ปค๋ฐ‹์˜ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋‚ด์šฉ๋งŒ์„ ๋ณด๊ณ  ์ •ํ˜•ํ™”๋œ ๊ทœ์น™๋งŒ์œผ๋กœ ์ผ์น˜์„ฑ์„ ํŒ๋‹จํ•˜๊ธฐ์—๋Š” ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

3. ๋™์ผํ•œ ํƒ€์ž…์ด์ง€๋งŒ ๋‹ค์–‘ํ•œ ํ•ด์„

๊ฐ™์€ ๋‹จ์–ด์ด์ง€๋งŒ ๋‹ค์–‘ํ•œ ์˜๋ฏธ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋นˆ๋ฒˆํ–ˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํƒ€์ž…์ด โ€œstyleโ€์ผ ๋•Œ ์ฝ”๋“œ ํฌ๋งท ๋ณ€๊ฒฝ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์ง€๋งŒ ๋””์ž์ธ์ ์ธ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ์— ์‚ฌ์šฉ๋˜๊ธฐ๋„ ํ–ˆ์œผ๋ฉฐ โ€œchoreโ€์ธ ๊ฒฝ์šฐ์—๋„ ๋นŒ๋“œ์— ๊ด€๋ จ ์ˆ˜์ •๋งŒ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์˜๋ฏธ๋กœ ์“ฐ์ด๊ฑฐ๋‚˜ ์ž์ž˜ํ•œ ์ˆ˜์ •์˜ ์˜๋ฏธ๊นŒ์ง€ ํฌํ•จํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Analysis

**1. ์ž‘์„ฑ์ž์˜ ์Šคํƒ€์ผ์— ๋”ฐ๋ฅธ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํ˜•์‹ ๋ถ„์„**

์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ํ˜•์‹์œผ๋กœ ๋ถ„๋ฅ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๊ฐ€ ์ž…๋ ฅ๋˜๋”๋ผ๋„ ์ง€์ •๋œ ํ˜•์‹์„ ๋”ฐ๋ฅผ ๊ฒฝ์šฐ ์ปค๋ฐ‹ ํ€„๋ฆฌํ‹ฐ๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

- ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํ˜•์‹ ์ง€์ • \*๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„์ด ์—†์Šต๋‹ˆ๋‹ค. (Case-insensitive)

1. ํ”„๋ฆฌ ํ”ฝ์Šค ์Šคํƒ€์ผ (Prefix Style)

`type(scope): subject`

์˜ˆ์‹œ: feat(auth): ๋กœ๊ทธ์ธ API ์—ฐ๋™

2. ์ผ๋ฐ˜ ํ…์ŠคํŠธ ์Šคํƒ€์ผ (Simple Text Style)

`type subject`

์˜ˆ์‹œ: Add ๋กœ๊ทธ์ธ API ์—ฐ๋™

3. ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜ ์Šคํƒ€์ผ (Template Based Style)

`[type] subject`

์˜ˆ์‹œ: [ADD] ๋กœ๊ทธ์ธ API ์—ฐ๋™

**2. ๋ชจํ˜ธํ•œ ์ปค๋ฐ‹ ํƒ€์ž…์˜ ๋ฌธ์ œํ•ด๊ฒฐ์„ ์œ„ํ•œ commit type ํ•„ํ„ฐ๋ง**

| ์ปค๋ฐ‹ ๋‚ด์šฉ[์นดํ…Œ๊ณ ๋ฆฌ] | Type | ์ถ”์ /๋ถ„์„ ์š”์ธ |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------- |
| 1. ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ | feat, make, implement | |
| 2. ํŒŒ์ผ์„ ์‚ญ์ œ | remove, removed, removes, delete, deletes, deleted, erase, erases, erased, discard, | |
| 3. ๋ฌธ์„œ์ž‘์—…๋งŒ | docs, doc, documentation, readme | ํŒŒ์ผํ™•์žฅ์ž๋ช… (.md, .mdx, .docs, ...) |
| 4. ๋ฒ„๊ทธ ์ˆ˜์ • | fix, fixed | |
| 5. ๋ฆฌํŒฉํ† ๋ง | refactor | |
| 6. ์ฝ”๋“œ ํฌ๋ฉงํŒ… | style, format, beautify, "reformatโ€ | |
| 7. ๋””์ž์ธ ์Šคํƒ€์ผ๋ง๋งŒ | design, css | ํŒŒ์ผํ™•์žฅ์ž๋ช… (.css, .scss) / tailwind (โ€ฆ) |
| 8. ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•˜๋Š” ์ฝ”๋“œ | test, tests, verify, unittest | ํŒŒ์ผํ™•์žฅ์ž ๋ฐ ์ƒ๋Œ€๊ฒฝ๋กœ (.jest, ...) |
| 9. ๋นŒ๋“œ ๋ฐ ์„ค์ •ํŒŒ์ผ ์ˆ˜์ •(ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋Šฅ๊ณผ ์ง์ ‘์ ์œผ๋กœ ์—ฐ๊ด€ x) | chore | |

"fix", "feat", "refactorโ€ ์™€ ๊ฐ™์€ ์ปค๋ฐ‹ ํƒ€์ž…์€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์—ˆ์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์€ ๋ช…ํ™•ํ•œ ๊ธฐ์ค€์„ ๊ฐ€์ง€๊ณ  ํŒ๋‹จํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์˜ ๋‚ด์šฉ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ „์ฒด ์ฝ”๋“œ์˜ ๋‚ด์šฉ๋„ ํŒŒ์•…์ด ๋˜์–ด์•ผ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์™€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋‚ด์šฉ์˜ ์ผ์น˜์„ฑ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ ์ปค๋ฐ‹์˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ(diff)์œผ๋กœ๋Š” ์ข‹์€ ์ปค๋ฐ‹์ธ์ง€ ์•Œ๊ธฐ ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ถ„์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ์ปค๋ฐ‹ ํƒ€์ž…์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ๋ชจํ˜ธ์„ฑ์„ ์ตœ์†Œํ™”ํ•˜๊ณ  ์ผ๊ด€๋œ ํ‰๊ฐ€๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ์—์„œ ์˜๋ฏธ๊ฐ€ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„๋˜๊ณ  ์‹ค์ œ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ๊ณผ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๊ฐ„์˜ ์ผ์น˜์„ฑ์„ ํŒ๋‹จํ•˜๋Š” ๊ธฐ์ค€์„ ์„ธ์šธ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ `style`, `remove`, `docs`, `test` 4๊ฐ€์ง€ ํƒ€์ž…์œผ๋กœ ๋ถ„์„ ๋Œ€์ƒ์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

**3. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ํƒ€์ž…๊ณผ ์˜๋ฏธ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ๊ธฐ์ค€ ์„ค์ •**

๋™์ผํ•œ ํƒ€์ž…์ด์ง€๋งŒ ๋‹ค์–‘ํ•œ ํ•ด์„์ด ๋  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด 4๊ฐ€์ง€ ํƒ€์ž…์ด ์‹ค์ œ๋กœ ์–ด๋–ค ์˜๋ฏธ๋กœ ์“ฐ์ด๊ณ  ๊ทธ์— ๋”ฐ๋ฅธ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ๋ถ„์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ํƒ€์ž…๋งˆ๋‹ค ๊ณตํ†ต๋œ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฐพ๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์ฃผ ์“ฐ์ด๋Š” ์˜๋ฏธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ช…ํ™•ํ•œ ๊ธฐ์ค€์„ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, style ํƒ€์ž…์€ HTMLํƒœ๊ทธ์— ์–ธ์–ด ์†์„ฑ ์ถ”๊ฐ€, configํŒŒ์ผ ์ˆ˜์ •, ์“ฐ์ด์ง€ ์•Š์€ ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•œ ๊ฒฝ์šฐ ๋“ฑ ํŒ๋‹จ ๊ธฐ์ค€์„ ์„ธ์šฐ๊ธฐ ์–ด๋ ค์šด ์ผ€์ด์Šค๋ณด๋‹ค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์“ฐ์ด๋Š” ์ฝ”๋“œ ํฌ๋งท์— ๊ด€๋ จํ•œ ์ˆ˜์ •์— ๋Œ€ํ•ด ๋ถ„์„ํ•˜์—ฌ ๊ธฐ์ค€์„ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

**- Commit Guardians๊ฐ€ ํ™•์ธํ•˜๋Š” ์ปค๋ฐ‹ ํƒ€์ž…๊ณผ ๊ธฐ์ค€**

- remove
- ํŒŒ์ผ ๋ฐ ํด๋”, ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•œ ์ปค๋ฐ‹
- ๋ณ€๊ฒฝ์‚ฌํ•ญ์— ์‚ญ์ œํ•œ ๋ถ€๋ถ„๋งŒ ํฌํ•จ๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์˜ˆ์‹œ
- ํŒŒ์ผ ์‚ญ์ œ์™€ ์ฝ”๋“œ ์ˆ˜์ •์„ ๊ฐ™์ด ์ปค๋ฐ‹ํ–ˆ์„ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
- ๋ณ€๊ฒฝ์‚ฌํ•ญ์— ์ฝ”๋“œ์˜ ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
- docs
- ๋ฌธ์„œ ์ž‘์—…๋งŒ์„ ํ•œ ์ปค๋ฐ‹
- ๋ฌธ์„œ์— ์‚ฌ์šฉ๋˜๋Š” ํŒŒ์ผ๋งŒ ํฌํ•จ๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ์ด๋ฏธ์ง€ ํŒŒ์ผ -ย `.img`,ย `.png`,ย `.jpeg`,ย `.svg`,ย `.ai`
- ๊ธฐํƒ€ ๋ฌธ์„œ ํŒŒ์ผ - `.pdf` ,`.docs`,ย `.md`,ย `.mdx`,ย `.rst`
- ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์˜ˆ์‹œ
- ๋ฌธ์„œ ํŒŒ์ผ๊ณผ ์†Œ์Šค ์ฝ”๋“œ ํŒŒ์ผ์˜ ์ˆ˜์ •์‚ฌํ•ญ์„ ๊ฐ™์ด ์ปค๋ฐ‹ํ–ˆ์„ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
- style
- ์ฃผ๋กœ ์ฝ”๋“œ ํฌ๋งคํŒ…, ๋“ค์—ฌ ์“ฐ๊ธฐ, ์ฝ”๋“œ ์ •๋ ฌ ๋“ฑ ์ฝ”๋“œ์˜ ๋™์ž‘์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š” ์ˆ˜์ •์„ ํ•œ ์ปค๋ฐ‹
- ํŒŒ์ผ๋ช…์— style์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‹จ์–ด ํ™•์ธ ("prettier", "eslint", "configโ€)
- ๋ณ€๊ฒฝ์‚ฌํ•ญ์— ํŠน์ˆ˜๋ฌธ์ž(`,` , `'` , `"` , `\n` , `;` ๋“ฑ)๋งŒ ์ˆ˜์ •๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด `console.log` ์™€ ๊ด€๋ จ๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ์š”์†Œ๋“ค์˜ ์œ„์น˜ ๋ณ€๊ฒฝ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- tailwind className์˜ ์†์„ฑ ์ˆœ์„œ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ๊ฐ์ฒด ์†์„ฑ๋“ค์˜ ์ˆœ์„œ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์˜ˆ์‹œ
- ๋ณ€์ˆ˜๋ช… ๋ณ€๊ฒฝ ๋“ฑ style ์ฒดํฌ ์‚ฌํ•ญ์— ๋ฒ—์–ด๋‚œ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
- test
- ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•œ ์ปค๋ฐ‹
- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ํŒŒ์ผ๋งŒ ํฌํ•จ๋๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
- `test`, `tests`, `spec`, `mock`
- ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์˜ˆ์‹œ
- test ๊ฒ€์ฆ ํ‚ค์›Œ๋“œ๊ฐ€ ํŒŒ์ผ๋ช…์— ์—†๊ฑฐ๋‚˜ ๋์— ์œ„์น˜ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
- `a/src/compiler-worker.ts`
- `a/mock_feed_repository_impl.dart`
- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ด€๋ จ ํŒŒ์ผ์ด ์•„๋‹Œ ์„ค์ • ํŒŒ์ผ ๋“ฑ์˜ ์ˆ˜์ •์‚ฌํ•ญ์„ ๊ฐ™์ด ์ปค๋ฐ‹ํ–ˆ์„ ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ๋Š” ๋ณ€๊ฒฝ ๋‚ด์šฉ๊ณผ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋ฅผ ํŒ๋‹จํ•  ๋•Œ ๋ช…ํ™•ํ•œ ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•œ ํƒ€์ž…๋งŒ์„ ์šฐ์„ ์ ์œผ๋กœ ์„ ํƒํ–ˆ์œผ๋ฉฐ ์ถ”ํ›„ ํ•„ํ„ฐ๋ง ๊ธฐ์ค€์„ ํ™•์žฅํ•˜์—ฌ feat, fix ๋“ฑ์„ ํฌํ•จํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€ ๊ฐœ์„ ์„ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

## 2. API ๊ด€๋ จ ๋ฆฌ์†Œ์Šค ์ตœ์ ํ™”

Problem |

REST API๋ฅผ ์ด์šฉํ•˜์—ฌ ์š”์ฒญ์„ ํ•  ๊ฒฝ์šฐ, ์—”๋“œํฌ์ธํŠธ๋งˆ๋‹ค ์ „๋‹ฌ๋ฐ›๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ๊ณ ์ •๋˜์–ด ์žˆ์–ด ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋„ ํ•จ๊ป˜ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋„คํŠธ์›Œํฌ, ๋ฉ”๋ชจ๋ฆฌ, ํ”„๋กœ์„ธ์„œ ๋“ฑ์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋‚ญ๋น„๋ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ, ๋งŽ์€ ์–‘์˜ ์ปค๋ฐ‹์„ ์š”์ฒญํ• ์ˆ˜๋ก ๋ฒ„๋ฒ…์ž„๊ณผ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ์ ์  ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์ฒด๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

Analysis |

GitHub๋Š” ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ๋ณด๋‹ค ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก GraphQL์ด๋ผ๋Š” ๋ฐ์ดํ„ฐ ์ฟผ๋ฆฌ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•œ API๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ •๋ณด๋งŒ ์Šคํ‚ค๋งˆ์— ๋ช…์‹œํ•˜์—ฌ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์‚ฌ์šฉ์ž๋Š” ๋Œ€์—ญํญ๊ณผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ ˆ์•ฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ GraphQL์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋˜ ๋‘ ๊ฐ€์ง€ ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

1. ํ† ํฐ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€๋„ค์ด์…˜ (Token-Based Pagination)

GraphQL์€ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์ง€์›ํ•˜์ง€๋งŒ, ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜์ด ์•„๋‹Œ ํ† ํฐ ๊ธฐ๋ฐ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ˆœ์ฐจ์ ์œผ๋กœ ๋‹ค์Œ ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ์š”์ฒญํ•ด์•ผ ํ–ˆ๊ณ , REST API์ฒ˜๋Ÿผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ปค๋ฐ‹ ๋ชฉ๋ก์„ ๋ณ‘๋ ฌ๋กœ ์š”์ฒญํ•  ์ˆ˜ ์—†์–ด ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ํฌ๊ฒŒ ์ฆ๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

2. ์ปค๋ฐ‹ ๋ณ€๊ฒฝ์‚ฌํ•ญ ๋ฏธ์ œ๊ณต
GraphQL์€ ์ปค๋ฐ‹์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ ์ œ๊ณตํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Result |

๊ธฐ์กด REST API๋กœ ์š”์ฒญํ•˜๋˜ ๋ฐ์ดํ„ฐ๋ฅผ GraphQL๋กœ ์ „ํ™˜ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค์˜ ์‚ฌ์šฉ์„ ์ตœ์ ํ™” ํ•˜๋ ค ํ–ˆ์—ˆ์ง€๋งŒ, ๊ธฐ๋Šฅ์ด ์ €ํฌ ํ”„๋กœ์ ํŠธ์˜ ์ ์šฉํ•  ์ˆ˜ ์—†์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

## 3. GitHub API Rate Limit ํšŒํ”ผ๋ฅผ ์œ„ํ•œ ํ† ํฐ ๋กœํ…Œ์ด์…˜ ๊ตฌํ˜„

[Github API Rate Limit ์ฐธ๊ณ ๋งํฌ](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#primary-rate-limit-for-authenticated-users)

Problem |

### **Github API ํ˜ธ์ถœ ์ธ์ฆ๋œ ํ† ํฐ ์‹œ๊ฐ„๋‹น 5,000ํšŒ ์ œํ•œ**

Github API ์— ์˜์กด๋„๊ฐ€ ๋†’์€ ํ”„๋กœ์ ํŠธ์˜€๊ธฐ์— **Github API ์š”์ฒญ ์ œํ•œ ์ˆ˜๋Š” ์ €ํฌ ํ”„๋กœ์ ํŠธ์—์„œ ์น˜๋ช…์ **์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ปค๋ฐ‹ ๋ถ„์„ ๋กœ์ง์€ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ํ•„์š”ํ•œ ๊ฐ’๋“ค์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์˜ ์ปค๋ฐ‹ ํƒ€์ž…์„ ๋ถ„์„ํ•œ ์ดํ›„, ๊ฒ€์‚ฌ๊ฐ€๋Šฅํ•œ ์ปค๋ฐ‹ ํƒ€์ž…๋“ค๋งŒ์„ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. ํ•„ํ„ฐ๋ง ํ•œ ์ปค๋ฐ‹์˜ `owner`, `repo`, `sha` ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ฝ”๋“œ์˜ ์ˆ˜์ • ์ •๋ณด์ธ diff ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

ํŠนํžˆ๋‚˜ ํ•œ ์ธ์ฆ๋œ ํ† ํฐ ์‹œ๊ฐ„๋‹น 5,000ํšŒ๊ฐ€ ์ตœ๋Œ€์˜€๊ธฐ ๋•Œ๋ฌธ์— ์˜ˆ๋ฅผ ๋“ค์–ด, [facebook/react](https://github.com/facebook/react) ์™€ ๊ฐ™์ด ์ปค๋ฐ‹ ๊ฐฏ์ˆ˜๊ฐ€ 19,000๊ฐœ ์ด์ƒ์˜ ๊ฒฝ์šฐ 19,000/100 = **190**ํšŒ API ํ˜ธ์ถœ์„ ํ†ตํ•ด ์ „์ฒด ์ปค๋ฐ‹์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ , ๊ฒ€์‚ฌ๊ฐ€๋Šฅํ•œ ์ปค๋ฐ‹์„ ์ถ”์ถœํ•˜๋ฉด (2024.12.25 ์ผ ๊ธฐ์ค€์œผ๋กœ) 1450 ๊ฐœ ์ด๋ฏ€๋กœ, **1450**ํšŒ์˜ diff API ํ˜ธ์ถœ์„ ๋” ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, facebook/react ๋Š” 190 + 1450 = **1640**ํšŒ์˜ API ํ˜ธ์ถœ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์‚ฌ์‹ค 2, 3๋ฒˆ์˜ facebook/react ์ •๋„์˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋งŒ ์กฐํšŒ๋ฅผ ํ•˜๋”๋ผ๋„ GitHub API Rate Limit ๋ฅผ ๋ชจ๋‘ ์†Œ์ง„ํ•˜๊ฒŒ ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ๊ฒ€์‚ฌ๊ฐ€๋Šฅํ•œ ์ปค๋ฐ‹ ํƒ€์ž…์ด ์ถ”๊ฐ€๊ฐ€ ๋œ๋‹ค๋ฉด ๋” ๋งŽ์€ API ํ˜ธ์ถœ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋ชจ๋“  ์ปค๋ฐ‹์ด ๊ฒ€์‚ฌ ๋Œ€์ƒ์ด๋ผ๋ฉด ์ปค๋ฐ‹ ๊ฐœ์ˆ˜์˜ 101% ๋งŒํผ API ํ˜ธ์ถœ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Analysis |

**์ธ์ฆ๋œ ํ† ํฐ ๋กœํ…Œ์ด์…˜ ๋ฐฉ์‹ ๊ฒ€ํ† **

GitHub API ์š”์ฒญ ์ œํ•œ์€ ๊ฐ ํ† ํฐ๋งˆ๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ ์ ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. API ํ˜ธ์ถœ์ด ๋งŽ์€ ์ž‘์—…์—์„œ Rate Limit ๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋ฐœ์ƒํ–ˆ๊ณ , ํ•˜๋‚˜์˜ ํ† ํฐ๋งŒ์œผ๋กœ๋Š” ํ”„๋กœ์ ํŠธ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ GitHub Personal Access Token(PAT)์„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ์ด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๋กœํ…Œ์ด์…˜ํ•˜๋Š” ๋ฐฉ์‹์„ ์ฐจ์šฐ์„ ์œผ๋กœ ๊ฒ€ํ† ํ–ˆ์Šต๋‹ˆ๋‹ค.

Action |

**ํ† ํฐ ๋กœํ…Œ์ด์…˜ ๋กœ์ง ๊ตฌํ˜„ํ•˜์—ฌ ์ผ์‹œ์ ์œผ๋กœ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค**. ์—ฌ๋Ÿฌ ํ† ํฐ์„ tokenStates ๋ฐฐ์—ด๋กœ ๊ด€๋ฆฌํ•˜๋ฉฐ, ๊ฐ ํ† ํฐ์˜ ๋‚จ์€ ํ˜ธ์ถœ ๊ฐ€๋Šฅ ํšŸ์ˆ˜(remaining)๋ฅผ ์ถ”์ ํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค. API ํ˜ธ์ถœ ์‹œ, ๋‚จ์€ ์š”์ฒญ๋Ÿ‰์ด ๊ฐ€์žฅ ๋งŽ์€ ํ† ํฐ์„ ์„ ํƒํ•ด Rate Limit ์ดˆ๊ณผ๋ฅผ ๋ฐฉ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ถœ ํ›„, GitHub API์˜ ์‘๋‹ต ํ—ค๋”์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” X-RateLimit-Remaining ๊ฐ’์„ ์‚ฌ์šฉํ•ด ํ† ํฐ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. `getBestGithubToken()` ํ˜„์žฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ† ํฐ ์ค‘ ๊ฐ€์žฅ ๋งŽ์€ ๋‚จ์€ ์š”์ฒญ ํšŸ์ˆ˜๋ฅผ ๊ฐ€์ง„ ํ† ํฐ์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. `updateTokenState()` ํ˜ธ์ถœ ํ›„, ์‚ฌ์šฉํ•œ ํ† ํฐ์˜ ์ƒํƒœ๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ํ† ํฐ์„ ๋“ค๊ณ ์˜ฌ ๋•Œ ์ตœ์‹  limit ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

```jsx
const GITHUB_REQUEST_LIMIT = 5000;

const tokenStates = [
{
token: import.meta.env.VITE_GITHUB_TOKEN,
remaining: GITHUB_REQUEST_LIMIT,
},
...
];

const getBestGithubToken = () => {
tokenStates.sort((a, b) => b.remaining - a.remaining);

return tokenStates[0].token;
};

const updateTokenState = (token, remaining) => {
const tokenState = tokenStates.find((t) => t.token === token);

if (tokenState) {
tokenState.remaining = remaining;
}
};

export { getBestGithubToken, updateTokenState };
```

Result |

์—ฌ๋Ÿฌ ํ† ํฐ์„ ํ™œ์šฉํ•œ ๋กœํ…Œ์ด์…˜ ๋ฐฉ์‹์œผ๋กœ, GitHub API ์š”์ฒญ ์ œํ•œ์— ๋„๋‹ฌํ•˜์ง€ ์•Š๊ณ  ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ facebook/react ์ฒ˜๋Ÿผ ์ปค๋ฐ‹์ด ๋งŽ์€ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ๋„ ๋ถ„์„์ด ์ค‘๋‹จ๋˜์ง€ ์•Š๊ณ  ์™„๋ฃŒ๋  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ† ํฐ์ด ์ถ”๊ฐ€๋  ๊ฒฝ์šฐ tokenStates ๋ฐฐ์—ด์—๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ์ž๋™์œผ๋กœ ์ ์šฉ๋˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

## 4. GitHub ๋กœ๊ทธ์ธ ๊ตฌํ˜„

Problem |

๊ฒ€์‚ฌํ•  ์ปค๋ฐ‹์ด ๋‹จ์ผ ํ† ํฐ์˜ ์š”์ฒญ๋Ÿ‰์ธ 5000๊ฐœ ์ด์ƒ์˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋„ ์ •์ƒ์ ์œผ๋กœ ๋ชจ๋‘ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ† ํฐ ๋กœํ…Œ์ด์…˜ ๋ฐฉ์‹์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ๋กœ์ปฌ์—์„œ๋งŒ ์šด์˜์„ ํ•œ๋‹ค๋ฉด ํ† ํฐ ๋กœํ…Œ์ด์…˜ ๋ฐฉ์‹์œผ๋กœ๋„ ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ, ๋ฐฐํฌํ•˜์—ฌ ์„œ๋น„์Šค๋ฅผ ํ•œ๋‹ค๋ฉด ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ด์šฉํ•˜๋Š” API ์‚ฌ์šฉ๋Ÿ‰์ด ์ €ํฌ๊ฐ€ ์ˆ˜๋™์œผ๋กœ ์ถ”๊ฐ€ํ•œ ํ† ํฐ์˜ ์š”์ฒญ๋Ÿ‰์„ ๊ฐ๋‹นํ•  ์ˆ˜ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Analysis |

์œ ์ €์˜ ์ ‘๊ทผ์„ฑ์„ ์œ„ํ•ด ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ๋ ค ํ–ˆ์ง€๋งŒ ๋ฐฐํฌ๋œ ์„œ๋น„์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋Œ์•„๊ฐ€๋ ค๋ฉด ๊ฐ ์œ ์ €์˜ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ตœ์„ ์ด๊ณ  ๊ฒฐ๊ตญ ๋กœ๊ทธ์ธ์€ ํ•„์ˆ˜๋ถˆ๊ฐ€๊ฒฐ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋กœ๊ทธ์ธ์„ ํ•˜์ง€์•Š๊ณ  ์„œ๋น„์Šค๋ฅผ ๊ฒฝํ—˜ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜๋‹ค ์ƒ๊ฐํ•˜์—ฌ ๋ฐฉ๋ฒ•์„ ์ฐพ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Action |

**- ๋ฐ๋ชจ ๋ฒ„์ „ ์ œ๊ณต ๊ณ ๋ ค**

์ฒ˜์Œ์—๋Š” ๋กœ๊ทธ์ธ์„ ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋งํฌ๋ฅผ ์ œ์ถœํ•˜๋ฉด ๊ธฐ๋ณธ ํ† ํฐ์˜ ์š”์ฒญ๋Ÿ‰(์‹œ๊ฐ„ ๋‹น 60๊ฐœ)์„ ์ด์šฉํ•˜์—ฌ ์ผ๋ถ€๋งŒ ๋ณด์—ฌ์ฃผ๋„๋ก ํ•˜๊ณ  ๋กœ๊ทธ์ธ์„ ์œ ๋„ ํ•˜๋ คํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ •๋ง ์ผ๋ถ€์˜ ์ปค๋ฐ‹ ๋ถ„์„๋งŒ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๊ณ  ํ†ต๊ณ„๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ํ† ํฐ์˜ ์š”์ฒญ๋Ÿ‰์„ ๋น ๋ฅด๊ฒŒ ์†Œ์ง„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋ ˆํฌ์ง€ํ† ๋ฆฌ๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ผ๋ถ€ ๊ฒฝ์šฐ์—๋Š” API์— ์ ‘๊ทผ ์ž์ฒด๊ฐ€ ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๋„ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

**- ๋ชฉ์—… ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•œ ๋™์ผํ•œ ๊ฒฝํ—˜ ์ œ๊ณต**

๋”ฐ๋ผ์„œ ์ผ๋ถ€ ์œ ๋ช…ํ•œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ๋ชฉ์—… ๋ฐ์ดํ„ฐ๋กœ ์ œ๊ณตํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ ์œ ์ €์™€ ์ตœ๋Œ€ํ•œ ๋น„์Šทํ•œ ์ฒดํ—˜์„ ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋Šฅ๊ณผ ์ธํ„ฐํŽ˜์ด์Šค์  ์š”์†Œ๋ฅผ ๋˜‘๊ฐ™์ด ์ด์šฉํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

Result |

๋น„๋กœ๊ทธ์ธ ์ƒํƒœ์—์„œ๋Š” ํ…์ŠคํŠธ ์ž…๋ ฅ ๋ฐ•์Šค๋ฅผ ์„ ํƒ ๋ฐ•์Šค๋กœ ๋ณ€๊ฒฝํ•˜๊ณ , ์ œ๊ณต๋˜๋Š” ์„ ํƒ์ง€๋ฅผ ์ด์šฉํ•ด ์ œ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ๋ชฉ์—… ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด ์‹ค์ œ ๊ธฐ๋Šฅ๊ณผ ๋™์ผํ•œ ๊ฒฝํ—˜์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ฌธ๊ตฌ๋ฅผ ๋ฐ•์Šค ์œ„์— ๋‘์–ด ๋กœ๊ทธ์ธ ์‹œ ์ง์ ‘ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•œ ์ ์„ ์•Œ๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

![without_login_selection_box](assets/readme/without_login_selection_box.gif)

![login_input](assets/readme/login_input.gif)

ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฑฐ์˜ ๋˜‘๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํ•˜์ง€์•Š๊ณ  ์ฒดํ—˜ํ•˜๋ฉด์„œ ํŠœํ† ๋ฆฌ์–ผ์˜ ๊ธฐ๋Šฅ๋„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

## 5. ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ

Problem |

**- ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ ์—๋Ÿฌ ๋ฐœ์ƒ**

์ปค๋ฐ‹์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋กœ ํŽ˜์ด์ง€ ๋ฆฌ๋กœ๋“œ ์‹œ ์ƒํƒœ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด sessionStorage์— ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.

GitHub API๋ฅผ ํ†ตํ•ด ์ปค๋ฐ‹๋“ค์˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ(diff)์„ ๊ฐ€์ ธ์˜ค๋Š” ๊ณผ์ •์—์„œ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋งŽ์„ ๊ฒฝ์šฐ ์ €์žฅ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๊ฐ€ ๋งค์šฐ ์ปค์กŒ๊ณ  ์ด์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ ์ €์žฅ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

sessionStorage ๋Š” ๋Œ€์šฉ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๊ฒฝ์šฐ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜์ง€ ์•Š๊ณ  ์šฉ๋Ÿ‰์ด ์ดˆ๊ณผ๋˜์—ˆ๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Analysis |

sessionStorage ๋Š” ๋ธŒ๋ผ์šฐ์ €๋งˆ๋‹ค ์•ฝ 5 MiB์˜ ์šฉ๋Ÿ‰ ์ œํ•œ์ด ์žˆ์—ˆ๊ณ  ์ด ์šฉ๋Ÿ‰ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ธฐ์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. GitHub API๋กœ ์‘๋‹ต ๋ฐ›๋Š” ์ปค๋ฐ‹ diff ๋ฐ์ดํ„ฐ๋Š” ๋ณ€๊ฒฝ๋œ ์ฝ”๋“œ ์–‘์— ๋”ฐ๋ผ ๋งค์šฐ ํฐ ํฌ๊ธฐ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ sessionStorage๋กœ๋Š” ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹คํŒจ๋กœ ์ธํ•œ ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ์ปค์กŒ์Šต๋‹ˆ๋‹ค.

Action |

์ด ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์„ ์œ„ํ•ด sessionStorage๋Œ€์‹  IndexedDB๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

- IndexedDB
๋ธŒ๋ผ์šฐ์ € ๋‚ด์—์„œ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ณ ์„ฑ๋Šฅ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ์ธ๋ฑ์‹ฑํ•˜๋Š” ์›น API ์ž…๋‹ˆ๋‹ค.

idb-keyval ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ฐ„๋‹จํ•œ API (get(), set(), del() ๋“ฑ)๋ฅผ ์จ์„œ IndexedDB ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ zustand ๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ IndexedDB ์— ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

- zustand ์˜ persist ๋ฏธ๋“ค์›จ์–ด(`storage: createJSONStorage(() => indexedDB)`)๋ฅผ ํ™œ์šฉํ•˜์—ฌ zustand ์ƒํƒœ๋ฅผ IndexedDB ์— ์ €์žฅํ•˜๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
- IndexedDB ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

```jsx
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
import { get, set, del } from "idb-keyval";
import { throwIndexedDBErrorMessage } from "../../../shared/error/throwCustomErrorMessage";

const indexedDB = {
getItem: async (name) => {
try {
const value = await get(name);
return value || null;
} catch (error) {
throwIndexedDBErrorMessage(error);
}
},
setItem: async (name, value) => {
try {
await set(name, value);
} catch (error) {
throwIndexedDBErrorMessage(error);
}
},
removeItem: async (name) => {
try {
await del(name);
} catch (error) {
throwIndexedDBErrorMessage(error);
}
},
};

const initialState = {};

const useCommitStore = create(
persist(
(set) => ({
...initialState,
}),
{
name: "commit-storage",
storage: createJSONStorage(() => indexedDB),
}
)
);

export default useCommitStore;
```

Result |

**- sessionStorage ์—์„œ ๋ฐœ์ƒํ•˜๋˜ ์ €์žฅ ์šฉ๋Ÿ‰ ์ดˆ๊ณผ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ**

IndexedDB๋Š” 5MiB ๋ณด๋‹ค ํ›จ์”ฌ ํฐ ์šฉ๋Ÿ‰(GB ๋‹จ์œ„)์„ ์ง€์›ํ•˜์—ฌ ์ปค๋ฐ‹ diff ๋ฐ์ดํ„ฐ์™€ ๊ฐ™์€ ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์›ํ™œํ•˜๊ฒŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

zustand์™€ ๊ฒฐํ•ฉํ•˜์—ฌ ์ปค๋ฐ‹ ๊ด€๋ จ ์ƒํƒœ๋ฅผ ์ง€์†์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ณ  idb-keyval ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ฝ”๋“œ ๋ณต์žก๋„๋ฅผ ์ค„์ด๊ณ  ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

## 6. ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํ™”๋ฉด์— ๋ Œ๋”๋ง ํ•˜๊ธฐ ์œ„ํ•œ virtual scroll ๋„์ž…

[virtual scroll ๋„์ž…ํ•œ PR ๋งํฌ](https://github.com/git-marvel/commit-guardians-client/pull/93)

![](assets/readme/before_virtualscroll.gif)

Problem |

**- INP ์ง€์ˆ˜ ์ƒ์Šน ๋ฐ ํ™”๋ฉด ๋ฒ„๋ฒ…์ž„**

์ด๋ฏธ ๊ฒ€์‚ฌ๊ฐ€ ๋๋‚œ ๋ชจ๋“  ์ปค๋ฐ‹๋“ค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๋””ํ…Œ์ผ ๋ทฐ์—๋Š” **ํ™”๋ฉด ์„ฑ๋Šฅ์— ๊ด€ํ•œ ๋ฌธ์ œ**๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ ์€ ์–‘์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์Šคํฌ๋กค ํ•  ๋•Œ๋Š” ํฐ ๋ฌธ์ œ๊ฐ€ ์—†์—ˆ์ง€๋งŒ, ๋งŽ์€ ์–‘์˜ ์ปดํฌ๋„ŒํŠธ๋“ค์„ (๋Œ€๋žต 1์ฒœ๊ฐœ ์ด์ƒ์˜ ์ปค๋ฐ‹ ์ปดํฌ๋„ŒํŠธ) ๊ฐ€์ง„ ๋””ํ…Œ์ผ ํ™”๋ฉด์— ์ฒซ ์ง„์ž…์‹œ ํ™”๋ฉด ๋ Œ๋”๋ง์˜ ์‹œ๊ฐ„์ด ์ง€์—ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ํผํฌ๋จผ์Šค ํƒญ์„ ํ™•์ธํ•ด๋ณด๋‹ˆ [**INP**](https://web.dev/articles/inp?hl=ko)(**Interaction to Nextย Paint**) ์ง€์ˆ˜๊ฐ€ ๊ธ‰๊ฒฉํžˆ ์ƒ์Šนํ•˜๊ณ , ํ™”๋ฉด์ด ๋™์ ์œผ๋กœ ๋ณ€ํ•  ๋•Œ, ํŠนํžˆ๋‚˜ ๋ฒ„๋ฒ…์ด๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์‚ฌ์šฉ์ž๋Š” ํ™”๋ฉด ์ „ํ™˜ ์‹œ์˜ ๋Š๋ฆฐ ๋ฐ˜์‘ ์†๋„์™€ ์ง€์—ฐ์œผ๋กœ ์ธํ•ด ๋‹ต๋‹ตํ•จ์„ ๋Š๋ผ๊ฒŒ ํ•˜๊ณ , ์ „์ฒด์ ์ธ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ €ํ•˜์‹œํ‚ค๊ณ , ์•ฑ ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ๋ถ€์ •์ ์ธ ์˜ํ–ฅ์„ ๋ผ์น  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Analysis |

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•œ ๋ฒˆ์— ๋ Œ๋”๋งํ•˜๋ ค๋Š” ๊ณผ์ •์—์„œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ๋ชจ๋‘ DOM ์— ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ์‹์ด ๋ณ‘๋ชฉํ˜„์ƒ์˜ ์ฃผ์š” ์›์ธ์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์Šคํฌ๋กค์ด ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ๋””ํ…Œ์ผํ™”๋ฉด์—์„œ ์Šคํฌ๋กค ์‚ฌ์šฉ ์‹œ ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๋”์šฑ ์‹ฌ๊ฐํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ INP ์ง€์ˆ˜๋ฅผ ๊ฐœ์„ ํ•˜๊ณ , ์Šคํฌ๋กค ์‹œ ๋ถ€๋“œ๋Ÿฌ์šด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

Action |

**- Virtual Scroll ๋„์ž…**

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ €ํฌ๋Š” **Virtual Scroll** ๊ธฐ์ˆ ์„ ๋„์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค. Virtual Scroll ์€ ์‚ฌ์šฉ์ž๊ฐ€ **ํ˜„์žฌ ํ™”๋ฉด์—์„œ ๋ณด๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ DOM ์— ๋ Œ๋”๋งํ•˜๊ณ , ๋ณด์ด์ง€ ์•Š๋Š” ๋ถ€๋ถ„์€ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์Œ**์œผ๋กœ์จ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ถˆํ•„์š”ํ•œ ์ž‘์—…์„ ์ค„์—ฌ์ฃผ๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์„ ํ†ตํ•ด ์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ณ , ๋ Œ๋”๋ง ์†๋„๋ฅผ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋”๋ถˆ์–ด ๋ฌดํ•œ์Šคํฌ๋กค์ฒ˜๋Ÿผ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์š”์ฒญ์„ ํ†ตํ•ด์„œ๋„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, ์ด๋ฏธ ์ปค๋ฐ‹๋“ค์ด ๋ถ„์„๋œ ๋‹ค์Œ ๋””ํ…Œ์ผ ํ™”๋ฉด ํŽ˜์ด์ง€๋ฅผ ๋ณด๋Š” ๊ฒƒ์ด๊ธฐ์— ๋ฌดํ•œ ์Šคํฌ๋กค ๊ธฐ๋Šฅ์€ ํ•„์š”์—†๋‹ค ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. Virtual Scroll ์„ ๋„์ž…ํ•˜๊ณ  ๋ Œ๋”๋ง ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ ๋ฐ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ์ ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

Result |

![](assets/readme/after_virtualscroll.gif)

์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ ๋ถˆํ•„์š”ํ•œ DOM ์ž‘์—…์„ ์ค„์ด๊ณ , ์Šคํฌ๋ฆฐ์— ๋ณด์—ฌ์ฃผ๋Š” ๋ถ€๋ถ„๋งŒ DOM ์— ๊ทธ๋ฆฌ๋„๋ก ํ•˜๋ฉด์„œ INP ์ง€์ˆ˜๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ, ๋‘๊ฐ€์ง€ ์ด์ ์„ ๋” ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

1. **์Šคํฌ๋กค ์„ฑ๋Šฅ ํ–ฅ์ƒ**: ๋Œ€๊ทœ๋ชจ ์ปค๋ฐ‹ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง„ ํ™”๋ฉด์—์„œ๋„ ์Šคํฌ๋กค์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์ฆ‰๊ฐ์ ์ธ ๋ฐ˜์‘์„ฑ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
2. **์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ **: ํ™”๋ฉด ์ „ํ™˜ ์†๋„๊ฐ€ ๋นจ๋ผ์ง€๊ณ , ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์€ ํ™”๋ฉด์—์„œ๋„ ๋†’์€ ์„ฑ๋Šฅ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ, ๋Œ€๊ทœ๋ชจ ์ปค๋ฐ‹ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ๋•Œ์—๋„ ์•ˆ์ •์ ์ธ ์„ฑ๋Šฅ๊ณผ ์›ํ™œํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋‹ฌ์„ฑํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

## ํŒ€์› ์†Œ๊ฐœ

**์‹ ์ฒ ํ™˜**

์„œ๋น„์Šค์˜ ๋ชฉ์ ์„ ๊ฐ€์ง„ ํ”„๋กœ์ ํŠธ์˜ ํ˜‘์—…์€ ์ด๋ฒˆ์ด ์ฒ˜์Œ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ „์—๋Š” ํŒ€์›๋“ค๊ณผ ๊ฐ™์ด ์ฝ”๋”ฉ์„ ํ•˜๋ฉด์„œ ํ˜‘์—…์ด๋ž€ ๋ฌด์—‡์ธ์ง€์— ๋Œ€ํ•ด ์ด๋ก ์ ์œผ๋กœ ์ ‘๊ทผํ–ˆ์ง€ ํฌ๊ฒŒ ์™€๋‹ฟ์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋ช‡ ์ฃผ ๋™์•ˆ ์—ญํ• ์„ ๋‚˜๋ˆ„๊ณ , ๋งŽ์€ ์‹œ๊ฐ„์„ ํ•˜๋‚˜์˜ ๋ชฉํ‘œ์— ๋Œ€ํ•ด ์ง‘์ค‘ํ•˜๊ฒŒ ๋˜๋ฉด์„œ ํ˜‘์—…์— ๋Œ€ํ•ด ๋งŽ์ด ์ƒ๊ฐ์„ ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ €ํฌ ํ”„๋กœ์ ํŠธ ์ฃผ์ œ๋กœ ์ปค๋ฐ‹์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์กฐ์‚ฌํ•˜๋ฉด์„œ ๋‹จ์ˆœํžˆ ์ปค๋ฐ‹์ด ๊ธฐ๋ก์˜ ์ˆ˜๋‹จ์ด ์•„๋‹ˆ๋ผ ์ €ํฌ๊ฐ€ ํ•˜๋Š” ํ˜‘์—…์˜ โ€˜์–ธ์–ดโ€™๋ผ๋Š” ๋Š๋‚Œ์„ ๋งŽ์ด ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Š” ๋ง์ด ๊ณ ์™€์•ผ ์˜ค๋Š” ๋ง์ด ๊ณฑ๋‹ค๋Š” ์†๋‹ด์ฒ˜๋Ÿผ ์ปค๋ฐ‹๋„ ์ž˜ ์ž‘์„ฑํ•˜๊ณ  ์ „๋‹ฌํ•ด์•ผ ์†Œํ†ต์ด ์ž˜ ์ง„ํ–‰๋˜๋Š” ๊ฒƒ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €์—๊ฒŒ ํ˜‘์—…์„ ์ž˜ํ–ˆ๋ƒ๊ณ  ๋ฌผ์œผ๋ฉด ์ €๋Š” ์ด๋ฒˆ์—๋Š” ์ปค๋ฐ‹์„ ์ž˜ ์“ฐ์ง€ ๋ชปํ•ด์„œ ์•„์‰ฝ๋‹ค๊ณ  ๋Œ€๋‹ตํ•  ๊ฒ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‚˜์ค‘์—๋Š” ๋ฉ‹์ง„ ์ปค๋ฐ‹์„ ์“ฐ๊ณ  ๋‹น๋‹นํ•˜๊ฒŒ โ€œ๋„คโ€๋ผ๊ณ  ๋‹ตํ–ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

**ํ™์œ ์ง„**

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์ปค๋ฐ‹์ด ๋‹จ์ˆœํ•œ ๊ธฐ๋ก์ด ์•„๋‹ˆ๋ผ, ํ”„๋กœ๋•ํŠธ์˜ ๊ธฐ๋ฐ˜์„ ์ด๋ฃจ๋Š” ์ค‘์š”ํ•œ ์š”์†Œ๋ผ๋Š” ์‚ฌ์‹ค์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‹ค๊ฐํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ์ปค๋ฐ‹์˜ ์ค‘์š”์„ฑ์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋Š” ์ž์ฃผ ๋“ค์—ˆ์—ˆ์ง€๋งŒ, ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ๊ฒฝํ—˜ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๊นŠ์ด ๊ณต๊ฐํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜์„ ํ†ตํ•ด, ์ข‹์€ ์ปค๋ฐ‹์ด ๋™๋ฃŒ ๊ฐœ๋ฐœ์ž์˜ ์ƒ์‚ฐ์„ฑ์„ ์–ผ๋งˆ๋‚˜ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์ฒด๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , ์ปค๋ฐ‹์— ๋Œ€ํ•œ ์ œ ๊ฐ€์น˜๊ด€ ๋˜ํ•œ ํฌ๊ฒŒ ๋ณ€ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜, ํŒ€ ํ”„๋กœ์ ํŠธ๋กœ ํ•จ๊ป˜ ํ˜‘์—…์„ ํ•˜๋ฉด์„œ ์„œ๋กœ์˜ ์ƒ๊ฐ์„ ๋งž์ถฐ๋‚˜๊ฐ€๋Š” ๊ณผ์ •์ด ์ฆ๊ฑฐ์› ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์ €ํฌ ํ”„๋กœ์ ํŠธ๊ฐ€ style, remove, test, docs ์˜ ์ปค๋ฐ‹ํƒ€์ž…๋งŒ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ์ดํ›„ ํ•˜๋‚˜์”ฉ ํ•˜๋‚˜์”ฉ ๋” ์ถ”๊ฐ€ํ•˜์—ฌ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค!

**๊น€์ˆ˜ํ•œ**

ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์ดˆ๊ธฐ์—๋Š” ์ปค๋ฐ‹๋ฉ”์‹œ์ง€์— ๊ด€ํ•œ ๊ธฐ์ค€์„ ์ •ํ•˜๋Š” ๊ณผ์ •์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ์ž‘์„ฑ๋œ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์™€ ๋ณ€๊ฒฝ ๋‚ด์šฉ์˜ ์ผ์น˜์„ฑ์„ ๊ทœ๊ฒฉํ™”๋œ ๊ธฐ์ค€์„ ์ •ํ•ด ํŒ๋‹จํ•ด์•ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ์ผ€์ด์Šค๊ฐ€ ๋‚˜์˜ฌ ๋•Œ๋งˆ๋‹ค ์–ด๋–ค ์‹์œผ๋กœ ๊ทœ๊ฒฉํ™”๋ฅผ ์‹œ์ผœ์•ผํ• ์ง€ ๊ณ ๋ฏผ์„ ๋งŽ์ด ํ–ˆ๋˜ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ API๋กœ ์‘๋‹ต๋ฐ›์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ด€๋ จํ•ด์„œ ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋“ค์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ณผ์ •์—์„œ IndexedDB ํ™œ์šฉ๊ณผ ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ API์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ ํšจ์œจ์ ์œผ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹ ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฅผ ๋ฐฐ์šฐ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ํŒ€์›๋“ค๊ณผ ๊ฐ์ž์˜ ์˜๊ฒฌ์„ ๊ณต์œ ํ•˜๊ณ  ํšŒ์˜๋ฅผ ํ•˜๋‹ค๋ณด๋ฉด ์ƒˆ๋กœ์šด ๋ฐฉํ–ฅ์˜ ํ•ด๊ฒฐ์ฑ…๋“ค์ด ๋‚˜์™€์„œ ๋‹ค์–‘ํ•œ ์‹œ๋„๋“ค์„ ํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์งง์€ ๊ธฐ๊ฐ„์ด์—ˆ์ง€๋งŒ ์ƒˆ๋กœ์šด ๊ฐœ๋…๋“ค์„ ๋ฐฐ์šฐ๊ฒŒ ๋˜์—ˆ๊ณ  ํšจ์œจ์ ์ธ ์†Œํ†ต ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด๋ณด๊ณ  ์ ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์—ˆ๋˜ ์ข‹์€ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค.