diff --git a/README.md b/README.md index e69de29b..5db14406 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,243 @@ +# 블로그 콘텐츠 자동화 플랫폼 + +### AI 기반 워크플로우 오케스트레이터를 활용한 RAG 기반 블로그 콘텐츠 자동화 시스템 + +----- + +### 목차 + +1. 서비스 개요 +2. 시스템 개요 +3. 시스템 아키텍처 +4. 유스케이스 다이어그램 +5. 시퀀스 다이어그램 +6. 기술 스택 +7. 주요 구성 요소 및 역할 +8. 프로젝트 디렉토리 구조 +9. 환경 변수 관리 전략 + +----- + +## 1\. 서비스 개요 + +최근 커머스 업계의 AI 기반 콘텐츠 자동화 트렌드에도 불구하고, 여전히 트렌드 분석, 상품 조사, 콘텐츠 생성 및 발행 등 각 단계에서 시간 소모적인 수작업이 필요합니다. 본 프로젝트는 이러한 비효율을 해결하기 위해, **RAG(검색 증강 생성)** 기술을 기반으로 블로그 콘텐츠 생성의 전 과정을 자동화하는 워크플로우 플랫폼을 구축하는 것을 목표로 합니다. + +----- + +## 2\. 시스템 개요 + +본 시스템은 `Spring Boot` 기반의 오케스트레이터와 `Python(FastAPI)` 기반의 AI 워커로 구성된 **이중 레이어 아키텍처**를 채택하여, 각 서비스의 역할을 명확히 분리했습니다. + +* **워크플로우 자동화**: 네이버 데이터 랩의 실시간 트렌드 키워드를 자동 수집하고, 싸다구몰(1688)에서 유사도 기반 검색을 통해 관련 상품을 매칭합니다. +* **AI 콘텐츠 생성**: 수집된 상품 정보와 이미지를 OCR 및 번역 기술로 분석한 후, RAG(검색 증강 생성) 기술을 통해 SEO에 최적화된 블로그 콘텐츠를 자동으로 생성합니다. +* **관리 및 모니터링**: 관리자 전용 대시보드에서 워크플로우의 실행, 스케줄 제어, 실행 이력 및 결과를 실시간으로 모니터링할 수 있습니다. 또한, Grafana를 통해 서버 리소스와 API 상태를 시각적으로 확인할 수 있습니다. + +----- + +## 3\. 시스템 아키텍처 + +역할과 책임을 명확히 분리하기 위해 `Spring Boot`가 Orchestrator, `FastAPI`가 Worker 역할을 수행하는 이중 레이어 아키텍처를 채택했습니다. + +* **Spring Boot (Orchestrator)**: `Workflow → Job → Task`의 계층적 구조를 기반으로 전체 비즈니스 흐름을 제어합니다. 스케줄링(`Quartz`), 상태 관리, 데이터 영속성, 사용자 인증/인가 등 핵심 로직을 담당합니다. +* **FastAPI (Worker)**: 키워드 추출, 상품 검색, 웹 크롤링, AI 연동(RAG), OCR 등 Python 생태계에 특화된 무거운 실제 작업을 API 형태로 제공합니다. + +![System Architecture](assets/시스템 아키텍처1.png) + +![System Architecture](assets/시스템 아키텍처2.png) + +----- + +## 4\. 유스케이스 다이어그램 + +시스템의 주요 액터는 \*\*관리자(Admin)\*\*와 \*\*스케줄러(Scheduler)\*\*입니다. 관리자는 워크플로우와 스케줄을 관리하고, 수동으로 워크플로우를 실행할 수 있습니다. 스케줄러는 정해진 시간에 워크플로우를 자동으로 실행합니다. + +![Usecase Diagram](assets/유스케이스 다이어그램.png) + +----- + +## 5\. 시퀀스 다이어그램 + +### 5.1. 워크플로우 실행 흐름 (스케줄/수동) + +1. **트리거**: `Quartz` 스케줄러 또는 사용자의 API 요청(`POST /v0/workflows/{id}/run`)으로 워크플로우 실행이 시작됩니다. +2. **비동기 실행**: `WorkflowController`는 `WorkflowExecutionService`를 \*\*비동기(`@Async`)\*\*로 호출하고, 즉시 `202 Accepted`를 응답하여 사용자 경험을 향상시킵니다. +3. **오케스트레이션**: `WorkflowExecutionService`가 `Job`과 `Task`를 순차적으로 실행하며, `TaskExecutionService`에 재시도 로직을 위임합니다. +4. **외부 API 호출**: `FastApiTaskRunner`와 `FastApiAdapter`를 거쳐 실제 FastAPI 서버와 통신합니다. +5. **결과 기록**: 모든 실행 결과는 DB에 기록되며, 실패 시에도 다음 작업은 계속 진행됩니다. + +#### 수동 실행 +![Sequence Diagram](assets/시퀀스 다이어그램(수동 실행).png) + +#### 스케줄 실행 +![Sequence Diagram](assets/시퀀스 다이어그램(스케줄 실행).png) + + +### 5.2. CI/CD 파이프라인 + +GitHub Actions를 사용하여 `main` 또는 `pre-processing` 브랜치에 Push 또는 PR이 발생했을 때 CI/CD 파이프라인이 자동으로 실행됩니다. 빌드, 테스트, Docker 이미지 빌드 및 푸시, EC2 배포까지의 과정이 자동화되어 있습니다. + +![Sequence Diagram](assets/CICD 시퀀스 다이어그램1.png) + +![Sequence Diagram](assets/CICD 시퀀스 다이어그램2.png) + +![Sequence Diagram](assets/CICD 시퀀스 다이어그램3.png) + +![Sequence Diagram](assets/CICD 시퀀스 다이어그램4.png) + +----- + +## 6\. 기술 스택 + +#### Backend (Orchestrator - `user-service`) + +* **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 + +#### Backend (Worker - `pre-processing-service`) + +* **Language & Framework**: Python 3.11, FastAPI 0.116.2 +* **Web Server**: Uvicorn, Gunicorn +* **AI & Machine Learning**: + * Transformers 4.56.2 + * Scikit-learn 1.7.2 + * OpenAI 1.109.1 +* **Web Scraping & Parsing**: BeautifulSoup4 4.13.5, Selenium 4.35.0 +* **Data Processing**: SQLAlchemy 2.0.43 +* **Translation**: Deep-Translator 1.11.4 +* **OCR**: Google Cloud Vision 3.10.2 +* **Package Manager**: Poetry + +#### Database + +* **Primary Database**: MariaDB 11.4 + +#### Frontend + +* **Framework**: React 18.0.0 + +#### DevOps & Monitoring + +* **Containerization**: Docker, Docker Compose +* **CI/CD**: GitHub Actions +* **Database Migration**: Flyway +* **Monitoring**: Spring Boot Actuator, Micrometer, Prometheus, Grafana +* **Logging**: Log4j2 + +----- + +## 7\. 주요 구성 요소 및 역할 + +* **`WorkflowExecutionService`**: 워크플로우의 전체 실행 흐름을 제어하는 메인 오케스트레이터. +* **`TaskExecutionService`**: 개별 Task 실행과 재시도 정책(`RetryTemplate`)을 전담하는 서비스. +* **`TaskBodyBuilder` (전략 패턴)**: 각 Task의 특성에 맞는 Request Body를 동적으로 생성하는 전략 구현체. +* **`FastApiAdapter`**: FastAPI 서버와의 모든 HTTP 통신을 캡슐화하는 어댑터. +* **`QuartzSchedulerInitializer`**: 애플리케이션 시작 시 DB의 스케줄 정보를 Quartz 엔진에 동기화. +* **`ExecutionMdcManager`**: MDC를 활용하여 비동기 환경에서도 실행 컨텍스트(`workflowRunId`, `traceId` 등) 기반의 분산 추적 로깅을 구현. + +----- + +## 8\. 프로젝트 디렉토리 구조 + +프로젝트는 Monorepo로 구성되어 있으며, `apps` 디렉토리 아래에 각 서비스가 독립적으로 위치합니다. + +```bash +Final-4team-icebang/ +├── apps/ +│ ├── user-service/ # Java/Spring Boot 서비스 +│ └── pre-processing-service/ # Python/FastAPI 서비스 +├── docker/ # Docker 설정 (docker-compose.yml) +├── .github/ # CI/CD 설정 (GitHub Actions) +└── logs/ # 로그 파일 +``` + +### 8.1. `user-service` (Spring Boot) + +도메인 중심 아키텍처를 채택하여, 각 비즈니스 기능(도메인)이 자신의 모든 구성요소를 포함하도록 설계했습니다. + +* **`domain`**: `user`, `workflow` 등 핵심 비즈니스 로직과 데이터를 캡슐화합니다. +* **`external`**: 외부 시스템(FastAPI)과의 통신을 추상화하는 '방화벽' 역할을 합니다. +* **`schedule`**: '언제(When)' 작업을 실행할지에 대한 책임을 전담합니다. +* **`global`**: `SecurityConfig`, `WebConfig`, 예외 처리 등 애플리케이션 전반에 적용되는 설정을 담당합니다. +* **`common`**: `ApiResponse`와 같이 여러 도메인에서 재사용 가능한 공용 유틸리티를 관리합니다. + + + +```bash +user-service/ +├── src/ +│ ├── main/ +│ │ ├── java/site/icebang/ +│ │ │ ├── UserServiceApplication.java +│ │ │ ├── common/ # 공통 기능 +│ │ │ ├── domain/ # 도메인별 기능 +│ │ │ │ ├── auth/ # 인증/인가 +│ │ │ │ ├── user/ # 사용자 관리 +│ │ │ │ ├── workflow/ # 워크플로우 관리 +│ │ │ │ ├── organization/ # 조직 관리 +│ │ │ │ ├── email/ # 이메일 서비스 +│ │ │ │ ├── schedule/ # 스케줄 관리 +│ │ │ │ └── log/ # 실행 로그 +│ │ │ ├── external/ # 외부 API 연동 +│ │ │ └── global/ # 글로벌 설정 +│ │ │ ├── aop/ # AOP (로깅) +│ │ │ ├── config/ # 설정 +│ │ │ ├── filter/ # 필터 +│ │ │ └── handler/ # 예외 핸들러 +│ │ └── resources/ +│ │ ├── application.yml +│ │ ├── application-dev.yml +│ │ └── application-prod.yml +├── build.gradle # Gradle 빌드 설정 +└── Dockerfile +``` + +### 8.2. `pre-processing-service` (FastAPI) + +* **`api`**: FastAPI의 엔드포인트와 라우터를 정의합니다. +* **`service`**: 실제 비즈니스 로직(크롤링, AI 연동 등)을 구현합니다. +* **`core`**: 데이터베이스 연결, 미들웨어 등 핵심 설정을 담당합니다. + + + +```bash +pre-processing-service/ +├── app/ +│ ├── main.py # FastAPI 진입점 +│ ├── api/ # API 레이어 +│ │ ├── router.py # 라우터 통합 +│ │ └── endpoints/ # API 엔드포인트 +│ ├── service/ # 비즈니스 로직 +│ │ ├── blog/ # 블로그 서비스 +│ │ ├── crawlers/ # 크롤러 +│ │ ├── ocr/ # OCR 서비스 +│ │ ├── crawl_service.py # 크롤링 서비스 +│ │ ├── keyword_service.py # 키워드 추출 +│ │ ├── search_service.py # 검색 서비스 +│ │ ├── match_service.py # 매칭 서비스 +│ │ ├── similarity_service.py # 유사도 분석 +│ │ ├── product_selection_service.py # 상품 선택 +│ │ └── s3_upload_service.py # S3 업로드 +│ ├── core/ # 핵심 설정 +│ ├── db/ # 데이터베이스 +│ ├── model/ # 데이터 모델 +│ ├── middleware/ # 미들웨어 +│ ├── errors/ # 예외 처리 +│ ├── utils/ # 유틸리티 +│ └── test/ # 테스트 코드 +├── pyproject.toml # Poetry 설정 +├── Dockerfile +└── .env # 환경 변수 +``` + +----- + +## 9\. 환경 변수 관리 전략 + +추후 작성 예정 + +* **FastAPI (`pre-processing-service`)**: +* **Spring Boot (`user-service`)**: \ No newline at end of file diff --git a/apps/user-service/src/main/java/site/icebang/common/dto/ApiResponse.java b/apps/user-service/src/main/java/site/icebang/common/dto/ApiResponseDto.java similarity index 81% rename from apps/user-service/src/main/java/site/icebang/common/dto/ApiResponse.java rename to apps/user-service/src/main/java/site/icebang/common/dto/ApiResponseDto.java index 8a986b4d..5b9c91d9 100644 --- a/apps/user-service/src/main/java/site/icebang/common/dto/ApiResponse.java +++ b/apps/user-service/src/main/java/site/icebang/common/dto/ApiResponseDto.java @@ -30,7 +30,7 @@ * @see lombok.Data */ @Data -public class ApiResponse { +public class ApiResponseDto { /** * 요청 처리 성공 여부. * @@ -60,7 +60,7 @@ public class ApiResponse { private HttpStatus status; // HttpStatus로 변경 /** 기본 생성자입니다. 모든 필드가 기본값으로 초기화됩니다. */ - public ApiResponse() {} + public ApiResponseDto() {} /** * 모든 필드를 초기화하는 생성자. @@ -70,7 +70,7 @@ public ApiResponse() {} * @param message 응답 메시지 * @param status HTTP 상태 코드 */ - public ApiResponse(boolean success, T data, String message, HttpStatus status) { + public ApiResponseDto(boolean success, T data, String message, HttpStatus status) { this.success = success; this.data = data; this.message = message; @@ -84,8 +84,8 @@ public ApiResponse(boolean success, T data, String message, HttpStatus status) { * @param 데이터 타입 * @return 성공 응답 객체 */ - public static ApiResponse success(T data) { - return new ApiResponse<>(true, data, "OK", HttpStatus.OK); + public static ApiResponseDto success(T data) { + return new ApiResponseDto<>(true, data, "OK", HttpStatus.OK); } /** @@ -96,8 +96,8 @@ public static ApiResponse success(T data) { * @param 데이터 타입 * @return 성공 응답 객체 */ - public static ApiResponse success(T data, String message) { - return new ApiResponse<>(true, data, message, HttpStatus.OK); + public static ApiResponseDto success(T data, String message) { + return new ApiResponseDto<>(true, data, message, HttpStatus.OK); } /** @@ -109,8 +109,8 @@ public static ApiResponse success(T data, String message) { * @param 데이터 타입 * @return 성공 응답 객체 */ - public static ApiResponse success(T data, String message, HttpStatus status) { - return new ApiResponse<>(true, data, message, status); + public static ApiResponseDto success(T data, String message, HttpStatus status) { + return new ApiResponseDto<>(true, data, message, status); } /** @@ -121,7 +121,7 @@ public static ApiResponse success(T data, String message, HttpStatus stat * @param 데이터 타입 * @return 오류 응답 객체 */ - public static ApiResponse error(String message, HttpStatus status) { - return new ApiResponse<>(false, null, message, status); + public static ApiResponseDto error(String message, HttpStatus status) { + return new ApiResponseDto<>(false, null, message, status); } } diff --git a/apps/user-service/src/main/java/site/icebang/common/dto/PageParams.java b/apps/user-service/src/main/java/site/icebang/common/dto/PageParamsDto.java similarity index 98% rename from apps/user-service/src/main/java/site/icebang/common/dto/PageParams.java rename to apps/user-service/src/main/java/site/icebang/common/dto/PageParamsDto.java index 6083bc43..7a53edfc 100644 --- a/apps/user-service/src/main/java/site/icebang/common/dto/PageParams.java +++ b/apps/user-service/src/main/java/site/icebang/common/dto/PageParamsDto.java @@ -25,7 +25,7 @@ * @see lombok.Data */ @Data -public class PageParams { +public class PageParamsDto { /** * 현재 페이지 번호 (1부터 시작). * diff --git a/apps/user-service/src/main/java/site/icebang/common/dto/PageResult.java b/apps/user-service/src/main/java/site/icebang/common/dto/PageResultDto.java similarity index 77% rename from apps/user-service/src/main/java/site/icebang/common/dto/PageResult.java rename to apps/user-service/src/main/java/site/icebang/common/dto/PageResultDto.java index 0982be0a..c3714ede 100644 --- a/apps/user-service/src/main/java/site/icebang/common/dto/PageResult.java +++ b/apps/user-service/src/main/java/site/icebang/common/dto/PageResultDto.java @@ -36,7 +36,7 @@ */ @Data @NoArgsConstructor -public class PageResult { +public class PageResultDto { /** 현재 페이지에 포함된 데이터 목록. */ private List data; @@ -67,7 +67,7 @@ public class PageResult { * @param current 현재 페이지 번호 * @param pageSize 페이지 크기 */ - public PageResult(List data, int total, int current, int pageSize) { + public PageResultDto(List data, int total, int current, int pageSize) { this.data = data; this.total = total; this.current = current; @@ -96,8 +96,8 @@ private void calculatePagination() { * @param 데이터 타입 * @return PageResult 객체 */ - public static PageResult of(List data, int total, int current, int pageSize) { - return new PageResult<>(data, total, current, pageSize); + public static PageResultDto of(List data, int total, int current, int pageSize) { + return new PageResultDto<>(data, total, current, pageSize); } /** @@ -105,12 +105,13 @@ public static PageResult of(List data, int total, int current, int pag * * @param data 현재 페이지 데이터 * @param total 전체 데이터 개수 - * @param pageParams 요청 파라미터 ({@link PageParams}) + * @param pageParamsDto 요청 파라미터 ({@link PageParamsDto}) * @param 데이터 타입 * @return PageResult 객체 */ - public static PageResult of(List data, int total, PageParams pageParams) { - return new PageResult<>(data, total, pageParams.getCurrent(), pageParams.getPageSize()); + public static PageResultDto of(List data, int total, PageParamsDto pageParamsDto) { + return new PageResultDto<>( + data, total, pageParamsDto.getCurrent(), pageParamsDto.getPageSize()); } /** @@ -118,28 +119,32 @@ public static PageResult of(List data, int total, PageParams pageParam * *

