Skip to content

feat: fastapi - #79

Merged
bong-coding merged 1 commit into
mainfrom
feat/cicd
Aug 15, 2026
Merged

feat: fastapi#79
bong-coding merged 1 commit into
mainfrom
feat/cicd

Conversation

@bong-coding

Copy link
Copy Markdown
Collaborator

변경 내용

영향

  • API 변경 없음
  • API 문서와 변경 이력 수정
  • DB·ERD 변경 없음
  • ERD와 필요한 migration 수정
  • 외부 API 영향 확인

테스트

# 실행한 명령과 결과

확인

  • 비밀값이 포함되지 않음
  • 관련 문서와 구현이 일치함
  • 의도하지 않은 변경이 없음

@bong-coding
bong-coding merged commit a904ca3 into main Aug 15, 2026
2 checks passed
@github-actions

Copy link
Copy Markdown

🤖 Gemini PR Review

1. [HIGH] FastApiSpontaneousProperties 빈 등록 누락으로 인한 애플리케이션 구동 실패 가능성

  • 파일: src/main/java/com/server/external/spontaneous/FastApiSpontaneousProperties.java
  • 라인: 3-12
  • 문제점:
    FastApiSpontaneousProperties 레코드에 @ConfigurationProperties가 선언되어 있지만, 이를 스프링 빈으로 등록하기 위한 @Component 어노테이션이 누락되었으며, 관련 설정 클래스에도 @EnableConfigurationProperties가 선언되어 있지 않습니다.
    만약 프로젝트 메인 클래스에 @ConfigurationPropertiesScan 설정이 전역적으로 적용되어 있지 않다면, 애플리케이션 구동 시 FastApiSpontaneousProperties 빈을 찾을 수 없어 NoSuchBeanDefinitionExceptionUnsatisfiedDependencyException이 발생하며 빌드 또는 실행이 실패하게 됩니다.
  • 개선 제안:
    FastApiSpontaneousConfig 클래스에 @EnableConfigurationProperties(FastApiSpontaneousProperties.class)를 명시하여 프로퍼티 클래스가 안전하게 빈으로 등록되고 주입될 수 있도록 개선해야 합니다.
  • 개선 예시:
// src/main/java/com/server/external/spontaneous/FastApiSpontaneousConfig.java

package com.server.external.spontaneous;

import java.net.http.HttpClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

@Configuration
@EnableConfigurationProperties(FastApiSpontaneousProperties.class) // 프로퍼티 활성화 명시
public class FastApiSpontaneousConfig {

    @Bean
    RestClient fastApiSpontaneousRestClient(
            FastApiSpontaneousProperties properties
    ) {
        // ... 기존 코드 동일
    }
}

2. [HIGH] 외부 API(FastAPI) 호출 시 예외 처리 누락 및 장애 전파 위험

  • 파일: src/main/java/com/server/external/spontaneous/FastApiSpontaneousClient.java
  • 라인: 23-36
  • 문제점:
    RestClient를 사용하여 외부 FastAPI 서버로 HTTP 요청을 보낼 때, 네트워크 장애, 타임아웃(Connect/Read Timeout), 또는 FastAPI 서버의 4xx/5xx 에러가 발생하면 RestClientResponseException 또는 ResourceAccessException 등의 런타임 예외가 발생합니다.
    현재 코드에는 이에 대한 예외 처리(try-catch)가 전혀 없기 때문에, 외부 AI 서버의 일시적인 장애가 우리 서비스의 500 Internal Server Error로 이어져 장애가 그대로 전파됩니다.
  • 개선 제안:
    외부 API 호출부를 try-catch 블록으로 감싸 예외를 안전하게 처리해야 합니다. 예외 발생 시 로그를 남기고, 사용자에게 명확한 에러 메시지를 전달할 수 있는 커스텀 예외로 전환하여 던지거나 적절한 Fallback 처리를 해야 합니다.
  • 개선 예시:
// src/main/java/com/server/external/spontaneous/FastApiSpontaneousClient.java

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.ResourceAccessException;

@Component
public class FastApiSpontaneousClient {

    private static final Logger log = LoggerFactory.getLogger(FastApiSpontaneousClient.class);
    private final RestClient restClient;
    private final FastApiSpontaneousProperties properties;

    // 생성자 동일...

