๊ฐ์กฑยทํ๋ฉ์ฉ ์ ํํธ์คํ ์ฐจ๋ ๊ด๋ฆฌ โ ์ ๋น ์ค์ผ์ค, ์ฃผ์ ๊ธฐ๋ก, ์๋ฆผ, OBD/GPS ์ฃผํ, Home Assistant ์ฐ๋(์ ํ).
์ต์ ๋ฆด๋ฆฌ์ค๋ GitHub Releases์์ ํ์ธํ์ธ์.
๋ฌธ์: docs/ARCHITECTURE.md ยท docs/INTEGRATIONS.md ยท docs/PROGRESS.md
- ์ฐจ๋ยท์ฌ์ฉ์ยท์ฐจ๋๋ณ ์ ๊ทผ ACL (๊ด๋ฆฌ์ / ์ผ๋ฐ)
- ๋ชจ๋ฐ์ผ ์ฐ์ ์ ๊ณ ์ ํ ํ๋จ ๋ค๋น๊ฒ์ด์ ๋ฐ๋ก ํ ์ ์กฐ์ ํธ์์ฑ ๊ทน๋ํ
- ์ค๋งํธ ํ ๋ฆฌ๋ค์ด๋ ํธ: ๊ณ์ ์ ๋ฑ๋ก๋ ์ฐจ๋์ด 1๋๋ฟ์ธ ๊ฒฝ์ฐ ์ฐจ๋ ๋ชฉ๋ก ๋์๋ณด๋๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ฐ๋ก ์ฐจ๋ ๊ฐ์๋ก ์ง์
- ์ ๋น + ํ์ ยท๋ฒ์ ์ค์ผ์ค, ๊ฑฐ๋ฆฌยท์๊ฐ ์ด์ค ์๋ฆผ
- ์ฐ๋ฃ ํ์ ๋ณ ์ ๋น ํ๋ฆฌ์ , ์ ์ญ ํ์ ยท๋ฒ์ ํ๋ฆฌ์
- ์ฃผ์ ๊ธฐ๋กยท์์์ฆ ์ฒจ๋ถ, ์คํผ๋ท ์ฃผ๋ณ ์ฃผ์ ์(์ ํ)
- ์ฒ์์ฌ๋์นด๋ ๊ฐ๋งน ์ฃผ์ ์(์ตํธ์ธ) โ ๊ฐ๊ฒฉยท๊ฑฐ๋ฆฌ์ ์ ์ฒด ๋ชฉ๋ก, ์ ์ ์ข ๊ฐ๊ฒฉ ํ์
- ์ ๊ธฐ์ฐจ ์ถฉ์ ์ ์ฐพ๊ธฐ(ํ๊ตญํ๊ฒฝ๊ณต๋จ API, ์ ํ) โ ์ฃผ์ ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฑฐ๋ฆฌ์/๊ฐ๊ฒฉ์ ๊ฒ์, ์ง๋์ ๋ฒํธ ๋ง์ปค๋ก ํ์
- OBD ์์ง(Torque Pro), REST/WebSocket ํ ๋ ๋ฉํธ๋ฆฌ, ์๋ ํธ๋ฆฝ ๋ถํ
- ํ๋ ๋ธ๋ฃจ๋งํฌ ์ปค๋ฅํฐ๋์นด ์ฐ๋(๋ฒ ํ, ๊ตญ๋ด ์ ์ฉ) โ OBD ๋๊ธ ์์ด ์ค์ ์ฃผํ๊ฑฐ๋ฆฌยท์ฃผํ๊ฐ๋ฅ๊ฑฐ๋ฆฌยท๊ฒฝ๊ณ ๋ฑ ์กฐํ, ์ค๋๋ฏธํฐ ์๋ ๋๊ธฐํ. ๊ฐ์กฑ ๊ตฌ์ฑ์ ๊ฐ์ ํ๋กํ์์ ๋ณธ์ธ ๊ณ์ ์ฐ๋
- ์ฃผํ ๋ฆฌํฌํธ, ๊ฒฝ๋ก ์ง๋ (OSM / ์นด์นด์ค / ๋ค์ด๋ฒ / T๋งต) ๋ฐ ์งํ ๋ฐฉํฅ ํ์ดํ, ์ฃผํ ๊ฐ๋ณ ๋ฉ๋ชจ ์ถ๊ฐ/ํธ์ง ๋ฐ ์ญ์ง์ค์ฝ๋ฉ
- ๋์๋ณด๋ ์๋ฆผ ๋ฐฐ์ง ๋ฐ ์ฐจ๋ ์์ฝ ์นด๋ (์ต๊ทผ ์ฃผ์ ๋น์ฉ ํฌํจ)
- ์ฐจ๋๋ณ ๊ด๋ฆฌ ๋ ๋ฒจยท๋ฑ์ง(๊ฒ์ด๋ฏธํผ์ผ์ด์ ) ์ ์ฉ ํ๋ฉด
- ๋ค๋น๊ฒ์ด์ ๊ตฌ์กฐ ๋จ์ผํ (์๋จ ํค๋ ์ ๊ฑฐ ๋ฐ ๋ฒ์ ํ์ ๋๋ณด๊ธฐ ์ํธ ์ด๋)
- ๊ด๋ฆฌ์ ๋ฐฑ์ /๋ณต์, PWA, ํ/์ i18n
- ์ฌ์ฉ์ ์์ ๋ ์ต์ด ๊ด๋ฆฌ์ ๋ถํธ์คํธ๋ฉ
๋ก๊ทธ์ธ ํ ํ ํ๋ฉด์ ๋๋ค. ์ฐจ๋์ด ์ฌ๋ฌ ๋์ธ ๊ฒฝ์ฐ์๋ ํตํฉ ๋์๋ณด๋๊ฐ ํ์๋์ด ๋ชจ๋ฐ์ผ์ ์ต์ ํ๋ ํ๋ฉด์์ ๊ฐ ์ฐจ๋ ์นด๋๋ณ ํ์ฌ ์ฃผํ๊ฑฐ๋ฆฌ, ์ต๊ทผ ์ฃผํ ๊ฑฐ๋ฆฌ, ์ต๊ทผ ์ฃผ์ ๋น์ฉ, ์ง๋จ/์๋ฐ ์๋ฆผ ๊ฑด์๋ฅผ ํ๋์ ๋ณผ ์ ์์ต๋๋ค. ํ๋จ ๋ค๋น๊ฒ์ด์ ๋ฐ๋ฅผ ํตํด ํ, ๋น ๋ฅธ ์ ๋ ฅ, ์ค์ ์ผ๋ก ๋ฐ๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์ฐจ๋๋ณ ํ๋ธ์ ๋๋ค. ์ต๊ทผ ์ง์ถ ์์ฝ ์นด๋, ์๊ฐ ๋น์ฉ ์ฐจํธ, ๋ง์ง๋ง ์ฃผํ ์ ๋ณด ๋ฐ ์ง๋๊ฐ ์ ๊ณต๋ฉ๋๋ค. ์ ๊ธฐ์ฐจ ํ๋ฉด์ ์ถฉ์ ์ํ์ ๋ฐฐํฐ๋ฆฌ ๊ด๋ จ ์ ๋ณด๋ฅผ ํ์ํ๋ฉฐ ์ฃผ๋ณ ์ถฉ์ ์ ์ฐพ๊ธฐ๊ฐ ์ฐ๋๋๊ณ , ๋ด์ฐ์ฐจ ํ๋ฉด์ ์ฐ๋ฃ ๊ฒ์ด์ง์ ์คํผ๋ท ๊ธฐ๋ฐ ์ฃผ๋ณ ์ฃผ์ ์ ์ฐพ๊ธฐ ์ฐ๋์ ์ ๊ณตํฉ๋๋ค.
์ด๋์๋ ์ฃผ์ /์ถฉ์ ๋ฐ ์ ๋น๋ฅผ ๋ฐ๋ก ๊ธฐ๋กํ๋ ํ๋ฉด์ ๋๋ค. ์ ๊ธฐ์ฐจ๋ ์ถฉ์ ์ ๋ ฅ๋(kWh) ์ ๋ ฅ, kWh๋น ๋จ๊ฐ, ์ถฉ์ ์ ๊ฒ์์ ์ง์ํ๋ฉฐ, ๋ด์ฐ์ฐจ๋ ์ ์ ์ฌ ๋ธ๋๋ ๋ก๊ณ ์ ํ(์คํผ๋ท), ์ฃผ์ ๋(L), ๋ฆฌํฐ๋น ๋จ๊ฐ ์ ๋ ฅ์ ์ง์ํฉ๋๋ค.
๊ฑฐ๋ฆฌ ๋ฐ ์๊ฐ ๊ธฐ์ค ์ ๋น ์ค์ผ์ค๊ณผ ํ์ ์๋ฆผ์ ๊ด๋ฆฌํฉ๋๋ค. ์์ง์ค์ผ/์ค์ผํํฐ ๊ต์ฒด ์ฃผ๊ธฐ(๋ด์ฐ์ฐจ ์ ์ฉ) ๋ฑ ์ฐจ์ข ์ ์ต์ ํ๋ ์ ๋น ํ๋ฆฌ์ ์ด ๊ธฐ๋ณธ ์ ์ฉ๋ฉ๋๋ค.
์ฃผํ ๋ฆฌํฌํธ, ์ถฉ์ /์ฃผ์ ๋ก๊ทธ, ์ ๋น ์ด๋ ฅ์ ํ๊ณณ์ ๋ชจ์ ๋ณด์ฌ์ค๋๋ค. ๋ด์ฐ์ฐจ๋ ํํฑํฌ ๊ธฐ์ค ์ฃผ์ ์ฐ๋น(km/L)๊ฐ ์๋ ๊ณ์ฐ๋๊ณ , ์ ๊ธฐ์ฐจ๋ ์๋์ง ์๋ชจ๋ ์งํ๋ฅผ ์ค์ฌ์ผ๋ก ๋ด์ญ์ ํ์ํฉ๋๋ค.
์ฃผ์ /์ถฉ์ ๋ฐ ์ ๋น๋ฅผ ๊พธ์คํ ๊ธฐ๋กํด ๊ฒฝํ์น๋ฅผ ๋ชจ์ผ๊ณ ์ฐจ๋ ๋ ๋ฒจ์ ์ฌ๋ ค ๋ฑ์ง๋ฅผ ํ๋ํ๋ ํ๋ฉด์ ๋๋ค.
์ฃผํ๊ฑฐ๋ฆฌยท๋น์ฉยท์ฐ๋น ํต๊ณ ์ฐจํธ๋ฅผ ์ ๊ณตํ๋ฉฐ 1์ฃผ/1๋ฌ ๋จ์ ๊ธฐ๊ฐ ํํฐ๋ง ๋ฐ ์ฃผํยท์ฃผ์ ยท์ ๋น ์ด๋ ฅ์ CSV/Excel ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์ง์ํฉ๋๋ค.
์คํผ๋ท ๊ธฐ๋ฐ ์ฃผ๋ณ ์ฃผ์ ์, ์ฒ์์ฌ๋์นด๋ ๊ฐ๋งน ์ฃผ์ ์, ํ๊ฒฝ๊ณต๋จ EV ์ถฉ์ ์ ๊ฒ์์ ๋จ์ผ ๋ฉ๋ด์์ ์ง๋ ๋ฒํธ ๋ง์ปค์ ํจ๊ป ๊ฑฐ๋ฆฌ์/๊ฐ๊ฒฉ์์ผ๋ก ์ ๊ณตํฉ๋๋ค.
์ฐจ๋ ๋ฑ๋ก/๊ด๋ฆฌ, ์ฌ์ฉ์ ์ถ๊ฐ/์์ , ์ฐ๋ฃํ์ ๋ณ ์ ๋น ํ๋ฆฌ์ ์ค์ , ์ง๋/๋ ์จ/์๋ฆผ API ์ฐ๋, ๋ฐฑ์ /๋ณต์, ๊ทธ๋ฆฌ๊ณ ๊ฐ์ธ ํ๋กํ ๋ณ๊ฒฝ ๋ฑ ๋ชจ๋ ๊ด๋ฆฌ์ฉ ์ค์ ๊ธฐ๋ฅ์ ํ๋จ ๋ค๋น๊ฒ์ด์ ์ํธ์์ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
Proxmox (๊ถ์ฅ)
bash -c "$(curl -fsSL https://raw.githubusercontent.com/eigger/garage/master/proxmox/ct/garage.sh)"์๋ฃ ํ ๋ธ๋ผ์ฐ์ ์์ http://<LXC_IP> ๋ก ์ ์ํฉ๋๋ค.
Docker Compose
docker compose -f docker-compose.prod.yml up -d์์ ์ ์ .env์ POSTGRES_PASSWORD, JWT_SECRET์ ์ค์ ํ์ธ์.
์ ๊ท ์ค์น ์ ์ฌ์ฉ์๊ฐ ์์ผ๋ฉด /login์ ์ต์ด ๊ด๋ฆฌ์ ์์ฑ์ด ํ์๋ฉ๋๋ค.
/login์ด๊ธฐ- ์ด๋ฆยท์ด๋ฉ์ผยท๋น๋ฐ๋ฒํธ ์ ๋ ฅ
- ์ ์ถ โ
ADMIN์ผ๋ก ๋ก๊ทธ์ธ๋จ
์ดํ ๊ฐ์กฑ ๊ตฌ์ฑ์์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
- ๋ณธ์ธ์ด ์ง์ ๊ฐ์
:
/login์ ํ์๊ฐ์ ์ผ๋ก ์ ์ฒญ โ ๊ด๋ฆฌ์๊ฐ ์ฌ์ฉ์ ๊ด๋ฆฌ์ ์น์ธ ๋๊ธฐ ๋ชฉ๋ก์์ ์น์ธ. ์น์ธ ์ ์๋ ๋ก๊ทธ์ธํด๋ ์๋ด ํ๋ฉด๋ง ๋ณด์ด๊ณ ์ด๋ค ๋ฐ์ดํฐ์๋ ์ ๊ทผํ์ง ๋ชปํฉ๋๋ค. - ๊ด๋ฆฌ์๊ฐ ์ง์ ์์ฑ: ์ฌ์ฉ์ ๊ด๋ฆฌ โ ๊ตฌ์ฑ์ ์ถ๊ฐ. ์น์ธ ์ ์ฐจ ์์ด ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ๊ถํ๋ ์ง์ ํ ์ ์์ต๋๋ค.
๊ด๋ฆฌ์๋ ์ฌ์ฉ์ ๊ด๋ฆฌ ํ๋ฉด์์ ๊ถํ(๊ด๋ฆฌ์/์ผ๋ฐ) ๋ณ๊ฒฝ, ์ฐจ๋ ๋ฐฐ์ , ๋น๋ฐ๋ฒํธ ์ด๊ธฐํ, ๊ณ์ ์ญ์ ๋ฅผ ํ ์ ์์ต๋๋ค. ๋ง์ง๋ง ๊ด๋ฆฌ์๋ฅผ ๊ฐ๋ฑยท์ญ์ ํ๋ ๊ฒ์ ์ฑ์ด ์ ๊ธฐ๋ ๊ฒ์ ๋ง๊ธฐ ์ํด ์ฐจ๋จ๋ฉ๋๋ค.
- ํ๋จ ๋ค๋น๊ฒ์ด์ ๋ฐ ๋๋ณด๊ธฐ ์ํธ โ ์ฐจ๋ ๊ด๋ฆฌ
- ์ด๋ฆ, ๋ฒํธํ, ์ ์กฐ์ฌ/๋ชจ๋ธ/์ฐ์, ์ฐ๋ฃ ํ์ ์ ๋ ฅ
- ์ ์ฅ
๊ด๋ฆฌ์๋ฟ ์๋๋ผ ์ผ๋ฐ ์ฌ์ฉ์๋ ์๊ธฐ ์ฐจ๋์ ๋ฑ๋กํ ์ ์์ต๋๋ค. ๋ฑ๋กํ ์ฌ๋์ด ๊ทธ ์ฐจ๋์ ์์ ์๊ฐ ๋์ด ์์ ยท์ญ์ ยท๊ณต์ ๋ฅผ ํ ์ ์์ต๋๋ค. ํ ์ฐจ๋์ ์ฌ๋ฌ ๋ช ์ด ํจ๊ป ์ธ ๋๋ ๊ฐ์ ๋ฑ๋กํ์ง ๋ง๊ณ (๊ธฐ๋ก์ด ๊ฐ๋ผ์ง๋๋ค) ํ ๋ช ์ด ๋ฑ๋กํ ๋ค ์ฐจ๋ โ ๋๋ณด๊ธฐ ์ํธ โ ์ฐจ๋ ๊ณต์ ์์ ๊ฐ์กฑ์ ์ถ๊ฐํ์ธ์. ์์น(์ขํยท์ฃผํ ๊ฒฝ๋ก) ์ด๋์ ๊ณต์ ์ ๋ณ๊ฐ๋ก ์ฌ๋๋ง๋ค ์ผ๊ณ ๋ ์ ์์ต๋๋ค.
ํด๋น ์ฐ๋ฃ ํ์ ์ ๋น ํ๋ฆฌ์ ๊ณผ ํ์ ยท๋ฒ์ ์ค์ผ์ค(๊ฒ์ฌ, ๋ณดํ, ์ธ๊ธ ๋ฑ)์ด ์๋์ผ๋ก ๋ณต์ฌ๋ฉ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ ๋๋ณด๊ธฐ ์ํธ ์๋์ ์ ๋น ๋ง์คํฐ ํ๋ฆฌ์ ๊ด๋ฆฌ์์ ์์ ํฉ๋๋ค.
| ํ ์ผ | ์์น |
|---|---|
| ์ฃผ์ / ์ ๋น ๊ธฐ๋ก | ํ๋จ ๋ค๋น๊ฒ์ด์ โ ๋น ๋ฅธ ์ ๋ ฅ |
| ์ฃผ๊ธฐ ์์ | ์ฐจ๋ โ ์ ๋น ์ค์ผ์ค |
| ์ด๋ ฅยท์ฐ๋นยท์ฃผํ | ์ฐจ๋ โ ๋ด์ญ |
| ํต๊ณ & ๋ฆฌํฌํธ ๋ด๋ณด๋ด๊ธฐ | ์ฐจ๋ โ ํต๊ณ |
| ์ฃผ์ ์ / ์ถฉ์ ์ ์ฐพ๊ธฐ | ์ฐจ๋ โ ์ฃผ์ ์/์ถฉ์ ์ |
| OBD / Torque / REST ํ ํฐ | ์ฐจ๋ โ ํฑ๋๋ฐํด โ OBD & GPS |
| ๊ฐ์กฑ ๊ณ์ | ํ๋จ ๋ค๋น๊ฒ์ด์ ๋๋ณด๊ธฐ ์ํธ โ ์ฌ์ฉ์ ๊ด๋ฆฌ |
| ์คํผ๋ท / ์ง๋ API ํค | ํ๋จ ๋ค๋น๊ฒ์ด์ ๋๋ณด๊ธฐ ์ํธ โ API ์ฐ๋ ๊ด๋ฆฌ |
| ๋ฐฑ์ / ๋ณต์ | ํ๋จ ๋ค๋น๊ฒ์ด์ ๋๋ณด๊ธฐ ์ํธ โ ๋ฐฑ์ /๋ณต์ |
Home Assistant๋ hass-garage ์ปค์คํ ํตํฉ๊ตฌ์ฑ์์(HACS)๋ก YAML ํธ์ง ์์ด ํ๋ฉด์์ ๋ฐ๋ก ์ฐ๋ํ ์ ์์ต๋๋ค โ ์์น/RPM/์๋/์ฐ๋ฃ/์ฃผํ๊ฑฐ๋ฆฌ๋ฅผ ์๋ ์ ์กํ๊ณ , Garage๊ฐ ๊ณ์ฐํ ๋ง์ง๋ง ์์นยท๋ฆฌ๋ง์ธ๋๋ฅผ ์ผ์๋ก ๋ฐ์์ต๋๋ค.
YAML๋ก ์ง์ ๋ถ์ด๊ณ ์ถ๋ค๋ฉด ์๋์ฒ๋ผ ์ฐจ๋ apiToken์ผ๋ก ํ
๋ ๋ฉํธ๋ฆฌ๋ฅผ ์ ์กํ ์๋ ์์ต๋๋ค(๋ก๊ทธ์ธ JWT ์๋).
POST /api/ingest/telemetry
Authorization: Bearer <apiToken>
Content-Type: application/json
{ "speed": 65, "lat": 37.56, "lon": 126.97, "odometer": 45230, "inVehicle": true }apiToken ์์ฒด๊ฐ ์ฐจ๋์ ํน์ ํ๋ฏ๋ก URL์ ๋ณ๋ vehicleId๊ฐ ํ์ ์์ต๋๋ค.
์ฃผ์ ยท์ ๋น ๊ธฐ๋ก API๋ docs/INTEGRATIONS.md๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์์ง URLยทํ ํฐ์ ์ฐจ๋ โ OBD & GPS์์ ๋ณต์ฌํฉ๋๋ค.
garage/
apps/
api/ # Fastify + Prisma
web/ # Next.js App Router (PWA, ํ/์)
packages/
shared/ # ๊ณต์ Zod ์คํค๋ง / ์นดํ๋ก๊ทธ
docker-compose.yml / docker-compose.prod.yml
Caddyfile
proxmox/ # LXC ์ํด๋ฆญ ์ค์น
npm install
cp .env.example .env # POSTGRES_PASSWORD, JWT_SECRET ์ค์
docker compose up -d postgres
npm run prisma:migrate
npm run seed -w apps/api # ๋ถํธ์คํธ๋ฉ UI ๋์ ์๋ ๊ด๋ฆฌ์๋ฅผ ์ธ ๋
npm run dev:api # :8080
npm run dev:web # :3000http://localhost:3000/login ์ผ๋ก ์ ์ํฉ๋๋ค.
์ ์ฉํ ์คํฌ๋ฆฝํธ: npm run build, npm run test, npm run prisma:generate.
- ๊ตฌ์ฑ: PostgreSQL 16 + API + Web + Caddy (
:80) - ํ๋ก๋์
compose์์ API ๊ธฐ๋ ์
prisma migrate deploy์คํ - ์ด๋ฏธ์ง:
ghcr.io/<owner>/garage-api/garage-web(latest+ semver) - LXC ์
๋ฐ์ดํธ: ์ปจํ
์ด๋์์
update(compose ์ด๋ฏธ์ง pull)
๊ธฐ๋ณธ์ ์ค๋ฆฌ์ง ๋ฃจํธ(https://example.com/)์
๋๋ค. ๋ฆฌ๋ฒ์ค ํ๋ก์์ ํ์ ๊ฒฝ๋ก์ ๋ถ์ด๋ ค๋ฉด web
์ปจํ
์ด๋์ BASE_PATH๋ง ๋๊ธฐ๋ฉด ๋ฉ๋๋ค โ ์ด๋ฏธ์ง๋ฅผ ๋ค์ ๋น๋ํ ํ์๋ ์์ต๋๋ค.
BASE_PATH=/garage docker compose -f docker-compose.prod.yml up -d webnext build๋ basePath๋ฅผ ์ฐ์ถ๋ฌผ์ ๋ฐ์๋ฒ๋ฆฌ๋๋ฐ, ๋ฐฐํฌ ๊ฒฝ๋ก๋ฅผ ๋น๋ ์์ ์ ์ ์ ์๋ ๊ฒฝ์ฐ๊ฐ
์์ต๋๋ค(Home Assistant Ingress๋ /api/hassio_ingress/<token>/ ์ด ์ค์น๋ณธ๋ง๋ค ๋ค๋ฆ
๋๋ค).
๊ทธ๋์ ์ด๋ฏธ์ง๋ /__BASE_PATH__ ํ๋ ์ด์คํ๋๋ก ๋น๋ํด๋๊ณ , ์ปจํ
์ด๋๊ฐ ๋ฐ ๋
apps/web/docker-entrypoint.sh๊ฐ ์ค์ ๊ฐ์ผ๋ก ์นํํฉ๋๋ค.
๊ฐ์ ๋ฐ๊ฟ ๋ค์ ๋์ฐ๋ฉด ์๋ณธ์์ ๋ค์ ์นํํ๋ฏ๋ก ์ฌ๋ฌ ๋ฒ ๋ฐ๊ฟ๋ ๋ฉ๋๋ค.
ํ๋ก์๋ ํ๋ฆฌํฝ์ค๋ฅผ ๋ผ๊ณ ๋๊ฒจ์ผ ํฉ๋๋ค(HA Ingress๋ ๊ธฐ๋ณธ ๋์์ด ๊ทธ๋ ์ต๋๋ค).
์ด๋ฉ์ผ์ด ์๋ฌธ์๋ก ์ ๊ทํ๋ฉ๋๋ค. ๋์๋ฌธ์๋ง ๋ค๋ฅธ ๊ณ์ ์ด ๋ ๊ฐ ์ด์ ์์ผ๋ฉด ๋ง์ด๊ทธ๋ ์ด์ ์ด ๋ค์ ๋ฉ์์ง์ ํจ๊ป ์ค๋จ๋๊ณ API ์ปจํ ์ด๋๊ฐ ๊ธฐ๋๋์ง ์์ต๋๋ค(๋ฐ์ดํฐ๋ ๋ณ๊ฒฝ๋์ง ์๊ณ ๊ทธ๋๋ก ๋กค๋ฐฑ๋ฉ๋๋ค).
Cannot normalize emails to lowercase: these addresses exist more than once ignoring case (...)
ํด๋น ๊ณ์ ์ค ํ๋๋ฅผ ์ง์ฐ๊ฑฐ๋ ์ด๋ฉ์ผ์ ๋ฐ๊พผ ๋ค, ์คํจ๋ก ํ์๋ ๋ง์ด๊ทธ๋ ์ด์ ์ ๋๋๋ฆฌ๊ณ ๋ค์ ์ฌ๋ฆฌ๋ฉด ๋ฉ๋๋ค.
docker compose -f docker-compose.prod.yml run --rm api npx prisma migrate resolve --rolled-back 20260806230000_user_management_lifecycle --schema apps/api/prisma/schema.prisma --config apps/api/prisma.config.ts๊ทธ ์ธ์๋ ๋ณ๋ ์กฐ์น๊ฐ ํ์ ์์ต๋๋ค โ ๊ธฐ์กด ๊ณ์ ์ ์ ๋ถ ์ฌ์ฉ ์ค(ACTIVE) ์ํ๋ก ์ ์ง๋๊ณ , ๋ก๊ทธ์ธ ์ธ์ ๋ ๋๊ธฐ์ง ์์ต๋๋ค. ๊ธฐ์กด ์ฐจ๋์ ๋ฑ๋ก์ ์ ๋ณด๊ฐ ์์ผ๋ฏ๋ก ์ข ์ ๊ณผ ๋์ผํ๊ฒ ๊ด๋ฆฌ์๋ง ์์ ยท์ญ์ ํ ์ ์์ต๋๋ค.
| ์ํฌํ๋ก | ํธ๋ฆฌ๊ฑฐ | ๋ชฉ์ |
|---|---|---|
.github/workflows/ci.yml |
master Push / PR |
์ค์นยท๋น๋ยทํ ์คํธ, ๋ง์ด๊ทธ๋ ์ด์ ๊ฒ์ฆ |
.github/workflows/docker-release.yml |
GitHub Release | GHCR ์ด๋ฏธ์ง ํธ์ |
ํ๋ก๋์
compose๊ฐ prisma migrate deploy && node ...๋ก ๊ธฐ๋ํ๋ ๊ตฌ์กฐ๋ผ, ๋ง์ด๊ทธ๋ ์ด์
์ด ์คํจํ๋ฉด API ์ปจํ
์ด๋๊ฐ ์์ ๋จ์ง ์์ต๋๋ค. ๊ทธ๋์ ๋งค PR๋ง๋ค scripts/ci/check-migrations.sh๊ฐ ๋ ๊ฐ์ง๋ฅผ ์๋ ํ์ธํฉ๋๋ค.
- ์ ๊ท ์ค์น โ ๋น DB์ ์ ์ฒด ๋ง์ด๊ทธ๋ ์ด์
์ ์ ์ฉํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ
schema.prisma์ ์ผ์นํ๋์ง ํ์ธํฉ๋๋ค(๋๋ฆฌํํธ ๊ฒ์ถ).schema.prisma๋ง ๊ณ ์น๊ณ ๋ง์ด๊ทธ๋ ์ด์ ์ ๋ง๋ค์ง ์์ ๊ฒฝ์ฐ๋ฅผ ์ก์ต๋๋ค. - ์ ๊ทธ๋ ์ด๋ โ ์ง์ ๋ฆด๋ฆฌ์ค ํ๊ทธ์ ๋ง์ด๊ทธ๋ ์ด์ ๋ง ์ ์ฉํ DB์ ๊ธฐ์กด ์ด์ ๋ฐ์ดํฐ๋ฅผ ํ๋ด๋ธ ํ์ ๋ฃ๊ณ , ์ด๋ฒ ๋ณ๊ฒฝ์ ๋ง์ด๊ทธ๋ ์ด์ ์ ๊ทธ ์์ ์ ์ฉํฉ๋๋ค. ๋น DB์์๋ ํต๊ณผํ์ง๋ง ๊ธฐ์กด ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ์ ์ฝ ์๋ฐ์ผ๋ก ์คํจํ๋ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ก์ต๋๋ค.
๋ก์ปฌ์์๋ ๊ฐ์ ๊ฒ์ฌ๋ฅผ ๋๋ฆด ์ ์์ต๋๋ค.
DATABASE_URL_BASE=postgresql://garage:<password>@localhost:5432 PG_CONTAINER=garage-postgres-1 scripts/ci/check-migrations.shUser/Vehicle์ ํ์ ์ปฌ๋ผ์ด ๋ฐ๋๋ฉด scripts/ci/legacy-fixture.sql๋ ํจ๊ป ๊ฐฑ์ ํด์ผ ํฉ๋๋ค(ํฝ์ค์ฒ ์ฝ์
์ด ์คํจํ๋ฉด ๊ทธ ์ฌ์ค์ ์๋ ค์ค๋๋ค).
MIT. LICENSE ์ฐธ๊ณ .




















