본문 바로가기
And - 실시간 조건 감지·자동매매 시스템

[신투 프디아] 파이널 프로젝트 - 백엔드 패키지 설계 의도(with. DDD)

by SoU330 2025. 9. 26.

 

 

 

 

 

이 글은 알파코에서 진행되는 [신한투자증권] 프로디지털아카데미 과정 중, 김송아 강사님과 함께하는 '파이널 프로젝트'를 기반으로 작성되었습니다

 

 

 

💭 회고 – 백엔드 패키지 DDD 설계

이번 프로젝트에서는 백엔드 아키텍처 설계를 맡으며 DDD(Domain-Driven Design) 방식으로 설계했다.

처음에는 익숙한 controller/service/repository 형태로만 나눠도 된다고 생각했지만 알림/유저/데이터 수집 등 도메인이 다양하게 얽히면서 책임 구분이 필요하다고 느꼈다.

 

 

모듈 단위 설계

우리는 처음부터 MSA를 염두에 두고, 서비스의 성격에 맞게 모듈을 나눴다.

Sprint Boot
 ├─ alert-module
 ├─ data-process-module
 ├─ trade-module
 └─ user-module

FastAPI
 └─ data-collect-module

 

 

 

 

패키지 단위 세분화

모듈을 정한 뒤에는 모듈 내부를 다시 도메인 책임 단위로 나눴다.

 

alert-module

알림 모듈 내부에서도 조건 확인 -> 알림 발송 -> 관리 라는 흐름이 자연스럽게 이어지도록 했다.

evaluation에서 조건 충족 여부를 평가하고, notification에서 해당 조건이 충족되면 발송 로직을 담당하며, management에서 사용자가 알림을 CRUD 형태로 직접 관리할 수 있도록 했다.

com.example.alert
 ├─ evaluation/             # 조건 검색, 충족 여부 평가
 │   ├─ controller/         # 조건 검사 API (테스트/재평가 등)
 │   ├─ service/            # ConditionEvaluator, AlertEvaluationService
 │   ├─ repository/         # 조건 관련 DB/Redis 접근
 │   └─ model/              # Alert, Condition, EvaluationResult 등
 │
 ├─ notification/           # 알림 발송
 │   ├─ service/            # AlertNotificationService
 │   ├─ infrastructure/     # 외부 연동 (FCM, SMTP 등)
 │   └─ message/            # 발송 메시지 템플릿, ErrorCode
 │
 ├─ management/             # 알림 CRUD 및 사용자 관리
 │   ├─ controller/         # REST API (알림 등록/수정/삭제)
 │   ├─ service/            # AlertService
 │   ├─ repository/         # AlertRepository (JPA)
 │   ├─ dto/                # Request/Response DTO
 │   └─ validator/          # 조건 검증
 │
 └─ common/                 # 공통 모듈
     ├─ dto/                # 모듈 내부 공용 DTO
     └─ util/               # 유틸리티 클래스

 

data-process-module

데이터가 들어와서 -> 계산/가공되고 -> 저장/전달 되는 파이프라인 구조를 그대로 반영했다.

ingest에서 FastAPI가 수집한 데이터를 진입점으로 받아오고, transform에서 SMA, RSI, Bollinger Band 같은 지표 계산과 변환을 수행하며, persist에서 변환된 데이터를 DB·Redis에 저장해 안정적으로 보관한다.

com.example.dataprocess
 ├─ ingest/                 # 수집 데이터 진입점
 │   ├─ controller/         # FastAPI → Spring 진입 API
 │   ├─ service/            # IngestService (수집 데이터 파이프라인 시작)
 │   └─ dto/                # MarketDataRequest DTO
 │
 ├─ transform/              # 지표 계산/데이터 변환
 │   ├─ service/            # TransformService (SMA, RSI, Bollinger 등)
 │   ├─ model/              # Candle, Indicator, MarketSnapshot
 │   └─ util/               # CalculationUtil
 │
 ├─ persist/                # 저장 계층
 │   ├─ service/            # PersistService (DB/Redis 동기화)
 │   ├─ repository/         # JPA/Redis 접근
 │   └─ entity/             # DailyCandleEntity, MinuteCandleEntity
 │
 ├─ scheduler/              # 배치/스케줄러
 │   └─ DailyIndicatorScheduler
 │
 └─ messaging/              # MQ 이벤트
     └─ MarketDataConsumer

 

 

trade-module

조건 -> 실행 -> 관리 -> 기록까지 이어지는 매매 라이프사이클을 반영했다.