    public Map<String, Object> recommendDestinations(Map<String, Object> request) {
        if (!properties.enabled()) {
            throw new IllegalStateException("Spontaneous FastAPI is disabled");
        }

        try {
            return restClient.post()
                    .uri("/api/v1/spontaneous-trips/destinations")
                    .body(request)
                    .retrieve()
                    .body(Map.class);
        } catch (RestClientResponseException e) {
            log.error("FastAPI server error: status={}, body={}", e.getStatusCode(), e.getResponseBodyAsString(), e);
            throw new RuntimeException("추천 서버 호출 중 에러가 발생했습니다.", e); // 적절한 커스텀 예외로 변경 권장
        } catch (ResourceAccessException e) {
            log.error("FastAPI connection timeout or network error", e);
            throw new RuntimeException("추천 서버와의 통신이 원활하지 않습니다.", e);
        }
    }
}

3. [MEDIUM] API 요청 및 응답에 Map<String, Object> 사용으로 인한 타입 안정성 결여

  • 파일: src/main/java/com/server/spontaneous/SpontaneousTripController.java, src/main/java/com/server/external/spontaneous/FastApiSpontaneousClient.java
  • 라인: SpontaneousTripController.java 25-32라인 / FastApiSpontaneousClient.java 23-36라인
  • 문제점:
    컨트롤러와 외부 연동 클라이언트에서 요청(Request Body)과 응답(Response Body) 데이터 타입으로 Map<String, Object>를 사용하고 있습니다.
    이는 다음과 같은 심각한 문제를 야기합니다.
    1. 컴파일 시점에 데이터 구조나 타입 검증이 불가능하여 런타임 시 ClassCastException 등의 오류가 발생할 수 있습니다.
    2. API 스펙(필드명, 데이터 타입)을 코드나 문서(Swagger 등)를 통해 명확히 파악하기 어렵습니다.
    3. API 스펙이 변경되었을 때 영향 범위를 파악하기 어렵고 유지보수성이 극도로 저하됩니다.
  • 개선 제안:
    요청과 응답 스펙에 맞는 명확한 DTO(Data Transfer Object) 클래스 또는 Java Record를 정의하여 사용해야 합니다.
  • 개선 예시:
// DTO 예시 정의
public record SpontaneousRecommendRequest(
    List<String> keywords,
    String currentRegion
) {}

public record SpontaneousRecommendResponse(
    List<DestinationDto> destinations
) {}

public record DestinationDto(
    String name,
    double latitude,
    double longitude
) {}

// Controller 적용 예시
@PostMapping("/destinations")
public ResponseEntity<SpontaneousRecommendResponse> recommendDestinations(
        @RequestBody SpontaneousRecommendRequest request
) {
    SpontaneousRecommendResponse response =
            fastApiSpontaneousClient.recommendDestinations(request);
    return ResponseEntity.ok(response);
}

4. [MEDIUM] FastApiSpontaneousClient 비활성화 시 IllegalStateException 발생으로 인한 500 에러 유발

  • 파일: src/main/java/com/server/external/spontaneous/FastApiSpontaneousClient.java
  • 라인: 26-30
  • 문제점:
    properties.enabled()false인 경우 IllegalStateException을 던지고 있습니다. 이 예외가 컨트롤러 단까지 그대로 전파되면, 별도의 예외 처리가 없는 한 스프링 부트는 사용자에게 500 Internal Server Error를 반환하게 됩니다.
    기능 비활성화는 시스템 내부 오류(500)가 아니라 일시적으로 서비스를 제공할 수 없는 상태이므로, 사용자에게 503 Service Unavailable 또는 명확한 안내 메시지와 함께 4xx/5xx 에러를 반환하는 것이 올바른 API 설계입니다.
  • 개선 제안:
    비활성화 상태일 때 던질 전용 예외(예: ServiceUnavailableException 등)를 정의하거나, @ControllerAdvice 등에서 이를 캐치하여 503 Service Unavailable 상태 코드로 응답하도록 예외 처리 로직을 추가해야 합니다.
  • 개선 예시:
// 예외 클래스 정의 예시
@ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
public class ServiceDisabledException extends RuntimeException {
    public ServiceDisabledException(String message) {
        super(message);
    }
}

// Client 수정
if (!properties.enabled()) {
    throw new ServiceDisabledException("Spontaneous FastAPI 서비스가 현재 비활성화 상태입니다.");
}

Model: `gemini-3.5-flash` · API key: `PRIMARY` · Commit: `dfc4ba3`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant