์ ์ฌ์ ํ๊ฒฝ์์์ ์ฑ๋ฅ ์ต์ ํ๋ถํฐ ํ์ฅ์ฑ ์๋ ๊ตฌ์กฐ๊น์ง, ๋์ํ๋ ์ฝ๋ ๋๋จธ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ๋๋ค.
- ์ด์ ์ค์ธ ๊ฒฐ์ ๋ชจ๋ ๋จ๋ ์ ์ง๋ณด์ โ PG์ฌ 2ํ ์ฌ์ด๊ด(KCP โ ํ ์ค โ NicePay)์ ๊ฑฐ์น๋ฉฐ ๋ฉฑ๋ฑ์ฑ / ๋ถ์ฐ ๋ฝ / DLQ / ์ํ๋จธ์ ์ PG-agnosticํ๊ฒ ์ถ์ํ
- ์ ์ฌ์ ์๋ฒ ํ๋ โ 1์ฝ์ด/1GB ํ๊ฒฝ์์ HikariCPยทTomcatยทioExecutor ํ๋ +
CallerRunsPolicy๋ฐฑํ๋ ์ ๋ก OOM ๋ฐฉ์ด - ๋ฉํฐ๋ชจ๋ + DIP ์ค๊ณ โ domain์ด ์ธํฐํ์ด์ค์๋ง ์์กดํ๋๋ก ๋ถ๋ฆฌ, JPA Entity โ ๋๋ฉ์ธ POJO ๋งคํ์ผ๋ก LLM/์คํ ๋ฆฌ์ง ๊ต์ฒด ๊ฐ๋ฅํ ๊ตฌ์กฐ ๋ฐ๋ณต ์ ์ฉ
| Issue | Description | Related PR |
|---|---|---|
| #5366 | ExitStatus#setExitException breaks immutability contract |
#5367 |
| Issue | Description | Related PR |
|---|---|---|
| #1033 | MockMvcRequestConverter uses US_ASCII for URL decoding while encoding uses UTF-8 |
#1034 |
| #1038 | WebTestClientRequestConverter mishandles cookies whose value contains = |
#1040 |
| #1039 | UriModifyingContentModifier.modifyContent decodes with the request charset but re-encodes with the platform default |
#1043 |
| Issue | Description | Related PR |
|---|---|---|
| #4242 | QueryUtils.FUNCTION_PATTERN fails to detect COUNT(*) AS alias, causing invalid ORDER BY alias rewriting in native queries |
#4249 |
- ๐ฑ ๋๋ฅด๋ฅต (drr) โ iOS App Store ์ ์ ์ถ์ ยท 2025 ํ์๋ ์บก์คํค ๋์์ธ ์ฐ์์
- ๐ฅ 2025 9ITHON ์ฐ์์ (2์) โ RoomGenie
- ๐ฅ 2023 ์ ๊ตญ ๋ํ์ SW์ฐฝ์ ์์ด๋์ดํค ๊ฒฐ์ ์ง์ถ
-
๐ข (์ฃผ)ํํ ์๋์๋ฃจ์ ํ์ฅ์ค์ต (2025.09 ~ 2026.02)
- Unicast (https://unicast.kr) ๊ตฌ๋
๊ฒฐ์ ๋ชจ๋ โ PayPal + ๊ตญ๋ด PG ์ฐ๋, PG์ฌ 2ํ ์ฌ์ด๊ด(KCP โ ํ ์ค โ NicePay) ๋์
- ๋ฐฉ์ด๋ก์ง: ๋ฉฑ๋ฑ์ฑ / ์ด์ค๊ฒฐ์ ๋ฐฉ์ง / ๋ถ์ฐ ๋ฝ / DLQ / ์ํ ์ ์ด ๊ฒ์ฆ / ์นํ ์ค๋ณต๋ฐฉ์ง
- GitHub Actions ๊ธฐ๋ฐ CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ, PG์ฌ ๊ฐ๋งน ์ฌ์ฌ ๋์
- Impact Design Canvas ํ์คํ ๋จ๋ ๊ฐ๋ฐ โ Spring Boot ยท MariaDB ยท OpenAI
- CX-INNOVATOR ๋์์ธ ์ฝํน ํ๋ซํผ ์ ์ง๋ณด์ โ http://www.abl-cxinno.kr/main
- ํ์ ์ ๋ณด ๊ด๋ จ ํ๋ฉด/DB ์ถ๊ฐ, ํ์ ํญยท๋ํ์์ฑ์ ์๊ด ํ์
- PDF ๋ณด๊ณ ์ ์ฐ๋ ๋ฒ๊ทธ ์์ , C-3 / F-1 / B-1 ๋จ๊ณ ๊ธฐ๋ฅ ์ถ๊ฐ, chatbot / ๋ฌธ์ ์ฌ์ ์ง๋ ์์
- Unicast (https://unicast.kr) ๊ตฌ๋
๊ฒฐ์ ๋ชจ๋ โ PayPal + ๊ตญ๋ด PG ์ฐ๋, PG์ฌ 2ํ ์ฌ์ด๊ด(KCP โ ํ ์ค โ NicePay) ๋์
-
๐ฑ ๊ตฌ๋ฆํค ์ ๋๋ธ 4๊ธฐ ๋ฐฑ์๋ (2025.03 ~ 2025.09)
- ๋ฐฑ์๋ Bํ ์คํฐ๋์ฅ
- ๊ฒฝ๊ธฐ๋ถ๋ถ ํด์ปคํค 9ITHON, ๊ตฌ๋ฆํค ์์ฆํค ์ฐธ์ฌ โ 9ITHON 2์(์ฐ์์)
๐ณ Unicast ๊ฒฐ์ ๋ชจ๋ โ PG 2ํ ์ฌ์ด๊ด ๋์ + ๋ฐฉ์ด๋ก์ง ์ถ์ํ (์ด์ ์ค) ๐ฅ
์์ ์๋ง ์ถ์ถยท๋ฒ์ญยท๋๋น ๋์งํธ ์ฝํ ์ธ ์๋น์ค์ ๊ฒฐ์ ๋ชจ๋ ๋จ๋ ์ ์ง๋ณด์ ๋ฐ ๋ฐฉ์ด๋ก์ง ๋ณด๊ฐ
- Role: ์ด์ ์ค์ธ ๊ฒฐ์ ๋ชจ๋ ๋จ๋ ์ ์ง๋ณด์ ๋ฐ ๋ฐฉ์ด๋ก์ง ๋ณด๊ฐ (ํ์ฅ์ค์ต)
- Scope: PayPal/๊ตญ๋ด PG ๊ฒฐ์ ํ๋ฆ, ์นํ ์ฒ๋ฆฌ, ์ ๊ธฐ๊ฒฐ์ ์ค์ผ์ค๋ฌ, PG ์ฌ์ฌ ๋์ (์๋น์ค ๋ณธ์ฒด ๊ธฐ๋ฅ์ ๋ฒ์ ์ธ)
- Tech: Spring Boot ยท Next.js ยท MongoDB(๋ถ์ฐ ๋ฝ) ยท NHN KCP ยท ํ ์คํ์ด๋จผ์ธ ยท NicePay ยท PayPal ยท Webhook ยท DLQ ยท State Machine ยท GitHub Actions ยท Docker
- Service: https://unicast.kr (์ด์ ์ค)
Key Work
- PG 2ํ ์ฌ์ด๊ด(KCP โ ํ ์ค โ NicePay) โ ๋ฐฉ์ด๋ก์ง์ PG-agnosticํ๊ฒ ์ถ์ํ
- 1์ฐจ (KCP โ ํ ์ค) : ์ด๊ธฐ์๋ NHN KCP๋ก ์ ๊ธฐ๊ฒฐ์ (๋ฐฐ์นํค ๋ฐ๊ธ โ ์ค์ผ์ค๋ฌ ์๋๊ฒฐ์ โ ๊ตฌ๋ ์ทจ์/๋ฐฐ์นํค ์ญ์ ) ํ๋ก ํธ+๋ฐฑ์๋ ์ ๊ตฌ๊ฐ์ ๊ตฌํํ์ผ๋, KCP ์ธก์์ "์ ๊ธฐ๊ณผ๊ธ(๊ตฌ๋ ) ์ํ์ ๊ณ์ฝ ๊ฒํ ๋ถ๊ฐ, ๋จ๊ฑด๊ฒฐ์ ๋ก๋ง ๊ณ์ฝ ๊ฐ๋ฅ" ์ ์ฑ ํ์ ์ ๋ฐ์ ํ ์คํ์ด๋จผ์ธ ๋ก ์ด๊ด
- 2์ฐจ (ํ ์ค โ NicePay) : ์ด์ ์ ์ฑ ๋ณํ์ ๋ง์ถฐ NicePay๋ก ์ฌ์ด๊ด
- ์ถ์ํ ์ฑ๊ณผ : ๋ ๋ฒ์ ์ฌ์ด๊ด์ ๊ฑฐ์น๋ฉฐ ๋ฉฑ๋ฑ์ฑยทDLQยท๋ถ์ฐ ๋ฝยท์ํ ์ ์ด ๊ฒ์ฆ ๋ก์ง์ PG ์ด๋ํฐ ์ธ๋ถ๋ก ๋ถ๋ฆฌ.
Provider ๋ฝยท๋น๋งํค ๋ฐ๊ธ + ์ฒซ ๊ฒฐ์ ์์์ฑยท์ฌํ์กฐํ ๊ธฐ๋ฐ ๋คํธ์ํฌ ๋ณต๊ตฌ๊ฐ์ ์์ ์ฑ ์ฅ์น๋ฅผ PG-๋ ๋ฆฝ์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ๋ค๋ฌ์
- ๊ฒฐ์ ๋ฐฉ์ด๋ก์ง ๊ฐํ โ ์ด์ ์ค ๋ฐ๊ฒฌ๋ race condition / ๋๋ฝ ์ผ์ด์ค์ ๋ํด ๋ฉฑ๋ฑ์ฑยท๋ถ์ฐ ๋ฝยทDLQยท์ํ ์ ์ด ๊ฒ์ฆ ๋์
- PG์ฌ ๊ฐ๋งน ์ฌ์ฌ ๋์ โ ๊ฒฐ์ ํ๋ก์ฐ ๋ณด์, ์ฝ๊ด/ํ๋ถ๊ท์ /ํต์ ํ๋งค์ ๋ฒํธ ๋ฑ๋ก
- CI/CD ํ์ดํ๋ผ์ธ ์ ๊ท ๊ตฌ์ถ โ GitHub Actions ๊ธฐ๋ฐ ์๋ ๋น๋ยท๋ฐฐํฌ
-
๋ฌธ์
- ์ด๊ธฐ ๊ตฌ์กฐ๋ "๋น๋งํค ๋ฐ๊ธ โ ๋ค์ ์ค์ผ์ค๋ฌ ์ฃผ๊ธฐ์ ์ฒซ ๊ฒฐ์ " ๋ฐฉ์์ด๋ผ ๊ฐ์ ์งํ ์ ๋ฃ ๊ธฐ๋ฅ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ๊ณ , ๊ฒฐ์ ๋๋ฝ์ฒ๋ผ ๋ณด์ด๋ UX ๋ฌธ์ ๊ฐ ์กด์ฌ
-
ํด๊ฒฐ
- ๋น๋งํค ๋ฐ๊ธ ์งํ ์ฒซ ๊ฒฐ์ ๋ฅผ ๋๊ธฐ ์คํ์ผ๋ก ๋ณ๊ฒฝ
- ๋ฐ๊ธยท๊ฒฐ์ ยท๊ฒ์ฆ ๋จ๊ณ๋ณ ์ฑ๊ณต ์ฌ๋ถ๋ฅผ ๊ธฐ๋กํด ์คํจ ์ ๋ณด์ ์ฒ๋ฆฌ(๋น๋งํค ๋ง๋ฃ / ์๋ ์ทจ์ / DLQ ์ ์ฌ)
nextBillingDate <= today๊ธฐ๋ฐ ๋ฐ๋ฆฐ ๊ฒฐ์ ๋ณต๊ตฌ ์ก ์ถ๊ฐ- UTC ์ปจํ
์ด๋ โ KST ์ด์ ํ๊ฒฝ ์ฐจ์ด๋ก ์ฒญ๊ตฌ์ผ์ด ํ๋ฃจ ์ด๊ธ๋๋ ๋ฌธ์ ๋ฅผ
ZoneId.of("Asia/Seoul")๋ช ์๋ก ํด๊ฒฐ
-
๊ฒฐ๊ณผ
- PG ์ฌ์ด๊ด(KCP โ ํ ์ค โ NicePay) ์ดํ์๋ ๋์ผ ํจํด ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
-
๋ฌธ์
- ๋ฒํผ ๋๋ธ ํด๋ฆญ/์ฌ์๋๋ก ์ธํ ์ด์ค ๊ฒฐ์
- ๋ค์ค ์ธ์คํด์ค ์ค์ผ์ค๋ฌ ๋์ ์คํ ์ ์ ์ฒด ๊ตฌ๋ ์ ์ค๋ณต ์ฒญ๊ตฌ ๊ฐ๋ฅ
- webhook ์ฒ๋ฆฌ ์คํจ ๋ฉ์์ง ์ ์ค ์ํ ์กด์ฌ
-
ํด๊ฒฐ
- MongoDB unique index + TTL์ ๊ณตํต primitive๋ก ์ฌ์ฉ
IdempotencyKey:(memberId + operation)์ ๋ํฌ ์ธ๋ฑ์ค + 24h TTLSchedulerLock:_id์ ๋ํฌ ์ ์ฝ ๊ธฐ๋ฐ ๋ถ์ฐ ๋ฝ + 30๋ถ TTLPaymentDeadLetter: ์คํจ ๋ฉ์์ง ๊ฒฉ๋ฆฌ ํ ์ง์ ๋ฐฑ์คํ ์ฌ์๋ ๋ฐ ์ด์์ ์๋ ๊ฐ์ ์ง์
-
๋น๊ณ
- ๋ฉฑ๋ฑ์ฑ๊ณผ DLQ๋ ๋จ์ผ ์ธ์คํด์ค์์๋ ํ์
- ๋ถ์ฐ ๋ฝ์ ๋ค์ค ์ธ์คํด์ค ์ค์ผ์ผ์์ ๋๋น ์ ์ ์ค๊ณ
-
๋ฌธ์
- webhook ์ค๋ณต ์์ ์ด๋ ์ฝ๋/์ด์ ๊ฐ์ ์ผ๋ก ์ธํด ๋น๋ ผ๋ฆฌ์ ์ธ ์ํ ์ ์ด(CANCELLED โ SUSPENDED ๋ฑ)๊ฐ ๊ฐ๋ฅ
- ์ํ ๋ณ๊ฒฝ ๊ท์น์ด ์ฝ๋ ๊ณณ๊ณณ์ ํฉ์ด์ง ์ํ ์กด์ฌ
-
ํด๊ฒฐ
SubscriptionStatusenum์ ํ์ฉ ์ ์ด ๊ท์น ์ ์- ์ํ ๋ณ๊ฒฝ์
transitTo()๋๋ฉ์ธ ๊ฐ๋๋ฅผ ๋ฐ๋์ ํต๊ณผํ๋๋ก ์ ํ(raw setter ์ ๊ฑฐ) activate()๋ ๋ฉฑ๋ฑ ์ฒ๋ฆฌํด ์ค๋ณต ACTIVATED webhook ํก์
-
๊ฒฐ๊ณผ
- ์ํ ์ ์ด ๊ท์น์ ๋๋ฉ์ธ ๋ด๋ถ๋ก ์บก์ํํด ๋น์ ์ ์ํ ์กฐํฉ ์ฐจ๋จ
- webhook/์ด์/์๋น์ค ์ฝ๋ ๋ฑ ์ด๋ค ์ ๋ ฅ ๊ฒฝ๋ก์์๋ ๋์ผ ๊ท์น ๊ฐ์ ๊ฐ๋ฅ
๐จ 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๋ฅผ ๋ฌด๊ฒ๊ฒ ์ ์ฉํ์ง ์๊ณ , Service(๋จ์ผ ์ฑ
์) / Facade(์ ์ค์ผ์ด์ค ์ค์ผ์คํธ๋ ์ด์
) / Aggregator(์ด์ข
๋ฐ์ดํฐ ์กฐ๋ฆฝ) 3๊ณ์ธต์ผ๋ก ์ ์ โ ์:
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๋๋ฉ์ธ ์์ธ๋ก ๋ํ, ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์ฌ์๋ ๋ฉ์์ง ๋ ธ์ถ
๐ฑ 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 ์ค ์ฌ๋ฆผํ. -
์ปจํธ๋กค๋ฌ ๋น๋ํ โ ๋๋ฉ์ธ ๋ก์ง ๋์ ํด์ (
c07de21) :HouseController/JobController์ ๋น์ฆ๋์ค ๋ถ๊ธฐยทDTO ์กฐ๋ฆฝยทRepository ์ง์ ํธ์ถ์ด ๋ฐํ ์์ด ์ฌ์ฌ์ฉยท๋จ์ ํ ์คํธ๊ฐ ๋ชจ๋ ๋ถ๊ฐ๋ฅ. โ ๋ก์ง์HouseService/JobService๋ก ์ด๋, ์ปจํธ๋กค๋ฌ๋ ์ธ์ฆยท์์ฒญ ๊ฒ์ฆยท์๋ต ๋ณํ๋ง ๋ด๋นํ๋ ์์ ๊ณ์ธต์ผ๋ก ์ ๋ฆฌ(์ปจํธ๋กค๋ฌ -130์ฌ ์ค). ์ดํHomeFacade๊ฐ์ ์กฐํฉ ์ ์ค์ผ์ด์ค์์ ๋์ผ ์๋น์ค๋ฅผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํด์ง.
๐ GitHub