evaluation에서 매매 조건을 판별하고, execution에서 실제 증권사 API(키움, 한투 등)를 호출해 거래를 실행하며, management에서 사용자가 자동매매 규칙을 직접 관리하고, history에서 거래 결과와 히스토리를 남겨 추후 검증·리포트에 활용할 수 있도록 했다.

com.example.trade
 ├─ evaluation/             # 자동매매 조건 판별
 │   ├─ service/            # TradeEvaluationService
 │   ├─ repository/         # 조건 저장/조회
 │   └─ model/              # TradeCondition, EvaluationResult
 │
 ├─ execution/              # 매매 실행
 │   ├─ service/            # TradeExecutionService
 │   ├─ infrastructure/     # 증권사 API 연동 (ex. 키움, 한투)
 │   └─ message/            # 매매 요청/응답 포맷
 │
 ├─ management/             # 사용자 자동매매 관리
 │   ├─ controller/         # CRUD API
 │   ├─ service/            # TradeService
 │   ├─ repository/         # TradeRepository
 │   ├─ dto/                # Request/Response DTO
 │   └─ validator/          # 조건 검증
 │
 └─ history/                # 매매 히스토리 관리
     ├─ entity/             # TradeHistoryEntity
     └─ repository/         # TradeHistoryRepository

 

 

user-module

사용자 관련 기능을 보안 -> 자산 -> 기본 정보 순으로 나눠 체계화했다.

auth에서 로그인, 회원가입, 토큰 발급 등 보안을 다루고, account에서 투자 계좌 정보를 관리하며, profile에서 사용자 개인 정보를 다룬다.

com.example.user
 ├─ auth/                   # 인증/인가
 │   ├─ controller/         # 로그인/회원가입 API
 │   ├─ service/            # AuthService, TokenProvider
 │   ├─ dto/                # AuthRequest, AuthResponse
 │   └─ validator/          # 로그인/회원가입 유효성 검증
 │
 ├─ account/                # 계좌 관리
 │   ├─ controller/         # 계좌 등록/조회 API
 │   ├─ service/            # AccountService
 │   ├─ entity/             # AccountEntity
 │   ├─ repository/         # AccountRepository
 │   └─ dto/                # AccountRequest, AccountResponse
 │
 ├─ profile/                # 사용자 정보 관리
 │   ├─ controller/         # 프로필 API
 │   ├─ service/            # UserService
 │   ├─ entity/             # UserEntity
 │   ├─ repository/         # UserRepository
 │   └─ dto/                # UserDto
 │
 └─ common/                 # 공통
     ├─ message/            # 에러 코드, 응답 메시지
     └─ util/               # 암호화, 패스워드 해시

 

 

data-collect-module

FastAPI는 가볍고 빠른 데이터 수집을 목표로 최소한의 단위로 단순하게 구성했다.

api에서 증권사·OpenAI API 등 외부 데이터 소스를 호출하고, scheduler에서 분 단위·일 단위로 반복 작업을 실행하며, service에서 수집된 데이터를 1차 가공하고, publisher에서 MQ·HTTP를 통해 다른 모듈로 전달하며, model에서 데이터 구조(Candle, Snapshot 등)를 정의했다.

data_collect/
 ├─ api/                    # 외부 API 연동
 │   ├─ broker_api.py       # 증권사 API 호출
 │   └─ openai_api.py       # OpenAI API 호출
 │
 ├─ scheduler/              # 주기적 수집 (APScheduler 등)
 │   ├─ minute_task.py      # 1분 단위 수집
 │   └─ daily_task.py       # 1일 단위 수집
 │
 ├─ service/                # 수집된 데이터 가공
 │   ├─ collector_service.py
 │   └─ transform_service.py
 │
 ├─ publisher/              # 수집 데이터 전달 (HTTP, MQ)
 │   └─ data_publisher.py
 │
 └─ model/                  # DTO/데이터 클래스
     ├─ candle.py
     └─ snapshot.py

 

 

 

✨ 이번 설계에서 깨달은 점

DDD 구조를 적용하면서 각 도메인마다 독립적인 패키지 경계를 만들 수 있었고, 팀원들이 기능을 개발 할 때도 '이건 어디에 넣어야 하지?' 라는 혼란이 줄었다. 나중에 모듈을 마이크로서비스로 분리하더라도 자연스럽게 확장할 수 있는 기반이 되었다.

이게 완벽한 DDD는 아니겠지만, 이번 경험을 통해 패키지 구조가 단순한 폴더 나누기가 아니라 도메인의 언어와 경계를 코드에 반영하는 작업이라는 걸 체감할 수 있었다.