์ ์ฌ์ ํ๊ฒฝ์์์ ์ฑ๋ฅ ์ต์ ํ๋ถํฐ ํ์ฅ์ฑ ์๋ ๊ตฌ์กฐ๊น์ง, ๋์ํ๋ ์ฝ๋ ๋๋จธ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ๋๋ค.
1GB ๋ฉ๋ชจ๋ฆฌ ์๋ฒ์์ JVM ํ๋์ ํด๋ณธ ๊ฒฝํ๋ถํฐ, ๋ฉํฐ๋ชจ๋ ๊ตฌ์กฐ ์ค๊ณ์ AI ํ์ดํ๋ผ์ธ ์ฐ๋๊น์ง โ "๋์ํ๋ ์ฝ๋" ๋๋จธ์ ๋ฌธ์ ๋ฅผ ๊ณ ๋ฏผํฉ๋๋ค. ์ค์๋น์ค ๊ฒฐ์ ๋ชจ๋์์ ๋ฉฑ๋ฑ์ฑยท๋ถ์ฐ ๋ฝยทDLQ ๊ฐ์ ๋ฐฉ์ด๋ก์ง์ ๋ค๋ค๊ณ , Spring ์ํ๊ณ ๊ธฐ๋ฐ ๋ฐฑ์๋ ๊ฐ๋ฐ๊ณผ ํด๋ผ์ฐ๋ ์ธํ๋ผ์ ๊ด์ฌ์ด ๋ง์ต๋๋ค.
| Issue | Description | Related PR |
|---|---|---|
| #5366 | ExitStatus#setExitException breaks immutability contract |
#5367 |
- ๐ฑ ๋๋ฅด๋ฅต (drr) โ iOS App Store ์ ์ ์ถ์ (2025)
- ๐ฅ 2025 ํ์๋ ์บก์คํค ๋์์ธ ์ฐ์์ โ Drr
- ๐ฅ 2025 9ITHON ์ฐ์์ (2์) โ RoomGenie
- ๐ฅ 2023 ์ ๊ตญ ๋ํ์ SW์ฐฝ์ ์์ด๋์ดํค ๊ฒฐ์ ์ง์ถ
-
๐ข (์ฃผ)ํํ ์๋์๋ฃจ์ ํ์ฅ์ค์ต (2025.09 ~ 2026.02)
- Impact Design Canvas ํ์คํ ๋จ๋ ๊ฐ๋ฐ โ Spring Boot ยท MariaDB ยท OpenAI
- Unicast (https://unicast.kr) ๊ตฌ๋
๊ฒฐ์ ๋ชจ๋ โ PayPal + NHN KCP ์ฐ๋
- ๋ฐฉ์ด๋ก์ง: ๋ฉฑ๋ฑ์ฑ / ์ด์ค๊ฒฐ์ ๋ฐฉ์ง / ๋ถ์ฐ ๋ฝ / DLQ / ์ํ์ ์ด ๊ฒ์ฆ / ์นํ ์ค๋ณต๋ฐฉ์ง
- GitHub Actions ๊ธฐ๋ฐ CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ, PG์ฌ ๊ฒฐ์ ๋ชจ๋ ์ฌ์ฌ ๋์
- CX-INNOVATOR ๋์์ธ ์ฝํน ํ๋ซํผ ์ ์ง๋ณด์ โ http://www.abl-cxinno.kr/main
- ํ์ ์ ๋ณด ๊ด๋ จ ํ๋ฉด/DB ์ถ๊ฐ, ํ์ ํญยท๋ํ์์ฑ์ ์๊ด ํ์ ๊ธฐ๋ฅ
- PDF ๋ณด๊ณ ์ ์ฐ๋ ๋ฒ๊ทธ ์์
- C-3 / F-1 / B-1 ๋จ๊ณ ๊ธฐ๋ฅ ์ถ๊ฐ, chatbot / ๋ฌธ์ ์ฌ์ ์ง๋ ์์
-
๐ฑ ๊ตฌ๋ฆํค ์ ๋๋ธ 4๊ธฐ ๋ฐฑ์๋ (2025.03 ~ 2025.09)
- ๋ฐฑ์๋ Bํ ์คํฐ๋์ฅ
- ๊ฒฝ๊ธฐ๋ถ๋ถ ํด์ปคํค 9ITHON, ๊ตฌ๋ฆํค ์์ฆํค ์ฐธ์ฌ
๐ณ Unicast ๊ฒฐ์ ๋ชจ๋ โ PayPal ๋ณด๊ฐ + KCP ์ ๊ท ์ฐ๋ + PG ์ฌ์ฌ ๋์ (์ด์ ์ค) ๐ฅ
์์ ์๋ง ์ถ์ถยท๋ฒ์ญยท๋๋น ๋์งํธ ์ฝํ ์ธ ์๋น์ค์ ๊ฒฐ์ ๋ชจ๋ ๋จ๋ ์ ์ง๋ณด์ ๋ฐ ๋ฐฉ์ด๋ก์ง ๋ณด๊ฐ
- Role: ๊ธฐ์กด ์ด์ ์๋น์ค์ ๊ฒฐ์ ๋ชจ๋ ๋จ๋ ์ ์ง๋ณด์ ๋ฐ ๋ฐฉ์ด๋ก์ง ๋ณด๊ฐ (ํ์ฅ์ค์ต)
- Scope: PayPal/KCP ๊ฒฐ์ ํ๋ฆ, ์นํ ์ฒ๋ฆฌ, ์ ๊ธฐ๊ฒฐ์ ์ค์ผ์ค๋ฌ, PG ์ฌ์ฌ ๋์ (์๋น์ค ๋ณธ์ฒด ๊ธฐ๋ฅ์ ๋ฒ์ ์ธ), paypal์ ๊ฒฝ์ฐ ๊ตญ๋ด๊ฒฐ์ ๊ฐ ์๋์ ์ถํ ์ถ๊ฐ์์
- Tech: Spring Boot ยท Next.js ยท MongoDB ยท Redis(๋ถ์ฐ ๋ฝ) ยท NHN KCP ยท Webhook ยท DLQ ยท State Machine ยท GitHub Actions ยท Docker
- Service: https://unicast.kr (์ด์ ์ค)
Key Work
- KCP ์ ๊ธฐ๊ฒฐ์ ์ ๊ท ์ฐ๋ โ ๋ฐฐ์นํค ๋ฐ๊ธ โ ์ค์ผ์ค๋ฌ ์๋๊ฒฐ์ โ ๊ตฌ๋ ์ทจ์/๋ฐฐ์นํค ์ญ์ ๊น์ง ํ๋ก ํธ+๋ฐฑ์๋ ์ ์ฒด ํ๋ฆ ๊ตฌํ
- ๊ฒฐ์ ๋ฐฉ์ด๋ก์ง ๊ฐํ โ ์ด์ ์ค ๋ฐ๊ฒฌ๋ race condition / ๋๋ฝ ์ผ์ด์ค์ ๋ํด ๋ฉฑ๋ฑ์ฑยท๋ถ์ฐ ๋ฝยทDLQยท์ํ ์ ์ด ๊ฒ์ฆ ๋์
- PG์ฌ ๊ฐ๋งน ์ฌ์ฌ ๋์ โ NHN KCP ์ฌ์ฌ ํต๊ณผ๋ฅผ ์ํ ๊ฒฐ์ ํ๋ก์ฐ ๋ณด์, ์ฝ๊ด/ํ๋ถ๊ท์ /ํต์ ํ๋งค์ ๋ฒํธ ๋ฑ๋ก
- CI/CD ํ์ดํ๋ผ์ธ ์ ๊ท ๊ตฌ์ถ โ GitHub Actions ๊ธฐ๋ฐ ์๋ ๋น๋ยท๋ฐฐํฌ
Troubleshooting
-
KCP ๋ฐฐ์นํค ๋ฐ๊ธ โ ์ฒซ ๊ฒฐ์ ์ฌ์ด ๊ณต๋ฐฑ ์ ๊ฑฐ (
d7e9637,f9fedff) : KCP ์ ๊ธฐ๊ฒฐ์ ์ด๊ธฐ ๊ตฌํ์ "๋ฐฐ์นํค ๋ฐ๊ธ โ ๋ค์ ์ค์ผ์ค๋ฌ ์ฃผ๊ธฐ์ ์ฒซ ๊ฒฐ์ ์คํ" ๊ตฌ์กฐ์์. ๊ฐ์ ์งํ ๊ฒฐ์ ๊ฐ ์ฆ์ ์ผ์ด๋์ง ์์ ์ฌ์ฉ์๊ฐ ์ ๋ฃ ๊ธฐ๋ฅ์ ๋ชป ์ฐ๊ณ ๊ฒฐ์ ๋๋ฝ์ฒ๋ผ ๋ณด์ด๋ UX ๋ฌธ์ ๋ฐ์. โ ๋ฐฐ์นํค ๋ฐ๊ธ ํธ๋์ญ์ ์งํ ์ฒซ ๊ฒฐ์ ๋ฅผ ์ฆ์ ๋๊ธฐ ์คํํ๊ณ , ์ค์ผ์ค๋ฌ ๋ค์ด/๋ฐฐํฌ ๋๋ฝ ๋ฑ์ผ๋ก ๋น ์ง ๊ฒฐ์ ๋nextBillingDate๊ธฐ์ค ๋ฐ๋ฆฐ ๊ฒฐ์ ๋ณต๊ตฌ ์ก์ผ๋ก ๋ณ๋ ๋ณด๊ฐ. -
๊ฒฐ์ ์์ฒญ ๋ฉฑ๋ฑ์ฑ + ์ค์ผ์ค๋ฌ ๋ถ์ฐ ๋ฝ + DLQ ๋์ (
0ec22b4) : โ ์ฌ์ฉ์๊ฐ ๊ฒฐ์ ๋ฒํผ์ ๋น ๋ฅด๊ฒ ๋ ๋ฒ ๋๋ฅด๊ฑฐ๋ ๋คํธ์ํฌ ์ฌ์๋๊ฐ ๋ฐ์ํ๋ฉด ๋์ผ ์์ฒญ์ด ๋ ๋ฒ ์ฒ๋ฆฌ๋์ด ์ด์ค ๊ฒฐ์ ์ํ. โก ์ ๊ธฐ๊ฒฐ์ ์ค์ผ์ค๋ฌ๋ ๋ค์ค ์ธ์คํด์ค ํ๊ฒฝ์์ ๊ฐ์ ์๊ฐ์ ๋์์ ๋๋ฉด ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ์ค๋ณต ์ฒญ๊ตฌ๋ ์ ์์. โข webhook ์ฒ๋ฆฌ๊ฐ ์ผ์ ์คํจํ๋ฉด ๊ทธ๋๋ก ์ ์ค๋จ. โ โIdempotencyKey์ปฌ๋ ์ ์(memberId + operation)ํค๋ฅผ MongoDB ์ ๋ํฌ ์ธ๋ฑ์ค๋ก ๊ฐ์ ํ๊ณ 24h TTL๋ก ์๋ ์ ๋ฆฌ, โกSchedulerLock์ปฌ๋ ์ ์_idunique ์ ์ฝ์ ํ์ฉํ MongoDB ๊ธฐ๋ฐ ๋ถ์ฐ ๋ฝ์ผ๋ก ์ ๊ธฐ๊ฒฐ์ ์ค์ผ์ค๋ฌ ์ค๋ณต ์คํ ์ฐจ๋จ(10๋ถ TTL ์์ ์ฅ์น ํฌํจ), โข webhook ์ฒ๋ฆฌ ์คํจ ๋ฉ์์ง๋PaymentDeadLetter๋ก ๊ฒฉ๋ฆฌ ํ ์ฌ์๋ ์ค์ผ์ค๋ฌ์์ ์๋ ์ฌ์ฒ๋ฆฌ + ์ด์์ ์๋ ๊ฐ์ ๊ฐ๋ฅ. -
๊ตฌ๋ ์ํ ์ ์ด ๊ฒ์ฆ โ ๋น์ ์ ์ ์ด ์ฐจ๋จ (
0ec22b4) : webhook ์์ ์ญ์ ์ด๋ ์ด์์ ์๋ ๊ฐ์ ์CANCELLED โ ACTIVE์ฒ๋ผ ๋น์ ์ ์ํ ์ ์ด๊ฐ ๋ฐ์ํ ์ ์๋ ๊ตฌ์กฐ์์. โSubscriptionStatusenum์ ํ์ฉ ์ ์ด ๊ท์น(PENDING โ ACTIVE/CANCELLED,ACTIVE โ CANCELLED/SUSPENDED/PENDING๋ฑ)์ ์ฝ๋ ๋ ๋ฒจ๋ก ์ ์ํ๊ณ ,canTransitionTo()๊ฒ์ฆ์ ๊ฑฐ์น์ง ์์ ์ํ ๋ณ๊ฒฝ์ ๋๋ฉ์ธ ์์ธ๋ก ์ฐจ๋จ. -
FREE ํฌ๋ ๋ง ์ผ๊ด ๋ฐฐ์น โ ์ฌ์ฉ์๋ณ ๊ฐ๋ณ ์ฃผ๊ธฐ ์ ํ (
30cb3d8) : ๋ชจ๋ FREE ์ฌ์ฉ์์ ํฌ๋ ๋ง์ ๋งค์ 1์ผ(cron 0 0 3 1 * *) ์ผ๊ด ์ง๊ธํ๋ ๊ธฐ์กด ๊ตฌ์กฐ๋ โ 1์ผ์ ๋ถํ๊ฐ ๋ชฐ๋ฆฌ๊ณ , โก ์ ์ค๊ฐ ๊ฐ์ ์๊ฐ ํ ๋ฌ์น ํฌ๋ ๋ง์ ๊ธฐ๋ค๋ ค์ผ ํ๋ ํํ์ฑ ๋ฌธ์ ๊ฐ ์์์. โ ์ค์ผ์ค๋ฌ๋ฅผ ๋งค์ผ ์คํ(cron 0 0 3 * * *)์ผ๋ก ๋ฐ๊พธ๊ณ ,nextBillingDate <= today์ธ FREE+ACTIVE ๊ตฌ๋ ๋ง ์ฒ๋ฆฌํ๋๋ก ๋ณ๊ฒฝ. ์ฌ์ฉ์๋ณ ๊ฐ์ ์ผ ๊ธฐ์ค ๊ฐ๋ณ ์ฃผ๊ธฐ๋ก ์ ํ๋์ด ๋ถํ ๋ถ์ฐ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ๋์์ ๊ฐ์ . -
LocalDate.now()ํ์์กด ๋๋ฝ์ผ๋ก ๊ฒฐ์ ์ผ ์ด๊ธ๋จ (d7e9637) : ๊ฒฐ์ ์ผ/๊ตฌ๋ ๋ง๋ฃ์ผ์LocalDate.now()๋ฅผ ์ฌ์ฉํ๋๋ฐ ์๋ฒ ์ปจํ ์ด๋๊ฐ UTC ๊ธฐ์ค์ด๋ผ KST ์์ ์งํ ๊ฒฐ์ ๊ฐ ์ ๋ ๋ก ์ธ์๋๋ ์ผ์ด์ค ๋ฐ์. ํ์์กด ๋ถ์ผ์น๋กnextBillingDate๊ณ์ฐ์ด ํ๋ฃจ์ฉ ์ด๊ธ๋จ. โ ๋ชจ๋LocalDate.now()ํธ์ถ์LocalDate.now(ZoneId.of("Asia/Seoul"))๋ก ๋ช ์ ๋ณ๊ฒฝ, ๊ฒฐ์ ์ผ ๊ณ์ฐ์ KST ๊ธฐ์ค์ผ๋ก ์ผ๊ด๋๊ฒ ํต์ผ.๊ณ์ ๋ฐ๊ธ -
์ฌ์ฌ ํต๊ณผ ํ ์ค์๋น์ค ์คํ
๐ Unicast
๐จ Impact Design Canvas โ AI ๊ธฐ๋ฐ ์ฑ๊ณผ ์ค๊ณ ๊ต์ก ํ๋ซํผ
๊ต์ก ํ์ฅ์์ ํ์ต ์ฑ๊ณผ๋ฅผ ์ค๊ณํ๊ณ ๊ด๋ฆฌํ๋ AI ๊ธฐ๋ฐ ํ๋ซํผ
- Role: ํ์คํ ๋จ๋ ๊ฐ๋ฐ
- Period: 2026.01 ~ 2026.02
- Tech: Spring Boot, Spring Security(JWT), MariaDB, OpenAI API, GitHub Actions
Key Features
- 6๋จ๊ณ ์บ๋ฒ์ค ์ํฌํ๋ก์ฐ โ Impact Check โ Identity โ Flow โ Quick Win โ Build Win โ Review๋ก ํ์ต์์ ์ฑ๊ณผ ์ค๊ณ๋ฅผ ๋จ๊ณ๋ณ ๊ฐ์ด๋
- AI ์๋ ๋ฆฌํฌํธ ์์ฑ โ ํ๋ณ ์บ๋ฒ์ค ๋ฐ์ดํฐ๋ฅผ OpenAI GPT-4.1๋ก ๋ถ์ํ์ฌ ๋น์ /๋ฏธ์ /SWOT ๋ฑ ์ข ํฉ ๋ฆฌํฌํธ ์ฐ์ถ
- ๊ฐ์ฌ์ฉ ํตํฉ ๊ด๋ฆฌ โ ์์ /ํ(์ต๋ 6ร10๋ช ) ๊ด๋ฆฌ, ํ์ ์งํ๋ ์ถ์ , ๋ฒํฌ PDF ๋ค์ด๋ก๋
Troubleshooting
- OpenAI ์๋ต ์ง์ฐ โ ํฐ์บฃ ์ค๋ ๋ ๋์ :
CompletableFuture4-fan-out ๋ณ๋ ฌํ + executor(60s) / HTTP read(50s) cascade ํ์์์์ผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋ ์ ๋ฆฌ ๋ณด์ฅ, fallback ์๋ต์ผ๋ก ์ฅ์ ๊ฒฉ๋ฆฌ - 1์ฝ์ด / 1GB RAM ๋ฉ๋ชจ๋ฆฌ ์๋ฐ : ํ 256MB ยท HikariCP 5 ยท Tomcat 30 ยท ioExecutor ํ 5 + ํ 50(
CallerRunsPolicy)๋ก ๋ฐฑํ๋ ์ ์ค๊ณ, ๋ฌด์ ํ ํ์ OOM ์ํ ์ฐจ๋จ - storageยทexternal ๊ฐ๊ฒฐํฉ ์ํ : domain ๋ ์ด์ด๊ฐ ์ธํฐํ์ด์ค(
Repository,AiClient,ExternalFileClient)์๋ง ์์กดํ๋๋ก DIP ์ ์ฉ, JPA ์ํฐํฐ โ ๋๋ฉ์ธ ๋ชจ๋ธ(POJO) ๋ถ๋ฆฌ๋ก LLM ์ ๊ณต์/์คํ ๋ฆฌ์ง ๊ต์ฒด ๊ฐ๋ฅ
๐ฌ ๋๋ฅด๋ฅต (AI ๋ฉ์ ์ ) โ SNS + AI ๊ธฐ๋ฐ ์ค์๊ฐ ์ฑํ ์๋น์ค ๐
์น๊ตฌ์์ ๋ํ๋ฅผ AI๊ฐ ํ์ตํ์ฌ, AI ํด๋ก ์ ํตํด ์น๊ตฌ์ ๋ต๋ณ์ ์์ธกํด๋ณด๋ ๋ฉ์ ์ ์๋น์ค (iOS ์ถ์)
- Role: ๋ฐฑ์๋ ๊ฐ๋ฐ ยท ํ 5์ธ
- Period: 2024.09 ~ 2025.06
- Tech: Kotlin, Spring Boot 3, WebSocket(STOMP), MySQL, MongoDB, Spring Security(JWT), NCP Object Storage, OpenAI, Docker, GitHub Actions
Key Features
- 3์ข ์ฑํ ๋ฐฉ ํตํฉ ์ํคํ ์ฒ โ Direct(1:1) / Group / AI ์ฑํ ๋ฐฉ์ ๋ณ๋ ๋๋ฉ์ธ์ผ๋ก ๋ถ๋ฆฌํ๋, ๋ฉ์์งยท์ํ์คยท์ฝ์ ์ฒ๋ฆฌ ๋ก์ง์ ๊ณตํต ์ถ์ํ
- AI ํด๋ก ์๋ต ํ์ดํ๋ผ์ธ โ ์ฌ์ฉ์ ๋ํ ํจํด์ OpenAI์ ์์, ๋ถ์ฌ ์ํฉ์์ AI๊ฐ ๋ณธ์ธ ๋์ ์๋ต
- ์ค์๊ฐ ๋ฉ์์ง ์ํ์ฑ โ MongoDB ๊ธฐ๋ฐ ์ฑํ
๋ฐฉ๋ณ sequence/์ฝ์ ์ํ ๊ด๋ฆฌ, STOMP
/topic+/user/{id}์ด์ค ์ฑ๋๋ก ๋ฉํฐ ๋๋ฐ์ด์ค ๋๊ธฐํ - ํผ๋(SNS) โ ์ฑํ ์ฐ๋ โ ์น๊ตฌ ํผ๋์ ๋๊ธ์ ๋ฌ๋ฉด ์๋์ผ๋ก 1:1 ์ฑํ ๋ฐฉ์ผ๋ก ์ ์ก๋๋ cross-domain ์ธํฐ๋์
Architecture
- 5๊ฐ ๋ฉํฐ๋ชจ๋ (api / domain / storage / external / common) + REST Docs ์ ์ฉ ๋ชจ๋๋ก ๊ณ์ธต ๋ถ๋ฆฌ, ์์กด ๋ฐฉํฅ:
api โ domain โ storage / external - DDD lean ๋๋ฉ์ธ + Service / Facade / Aggregator 3๊ณ์ธต โ Service๋ ๋จ์ผ ์ฑ
์, Facade๋ ์ ์ค์ผ์ด์ค ์ค์ผ์คํธ๋ ์ด์
, Aggregator๋ ์ด์ข
๋ฐ์ดํฐ ์กฐ๋ฆฝ(
DirectChatRoomAggregator๋ก ์ฑํ ๋ฐฉ + ์ต์ ๋ฉ์์ง ๊ฒฐํฉ) - DIP ์ ์ฉ โ domain์
RepositoryยทExternalAiClientยทExternalPushNotificationClient์ธํฐํ์ด์ค์๋ง ์์กด, JPA/Mongo Entity โ ๋๋ฉ์ธ ๋ชจ๋ธ ๋ถ๋ฆฌ
Troubleshooting
-
์ด๊ธฐ์ข DB(MySQL + MongoDB) ํธ๋์ญ์ ์๋์ ๋ฐฐ์ โ Saga ์คํ์ผ ์กฐํฉ : ์ฑํ ๋ฐฉ ์ํ(MySQL)ยท๋ฉ์์ง ๋ก๊ทธ(MongoDB)ยท์ธ๋ถ ์๋ฆผ(FCM/Expo)์ด ํ ์ ์ค์ผ์ด์ค์์ ๊ฐ์ด ๋ณ๊ฒฝ๋จ.
@Transactional์ ๊ฑธ๋ฉด MySQL๋ง ๋กค๋ฐฑ๋๊ณ Mongoยทํธ์๋ ๋จ๋ ๊ฐ์ง ์์ ๊ฐ๋ง ์ฃผ๋ ๋ฌธ์ โ Facade์์ ํธ๋์ญ์ ์ ๋นผ๊ณ , ๊ฐ ์์ service๋ง ์์ ์ ์ ์ฅ์ ํธ๋์ญ์ ์ ์ฑ ์์ง๋๋ก ๊ฒฝ๊ณ ์ถ์. ์คํจ ์chatErrorMessages()๋ฅผ ๊ฐ์ ์๋ฆผ ์ฑ๋๋ก ํ๋ ค๋ณด๋ด ํด๋ผ์ด์ธํธ๊ฐ ์ค๋ฅ ์ํ๋ฅผ ์ธ์งยท์ฌ์๋ํ๋ eventual consistency ํจํด์ผ๋ก ์ ํ. -
์ํ์ค ์ฆ๊ฐ race condition (
5e49963) : ์ฑํ ๋ฐฉ ์กด์ฌ ์ฌ๋ถ ํ์ธ ์์ด sequence๋ฅผ ๋จผ์ ์ฆ๊ฐ์ํค๋ค ๋ณด๋, ์ญ์ ๋ ๋ฐฉ์ ๋ํด ์ํ์ค๋ง ์ฆ๊ฐํ๋ ์ ๋ น ์ํ๊ฐ ๋ฐ์ โincreaseDirectChatRoomSequenceํธ์ถ ์ ์ ์ฑํ ๋ฐฉ ์กด์ฌ ๊ฒ์ฆ์ ์ ํํ๋๋ก Facade ๋ก์ง ์ฌ๋ฐฐ์น, ์ํ์ค ์นด์ดํฐ์ ๋ฌด๊ฒฐ์ฑ ํ๋ณต. -
MongoDB ์ธ๋ฑ์ค ์ ๋ต ์ฌ์ค๊ณ (
4ec7f92) : ์ด๊ธฐ partial index({chatRoomId, type, message})๋ ์กฐ๊ฑด์ด ๊น๋ค๋ก์ ์ฑํ ๋ก๊ทธ ๋ฒ์ ์กฐํ / ํค์๋ ๊ฒ์ ๋ ๋ค ๋ชป ์ก์๋จน์ โ โ ๋ฒ์ ์กฐํ์ฉ ๋ณตํฉ ์ธ๋ฑ์ค{chatRoomId: 1, sequence: -1}, โก ๋ฉ์์ง ๋ณธ๋ฌธ์ฉ text ์ธ๋ฑ์ค{message: 'text'}๋ ๊ฐ์ง๋ก ๋ถ๋ฆฌ. ํ์ด์ง๋ค์ด์ ๊ณผ ํค์๋ ๊ฒ์ ๋ชจ๋ ์ธ๋ฑ์ค๋ฅผ ํ๊ฒ ๋จ. -
MySQL ํซํจ์ค ์ธ๋ฑ์ค ๋ถ์ฌ (
33b1acb) : 1:1 ์ฑํ ๋ฐฉ ๋ชฉ๋ก ์กฐํ(userAId/userBId ร status), ์น๊ตฌ ์ฆ๊ฒจ์ฐพ๊ธฐ ์กฐํ ๋ฑ ํซํจ์ค๊ฐ ํ์ค์บ โdirect_chat_room์ (userA/userB, status) ๋ณตํฉ ์ธ๋ฑ์ค 3์ข ,friend_ship์(user_id, favorite)์ธ๋ฑ์ค ์ถ๊ฐ๋ก ์๋ต ์๊ฐ ๊ฐ์ . -
STOMP ํธ๋์ ฐ์ดํฌ ์ธ์ฆ ํ๋ฆ ์ ๋น (
0e8a3d2,ca8e2e8) : ํธ๋์ ฐ์ดํฌ ์์ ์๋ HTTP ํค๋์ JWT๊ฐ ์๋ ๊ฒฝ์ฐ๊ฐ ์์ด ์ธ์ฆ ๋๋ฝ โCustomHandshakeHandler+StompChannelInterceptor์์ CONNECT ํ๋ ์ ์์ ์Authorizationํค๋ ๊ฒ์ฆ, JWT์์ ์ถ์ถํuserId๋ฅผPrincipal๋ก ์ฃผ์ ํด ์ดํ ๋ฉ์์ง ํธ๋ค๋ฌ๊ฐ ์ผ๊ด๋๊ฒ ์ ๊ทผ. -
์ด๋ฏธ์ง ํธ๋ํฝ ์ ๊ฐ (
42ded85) : ์ฑํ ์ฒจ๋ถ ์ด๋ฏธ์ง ์๋ณธ ๊ทธ๋๋ก NCP ์ ๋ก๋ โ ๋์ญํญ/๋ชจ๋ฐ์ผ ๋ฐ์ดํฐ ๋ถ๋ด โ Scrimage ๊ธฐ๋ฐ WebP ๋ณํ ํ์ดํ๋ผ์ธ ๋์ , ์ ๋ก๋ ๋จ๊ณ์์ ์์ค ์์ถ ์ ์ฉ.
๐งน RoomGenie โ AI ์ด๋ฏธ์ง ๊ธฐ๋ฐ ๋ฐฉ ์ ๋ฆฌ ์๋น์ค ๐
AI๊ฐ ๋ฐฉ ์ฌ์ง์ ๋ถ์ํ์ฌ ์ ๋ฆฌ ๋ฐฉ๋ฒ์ ์ ์ํ๋ ์๋น์ค
- Role: ๋ฐฑ์๋ ๊ฐ๋ฐ ยท ํ 5์ธ
- Period: 2025.05 ~ 2025.07
- Tech: Java 17, Spring Boot 3.5, Spring Security(JWT), JPA/MySQL, AWS S3, OpenAI GPT-4 Vision, YOLO, LAMA, NCP Sens(SMS)
Key Features
- 3์ข AI ํ์ดํ๋ผ์ธ โ YOLO(๊ฐ์ฒด ๊ฐ์ง) โ LAMA(์ธํ์ธํ )๋ก "์ ๋ฆฌ๋ ๋ฐฉ" ์๋ฎฌ๋ ์ด์ ์ด๋ฏธ์ง ์์ฑ + GPT-4 Vision์ผ๋ก ๋จ๊ณ๋ณ ์ ๋ฆฌ ๊ฐ์ด๋ ์ ๊ณต
- AI ๊ธฐ๋ฐ ๋ฏธ์
์๋ ๊ฒ์ฆ โ before/after ์ด๋ฏธ์ง๋ฅผ GPT-4 Vision์ผ๋ก ๋น๊ต, ์๋ต ํ ํฐ(
[RESULT:SUCCESS]) ํ์ฑ์ผ๋ก ๋ฏธ์ ์ํ๋จธ์ ์๋ ์ ์ด - ํด๋ํฐ OTP 2๋จ๊ณ ์ธ์ฆ โ NCP Sens HMAC-SHA256 + Caffeine ์บ์ ๊ธฐ๋ฐ OTP ๊ฒ์ฆ ํ JWT ๋ฐ๊ธ
Architecture
- 6๊ฐ ๋ฉํฐ๋ชจ๋(api/domain/storage/external/common/api-docs) ๊ณ์ธต ๋ถ๋ฆฌ
- DIP ์ ์ฉ โ domain์ด
ExternalAiClient/ExternalFileClient์ธํฐํ์ด์ค์๋ง ์์กด, JPA Entity โ Domain POJO ๋ถ๋ฆฌ๋ก LLMยท์คํ ๋ฆฌ์ง ๊ต์ฒด ๊ฐ๋ฅ - DDD Value Object โ
UserId,MissionId,PostId๋ก ์๋ณ์ ํ์ ์์ ์ฑ ํ๋ณด - Facade ํจํด์ผ๋ก AI ๋ถ์ยท๋ฏธ์ ๊ฒ์ฆยท์ด๋ฏธ์ง ์์ฑ ์ ์ค์ผ์ด์ค ์ค์ผ์คํธ๋ ์ด์
Troubleshooting
- LAMA ์ธํ์ธํ
๊ฐ์ฅ์๋ฆฌ ์์ : YOLO bounding box๋ฅผ ๊ทธ๋๋ก mask๋ก ์ฌ์ฉํ๋ ๊ฐ์ฒด ๊ฒฝ๊ณ์ ํ์ ์ด ๋จ๋ ๋ฌธ์ โ ๋ฐ์ค๋ฅผ 20px ํ์ฅ +
fillRoundRect+ AntiAliasing์ผ๋ก ๋ง์คํฌ ํ์ฒ๋ฆฌ ์ ์ฉํ์ฌ ์์ฐ์ค๋ฌ์ด ๋ฐฐ๊ฒฝ ๋ณต์ ๋ฌ์ฑ - LAMA ์๋ฒ multipart ์ง๋ ฌํ ์คํจ : ๊ธฐ๋ณธ
RestTemplate์ด binary mask + form ํ๋ผ๋ฏธํฐ ๋์ ์ ์ก์ ์ฒ๋ฆฌํ์ง ๋ชปํจ โFormHttpMessageConverter/ByteArrayHttpMessageConverter๋ฅผ ๋ฑ๋กํ ์ ์ฉ RestTemplate ๋ถ๋ฆฌ๋ก ํด๊ฒฐ - Private S3 โ GPT-4 Vision ์ฐ๋ ๋ถ๊ฐ : ๋น๊ณต๊ฐ ๋ฒํท์ด๋ผ OpenAI๊ฐ ์ด๋ฏธ์ง URL์ ์ง์ fetch ํ ์ ์๋ ๋ฌธ์ โ S3์์ ๋ค์ด๋ก๋ ํ Base64 data URL ๋ก ๋ณํํด ์ ๋ฌ, ๋ณด์๊ณผ AI ํธ์ถ์ ๋ชจ๋ ๋ง์กฑ
- OpenAI 429 ์ฅ์ ๊ฒฉ๋ฆฌ :
HttpClientErrorException.TooManyRequests๋ฅผ ๋ณ๋ ์บ์นํ์ฌAI_RATE_LIMIT_EXCEEDED๋๋ฉ์ธ ์์ธ๋ก ๋ํ, ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์ฌ์๋ ๋ฉ์์ง ๋ ธ์ถ
๐ GitHub
๐ฑ FutureFinder โ ์ฒญ๋ ๋ง์ถคํ ๊ธ์ตยท์ง๋ก ํตํฉ ํ๋ซํผ
์ฒญ์ฝยท์์ฐยท์ทจ์ ยท๊ฒฝ์ ์ ๋ณด๋ฅผ ํ ๊ณณ์ ๋ชจ์ ์ฒญ๋ ์๊ฒ ๋ง์ถคํ ์ธ์ฌ์ดํธ๋ฅผ ์ ๊ณตํ๋ ํตํฉ ํ๋ซํผ
- Role: ๋ฐฑ์๋ ๊ฐ๋ฐ ยท ํ 5์ธ
- Period: 2025.08 ~ 2025.09 (์ดํ ๊ฐ์ธ ๋ฆฌํฉํ ๋ง ์งํ)
- Tech: Java 17, Spring Boot 3.5, Spring Security(JWT), JPA/MySQL(RDS), AWS S3, WebFlux WebClient, OpenAI
Key Features
- ํ ๋์๋ณด๋ ํตํฉ ์ง๊ณ โ KRX ์ฃผ์ ๊ธ๋ฑ๋ฝ Top3 + ๋ค์ด๋ฒ ๊ฒฝ์ ๋ด์ค + ๊ณต๊ณต๊ธฐ๊ด ์ฑ์ฉ ๊ณต๊ณ ๋ฅผ ๋จ์ผ ์๋ํฌ์ธํธ(
GET /api/home)๋ก ๋ฌถ์ด ์ ๊ณต,HomeFacade๋ก ์ด์ข ์ธ๋ถ ๋ฐ์ดํฐ ์กฐ๋ฆฝ - ์ฃผ๊ฑฐ ๊ธ์ต ๊ด๋ฆฌ + AI ์ฑ๋ด โ ์ฒญ์ฝ ๊ณ์ขยท์ ๊ธ ๋ด์ญยทํ์ฌ/๊ด์ฌ ๊ฑฐ์ฃผ์ง ๊ด๋ฆฌ + OpenAI ๊ธฐ๋ฐ ์ฃผ๊ฑฐ ๊ธ์ต Q&A ์ฑ๋ด, ์ฌ์ฉ์๋ณ ๋ํ ์ด๋ ฅ ์์ํ๋ก ์ปจํ ์คํธ ์ฐ์์ฑ ํ๋ณด
- AI ๋ง์ถค ์ทจ์ ์ถ์ฒ โ ํ๋ ฅยท๋์ธํ๋ยท์์ ์ด๋ ฅ์ ์ ๋ ฅ์ผ๋ก OpenAI์ ์์, ์ฌ์ฉ์ ํ๋กํ ๊ธฐ๋ฐ ์ถ์ฒ ๋์ธํ๋ยท์ฑ์ฉ ๊ณต๊ณ ์ฐ์ถ
- ๊ฒฝ์ ์ฌ์ + ์นด์นด์ค OAuth โ ํ๊ตญ์ํ ECOS ๊ธฐ๋ฐ ๊ฒฝ์ ์ฉ์ด ๊ฒ์ยท์คํฌ๋ฉยท์ธ๊ธฐ ๋จ์ด, ์นด์นด์ค ์์ ๋ก๊ทธ์ธ + JWT Access/Refresh ์ด์ค ํ ํฐ
Architecture
- 5๊ฐ ๋ฉํฐ๋ชจ๋(api / domain / external / storage / common) ๊ณ์ธต ๋ถ๋ฆฌ, ์์กด ๋ฐฉํฅ:
api โ domain โ storage / external - CQRS ์คํ์ผ ๋๋ฉ์ธ ๊ตฌํ โ ์๋น์ค๋ฅผ
AppenderยทReaderยทUpdaterยทValidatorยทRemover๋ก ๋ถํดํด ๋จ์ผ ์ฑ ์ ๊ฐ์ - Facade ์ค์ผ์คํธ๋ ์ด์
โ
HomeFacade(์ด์ข ๋ฐ์ดํฐ ์ง๊ณ)ยทAccountFacade(ํ์/OAuth)ยทAcademicFacade๋ก ์ ์ค์ผ์ด์ค ์กฐ๋ฆฝ, ์ปจํธ๋กค๋ฌ๋ ์๊ฒ ์ ์ง - DIP ์ ์ฉ โ domain์
ExternalOAuthClientยทExternalNewsClientยทExternalStockClientยทOpenAIService์ธํฐํ์ด์ค์๋ง ์์กด, ์ธ๋ถ ๋ฒค๋(์นด์นด์ค/๋ค์ด๋ฒ/ECOS/KRX/OpenAI) ๊ต์ฒด ๊ฐ๋ฅ - Value Object โ
UserId๋ฑ ์๋ณ์ ํ์ ์์ ์ฑ + JPA Entity โ ๋๋ฉ์ธ ๋ชจ๋ธ ๋ถ๋ฆฌ
Troubleshooting
-
์ธ๋ถ API ํธ์ถ ํญ์ฆยท์ง์ฐ โ TTL ์บ์ ๋ ์ด์ด ๋์ (
c07de21) : ํ ๋์๋ณด๋ ํ ๋ฒ ํธ์ถ ์ KRX(์ฃผ์ ๊ธ๋ฑ๋ฝ)ยท๋ค์ด๋ฒ(๋ด์ค)ยท๊ณต๊ณต์ฑ์ฉ API๊ฐ ๋์์ ํธ๋ฆฌ๊ฑฐ๋์ด ์๋ต ์ง์ฐ์ด ๋์ ๋๊ณ , ์ผ์ผ ์ฟผํฐ ํ๋๊น์ง ์ํํ๋ ๊ตฌ์กฐ์์. ํค์๋ยท๋ ์ง ๋จ์๋ก ์๋ต์ด ๊ฑฐ์ ๋์ผํจ์๋ ๋งค ์์ฒญ๋ง๋ค ์ธ๋ถ๋ฅผ ์ง์ ๋๋ฆฌ๋ ์ค๊ณ๊ฐ ์์ธ. โ ์ธ๋ถ ํด๋ผ์ด์ธํธ ์๋จ์TtlCache๋ ์ด์ด๋ฅผ ๋์ ํด ๋์ผ ํค ์์ฒญ์ ๋ฉ๋ชจ๋ฆฌ์์ ํก์, ์ธ๋ถ ํธ์ถ ๋น๋์ ํ ๋์๋ณด๋ ์๋ต ์๊ฐ์ ๋์์ ์ ๊ฐ. -
External ๋ชจ๋ 800์ฌ ์ค ์ค๋ณต ์ ๊ฑฐ โ ์ ์ง๋ณด์์ฑ ๊ฐ์ (
c07de21) : 6๊ฐ ์ธ๋ถ API ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ HTTP ์ ์กยทJSON ํ์ฑยทHTML ๋ฉํ ์คํฌ๋ํยท์บ์ฑ ๋ก์ง์ ๊ฐ๋ณ ๋ณด์ ํด,ExternalNewsClientImpl์ด ~400์ค๊น์ง ๋น๋ํด์ง๊ณ ๋์ผ ๋ฒ๊ทธ๋ฅผ ์ฌ๋ฌ ํ์ผ์์ ๋ฐ๋ณต ์์ ํด์ผ ํ๋ ์ํ์์. โ ๊ณตํต ์ฑ ์์ArticleMetaScraper/GovApiJsonParser/ExternalClientUtils/TtlCache4๊ฐ ์ ํธ๋ก ์ถ์ถํ๊ณ ์ค์ ๊ฐ์*Propertiesํด๋์ค๋ก ๋ถ๋ฆฌ. News -309 / JobAI -254 / Recruitment -176 / Stock -102 ์ค ์ฌ๋ฆผํํ์ฌ, ์ ์ธ๋ถ API ์ถ๊ฐ ์ ๋น์ฉ๋ ํจ๊ป ๊ฐ์. -
์ปจํธ๋กค๋ฌ ๋น๋ํ โ ๋๋ฉ์ธ ๋ก์ง ๋์ ํด์ (
c07de21) :HouseController/JobController์ ๋น์ฆ๋์ค ๋ถ๊ธฐยทDTO ์กฐ๋ฆฝยทRepository ์ง์ ํธ์ถ์ด ๋ฐํ ์์ด ์ฌ์ฌ์ฉยท๋จ์ ํ ์คํธ๊ฐ ๋ชจ๋ ๋ถ๊ฐ๋ฅํ๊ณ , ๋์ผ ๋ก์ง์ด ๋ค๋ฅธ ์ ์ค์ผ์ด์ค์์๋ ๋ณต์ ๋๋ ์ํ์ด ์์์. โ ๋ก์ง์HouseService/JobService๋ก ์ด๋, ์ปจํธ๋กค๋ฌ๋ ์ธ์ฆยท์์ฒญ ๊ฒ์ฆยท์๋ต ๋ณํ๋ง ๋ด๋นํ๋ ์์ ๊ณ์ธต์ผ๋ก ์ ๋ฆฌ(์ปจํธ๋กค๋ฌ -130์ฌ ์ค). ์ดํHomeFacade๊ฐ์ ์กฐํฉ ์ ์ค์ผ์ด์ค์์ ๋์ผ ์๋น์ค๋ฅผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํด์ง.
๐ GitHub


