우와한 개발자

[Spring] WebClient로 OpenAI API 연동하기

by 우와한개발자

1. 사전 준비

변수명 : OPENAI_API_KEY
값     : sk-xxxxxxxxxxxxxxxxxxxxxxxx

 

2. 프로젝트 설정 (build.gradle)

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'io.projectreactor:reactor-test'
    testCompileOnly 'org.projectlombok:lombok'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    testAnnotationProcessor 'org.projectlombok:lombok'
}

 

3. OpenAI API 키 설정

  • 시스템 환경변수에 등록한 API 키를 application.properties 에서 읽는다.
openai.api.key=${OPENAI_API_KEY}
openai.api.url=https://api.openai.com

 

4. WebClient 빈 설정

@Configuration
public class WebClientConfig {

    @Value("${openai.api.key}")
    private String openAiApiKey;

    @Value("${openai.api.url}")
    private String openAiApiUrl;

    @Bean
    public WebClient openAiWebClient() {
        return WebClient.builder()
                .baseUrl(openAiApiUrl)                          // 기본 URL 설정
                .defaultHeader("Authorization", "Bearer " + openAiApiKey)  // API 키 헤더
                .defaultHeader("Content-Type", "application/json")
                .build();
    }
}

 

5. 서비스 구현

@Service
@RequiredArgsConstructor
public class WebClientService {

    @Qualifier("openAiWebClient")
    private final WebClient webClient;

    public Mono<String> getChatCompletion(String userMessage) {

        // 요청 바디 구성
        Map<String, Object> requestBody = Map.of(
                "model", "gpt-4o-mini",
                "messages", List.of(
                        Map.of("role", "user", "content", userMessage)
                )
        );

        return webClient.post()
                .uri("/v1/chat/completions")       // OpenAI 엔드포인트
                .bodyValue(requestBody)             // 요청 바디 전송
                .retrieve()
                .bodyToMono(String.class)           // 응답을 String으로 수신
                .timeout(Duration.ofSeconds(30));   // 30초 초과 시 에러
    }
}

 

6. 컨트롤러 구현

@RestController
@RequiredArgsConstructor
public class WebClientController {

    private final WebClientService openAiService;

    @GetMapping("/chat/webclient")
    public Mono<String> chat(@RequestParam("q") String q) {
        return openAiService.getChatCompletion(q);  // 서비스로 위임
    }
}

 

7. 실행 및 테스트

GET <http://localhost:8080/chat/webclient?q=안녕하세요>
{
    "id": "chatcmpl-xxxxxx",
    "object": "chat.completion",
    "choices": [{
        "message": {
            "role": "assistant",
            "content": "안녕하세요! 무엇을 도와드릴까요?"
        }
    }]
}

블로그의 정보

우와한개발자 님의 블로그

우와한개발자

활동하기