데이터 조회와 카운트 조회를 별도의 Supplier로 받아 트랜잭션 내에서 실행할 수 있습니다. * - * @param pageParams 요청 파라미터 ({@link PageParams}) + * @param pageParamsDto 요청 파라미터 ({@link PageParamsDto}) * @param dataSupplier 데이터 조회 함수 * @param countSupplier 전체 개수 조회 함수 * @param 데이터 타입 * @return PageResult 객체 */ - public static PageResult from( - PageParams pageParams, Supplier> dataSupplier, Supplier countSupplier) { + public static PageResultDto from( + PageParamsDto pageParamsDto, + Supplier> dataSupplier, + Supplier countSupplier) { List data = dataSupplier.get(); int total = countSupplier.get(); - return new PageResult<>(data, total, pageParams.getCurrent(), pageParams.getPageSize()); + return new PageResultDto<>( + data, total, pageParamsDto.getCurrent(), pageParamsDto.getPageSize()); } /** * 비어 있는 페이지 결과를 생성합니다. * - * @param pageParams 요청 파라미터 ({@link PageParams}) + * @param pageParamsDto 요청 파라미터 ({@link PageParamsDto}) * @param 데이터 타입 * @return 빈 PageResult 객체 */ - public static PageResult empty(PageParams pageParams) { - return new PageResult<>(List.of(), 0, pageParams.getCurrent(), pageParams.getPageSize()); + public static PageResultDto empty(PageParamsDto pageParamsDto) { + return new PageResultDto<>( + List.of(), 0, pageParamsDto.getCurrent(), pageParamsDto.getPageSize()); } /** @@ -148,8 +153,8 @@ public static PageResult empty(PageParams pageParams) { * @param 데이터 타입 * @return 빈 PageResult 객체 */ - public static PageResult empty() { - return new PageResult<>(List.of(), 0, 1, 10); + public static PageResultDto empty() { + return new PageResultDto<>(List.of(), 0, 1, 10); } /** diff --git a/apps/user-service/src/main/java/site/icebang/common/service/PageableService.java b/apps/user-service/src/main/java/site/icebang/common/service/PageableService.java index da3ae215..7b83c524 100644 --- a/apps/user-service/src/main/java/site/icebang/common/service/PageableService.java +++ b/apps/user-service/src/main/java/site/icebang/common/service/PageableService.java @@ -1,13 +1,13 @@ package site.icebang.common.service; -import site.icebang.common.dto.PageParams; -import site.icebang.common.dto.PageResult; +import site.icebang.common.dto.PageParamsDto; +import site.icebang.common.dto.PageResultDto; /** * 페이징 가능한 서비스 인터페이스. * - *

엔티티나 DTO 목록을 페이징 처리하여 반환해야 하는 서비스에서 구현합니다. 공통적으로 {@link PageParams} 요청 파라미터를 받아 {@link - * PageResult} 응답을 제공합니다. + *

엔티티나 DTO 목록을 페이징 처리하여 반환해야 하는 서비스에서 구현합니다. 공통적으로 {@link PageParamsDto} 요청 파라미터를 받아 {@link + * PageResultDto} 응답을 제공합니다. * *

사용 예시: * @@ -37,8 +37,8 @@ public interface PageableService { /** * 페이징 처리된 결과를 반환합니다. * - * @param pageParams 페이징 및 검색/정렬 요청 파라미터 + * @param pageParamsDto 페이징 및 검색/정렬 요청 파라미터 * @return 페이징 처리된 결과 객체 */ - PageResult getPagedResult(PageParams pageParams); + PageResultDto getPagedResult(PageParamsDto pageParamsDto); } diff --git a/apps/user-service/src/main/java/site/icebang/domain/auth/controller/AuthController.java b/apps/user-service/src/main/java/site/icebang/domain/auth/controller/AuthController.java index 2303cf74..629cc226 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/auth/controller/AuthController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/auth/controller/AuthController.java @@ -14,7 +14,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; import site.icebang.domain.auth.dto.LoginRequestDto; import site.icebang.domain.auth.dto.RegisterDto; import site.icebang.domain.auth.model.AuthCredential; @@ -29,13 +29,13 @@ public class AuthController { @PostMapping("/register") @ResponseStatus(HttpStatus.CREATED) - public ApiResponse register(@Valid @RequestBody RegisterDto registerDto) { + public ApiResponseDto register(@Valid @RequestBody RegisterDto registerDto) { authService.registerUser(registerDto); - return ApiResponse.success(null); + return ApiResponseDto.success(null); } @PostMapping("/login") - public ApiResponse login( + public ApiResponseDto login( @RequestBody LoginRequestDto request, HttpServletRequest httpRequest) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(request.getEmail(), request.getPassword()); @@ -49,21 +49,22 @@ public ApiResponse login( HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); - return ApiResponse.success(null); + return ApiResponseDto.success(null); } @GetMapping("/check-session") - public ApiResponse checkSession(@AuthenticationPrincipal AuthCredential user) { - return ApiResponse.success(user != null); + public ApiResponseDto checkSession(@AuthenticationPrincipal AuthCredential user) { + return ApiResponseDto.success(user != null); } @GetMapping("/permissions") - public ApiResponse getPermissions(@AuthenticationPrincipal AuthCredential user) { - return ApiResponse.success(user); + public ApiResponseDto getPermissions( + @AuthenticationPrincipal AuthCredential user) { + return ApiResponseDto.success(user); } @PostMapping("/logout") - public ApiResponse logout(HttpServletRequest request) { + public ApiResponseDto logout(HttpServletRequest request) { // SecurityContext 정리 SecurityContextHolder.clearContext(); @@ -73,6 +74,6 @@ public ApiResponse logout(HttpServletRequest request) { session.invalidate(); } - return ApiResponse.success(null); + return ApiResponseDto.success(null); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/auth/service/AuthService.java b/apps/user-service/src/main/java/site/icebang/domain/auth/service/AuthService.java index 25a5bd42..b1a7a7bd 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/auth/service/AuthService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/auth/service/AuthService.java @@ -10,7 +10,7 @@ import site.icebang.common.utils.RandomPasswordGenerator; import site.icebang.domain.auth.dto.RegisterDto; import site.icebang.domain.auth.mapper.AuthMapper; -import site.icebang.domain.email.dto.EmailRequest; +import site.icebang.domain.email.dto.EmailRequestDto; import site.icebang.domain.email.service.EmailService; @Service @@ -42,13 +42,13 @@ public void registerUser(RegisterDto registerDto) { authMapper.insertUserRoles(registerDto); } - EmailRequest emailRequest = - EmailRequest.builder() + EmailRequestDto emailRequestDto = + EmailRequestDto.builder() .to(registerDto.getEmail()) .subject("[ice-bang] 비밀번호") .body(randomPassword) .build(); - emailService.send(emailRequest); + emailService.send(emailRequestDto); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDo.java b/apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDto.java similarity index 87% rename from apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDo.java rename to apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDto.java index 7644eb8e..f08c5d28 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDo.java +++ b/apps/user-service/src/main/java/site/icebang/domain/department/dto/DepartmentCardDto.java @@ -9,7 +9,7 @@ @Data @Builder @AllArgsConstructor -public class DepartmentCardDo { +public class DepartmentCardDto { private BigInteger id; private String name; } diff --git a/apps/user-service/src/main/java/site/icebang/domain/email/controller/EmailTestController.java b/apps/user-service/src/main/java/site/icebang/domain/email/controller/EmailTestController.java index 633e3ee7..ef38b607 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/email/controller/EmailTestController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/email/controller/EmailTestController.java @@ -6,7 +6,7 @@ import lombok.RequiredArgsConstructor; -import site.icebang.domain.email.dto.EmailRequest; +import site.icebang.domain.email.dto.EmailRequestDto; import site.icebang.domain.email.service.EmailService; @RestController @@ -19,15 +19,15 @@ public class EmailTestController { @PreAuthorize("permitAll()") public ResponseEntity sendTestEmail(@RequestParam String to) { try { - EmailRequest emailRequest = - EmailRequest.builder() + EmailRequestDto emailRequestDto = + EmailRequestDto.builder() .to(to) .subject("IceBang 실제 테스트 이메일") .body("안녕하세요!\n\nIceBang에서 보내는 실제 Gmail 테스트 이메일입니다.\n\n성공적으로 연동되었습니다!") .isHtml(false) .build(); - emailService.send(emailRequest); + emailService.send(emailRequestDto); return ResponseEntity.ok("실제 Gmail 테스트 이메일 전송 완료! 받은편지함을 확인하세요!"); } catch (Exception e) { diff --git a/apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequest.java b/apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequestDto.java similarity index 90% rename from apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequest.java rename to apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequestDto.java index 89898055..dc0afc98 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequest.java +++ b/apps/user-service/src/main/java/site/icebang/domain/email/dto/EmailRequestDto.java @@ -7,7 +7,7 @@ @Builder @Getter -public class EmailRequest { +public class EmailRequestDto { private String to; private String subject; private String body; diff --git a/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailService.java b/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailService.java index 51646cc3..e0977867 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailService.java @@ -1,7 +1,7 @@ package site.icebang.domain.email.service; -import site.icebang.domain.email.dto.EmailRequest; +import site.icebang.domain.email.dto.EmailRequestDto; public interface EmailService { - void send(EmailRequest emailRequest); + void send(EmailRequestDto emailRequestDto); } diff --git a/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailServiceImpl.java b/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailServiceImpl.java index 1bf7454b..5c573331 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailServiceImpl.java +++ b/apps/user-service/src/main/java/site/icebang/domain/email/service/EmailServiceImpl.java @@ -12,7 +12,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import site.icebang.domain.email.dto.EmailRequest; +import site.icebang.domain.email.dto.EmailRequestDto; @Slf4j @Service @@ -27,7 +27,7 @@ public class EmailServiceImpl implements EmailService { private String defaultSender; @Override - public void send(EmailRequest request) { + public void send(EmailRequestDto request) { try { if (request.isHtml()) { sendHtmlEmail(request); @@ -40,7 +40,7 @@ public void send(EmailRequest request) { } } - private void sendSimpleEmail(EmailRequest request) { + private void sendSimpleEmail(EmailRequestDto request) { try { SimpleMailMessage message = new SimpleMailMessage(); message.setTo(request.getTo()); @@ -67,7 +67,7 @@ private void sendSimpleEmail(EmailRequest request) { } } - private void sendHtmlEmail(EmailRequest request) throws MessagingException { + private void sendHtmlEmail(EmailRequestDto request) throws MessagingException { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); diff --git a/apps/user-service/src/main/java/site/icebang/domain/email/service/MockEmailService.java b/apps/user-service/src/main/java/site/icebang/domain/email/service/MockEmailService.java index ee84e8ea..d40e8fa1 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/email/service/MockEmailService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/email/service/MockEmailService.java @@ -5,7 +5,7 @@ import lombok.extern.slf4j.Slf4j; -import site.icebang.domain.email.dto.EmailRequest; +import site.icebang.domain.email.dto.EmailRequestDto; @Service @Profile({"develop", "test-e2e", "test-integration", "test-unit"}) @@ -13,9 +13,9 @@ public class MockEmailService implements EmailService { @Override - public void send(EmailRequest emailRequest) { - log.info("Mock send mail to: {}", emailRequest.getTo()); - log.info("Subject: {}", emailRequest.getSubject()); - log.info("Body: {}", emailRequest.getBody()); + public void send(EmailRequestDto emailRequestDto) { + log.info("Mock send mail to: {}", emailRequestDto.getTo()); + log.info("Subject: {}", emailRequestDto.getSubject()); + log.info("Body: {}", emailRequestDto.getBody()); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/log/mapper/ExecutionLogMapper.java b/apps/user-service/src/main/java/site/icebang/domain/log/mapper/ExecutionLogMapper.java index 772c47e2..281ed526 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/log/mapper/ExecutionLogMapper.java +++ b/apps/user-service/src/main/java/site/icebang/domain/log/mapper/ExecutionLogMapper.java @@ -5,9 +5,9 @@ import org.apache.ibatis.annotations.Mapper; import site.icebang.domain.workflow.dto.ExecutionLogDto; -import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteria; +import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteriaDto; @Mapper public interface ExecutionLogMapper { - List selectLogsByCriteria(WorkflowLogQueryCriteria criteria); + List selectLogsByCriteria(WorkflowLogQueryCriteriaDto criteria); } diff --git a/apps/user-service/src/main/java/site/icebang/domain/log/service/ExecutionLogService.java b/apps/user-service/src/main/java/site/icebang/domain/log/service/ExecutionLogService.java index 7cd9a820..3fbf08bf 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/log/service/ExecutionLogService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/log/service/ExecutionLogService.java @@ -8,14 +8,14 @@ import site.icebang.domain.log.mapper.ExecutionLogMapper; import site.icebang.domain.workflow.dto.ExecutionLogDto; -import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteria; +import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteriaDto; @Service @RequiredArgsConstructor public class ExecutionLogService { private final ExecutionLogMapper executionLogMapper; - public List getRawLogs(WorkflowLogQueryCriteria criteria) { + public List getRawLogs(WorkflowLogQueryCriteriaDto criteria) { return executionLogMapper.selectLogsByCriteria(criteria); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/organization/controller/OrganizationController.java b/apps/user-service/src/main/java/site/icebang/domain/organization/controller/OrganizationController.java index 16ccbb65..dd8851ff 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/organization/controller/OrganizationController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/organization/controller/OrganizationController.java @@ -11,7 +11,7 @@ import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; import site.icebang.domain.organization.dto.OrganizationCardDto; import site.icebang.domain.organization.dto.OrganizationOptionDto; import site.icebang.domain.organization.service.OrganizationService; @@ -23,13 +23,14 @@ public class OrganizationController { private final OrganizationService organizationService; @GetMapping("") - public ResponseEntity>> getOrganizations() { - return ResponseEntity.ok(ApiResponse.success(organizationService.getAllOrganizationList())); + public ResponseEntity>> getOrganizations() { + return ResponseEntity.ok(ApiResponseDto.success(organizationService.getAllOrganizationList())); } @GetMapping("/{id}/options") - public ResponseEntity> getOrganizationDetails( + public ResponseEntity> getOrganizationDetails( @PathVariable BigInteger id) { - return ResponseEntity.ok(ApiResponse.success(organizationService.getOrganizationOptions(id))); + return ResponseEntity.ok( + ApiResponseDto.success(organizationService.getOrganizationOptions(id))); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/organization/dto/OrganizationOptionDto.java b/apps/user-service/src/main/java/site/icebang/domain/organization/dto/OrganizationOptionDto.java index d7e670eb..614a6c40 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/organization/dto/OrganizationOptionDto.java +++ b/apps/user-service/src/main/java/site/icebang/domain/organization/dto/OrganizationOptionDto.java @@ -6,7 +6,7 @@ import lombok.Builder; import lombok.Data; -import site.icebang.domain.department.dto.DepartmentCardDo; +import site.icebang.domain.department.dto.DepartmentCardDto; import site.icebang.domain.position.dto.PositionCardDto; import site.icebang.domain.roles.dto.RoleCardDto; @@ -14,7 +14,7 @@ @Data @AllArgsConstructor public class OrganizationOptionDto { - List departments; + List departments; List positions; List roles; } diff --git a/apps/user-service/src/main/java/site/icebang/domain/organization/mapper/OrganizationMapper.java b/apps/user-service/src/main/java/site/icebang/domain/organization/mapper/OrganizationMapper.java index ed504cca..5d69ff07 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/organization/mapper/OrganizationMapper.java +++ b/apps/user-service/src/main/java/site/icebang/domain/organization/mapper/OrganizationMapper.java @@ -6,7 +6,7 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import site.icebang.domain.department.dto.DepartmentCardDo; +import site.icebang.domain.department.dto.DepartmentCardDto; import site.icebang.domain.organization.dto.OrganizationCardDto; import site.icebang.domain.position.dto.PositionCardDto; import site.icebang.domain.roles.dto.RoleCardDto; @@ -15,7 +15,7 @@ public interface OrganizationMapper { List findAllOrganizations(); - List findDepartmentsByOrganizationId( + List findDepartmentsByOrganizationId( @Param("organizationId") BigInteger organizationId); List findPositionsByOrganizationId( diff --git a/apps/user-service/src/main/java/site/icebang/domain/organization/service/OrganizationService.java b/apps/user-service/src/main/java/site/icebang/domain/organization/service/OrganizationService.java index cc035935..f77e859e 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/organization/service/OrganizationService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/organization/service/OrganizationService.java @@ -8,7 +8,7 @@ import lombok.RequiredArgsConstructor; -import site.icebang.domain.department.dto.DepartmentCardDo; +import site.icebang.domain.department.dto.DepartmentCardDto; import site.icebang.domain.organization.dto.OrganizationCardDto; import site.icebang.domain.organization.dto.OrganizationOptionDto; import site.icebang.domain.organization.mapper.OrganizationMapper; @@ -26,7 +26,7 @@ public List getAllOrganizationList() { } public OrganizationOptionDto getOrganizationOptions(BigInteger id) { - List departments = organizationMapper.findDepartmentsByOrganizationId(id); + List departments = organizationMapper.findDepartmentsByOrganizationId(id); List positions = organizationMapper.findPositionsByOrganizationId(id); List roles = organizationMapper.findRolesByOrganizationId(id); diff --git a/apps/user-service/src/main/java/site/icebang/domain/user/controller/UserController.java b/apps/user-service/src/main/java/site/icebang/domain/user/controller/UserController.java index db9b3fcf..432b4f64 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/user/controller/UserController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/user/controller/UserController.java @@ -6,10 +6,10 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; import site.icebang.domain.auth.model.AuthCredential; -import site.icebang.domain.user.dto.CheckEmailRequest; -import site.icebang.domain.user.dto.CheckEmailResponse; +import site.icebang.domain.user.dto.CheckEmailRequestDto; +import site.icebang.domain.user.dto.CheckEmailResponseDto; import site.icebang.domain.user.dto.UserProfileResponseDto; import site.icebang.domain.user.service.UserService; @@ -20,17 +20,18 @@ public class UserController { private final UserService userService; @PostMapping("/check-email") - public ApiResponse checkEmailAvailable( - @Valid @RequestBody CheckEmailRequest request) { + public ApiResponseDto checkEmailAvailable( + @Valid @RequestBody CheckEmailRequestDto request) { Boolean available = !userService.isExistEmail(request); String message = available.equals(Boolean.TRUE) ? "사용 가능한 이메일입니다." : "이미 가입된 이메일입니다."; - return ApiResponse.success(CheckEmailResponse.builder().available(available).build(), message); + return ApiResponseDto.success( + CheckEmailResponseDto.builder().available(available).build(), message); } @GetMapping("/me") - public ApiResponse getUserProfile( + public ApiResponseDto getUserProfile( @AuthenticationPrincipal AuthCredential user) { - return ApiResponse.success(UserProfileResponseDto.from(user)); + return ApiResponseDto.success(UserProfileResponseDto.from(user)); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequest.java b/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequestDto.java similarity index 91% rename from apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequest.java rename to apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequestDto.java index fb4c9844..3a8bc245 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequest.java +++ b/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailRequestDto.java @@ -9,7 +9,7 @@ @Data @AllArgsConstructor @NoArgsConstructor -public class CheckEmailRequest { +public class CheckEmailRequestDto { @NotBlank(message = "이메일은 필수입니다") @Email(message = "올바른 이메일 형식이 아닙니다") private String email; diff --git a/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponse.java b/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponseDto.java similarity index 77% rename from apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponse.java rename to apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponseDto.java index adda35d4..16aabd42 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponse.java +++ b/apps/user-service/src/main/java/site/icebang/domain/user/dto/CheckEmailResponseDto.java @@ -5,6 +5,6 @@ @Data @Builder -public class CheckEmailResponse { +public class CheckEmailResponseDto { private Boolean available; } diff --git a/apps/user-service/src/main/java/site/icebang/domain/user/service/UserService.java b/apps/user-service/src/main/java/site/icebang/domain/user/service/UserService.java index e3dce655..28225405 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/user/service/UserService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/user/service/UserService.java @@ -6,7 +6,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.domain.user.dto.CheckEmailRequest; +import site.icebang.domain.user.dto.CheckEmailRequestDto; import site.icebang.domain.user.mapper.UserMapper; @Service @@ -15,7 +15,7 @@ public class UserService { private final UserMapper userMapper; @Transactional(readOnly = true) - public Boolean isExistEmail(@Valid CheckEmailRequest request) { + public Boolean isExistEmail(@Valid CheckEmailRequestDto request) { return userMapper.existsByEmail(request.getEmail()); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/TaskController.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/TaskController.java index c0ba5542..f5ee13ae 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/TaskController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/TaskController.java @@ -10,7 +10,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; import site.icebang.domain.workflow.dto.TaskDto; import site.icebang.domain.workflow.model.TaskIoData; import site.icebang.domain.workflow.service.WorkflowService; @@ -46,7 +46,7 @@ public ResponseEntity> getTask(@PathVariable Long id) { * @return Task IO 데이터 목록 (created_at 기준 내림차순 정렬) */ @GetMapping("/io-data") - public ResponseEntity>> getTaskIoData( + public ResponseEntity>> getTaskIoData( @RequestParam List taskRunIds, @RequestParam(required = false) String ioType, @RequestParam(required = false) Integer limit) { @@ -54,11 +54,11 @@ public ResponseEntity>> getTaskIoData( try { List ioData = workflowService.getTaskIoDataByTaskRunIds(taskRunIds, ioType, limit); - return ResponseEntity.ok(ApiResponse.success(ioData, "Task IO 데이터 조회 성공")); + return ResponseEntity.ok(ApiResponseDto.success(ioData, "Task IO 데이터 조회 성공")); } catch (Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body( - ApiResponse.error( + ApiResponseDto.error( "Task IO 데이터 조회 실패: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR)); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java index 2bc388af..40550e44 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowController.java @@ -10,11 +10,11 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; -import site.icebang.common.dto.PageParams; -import site.icebang.common.dto.PageResult; +import site.icebang.common.dto.ApiResponseDto; +import site.icebang.common.dto.PageParamsDto; +import site.icebang.common.dto.PageResultDto; import site.icebang.domain.auth.model.AuthCredential; -import site.icebang.domain.workflow.dto.RequestContext; +import site.icebang.domain.workflow.dto.RequestContextDto; import site.icebang.domain.workflow.dto.WorkflowCardDto; import site.icebang.domain.workflow.dto.WorkflowCreateDto; import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; @@ -31,15 +31,15 @@ public class WorkflowController { private final RequestContextService requestContextService; @GetMapping("") - public ApiResponse> getWorkflowList( - @ModelAttribute PageParams pageParams) { - PageResult result = workflowService.getPagedResult(pageParams); - return ApiResponse.success(result); + public ApiResponseDto> getWorkflowList( + @ModelAttribute PageParamsDto pageParamsDto) { + PageResultDto result = workflowService.getPagedResult(pageParamsDto); + return ApiResponseDto.success(result); } @PostMapping("") @ResponseStatus(HttpStatus.CREATED) - public ApiResponse createWorkflow( + public ApiResponseDto createWorkflow( @Valid @RequestBody WorkflowCreateDto workflowCreateDto, @AuthenticationPrincipal AuthCredential authCredential) { // 인증 체크 @@ -51,21 +51,22 @@ public ApiResponse createWorkflow( BigInteger userId = authCredential.getId(); workflowService.createWorkflow(workflowCreateDto, userId); - return ApiResponse.success(null); + return ApiResponseDto.success(null); } @PostMapping("/{workflowId}/run") public ResponseEntity runWorkflow(@PathVariable Long workflowId) { - RequestContext context = requestContextService.extractRequestContext(); + RequestContextDto context = requestContextService.extractRequestContext(); // HTTP 요청/응답 스레드를 블로킹하지 않도록 비동기 실행 workflowExecutionService.executeWorkflow(workflowId, context); return ResponseEntity.accepted().build(); } @GetMapping("/{workflowId}/detail") - public ApiResponse getWorkflowDetail(@PathVariable BigInteger workflowId) { + public ApiResponseDto getWorkflowDetail( + @PathVariable BigInteger workflowId) { WorkflowDetailCardDto result = workflowService.getWorkflowDetail(workflowId); - return ApiResponse.success(result); + return ApiResponseDto.success(result); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowHistoryController.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowHistoryController.java index 0f8535cf..272f3ed4 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowHistoryController.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/controller/WorkflowHistoryController.java @@ -7,14 +7,14 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; -import site.icebang.common.dto.PageParams; -import site.icebang.common.dto.PageResult; +import site.icebang.common.dto.ApiResponseDto; +import site.icebang.common.dto.PageParamsDto; +import site.icebang.common.dto.PageResultDto; import site.icebang.domain.log.service.ExecutionLogService; import site.icebang.domain.workflow.dto.WorkflowHistoryDTO; -import site.icebang.domain.workflow.dto.WorkflowRunDetailResponse; +import site.icebang.domain.workflow.dto.WorkflowRunDetailResponseDto; import site.icebang.domain.workflow.dto.log.ExecutionLogSimpleDto; -import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteria; +import site.icebang.domain.workflow.dto.log.WorkflowLogQueryCriteriaDto; import site.icebang.domain.workflow.service.WorkflowHistoryService; @RestController @@ -25,10 +25,11 @@ public class WorkflowHistoryController { private final ExecutionLogService executionLogService; @GetMapping("") - public ApiResponse> getWorkflowHistoryList( - @ModelAttribute PageParams pageParams) { - PageResult response = workflowHistoryService.getPagedResult(pageParams); - return ApiResponse.success(response); + public ApiResponseDto> getWorkflowHistoryList( + @ModelAttribute PageParamsDto pageParamsDto) { + PageResultDto response = + workflowHistoryService.getPagedResult(pageParamsDto); + return ApiResponseDto.success(response); } /** @@ -38,15 +39,16 @@ public ApiResponse> getWorkflowHistoryList( * @return WorkflowRunDetailResponse */ @GetMapping("/{runId}") - public ApiResponse getWorkflowRunDetail(@PathVariable Long runId) { - WorkflowRunDetailResponse response = workflowHistoryService.getWorkflowRunDetail(runId); - return ApiResponse.success(response); + public ApiResponseDto getWorkflowRunDetail( + @PathVariable Long runId) { + WorkflowRunDetailResponseDto response = workflowHistoryService.getWorkflowRunDetail(runId); + return ApiResponseDto.success(response); } @GetMapping("/logs") - public ApiResponse> getTaskExecutionLog( - @Valid @ModelAttribute WorkflowLogQueryCriteria requestDto) { - return ApiResponse.success( + public ApiResponseDto> getTaskExecutionLog( + @Valid @ModelAttribute WorkflowLogQueryCriteriaDto requestDto) { + return ApiResponseDto.success( ExecutionLogSimpleDto.from(executionLogService.getRawLogs(requestDto))); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContext.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContextDto.java similarity index 79% rename from apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContext.java rename to apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContextDto.java index 1812cd32..66ef57aa 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContext.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/RequestContextDto.java @@ -4,7 +4,7 @@ /** 요청 컨텍스트 정보를 담는 DTO 클래스 분산 추적, 클라이언트 정보 등을 포함하여 워크플로우 실행 시 필요한 컨텍스트를 관리합니다. */ @Data -public class RequestContext { +public class RequestContextDto { private final String traceId; private final String clientIp; @@ -16,7 +16,7 @@ public class RequestContext { * @param traceId 분산 추적 ID * @return 스케줄러용 RequestContext 객체 (clientIp와 userAgent는 기본값 설정) */ - public static RequestContext forScheduler(String traceId) { - return new RequestContext(traceId, "scheduler", "quartz-scheduler"); + public static RequestContextDto forScheduler(String traceId) { + return new RequestContextDto(traceId, "scheduler", "quartz-scheduler"); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponse.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponseDto.java similarity index 88% rename from apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponse.java rename to apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponseDto.java index 194e8583..f939fe03 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponse.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunDetailResponseDto.java @@ -11,7 +11,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class WorkflowRunDetailResponse { +public class WorkflowRunDetailResponseDto { private String traceId; private WorkflowRunDto workflowRun; private List jobRuns; diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponse.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponseDto.java similarity index 87% rename from apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponse.java rename to apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponseDto.java index ff5304f5..62a8cfca 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponse.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/WorkflowRunLogsResponseDto.java @@ -11,7 +11,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class WorkflowRunLogsResponse { +public class WorkflowRunLogsResponseDto { private String traceId; private List logs; } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteria.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteriaDto.java similarity index 90% rename from apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteria.java rename to apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteriaDto.java index f2c2ed06..6c67f0bd 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteria.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/dto/log/WorkflowLogQueryCriteriaDto.java @@ -8,7 +8,7 @@ @Data @Builder -public class WorkflowLogQueryCriteria { +public class WorkflowLogQueryCriteriaDto { private final String traceId; private final BigInteger sourceId; diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowHistoryMapper.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowHistoryMapper.java index aec0bb36..a1ba5b09 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowHistoryMapper.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowHistoryMapper.java @@ -4,7 +4,7 @@ import org.apache.ibatis.annotations.Mapper; -import site.icebang.common.dto.PageParams; +import site.icebang.common.dto.PageParamsDto; import site.icebang.domain.workflow.dto.JobRunDto; import site.icebang.domain.workflow.dto.TaskRunDto; import site.icebang.domain.workflow.dto.WorkflowHistoryDTO; @@ -55,16 +55,16 @@ public interface WorkflowHistoryMapper { /** * 페이지네이션을 적용한 워크플로우 히스토리 목록을 조회합니다. * - * @param pageParams 페이지 매개변수 + * @param pageParamsDto 페이지 매개변수 * @return 워크플로우 히스토리 정보 목록 */ - List selectWorkflowHistoryList(PageParams pageParams); + List selectWorkflowHistoryList(PageParamsDto pageParamsDto); /** * 워크플로우 런 인스턴스의 총 개수를 조회합니다. * - * @param pageParams 페이지 매개변수 + * @param pageParamsDto 페이지 매개변수 * @return 총 결과 개수 */ - int selectWorkflowHistoryCount(PageParams pageParams); + int selectWorkflowHistoryCount(PageParamsDto pageParamsDto); } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java index 417dfd1d..df3ff8b7 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/mapper/WorkflowMapper.java @@ -3,15 +3,15 @@ import java.math.BigInteger; import java.util.*; -import site.icebang.common.dto.PageParams; +import site.icebang.common.dto.PageParamsDto; import site.icebang.domain.workflow.dto.ScheduleDto; import site.icebang.domain.workflow.dto.WorkflowCardDto; import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; public interface WorkflowMapper { - List selectWorkflowList(PageParams pageParams); + List selectWorkflowList(PageParamsDto pageParamsDto); - int selectWorkflowCount(PageParams pageParams); + int selectWorkflowCount(PageParamsDto pageParamsDto); int insertWorkflow(Map params); // insert workflow diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/RequestContextService.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/RequestContextService.java index a4c501af..dd74a066 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/RequestContextService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/RequestContextService.java @@ -5,7 +5,7 @@ import org.slf4j.MDC; import org.springframework.stereotype.Service; -import site.icebang.domain.workflow.dto.RequestContext; +import site.icebang.domain.workflow.dto.RequestContextDto; /** 요청 컨텍스트 정보를 추출하고 관리하는 서비스 MDC(Mapped Diagnostic Context)를 사용하여 분산 추적 정보를 처리합니다. */ @Service @@ -16,12 +16,12 @@ public class RequestContextService { * * @return 추출된 요청 컨텍스트 */ - public RequestContext extractRequestContext() { + public RequestContextDto extractRequestContext() { String traceId = MDC.get("traceId") != null ? MDC.get("traceId") : UUID.randomUUID().toString(); String clientIp = MDC.get("clientIp"); String userAgent = MDC.get("userAgent"); - return new RequestContext(traceId, clientIp, userAgent); + return new RequestContextDto(traceId, clientIp, userAgent); } /** @@ -29,9 +29,9 @@ public RequestContext extractRequestContext() { * * @return 스케줄러용 요청 컨텍스트 */ - public RequestContext quartzContext() { + public RequestContextDto quartzContext() { String traceId = MDC.get("traceId") != null ? MDC.get("traceId") : UUID.randomUUID().toString(); - return RequestContext.forScheduler(traceId); + return RequestContextDto.forScheduler(traceId); } } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowExecutionService.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowExecutionService.java index 073d81ce..b18b87fe 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowExecutionService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowExecutionService.java @@ -16,7 +16,7 @@ import lombok.RequiredArgsConstructor; import site.icebang.domain.workflow.dto.JobDto; -import site.icebang.domain.workflow.dto.RequestContext; +import site.icebang.domain.workflow.dto.RequestContextDto; import site.icebang.domain.workflow.dto.TaskDto; import site.icebang.domain.workflow.dto.WorkflowDetailCardDto; import site.icebang.domain.workflow.manager.ExecutionMdcManager; @@ -51,7 +51,7 @@ public class WorkflowExecutionService { private final WorkflowMapper workflowMapper; @Async("traceExecutor") - public void executeWorkflow(Long workflowId, RequestContext context) { + public void executeWorkflow(Long workflowId, RequestContextDto context) { WorkflowRun workflowRun = WorkflowRun.start(workflowId, context.getTraceId()); workflowRunMapper.insert(workflowRun); diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowHistoryService.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowHistoryService.java index 17887630..578bba14 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowHistoryService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowHistoryService.java @@ -7,15 +7,15 @@ import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.PageParams; -import site.icebang.common.dto.PageResult; +import site.icebang.common.dto.PageParamsDto; +import site.icebang.common.dto.PageResultDto; import site.icebang.common.service.PageableService; import site.icebang.domain.workflow.dto.JobRunDto; import site.icebang.domain.workflow.dto.TaskRunDto; import site.icebang.domain.workflow.dto.WorkflowHistoryDTO; -import site.icebang.domain.workflow.dto.WorkflowRunDetailResponse; +import site.icebang.domain.workflow.dto.WorkflowRunDetailResponseDto; import site.icebang.domain.workflow.dto.WorkflowRunDto; -import site.icebang.domain.workflow.dto.WorkflowRunLogsResponse; +import site.icebang.domain.workflow.dto.WorkflowRunLogsResponseDto; import site.icebang.domain.workflow.mapper.WorkflowHistoryMapper; /** @@ -44,19 +44,19 @@ public class WorkflowHistoryService implements PageableService이 메소드는 {@code PageableService} 인터페이스를 구현하며, {@code PageResult} 유틸리티를 사용하여 전체 카운트 쿼리와 목록 조회 * 쿼리를 실행하고 페이징 결과를 생성합니다. * - * @param pageParams 페이징 처리에 필요한 파라미터 (페이지 번호, 페이지 크기 등) + * @param pageParamsDto 페이징 처리에 필요한 파라미터 (페이지 번호, 페이지 크기 등) * @return 페이징 처리된 워크플로우 실행 이력 목록 - * @see PageResult + * @see PageResultDto * @since v0.1.0 */ @Override @Transactional(readOnly = true) - public PageResult getPagedResult(PageParams pageParams) { + public PageResultDto getPagedResult(PageParamsDto pageParamsDto) { - return PageResult.from( - pageParams, - () -> workflowHistoryMapper.selectWorkflowHistoryList(pageParams), - () -> workflowHistoryMapper.selectWorkflowHistoryCount(pageParams)); + return PageResultDto.from( + pageParamsDto, + () -> workflowHistoryMapper.selectWorkflowHistoryList(pageParamsDto), + () -> workflowHistoryMapper.selectWorkflowHistoryCount(pageParamsDto)); } /** @@ -70,7 +70,7 @@ public PageResult getPagedResult(PageParams pageParams) { * @since v0.1.0 */ @Transactional(readOnly = true) - public WorkflowRunDetailResponse getWorkflowRunDetail(Long runId) { + public WorkflowRunDetailResponseDto getWorkflowRunDetail(Long runId) { // 1. 워크플로우 실행 정보 조회 WorkflowRunDto workflowRunDto = workflowHistoryMapper.selectWorkflowRun(runId); @@ -90,7 +90,7 @@ public WorkflowRunDetailResponse getWorkflowRunDetail(Long runId) { // 4. TraceId 조회 String traceId = workflowHistoryMapper.selectTraceIdByRunId(runId); - return WorkflowRunDetailResponse.builder() + return WorkflowRunDetailResponseDto.builder() .workflowRun(workflowRunDto) .jobRuns(jobRunDtos) .traceId(traceId) @@ -104,7 +104,7 @@ public WorkflowRunDetailResponse getWorkflowRunDetail(Long runId) { * @return 워크플로우 실행 로그 응답 객체 * @since v0.1.0 */ - public WorkflowRunLogsResponse getWorkflowRunLogs(Long runId) { + public WorkflowRunLogsResponseDto getWorkflowRunLogs(Long runId) { // TODO: 구현 예정 return null; } @@ -116,7 +116,7 @@ public WorkflowRunLogsResponse getWorkflowRunLogs(Long runId) { * @return 워크플로우 실행 상세 응답 객체 * @since v0.1.0 */ - public WorkflowRunDetailResponse getWorkflowRunByTraceId(String traceId) { + public WorkflowRunDetailResponseDto getWorkflowRunByTraceId(String traceId) { // TODO: 구현 예정 return null; } diff --git a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java index 6362d061..1cd553c9 100644 --- a/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java +++ b/apps/user-service/src/main/java/site/icebang/domain/workflow/service/WorkflowService.java @@ -15,8 +15,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import site.icebang.common.dto.PageParams; -import site.icebang.common.dto.PageResult; +import site.icebang.common.dto.PageParamsDto; +import site.icebang.common.dto.PageResultDto; import site.icebang.common.exception.DuplicateDataException; import site.icebang.common.service.PageableService; import site.icebang.domain.schedule.mapper.ScheduleMapper; @@ -62,18 +62,18 @@ public class WorkflowService implements PageableService { *

이 메소드는 {@code PageableService} 인터페이스를 구현하며, {@code PageResult} 유틸리티를 사용하여 전체 카운트 쿼리와 목록 조회 * 쿼리를 실행하고 페이징 결과를 생성합니다. * - * @param pageParams 페이징 처리에 필요한 파라미터 (페이지 번호, 페이지 크기 등) + * @param pageParamsDto 페이징 처리에 필요한 파라미터 (페이지 번호, 페이지 크기 등) * @return 페이징 처리된 워크플로우 카드 목록 - * @see PageResult + * @see PageResultDto * @since v0.1.0 */ @Override @Transactional(readOnly = true) - public PageResult getPagedResult(PageParams pageParams) { - return PageResult.from( - pageParams, - () -> workflowMapper.selectWorkflowList(pageParams), - () -> workflowMapper.selectWorkflowCount(pageParams)); + public PageResultDto getPagedResult(PageParamsDto pageParamsDto) { + return PageResultDto.from( + pageParamsDto, + () -> workflowMapper.selectWorkflowList(pageParamsDto), + () -> workflowMapper.selectWorkflowCount(pageParamsDto)); } /** diff --git a/apps/user-service/src/main/java/site/icebang/global/handler/exception/GlobalExceptionHandler.java b/apps/user-service/src/main/java/site/icebang/global/handler/exception/GlobalExceptionHandler.java index 1c064368..6a17766c 100644 --- a/apps/user-service/src/main/java/site/icebang/global/handler/exception/GlobalExceptionHandler.java +++ b/apps/user-service/src/main/java/site/icebang/global/handler/exception/GlobalExceptionHandler.java @@ -14,14 +14,14 @@ import lombok.extern.slf4j.Slf4j; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; import site.icebang.common.exception.DuplicateDataException; /** * 전역 예외 처리기 (Global Exception Handler). * - *

이 클래스는 애플리케이션 전역에서 발생하는 예외를 {@link ApiResponse} 형태로 변환하여 클라이언트에게 반환합니다. 예외 유형에 따라 적절한 {@link - * HttpStatus} 코드를 설정하며, 공통적인 예외 처리 로직을 중앙화합니다. + *

이 클래스는 애플리케이션 전역에서 발생하는 예외를 {@link ApiResponseDto} 형태로 변환하여 클라이언트에게 반환합니다. 예외 유형에 따라 적절한 + * {@link HttpStatus} 코드를 설정하며, 공통적인 예외 처리 로직을 중앙화합니다. * *

처리되는 주요 예외는 다음과 같습니다: * @@ -44,91 +44,92 @@ public class GlobalExceptionHandler { * 요청 데이터 유효성 검증 실패 시 발생하는 예외를 처리합니다. * * @param ex 발생한 {@link MethodArgumentNotValidException} - * @return {@link ApiResponse} - 검증 실패 메시지와 {@link HttpStatus#BAD_REQUEST} + * @return {@link ApiResponseDto} - 검증 실패 메시지와 {@link HttpStatus#BAD_REQUEST} */ @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public ApiResponse handleValidation(MethodArgumentNotValidException ex) { + public ApiResponseDto handleValidation(MethodArgumentNotValidException ex) { String errorMessage = ex.getBindingResult().getFieldErrors().stream() .map(FieldError::getDefaultMessage) .collect(Collectors.joining(", ")); - return ApiResponse.error("입력 값 검증 실패: " + errorMessage, HttpStatus.BAD_REQUEST); + return ApiResponseDto.error("입력 값 검증 실패: " + errorMessage, HttpStatus.BAD_REQUEST); } /** * 처리되지 않은 모든 일반 예외를 처리합니다. 서버 내부 오류로 간주되며, 에러 로그를 남깁니다. * * @param ex 발생한 {@link Exception} - * @return {@link ApiResponse} - 내부 오류 메시지와 {@link HttpStatus#INTERNAL_SERVER_ERROR} + * @return {@link ApiResponseDto} - 내부 오류 메시지와 {@link HttpStatus#INTERNAL_SERVER_ERROR} */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public ApiResponse handleGeneric(Exception ex) { + public ApiResponseDto handleGeneric(Exception ex) { log.error(ex.getMessage(), ex); - return ApiResponse.error("Internal error: ", HttpStatus.INTERNAL_SERVER_ERROR); + return ApiResponseDto.error("Internal error: ", HttpStatus.INTERNAL_SERVER_ERROR); } /** * 존재하지 않는 리소스 접근 시 발생하는 예외를 처리합니다. * * @param ex 발생한 {@link NoResourceFoundException} - * @return {@link ApiResponse} - 리소스 없음 메시지와 {@link HttpStatus#NOT_FOUND} + * @return {@link ApiResponseDto} - 리소스 없음 메시지와 {@link HttpStatus#NOT_FOUND} */ @ExceptionHandler(NoResourceFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) - public ApiResponse handleNotFound(NoResourceFoundException ex) { - return ApiResponse.error("Notfound: " + ex.getMessage(), HttpStatus.NOT_FOUND); + public ApiResponseDto handleNotFound(NoResourceFoundException ex) { + return ApiResponseDto.error("Notfound: " + ex.getMessage(), HttpStatus.NOT_FOUND); } /** * 인증 실패 시 발생하는 예외를 처리합니다. * * @param ex 발생한 {@link AuthenticationException} - * @return {@link ApiResponse} - 인증 실패 메시지와 {@link HttpStatus#UNAUTHORIZED} + * @return {@link ApiResponseDto} - 인증 실패 메시지와 {@link HttpStatus#UNAUTHORIZED} */ @ExceptionHandler(AuthenticationException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) - public ApiResponse handleAuthentication(AuthenticationException ex) { - return ApiResponse.error("Authentication failed: " + ex.getMessage(), HttpStatus.UNAUTHORIZED); + public ApiResponseDto handleAuthentication(AuthenticationException ex) { + return ApiResponseDto.error( + "Authentication failed: " + ex.getMessage(), HttpStatus.UNAUTHORIZED); } /** * 인가(권한) 실패 시 발생하는 예외를 처리합니다. * * @param ex 발생한 {@link AccessDeniedException} - * @return {@link ApiResponse} - 접근 거부 메시지와 {@link HttpStatus#FORBIDDEN} + * @return {@link ApiResponseDto} - 접근 거부 메시지와 {@link HttpStatus#FORBIDDEN} */ @ExceptionHandler(AccessDeniedException.class) @ResponseStatus(HttpStatus.FORBIDDEN) - public ApiResponse handleAccessDenied(AccessDeniedException ex) { - return ApiResponse.error("Access denied: " + ex.getMessage(), HttpStatus.FORBIDDEN); + public ApiResponseDto handleAccessDenied(AccessDeniedException ex) { + return ApiResponseDto.error("Access denied: " + ex.getMessage(), HttpStatus.FORBIDDEN); } /** * 중복 데이터 발생 시 발생하는 예외를 처리합니다. * * @param ex 발생한 {@link DuplicateDataException} - * @return {@link ApiResponse} - 중복 데이터 메시지와 {@link HttpStatus#CONFLICT} + * @return {@link ApiResponseDto} - 중복 데이터 메시지와 {@link HttpStatus#CONFLICT} */ @ExceptionHandler(DuplicateDataException.class) @ResponseStatus(HttpStatus.CONFLICT) - public ApiResponse handleDuplicateData(DuplicateDataException ex) { + public ApiResponseDto handleDuplicateData(DuplicateDataException ex) { log.warn(ex.getMessage(), ex); - return ApiResponse.error("Duplicate: " + ex.getMessage(), HttpStatus.CONFLICT); + return ApiResponseDto.error("Duplicate: " + ex.getMessage(), HttpStatus.CONFLICT); } /** * IllegalArgumentException을 400 Bad Request로 처리합니다. WorkflowService에서 던지는 검증 오류를 처리하기 위해 추가되었습니다. * * @param ex 발생한 {@link IllegalArgumentException} - * @return {@link ApiResponse} - 검증 실패 메시지와 {@link HttpStatus#BAD_REQUEST} + * @return {@link ApiResponseDto} - 검증 실패 메시지와 {@link HttpStatus#BAD_REQUEST} */ @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public ApiResponse handleIllegalArgument(IllegalArgumentException ex) { + public ApiResponseDto handleIllegalArgument(IllegalArgumentException ex) { log.warn("Validation failed: {}", ex.getMessage()); - return ApiResponse.error("입력값 검증 실패: " + ex.getMessage(), HttpStatus.BAD_REQUEST); + return ApiResponseDto.error("입력값 검증 실패: " + ex.getMessage(), HttpStatus.BAD_REQUEST); } } diff --git a/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAccessDeniedHandler.java b/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAccessDeniedHandler.java index 9e6672f3..0b4e7950 100644 --- a/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAccessDeniedHandler.java +++ b/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAccessDeniedHandler.java @@ -13,7 +13,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; /** * 접근 거부 처리기 (REST 전용 AccessDeniedHandler). @@ -25,7 +25,7 @@ * *

    *
  • HTTP 상태 코드: {@link HttpStatus#FORBIDDEN} (403) - *
  • 응답 본문: {@link ApiResponse} 형식의 에러 메시지 + *
  • 응답 본문: {@link ApiResponseDto} 형식의 에러 메시지 *
  • 응답 Content-Type: {@code application/json;charset=UTF-8} *
* @@ -50,7 +50,7 @@ public class RestAccessDeniedHandler implements AccessDeniedHandler { public void handle( HttpServletRequest request, HttpServletResponse response, AccessDeniedException ex) throws IOException { - ApiResponse body = ApiResponse.error("Access denied", HttpStatus.FORBIDDEN); + ApiResponseDto body = ApiResponseDto.error("Access denied", HttpStatus.FORBIDDEN); response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.setContentType("application/json;charset=UTF-8"); diff --git a/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAuthenticationEntryPoint.java b/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAuthenticationEntryPoint.java index 9d3ec7b5..8f9255c4 100644 --- a/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAuthenticationEntryPoint.java +++ b/apps/user-service/src/main/java/site/icebang/global/handler/exception/RestAuthenticationEntryPoint.java @@ -13,7 +13,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import site.icebang.common.dto.ApiResponse; +import site.icebang.common.dto.ApiResponseDto; /** * 인증 진입점 처리기 (REST 전용 AuthenticationEntryPoint). @@ -25,7 +25,7 @@ * *
    *
  • HTTP 상태 코드: {@link HttpStatus#UNAUTHORIZED} (401) - *
  • 응답 본문: {@link ApiResponse} 형식의 에러 메시지 + *
  • 응답 본문: {@link ApiResponseDto} 형식의 에러 메시지 *
  • 응답 Content-Type: {@code application/json;charset=UTF-8} *
* @@ -50,8 +50,8 @@ public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { public void commence( HttpServletRequest request, HttpServletResponse response, AuthenticationException ex) throws IOException { - ApiResponse body = - ApiResponse.error("Authentication required", HttpStatus.UNAUTHORIZED); + ApiResponseDto body = + ApiResponseDto.error("Authentication required", HttpStatus.UNAUTHORIZED); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); diff --git a/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml b/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml index 40abe4d5..d992be29 100644 --- a/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml +++ b/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml @@ -14,7 +14,7 @@ - - SELECT w.id, @@ -19,7 +19,7 @@ LIMIT #{pageSize} OFFSET #{offset} -