- 서비스 개요
- 주요 기능
- 데이터 베이스 설계(ERD)
- 시스템 아키텍처
- 유스케이스 다이어그램
- 시퀀스 다이어그램
- 기술 스택
- 주요 구성 요소 및 역할
- 프로젝트 디렉토리 구조
- 환경 변수 관리 전략
- 실행 방법 (Getting Started)
- 배포 방법 (Deployment)
- 시연 영상
최근 커머스 업계의 AI 기반 콘텐츠 자동화 트렌드에도 불구하고, 여전히 트렌드 분석, 상품 조사, 콘텐츠 생성 및 발행 등 각 단계에서 시간 소모적인 수작업이 필요합니다.
본 프로젝트는 이러한 비효율을 해결하기 위해, 특정 도메인에 국한되지 않고 다양한 비즈니스 프로세스를 자동화할 수 있는 확장 가능한 워크플로우 플랫폼을 구축하는 것을 목표로 합니다. 초기 MVP 모델로 RAG(검색 증강 생성) 기반 블로그 콘텐츠 자동 생성 및 발행하는 마케팅 워크플로우를 구현했습니다.
- 워크플로우 자동화:
Workflow → Job → Task의 계층적 구조에 따라 복잡한 프로세스를 순차적으로 자동 실행합니다.- 대표 워크플로우: 블로그 콘텐츠 자동 생성 및 발행
- 네이버 데이터 랩 트렌드 분석 → 싸다구몰 상품 정보 수집 → RAG 기반 AI 콘텐츠 생성 → 블로그 자동 발행
- 대표 워크플로우: 블로그 콘텐츠 자동 생성 및 발행
- 동적 스케줄링: API를 통해 재배포 없이 스케줄을 실시간으로 생성, 수정, 삭제할 수 있습니다.
- 데이터 파이프라이닝: 이전 Task의 실행 결과(Output)를 다음 Task의 입력(Input)으로 동적으로 전달합니다.
- 관리 및 모니터링: 관리자 대시보드에서 워크플로우 실행 이력 및 결과를 실시간으로 모니터링하고, Grafana를 통해 서버 리소스를 시각적으로 확인합니다.
서비스의 모든 데이터를 관리하고 워크플로우의 실행 상태를 추적하기 위해, 역할과 책임에 따라 정규화된 데이터베이스 스키마를 설계했습니다.
- ERD 다이어그램: ERDCloud 바로가기
데이터베이스는 크게 '워크플로우 정의', '실행 이력', '사용자 및 조직' 세 가지 핵심 영역으로 구성됩니다.
- 워크플로우 정의 계층:
WORKFLOW,JOB,TASK및 관계 테이블(WORKFLOW_JOB,JOB_TASK) - 실행 이력 계층:
WORKFLOW_RUN,JOB_RUN,TASK_RUN,TASK_IO_DATA,EXECUTION_LOG - 사용자 및 권한 계층:
USER,ORGANIZATION,ROLE,PERMISSION
워크플로우의 유연성과 재사용성을 극대화하기 위해, TASK와 WORKFLOW 테이블의 설정 관련 컬럼에 JSON 데이터 타입을 적극적으로 활용했습니다.
-
TASK테이블의parameters컬럼:- 역할: Task의 '정적 설계도(Blueprint)' 역할을 합니다.
- 내용: 해당 Task를 실행하기 위해 필요한 고정 정보(예:
endpoint,method)와, Request Body의 구조 및 각 필드의 데이터 타입을 JSON 형태로 정의합니다. - 예시:
{"endpoint": "/keywords/search", "method": "POST", "body": {"tag": "String"}}
-
WORKFLOW테이블의default_config컬럼:- 역할: 워크플로우가 실행될 때 각 Task에 주입될 '동적 설정값(Dynamic Configuration)' 역할을 합니다.
- 내용: JSON 객체 형태로,
key는task_id,value는 해당 Task에만 적용될 설정값을 가집니다. 이 값은TASK의parameters에 정의된 구조를 덮어쓰거나(override) 보완합니다. - 예시:
{"1": {"tag": "google_trends"}, "2": {"some_param": 123}}
-
JSON 타입 채택 이유 (유연성 및 재사용성):
- 스키마 변경 없는 확장: 만약 새로운 Task에
timeout이라는 파라미터가 추가되더라도, DB 스키마를 변경(ALTER TABLE)할 필요 없이parametersJSON의 내용만 수정하면 됩니다. 이는 잦은 변경과 확장이 예상되는 플랫폼에서 변경에 대한 유연성을 극대화합니다. - Task의 재사용성 증대:
TASK는 순수한 '템플릿'으로 존재하고, 실제 동작에 필요한 구체적인 값은WORKFLOW의default_config를 통해 주입됩니다. 이 덕분에 동일한 '키워드 검색 태스크'를 A 워크플로우에서는naver로, B 워크플로우에서는google_trends로 재배포 없이 다르게 동작시킬 수 있어 Task의 재사용성이 크게 향상됩니다. - 구조적 데이터 저장: 단순
TEXT타입과 달리, Key-Value 형태의 구조적인 데이터를 저장할 수 있어 애플리케이션에서 데이터를 파싱하고 사용하기 용이합니다.
- 스키마 변경 없는 확장: 만약 새로운 Task에
- 네이밍 컨벤션: 일관성을 위해 테이블 이름은 단수형(
user,workflow)으로, PK는[table_name]_id형식(workflow_id)으로 통일했습니다. - 외래 키(FK) 제약 조건 미설정: 물리적인 FK 제약 대신 애플리케이션 레이어에서 참조 무결성을 보장하여, 데이터 마이그레이션과 배포 유연성을 확보했습니다.
- 인조키(Surrogate Key) 사용: 다대다 관계의 중간 테이블에도 독립적인 인조키를 PK로 사용하여 JOIN 성능을 향상시키고 유지보수성을 높였습니다.
역할과 책임을 명확히 분리하기 위해 Spring Boot가 Orchestrator, FastAPI가 AI Worker 역할을 수행하는 이중 레이어 아키텍처를 채택했습니다.
- Spring Boot (Orchestrator):
Workflow → Job → Task구조를 기반으로 전체 비즈니스 흐름을 제어합니다. 스케줄링(Quartz), 상태 관리, 데이터 영속성, 인증/인가 등 핵심 로직 담당. - FastAPI (Worker): 키워드 추출, 상품 검색, 웹 크롤링, AI 연동(RAG), OCR 등 Python 생태계 특화 작업을 담당.
시스템의 주요 액터는 관리자(Admin) 와 스케줄러(Scheduler) 입니다. 관리자는 워크플로우와 스케줄을 관리하고 수동 실행이 가능하며, 스케줄러는 자동 실행을 담당합니다.
- 트리거: Quartz 스케줄러 또는 사용자의
POST /v0/workflows/{id}/run요청으로 워크플로우 실행 시작 - 비동기 실행:
WorkflowController가WorkflowExecutionService를@Async로 호출하고 즉시202 Accepted응답 - 오케스트레이션:
WorkflowExecutionService가 Job, Task 순차 실행 및TaskExecutionService에 재시도 위임 - 외부 API 호출:
FastApiTaskRunner와FastApiAdapter를 통해 FastAPI와 통신 - 결과 기록: 모든 실행 결과는 DB에 기록되며, 실패 시에도 다음 작업은 계속 진행
GitHub Actions 기반으로 빌드 → 테스트 → Docker 빌드 및 푸시 → EC2 배포까지 자동화되어 있습니다.
- Language & Framework: Java 21, Spring Boot 3.5.4
- Data Access: MyBatis 3.0.5, MariaDB Java Client 3.3.3
- Scheduling: Spring Quartz
- Resilience: Spring Retry
- Security: Spring Security
- Build Tool: Gradle
- Language & Framework: Python 3.11, FastAPI 0.116.2
- AI & ML: Transformers, Scikit-learn, OpenAI API
- Web Scraping & OCR: BeautifulSoup4, Selenium, Google Cloud Vision
- DB & Translation: SQLAlchemy, Deep-Translator
- Package Manager: Poetry
- MariaDB 11.4
- Containerization: Docker, Docker Compose
- CI/CD: GitHub Actions
- Monitoring: Prometheus, Grafana
- Migration: Flyway
- Logging: Log4j2
- WorkflowExecutionService: 워크플로우 전체 실행 흐름 제어
- TaskExecutionService: Task 실행 및 재시도 정책 관리
- TaskBodyBuilder (전략 패턴): 각 Task별 동적 Request Body 생성
- WorkflowContextService (퍼사드 패턴): 각 TaskBodyBuilder가 이전 Task의 결과를 조회할 때 필요한 복잡한 DB 접근 로직(TaskIoDataMapper 사용 등)을 캡슐화하고, 단순화된 인터페이스를 제공하는 퍼사드(Facade) 역할
- FastApiAdapter: FastAPI 서버 통신 캡슐화
- QuartzSchedulerInitializer: DB 스케줄 정보 Quartz 엔진 동기화
- ExecutionMdcManager: 비동기 환경에서도 traceId 기반 분산 추적 로깅
Monorepo 형태로, apps 하위에 서비스별 디렉토리가 존재합니다.
FlowWeaver/backend/
├── apps/
│ ├── user-service/ # Java/Spring Boot 서비스
│ └── pre-processing-service/# Python/FastAPI 서비스
├── docker/ # Docker 설정
├── .github/ # GitHub Actions (CI/CD)
└── logs/ # 로그 파일도메인 중심 아키텍처 적용. 각 도메인이 자체 구성요소를 포함.
user-service/
├── src/main/java/site/icebang/
│ ├── domain/ # 도메인 로직
│ ├── external/ # 외부 API 연동
│ ├── global/ # 글로벌 설정
│ └── common/ # 공용 유틸리티
└── Dockerfilepre-processing-service/
├── app/
│ ├── api/ # 엔드포인트
│ ├── service/ # 비즈니스 로직
│ ├── core/ # 핵심 설정
│ ├── db/ # DB 관련
│ └── utils/ # 유틸리티
└── pyproject.toml각 서비스는 환경별 설정 관리를 위해 다음과 같은 전략을 사용합니다.
.env 파일을 통해 환경 변수를 로드합니다. apps/pre-processing-service/app/core/config.py의 BaseSettings를 기반으로 동작합니다.
-
필수 변수:
-
DB_HOST,DB_PORT,DB_USER,DB_PASS,DB_NAME: MariaDB 연결 정보 -
LOKI_HOST,LOKI_PORT: Loki 로깅 서버 정보 -
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,S3_BUCKET_NAME: AWS S3 저장소 설정 (OCR 및 이미지 업로드)
-
-
선택 변수:
-
OPENAI_API_KEY: AI 콘텐츠 생성 기능 사용 시 필요 -
MODE:dev또는prd(기본값:dev)
-
Spring Profiles(develop, production)를 사용하여 환경을 분리합니다.
-
Local (Develop):
application-develop.yml을 사용하며, 로컬 Docker 인프라(localhost)에 맞춰져 있습니다. -
Production:
application-production.yml을 사용하며, 민감한 정보(DB 비밀번호, API 키 등)는 배포 시점의 환경 변수 또는 Docker Compose의 environment 설정을 통해 주입받습니다.
로컬 개발 환경에서 프로젝트를 실행하는 방법입니다.
-
Java 21 (Amazon Corretto 21 권장)
-
Python 3.11 (Poetry 패키지 매니저 설치 필요)
-
Docker & Docker Compose
프로젝트 실행에 필요한 DB(MariaDB)와 모니터링 도구(Loki, Promtail, Grafana)를 Docker로 실행합니다.
cd docker/local
docker-compose up -d
Python 기반의 AI/전처리 워커 서비스를 실행합니다.
cd apps/pre-processing-service
# 1. 의존성 설치
poetry install
# 2. 서비스 실행 (Uvicorn)
poetry run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
Java 기반의 메인 오케스트레이터 서비스를 실행합니다.
cd apps/user-service
# develop 프로파일로 실행
./gradlew bootRun --args='--spring.profiles.active=develop'
-
API 문서 (Swagger):
-
Spring Boot:
http://localhost:8081/swagger-ui/index.html(설정 필요 시) -
FastAPI:
http://localhost:8000/docs
-
본 프로젝트는 GitHub Actions를 통해 CI/CD 파이프라인이 구축되어 있습니다.
-
CI (Continuous Integration):
main브랜치에 Push 또는 PR 시 자동으로 Java/Python 테스트 및 빌드가 수행됩니다.
-
CD (Continuous Deployment):
-
릴리즈 태그 생성 시 Docker Image를 빌드하여 Docker Hub에 Push 합니다.
-
AWS EC2 인스턴스에 SSH로 접속하여 최신 이미지를 Pull 하고
docker-compose를 재실행합니다.
-
프로덕션 환경의 Docker 설정은 docker/production 디렉토리에 위치합니다.
cd docker/production
docker-compose up -d



.png)
.png)




