Skip to content

Latest commit

ย 

History

204 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Garage

CI Docker Release Node.js License Self-hosted Docker

English README

๊ฐ€์กฑยทํ™ˆ๋žฉ์šฉ ์…€ํ”„ํ˜ธ์ŠคํŒ… ์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ โ€” ์ •๋น„ ์Šค์ผ€์ค„, ์ฃผ์œ  ๊ธฐ๋ก, ์•Œ๋ฆผ, 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
  • ์‚ฌ์šฉ์ž ์—†์„ ๋•Œ ์ตœ์ดˆ ๊ด€๋ฆฌ์ž ๋ถ€ํŠธ์ŠคํŠธ๋žฉ

์Šคํฌ๋ฆฐ์ƒท & ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

1. ๋Œ€์‹œ๋ณด๋“œ

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

๋Œ€์‹œ๋ณด๋“œ

2. ์ฐจ๋Ÿ‰ ๊ฐœ์š” (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

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

์ฐจ๋Ÿ‰ ๊ฐœ์š” (์ „๊ธฐ์ฐจ) ย ย ย ย  ์ฐจ๋Ÿ‰ ๊ฐœ์š” (๋‚ด์—ฐ์ฐจ)

3. ๋น ๋ฅธ ์ž…๋ ฅ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

์–ด๋””์„œ๋‚˜ ์ฃผ์œ /์ถฉ์ „ ๋ฐ ์ •๋น„๋ฅผ ๋ฐ”๋กœ ๊ธฐ๋กํ•˜๋Š” ํ™”๋ฉด์ž…๋‹ˆ๋‹ค. ์ „๊ธฐ์ฐจ๋Š” ์ถฉ์ „ ์ „๋ ฅ๋Ÿ‰(kWh) ์ž…๋ ฅ, kWh๋‹น ๋‹จ๊ฐ€, ์ถฉ์ „์†Œ ๊ฒ€์ƒ‰์„ ์ง€์›ํ•˜๋ฉฐ, ๋‚ด์—ฐ์ฐจ๋Š” ์ •์œ ์‚ฌ ๋ธŒ๋žœ๋“œ ๋กœ๊ณ  ์„ ํƒ(์˜คํ”ผ๋„ท), ์ฃผ์œ ๋Ÿ‰(L), ๋ฆฌํ„ฐ๋‹น ๋‹จ๊ฐ€ ์ž…๋ ฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋น ๋ฅธ ์ž…๋ ฅ (์ „๊ธฐ์ฐจ) ย ย ย ย  ๋น ๋ฅธ ์ž…๋ ฅ (๋‚ด์—ฐ์ฐจ)

4. ์ •๋น„ ์Šค์ผ€์ค„ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

๊ฑฐ๋ฆฌ ๋ฐ ์‹œ๊ฐ„ ๊ธฐ์ค€ ์ •๋น„ ์Šค์ผ€์ค„๊ณผ ํ–‰์ • ์•Œ๋ฆผ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„์˜ค์ผ/์˜ค์ผํ•„ํ„ฐ ๊ต์ฒด ์ฃผ๊ธฐ(๋‚ด์—ฐ์ฐจ ์ „์šฉ) ๋“ฑ ์ฐจ์ข…์— ์ตœ์ ํ™”๋œ ์ •๋น„ ํ”„๋ฆฌ์…‹์ด ๊ธฐ๋ณธ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ •๋น„ ์Šค์ผ€์ค„ (์ „๊ธฐ์ฐจ) ย ย ย ย  ์ •๋น„ ์Šค์ผ€์ค„ (๋‚ด์—ฐ์ฐจ)

5. ๋‚ด์—ญ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

์ฃผํ–‰ ๋ฆฌํฌํŠธ, ์ถฉ์ „/์ฃผ์œ  ๋กœ๊ทธ, ์ •๋น„ ์ด๋ ฅ์„ ํ•œ๊ณณ์— ๋ชจ์•„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋‚ด์—ฐ์ฐจ๋Š” ํ’€ํƒฑํฌ ๊ธฐ์ค€ ์ฃผ์œ  ์—ฐ๋น„(km/L)๊ฐ€ ์ž๋™ ๊ณ„์‚ฐ๋˜๊ณ , ์ „๊ธฐ์ฐจ๋Š” ์—๋„ˆ์ง€ ์†Œ๋ชจ๋Ÿ‰ ์ง€ํ‘œ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋‚ด์—ญ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋‚ด์—ญ (์ „๊ธฐ์ฐจ) ย ย ย ย  ๋‚ด์—ญ (๋‚ด์—ฐ์ฐจ)

6. ์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ ๋ ˆ๋ฒจ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

์ฃผ์œ /์ถฉ์ „ ๋ฐ ์ •๋น„๋ฅผ ๊พธ์ค€ํžˆ ๊ธฐ๋กํ•ด ๊ฒฝํ—˜์น˜๋ฅผ ๋ชจ์œผ๊ณ  ์ฐจ๋Ÿ‰ ๋ ˆ๋ฒจ์„ ์˜ฌ๋ ค ๋ฑƒ์ง€๋ฅผ ํš๋“ํ•˜๋Š” ํ™”๋ฉด์ž…๋‹ˆ๋‹ค.

์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ ๋ ˆ๋ฒจ (์ „๊ธฐ์ฐจ) ย ย ย ย  ์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ ๋ ˆ๋ฒจ (๋‚ด์—ฐ์ฐจ)

7. ํ†ต๊ณ„ & ๋ฆฌํฌํŠธ ๋‚ด๋ณด๋‚ด๊ธฐ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

์ฃผํ–‰๊ฑฐ๋ฆฌยท๋น„์šฉยท์—ฐ๋น„ ํ†ต๊ณ„ ์ฐจํŠธ๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ 1์ฃผ/1๋‹ฌ ๋‹จ์œ„ ๊ธฐ๊ฐ„ ํ•„ํ„ฐ๋ง ๋ฐ ์ฃผํ–‰ยท์ฃผ์œ ยท์ •๋น„ ์ด๋ ฅ์˜ CSV/Excel ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

ํ†ต๊ณ„ & ๋ฆฌํฌํŠธ (์ „๊ธฐ์ฐจ) ย ย ย ย  ํ†ต๊ณ„ & ๋ฆฌํฌํŠธ (๋‚ด์—ฐ์ฐจ)

8. ์ฃผ์œ ์†Œ & ์ถฉ์ „์†Œ ์ฐพ๊ธฐ (์ „๊ธฐ์ฐจ vs. ๋‚ด์—ฐ์ฐจ)

์˜คํ”ผ๋„ท ๊ธฐ๋ฐ˜ ์ฃผ๋ณ€ ์ฃผ์œ ์†Œ, ์ฒœ์•ˆ์‚ฌ๋ž‘์นด๋“œ ๊ฐ€๋งน ์ฃผ์œ ์†Œ, ํ™˜๊ฒฝ๊ณต๋‹จ EV ์ถฉ์ „์†Œ ๊ฒ€์ƒ‰์„ ๋‹จ์ผ ๋ฉ”๋‰ด์—์„œ ์ง€๋„ ๋ฒˆํ˜ธ ๋งˆ์ปค์™€ ํ•จ๊ป˜ ๊ฑฐ๋ฆฌ์ˆœ/๊ฐ€๊ฒฉ์ˆœ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ถฉ์ „์†Œ ์ฐพ๊ธฐ (์ „๊ธฐ์ฐจ) ย ย ย ย  ์ฃผ์œ ์†Œ ์ฐพ๊ธฐ (๋‚ด์—ฐ์ฐจ)

9. ๋”๋ณด๊ธฐ ์‹œํŠธ ๋ฉ”๋‰ด (๊ด€๋ฆฌ ๋ฐ ๊ณ„์ •)

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

API ์—ฐ๋™ ์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ

์ •๋น„ ํ”„๋ฆฌ์…‹ ๋ฐฑ์—… ๋ฐ ๋ณต์› ํ”„๋กœํ•„ ์„ค์ •


๋น ๋ฅธ ์‹œ์ž‘

1. ์„ค์น˜

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์„ ์„ค์ •ํ•˜์„ธ์š”.

2. ์ตœ์ดˆ ๊ด€๋ฆฌ์ž ์ƒ์„ฑ

์‹ ๊ทœ ์„ค์น˜ ์‹œ ์‚ฌ์šฉ์ž๊ฐ€ ์—†์œผ๋ฉด /login์— ์ตœ์ดˆ ๊ด€๋ฆฌ์ž ์ƒ์„ฑ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  1. /login ์—ด๊ธฐ
  2. ์ด๋ฆ„ยท์ด๋ฉ”์ผยท๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ
  3. ์ œ์ถœ โ†’ ADMIN์œผ๋กœ ๋กœ๊ทธ์ธ๋จ

์ดํ›„ ๊ฐ€์กฑ ๊ตฌ์„ฑ์›์€ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

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

๊ด€๋ฆฌ์ž๋Š” ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ ํ™”๋ฉด์—์„œ ๊ถŒํ•œ(๊ด€๋ฆฌ์ž/์ผ๋ฐ˜) ๋ณ€๊ฒฝ, ์ฐจ๋Ÿ‰ ๋ฐฐ์ •, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ดˆ๊ธฐํ™”, ๊ณ„์ • ์‚ญ์ œ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ๊ด€๋ฆฌ์ž๋ฅผ ๊ฐ•๋“ฑยท์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ ์•ฑ์ด ์ž ๊ธฐ๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค.

3. ์ฐจ๋Ÿ‰ ๋“ฑ๋ก

  1. ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ” ๋”๋ณด๊ธฐ ์‹œํŠธ โ†’ ์ฐจ๋Ÿ‰ ๊ด€๋ฆฌ
  2. ์ด๋ฆ„, ๋ฒˆํ˜ธํŒ, ์ œ์กฐ์‚ฌ/๋ชจ๋ธ/์—ฐ์‹, ์—ฐ๋ฃŒ ํƒ€์ž… ์ž…๋ ฅ
  3. ์ €์žฅ

๊ด€๋ฆฌ์ž๋ฟ ์•„๋‹ˆ๋ผ ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋„ ์ž๊ธฐ ์ฐจ๋Ÿ‰์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋“ฑ๋กํ•œ ์‚ฌ๋žŒ์ด ๊ทธ ์ฐจ๋Ÿ‰์˜ ์†Œ์œ ์ž๊ฐ€ ๋˜์–ด ์ˆ˜์ •ยท์‚ญ์ œยท๊ณต์œ ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ์ฐจ๋Ÿ‰์„ ์—ฌ๋Ÿฌ ๋ช…์ด ํ•จ๊ป˜ ์“ธ ๋•Œ๋Š” ๊ฐ์ž ๋“ฑ๋กํ•˜์ง€ ๋ง๊ณ (๊ธฐ๋ก์ด ๊ฐˆ๋ผ์ง‘๋‹ˆ๋‹ค) ํ•œ ๋ช…์ด ๋“ฑ๋กํ•œ ๋’ค ์ฐจ๋Ÿ‰ โ†’ ๋”๋ณด๊ธฐ ์‹œํŠธ โ†’ ์ฐจ๋Ÿ‰ ๊ณต์œ ์—์„œ ๊ฐ€์กฑ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. ์œ„์น˜(์ขŒํ‘œยท์ฃผํ–‰ ๊ฒฝ๋กœ) ์—ด๋žŒ์€ ๊ณต์œ ์™€ ๋ณ„๊ฐœ๋กœ ์‚ฌ๋žŒ๋งˆ๋‹ค ์ผœ๊ณ  ๋Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ์—ฐ๋ฃŒ ํƒ€์ž… ์ •๋น„ ํ”„๋ฆฌ์…‹๊ณผ ํ–‰์ •ยท๋ฒ•์ • ์Šค์ผ€์ค„(๊ฒ€์‚ฌ, ๋ณดํ—˜, ์„ธ๊ธˆ ๋“ฑ)์ด ์ž๋™์œผ๋กœ ๋ณต์‚ฌ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ๋”๋ณด๊ธฐ ์‹œํŠธ ์•„๋ž˜์˜ ์ •๋น„ ๋งˆ์Šคํ„ฐ ํ”„๋ฆฌ์…‹ ๊ด€๋ฆฌ์—์„œ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

4. ์ผ์ƒ ์‚ฌ์šฉ

ํ•  ์ผ ์œ„์น˜
์ฃผ์œ  / ์ •๋น„ ๊ธฐ๋ก ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ โ†’ ๋น ๋ฅธ ์ž…๋ ฅ
์ฃผ๊ธฐ ์ˆ˜์ • ์ฐจ๋Ÿ‰ โ†’ ์ •๋น„ ์Šค์ผ€์ค„
์ด๋ ฅยท์—ฐ๋น„ยท์ฃผํ–‰ ์ฐจ๋Ÿ‰ โ†’ ๋‚ด์—ญ
ํ†ต๊ณ„ & ๋ฆฌํฌํŠธ ๋‚ด๋ณด๋‚ด๊ธฐ ์ฐจ๋Ÿ‰ โ†’ ํ†ต๊ณ„
์ฃผ์œ ์†Œ / ์ถฉ์ „์†Œ ์ฐพ๊ธฐ ์ฐจ๋Ÿ‰ โ†’ ์ฃผ์œ ์†Œ/์ถฉ์ „์†Œ
OBD / Torque / REST ํ† ํฐ ์ฐจ๋Ÿ‰ โ†’ ํ†ฑ๋‹ˆ๋ฐ”ํ€ด โ†’ OBD & GPS
๊ฐ€์กฑ ๊ณ„์ • ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋”๋ณด๊ธฐ ์‹œํŠธ โ†’ ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ
์˜คํ”ผ๋„ท / ์ง€๋„ API ํ‚ค ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋”๋ณด๊ธฐ ์‹œํŠธ โ†’ API ์—ฐ๋™ ๊ด€๋ฆฌ
๋ฐฑ์—… / ๋ณต์› ํ•˜๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋”๋ณด๊ธฐ ์‹œํŠธ โ†’ ๋ฐฑ์—…/๋ณต์›

5. OBD / Home Assistant (์š”์•ฝ)

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            # :3000

http://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)

์„œ๋ธŒํŒจ์Šค์— ์˜ฌ๋ฆฌ๊ธฐ (BASE_PATH)

๊ธฐ๋ณธ์€ ์˜ค๋ฆฌ์ง„ ๋ฃจํŠธ(https://example.com/)์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์˜ ํ•˜์œ„ ๊ฒฝ๋กœ์— ๋ถ™์ด๋ ค๋ฉด web ์ปจํ…Œ์ด๋„ˆ์— BASE_PATH๋งŒ ๋„˜๊ธฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค โ€” ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์‹œ ๋นŒ๋“œํ•  ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

BASE_PATH=/garage docker compose -f docker-compose.prod.yml up -d web

next 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) ์ƒํƒœ๋กœ ์œ ์ง€๋˜๊ณ , ๋กœ๊ทธ์ธ ์„ธ์…˜๋„ ๋Š๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด ์ฐจ๋Ÿ‰์€ ๋“ฑ๋ก์ž ์ •๋ณด๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ข…์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ด€๋ฆฌ์ž๋งŒ ์ˆ˜์ •ยท์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


CI/CD

์›Œํฌํ”Œ๋กœ ํŠธ๋ฆฌ๊ฑฐ ๋ชฉ์ 
.github/workflows/ci.yml master Push / PR ์„ค์น˜ยท๋นŒ๋“œยทํ…Œ์ŠคํŠธ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฒ€์ฆ
.github/workflows/docker-release.yml GitHub Release GHCR ์ด๋ฏธ์ง€ ํ‘ธ์‹œ

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ฒ€์ฆ (migrations ์žก)

ํ”„๋กœ๋•์…˜ compose๊ฐ€ prisma migrate deploy && node ...๋กœ ๊ธฐ๋™ํ•˜๋Š” ๊ตฌ์กฐ๋ผ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์‹คํŒจํ•˜๋ฉด API ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์•„์˜ˆ ๋œจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งค PR๋งˆ๋‹ค scripts/ci/check-migrations.sh๊ฐ€ ๋‘ ๊ฐ€์ง€๋ฅผ ์ž๋™ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  1. ์‹ ๊ทœ ์„ค์น˜ โ€” ๋นˆ DB์— ์ „์ฒด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ ์šฉํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ schema.prisma์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค(๋“œ๋ฆฌํ”„ํŠธ ๊ฒ€์ถœ). schema.prisma๋งŒ ๊ณ ์น˜๊ณ  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋งŒ๋“ค์ง€ ์•Š์€ ๊ฒฝ์šฐ๋ฅผ ์žก์Šต๋‹ˆ๋‹ค.
  2. ์—…๊ทธ๋ ˆ์ด๋“œ โ€” ์ง์ „ ๋ฆด๋ฆฌ์Šค ํƒœ๊ทธ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜๋งŒ ์ ์šฉํ•œ DB์— ๊ธฐ์กด ์šด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ‰๋‚ด๋‚ธ ํ–‰์„ ๋„ฃ๊ณ , ์ด๋ฒˆ ๋ณ€๊ฒฝ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๊ทธ ์œ„์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋นˆ DB์—์„œ๋Š” ํ†ต๊ณผํ•˜์ง€๋งŒ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์œผ๋ฉด ์ œ์•ฝ ์œ„๋ฐ˜์œผ๋กœ ์‹คํŒจํ•˜๋Š” ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์žก์Šต๋‹ˆ๋‹ค.

๋กœ์ปฌ์—์„œ๋„ ๊ฐ™์€ ๊ฒ€์‚ฌ๋ฅผ ๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

DATABASE_URL_BASE=postgresql://garage:<password>@localhost:5432 PG_CONTAINER=garage-postgres-1 scripts/ci/check-migrations.sh

User/Vehicle์˜ ํ•„์ˆ˜ ์ปฌ๋Ÿผ์ด ๋ฐ”๋€Œ๋ฉด scripts/ci/legacy-fixture.sql๋„ ํ•จ๊ป˜ ๊ฐฑ์‹ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(ํ”ฝ์Šค์ฒ˜ ์‚ฝ์ž…์ด ์‹คํŒจํ•˜๋ฉด ๊ทธ ์‚ฌ์‹ค์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค).


๋ผ์ด์„ ์Šค

MIT. LICENSE ์ฐธ๊ณ .

About

An all-in-one, self-hosted car management server for tracking maintenance, fuel, and OBD/GPS trips.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages