μκΈ λ‘κ·Έμμμ λ§μμ£Όλ λλ§μ λΉλ° κΈκ³
- κ°λ° κΈ°κ° : 2026.02.16 ~ 2026.03.30 (6μ£Ό)
- νλ«νΌ : Mobile App (Android / iOS)
- κ°λ° μΈμ : 6λͺ
- κΈ°κ΄ : μΌμ± μ²λ SW μμΉ΄λ°λ―Έ 14κΈ° (νν ν¬ νλ‘μ νΈ)
**λλμ₯(Donttaz)**λ μ¬λ°λ₯Έ μλΉμ΅κ΄μ νμ±νκ³ μΆμ μ¬λλ€μ μν AI κΈ°λ° μ€λ§νΈ κΈκ³ νν ν¬ μλΉμ€μ λλ€.
λ¨μν λμ "μλΌκ²" νλ κ²μ΄ μλλΌ, μΈ λμ μ°λ©΄μ λͺ¨μ λμ 체κ³μ μΌλ‘ λͺ¨μ μ μλλ‘ λμμ€λλ€. μ¬μ©μλ λͺ©μ λ³ κ°μ κΈκ³ (μμ)λ₯Ό μμ λ‘κ² μμ±νκ³ , κΈμ΅λ§ APIλ₯Ό ν΅ν΄ μμ νκ² μκΈμ μ μΆκΈνλ©°, AIκ° μλΉ ν¨ν΄μ λΆμνμ¬ λ§μΆ€ν κΈμ΅ μ‘°μΈμ μ 곡ν©λλ€.
π‘ μνμ 'μΈμ΄νλ°μ€' + ν μ€ 'μ κΈν΅' + AI μ½λ©νΈ + AI κΈ°λ° μλΉ νλμ νλλ‘ ν©μΉ μ°¨μΈλ μ μΆ νλ«νΌ
2030 μΈλμ 78% κ° "μκΈλ ν΅μ₯μ μ€μ³κ°λ λ"μ μ€νΈλ μ€λ₯Ό λλλ€κ³ λ΅ν©λλ€. κ³ μ μ§μΆ, ꡬλ μλΉμ€, μΆ©λ μλΉκ° κ²ΉμΉλ©΄μ μκΈμ΄ λ€μ΄μ€μλ§μ μ¬λΌμ§λ 'μκΈ λ‘κ·Έμμ' νμμ΄ μΌμμ΄ λμμ΅λλ€.
κΈ°μ‘΄ μ μΆ μ±μ λ¨μν "μ°μ§ λ§λΌ"λ λ©μμ§λ₯Ό μ λ¬νμ§λ§, μ΄λ μ€μ§μ μΈ νλ λ³νλ₯Ό μ λνμ§ λͺ»ν©λλ€.
λλμ₯λ μ¬μ©μμ μλΉλ₯Ό μ΅μ νλ κ²μ΄ μλλΌ, μλΉμ μ μΆμ λ³λ ¬λ‘ κ΄λ¦¬νλ ꡬ쑰λ₯Ό μ μν©λλ€.
| κΈ°μ‘΄ μ μΆ μ± | λλμ₯ |
|---|---|
| "μ΄λ² λ¬ μΉ΄ν μ§μΆμ΄ μ΄κ³Όνμ΅λλ€" | "μ€μ¬μΉ΄ μ¬ν κΈκ³ μ 5λ§μ μΆκ°νλ©΄ λͺ©νμ 80%!" |
| λ¨μΌ μ μΆ λͺ©ν | λͺ©μ λ³ κΈκ³ μμ± |
| μ¬ν μλ¦Ό | AI μ μ λΆμ + μ€μκ° νΈμ |
| μλ μ΄μ²΄ | AI κΈ°λ° μμ¬ κΈμ‘ μλ λ΄μΈ |
![]() |
![]() |
|---|---|
| κ°μ€ κ³Όμ 1 | κ°μ€ κ³Όμ 2 |
![]() |
![]() |
|---|---|
| μμ리μ€νΈ κΈκ³ μ‘°ν | κΈκ³ μμ± |
![]() |
![]() |
| κΈκ³ μ κΈ (λͺ¨κ³μ’ μ΄μ²΄) | κΈκ³ μΆκΈ (μ΄μ ν¬ν¨) |
![]() |
![]() |
|---|---|
| AI μλΉ λΆμ 리ν¬νΈ | AI μ μΆ νλ μΆμ² |
![]() |
![]() |
![]() |
|---|---|---|
| μ€μκ° νΈμ μλ¦Ό (FCM) | μμ κΈκ³ κΈ΄κΈ μΆκΈ μ μΉν μ μ‘ (Discord) | μμ κΈκ³ κΈ΄κΈ ν΄μ§ μ μΉν μ μ‘ (Mattermost) |
| Category | Stack |
|---|---|
| Language | TypeScript 5.9.2 |
| Framework | React Native 0.81.5, Expo 54.0.33 |
| State Management | Zustand 5.0.12 |
| Architecture | FSD (Feature-Sliced Design) |
| Library | Axios 1.13.6, Expo Router 6.0, PortOne SDK 0.6.0, React Native Reanimated 4.1 |
| IDE | Visual Studio Code |
| Category | Stack |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.5.11 |
| Library | Spring Security 6.x, Spring Data JPA 3.x, Spring AMQP 3.x, springdoc-openapi 2.8.8 |
| Database | MySQL 8.0 |
| Cache | Redis 7 (Alpine) |
| Message Broker | RabbitMQ 3 (Management Alpine) |
| Push | Firebase Admin SDK 9.4.3 (FCM) |
| Build Tool | Gradle 8.x |
| IDE | IntelliJ IDEA |
| Category | Stack |
|---|---|
| Language | Python 3.10+ |
| Framework | FastAPI 0.110.0 |
| Runtime | Uvicorn 0.27.1 |
| Library | OpenAI API, NeuralForecast, Sentence-Transformers, Pandas, NumPy |
| IDE | Visual Studio Code |
| Category | Spec |
|---|---|
| Container | Docker 27.x, Docker Compose 2.x |
| CI/CD | Jenkins LTS (Blue-Green 무μ€λ¨ λ°°ν¬) |
| Web Server | Nginx 1.27 (Reverse Proxy, SSL) |
| Monitoring | Prometheus (latest), Grafana (latest) |
| μ€κ³ μμ | ꡬν λ°©μ | ν¨κ³Ό |
|---|---|---|
| κΈκ³ (Vault) κ΄λ¦¬ | λͺ¨κ³μ’(Master Account) + DB λ Όλ¦¬ λΆλ¦¬ | 무μ ν κΈκ³ μμ±, 20μΌ κ³μ’ κ·μ ννΌ |
| AI / API μλ² λΆλ¦¬ | FastAPI AI μλ²λ₯Ό Spring Boot API μλ²μ λ 립 컨ν μ΄λλ‘ λΆλ¦¬ | AI λͺ¨λΈ μ λ°μ΄νΈ μ API 무μ€λ¨, κ°λ³ μ€μΌμΌλ§ κ°λ₯ |
| λΉλκΈ° μλ¦Ό | RabbitMQ μ΄λ²€νΈ κΈ°λ° μ²λ¦¬ | μΈλΆ API λ μ΄ν΄μλ‘λΆν° μ μ μλ΅ κ²©λ¦¬ |
| 무μ€λ¨ λ°°ν¬ | Jenkins Blue-Green Deploy | μλΉμ€ λ€μ΄νμ μ λ‘ |
| νλ‘ νΈμλ | FSD (Feature-Sliced Design) μν€ν μ² | λλ©μΈ κΈ°λ° λͺ¨λ λΆλ¦¬, νμ₯μ± ν보 |
μμΈν
| λ¨κ³ | μ€ν μ΄μ§λͺ | μ€λͺ |
|---|---|---|
| β | Checkout SCM | GitLabμμ develop λΈλμΉ μμ€ μ½λ 체ν¬μμ |
| β‘ | Prepare Backend | Jenkins Credentialμμ firebase-service-account.json λ° .env 23κ° νκ²½λ³μ μ£Όμ
|
| β’ | Test Backend (CT) | ./gradlew clean test β 6κ° νμ€ν¬ λ¨μ ν
μ€νΈ μ€ν (BUILD SUCCESSFUL) |
| β£-1 | Docker Image Build | docker compose up -d --build β API(Spring Boot) + AI(FastAPI) μ΄λ―Έμ§ λΉλ λ° μ»¨ν
μ΄λ μ€ν |
| β£-2 | Health Check Polling | /actuator/health, /health μλν¬μΈνΈλ₯Ό μ΅λ 40ν(3μ΄ κ°κ²©) ν΄λ§νμ¬ κΈ°λ νμΈ |
| β£-3 | Nginx Switching | Nginx service-env.inc BlueβGreen μ€μμΉ β nginx -s reload β μ΄μ νκ²½ 컨ν
μ΄λ μ’
λ£ |
| β€ | Clean up Image | docker image prune -f β λκΈλ§ μ΄λ―Έμ§ μμ |
| β₯ | Post Actions | .env / Firebase ν€ μ¦μ μμ (보μ) β Mattermost λ°°ν¬ μ±κ³΅ μλ¦Ό μ μ‘ |
- Java 17+ / Node.js v24.12.0 (LTS) / Python 3.10+ / Docker & Docker Compose
git clone https://lab.ssafy.com/s14-fintech-finance-sub1/S14P21C104.git
cd S14P21C104cd donttaz-infra
docker network create donttaz-net # μ΅μ΄ 1ν
docker compose up -dcd donttaz-BE/api
cp ../.env.example ../.env # νκ²½ λ³μ μ€μ (μλ ν μ°Έκ³ )
./gradlew clean build
./gradlew bootRunπ Swagger:
http://localhost:8080/swagger-ui/index.html
cd donttaz-BE/ai
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --host 0.0.0.0 --port 8000 --reloadcd donttaz-APP/front
npm install && npm startπ± Expo Go μ±μμ QR μ½λλ₯Ό μ€μΊνμ¬ λλ°μ΄μ€μμ μ€ν
| λ³μλͺ | μ€λͺ |
|---|---|
DB_URL |
MySQL μ μ URL |
DB_USERNAME / DB_PASSWORD |
DB μ¬μ©μ μΈμ¦ |
REDIS_HOST / REDIS_PORT |
Redis μ μ μ 보 |
RABBITMQ_HOST / RABBITMQ_PORT |
RabbitMQ μ μ μ 보 |
KAKAO_CLIENT_ID / KAKAO_CLIENT_SECRET |
μΉ΄μΉ΄μ€ OAuth ν€ |
FIN_API_BASE_URL / FIN_API_API_KEY |
κΈμ΅λ§ API |
AI_SERVER_URL / GMS_KEY |
AI μλ² λ° LLM API |
DISCORD_WEBHOOK_URL / MATTERMOST_WEBHOOK_URL |
μλ¦Ό μΉν |
β οΈ .envνμΌμ.gitignoreμ ν¬ν¨λμ΄ Gitμ 컀λ°λμ§ μμ΅λλ€.
π¦ Backend (Spring Boot API)
donttaz-BE/api/src/main/java/com/donttaz/donttazapi/
βββ π account/ # κ³μ’ κ΄λ¦¬
βββ π ai/ # AI μλΉμ€ μ°λ (Proxy)
βββ π auth/ # μΈμ¦ (Kakao OAuth + JWT)
βββ π common/ # κ³΅ν΅ μ€μ (Security, Swagger, AOP)
βββ π company/ # νμ¬(κΈμ¬) κ΄λ¦¬
βββ π notification/ # FCM νΈμ μλ¦Ό
βββ π payment/ # κ²°μ /κ±°λ λ΄μ
βββ π user/ # μ¬μ©μ κ΄λ¦¬
βββ π vault/ # π° κΈκ³ (ν΅μ¬ λλ©μΈ)
βββ π webhook/ # λΉλκΈ° μΉν
(RabbitMQ)
π€ AI Server (FastAPI)
donttaz-BE/ai/
βββ main.py # FastAPI μ§μ
μ
βββ π app/api/
β βββ report.py # AI μλΉ λΆμ 리ν¬νΈ
β βββ plan.py # AI μ μΆ νλ μΆμ²
β βββ category.py # μλΉ μΉ΄ν
κ³ λ¦¬ μλ λΆλ₯
β βββ burndown.py # λ²λ€μ΄ μ°¨νΈ μμΈ‘
βββ requirements.txt
βββ Dockerfile
π± Frontend (React Native / Expo)
donttaz-APP/front/
βββ π app/ # Expo Router (νμΌ κΈ°λ° λΌμ°ν
)
β βββ _layout.tsx # μ± μ 체 λ μ΄μμ
β βββ index.tsx # μ€νλμ
β βββ (tabs)/ # ν λ€λΉκ²μ΄μ
βββ π pages/ # νλ©΄ λ¨μ μ»΄ν¬λνΈ
βββ π widgets/ # μ¬μ¬μ© μμ ― (λμ보λ μΉ΄λ λ±)
βββ π features/ # κΈ°λ₯ λ¨μ (λ‘κ·ΈμΈ, μ΄μ²΄ λ±)
βββ π entities/ # λλ©μΈ λͺ¨λΈ (κ³μ’, κΈκ³ , μ μ )
βββ π shared/ # κ³΅ν΅ μ νΈ, UI, API Client
βββ package.json
π Infrastructure (Docker Compose)
donttaz-infra/
βββ docker-compose.yml # MySQL, Redis, RabbitMQ, Prometheus, Grafana, Nginx
βββ π nginx/ # Nginx μ μ μ€μ
βββ π prometheus/ # λ©νΈλ¦ μμ§ μ€μ
βββ π grafana/ # λμ보λ νλ‘λΉμ λ
RabbitMQ λΉλκΈ° μ ν μ λ©μμ§ μ μ€ λ¬Έμ
- λ¬Έμ : μΈλΆ μΉν (Discord/Mattermost) μλ¦Όμ RabbitMQ λΉλκΈ°λ‘ μ ννμ λ, Consumer μ₯μ μ λ©μμ§κ° μ μ€λλ νμ
- μμΈ: Auto-Acknowledge μ€μ μΌλ‘ μΈν΄ Consumerκ° λ©μμ§λ₯Ό λ°λ μ¦μ νμμ μμ λ¨
- ν΄κ²°: Manual Acknowledge + μ§μ λ°±μ€ν(Exponential Backoff) μ¬μλ μ μ± μ μ©. 3ν μ€ν¨ μ DLQ(Dead Letter Queue)λ‘ μ΄λνμ¬ λ©μμ§ μ μ€ λ°©μ§
λͺ¨κ³μ’ λμμ± μ΄μ (κΈκ³ μ μΆκΈ)
- λ¬Έμ : λ€μ μ¬μ©μκ° λμμ κΈκ³ μ μΆκΈ μμ² μ, λͺ¨κ³μ’ μμ‘μ Race Condition λ°μ
- μμΈ: DB λ 벨μ νΈλμμ 격리 μμ€λ§μΌλ‘λ λΆμ° νκ²½μμ λμμ± λ³΄μ₯ λΆκ°
- ν΄κ²°: Redis κΈ°λ° λΆμ° λ½(Distributed Lock) μ μ©μΌλ‘ λͺ¨κ³μ’ μ κ·Όμ μ§λ ¬ννμ¬ λ°μ΄ν° μ ν©μ± ν보
Blue-Green λ°°ν¬ μ Health Check νμ΄λ° μ΄μ
- λ¬Έμ : μ μΈμ€ν΄μ€ κΈ°λ μ Spring Boot μ΄κΈ°ν μλ£ μ Nginxκ° νΈλν½μ μ λ¬νμ¬ 502 μλ¬ λ°μ
- μμΈ: deploy.sh μ€ν¬λ¦½νΈμμ Health Check κ°κ²©μ΄ λ무 μ§§μ JVM Warm-up μ΄μ μ νΈλν½ μ€μμΉ
- ν΄κ²°: Spring Actuator
/healthμλν¬μΈνΈλ₯Ό ν΄λ§νλ λ°©μμΌλ‘ λ³κ²½. μ΅λ 30μ΄ λκΈ° + 3ν μ°μ μ±κ³΅ 쑰건μΌλ‘ μμ μ μ€μμΉ κ΅¬ν
μ΄ νλ‘μ νΈλ SSAFY(μΌμ± μ²λ SW μμΉ΄λ°λ―Έ) κ΅μ‘ κ³Όμ μ μΌνμΌλ‘ μ μλμμ΅λλ€.
Made with β€οΈ by Team Donttaz (C104)





































