백엔드 개발/Spring&JPA

[리팩토링] HTTP Client 및 RestTemplate을 OpenFeign으로 전환하기 + Resilience4j 서킷 브레이커 패턴 적용

태기 2025. 4. 6. 01:44

[핵심 요약]

1. 자체 HTTP Client 및 RestTemplate을 OpenFeign으로 전환

  • 기존에는 RestTemplate이나 직접 구현한 HTTP Client를 사용하여 외부 API를 호출했지만, 이를 OpenFeign으로 변경했다.
  • OpenFeign을 사용하면 API 호출을 인터페이스 기반으로 선언형으로 작성할 수 있어 코드가 간결해지고 유지보수가 쉬워진다.
  • 테스트 시에도 API 호출을 Mock 객체로  대체하기 쉬워 테스트 용이성이 증가한다. 

2. OpenFeign + Resilience4j로 서킷 브레이커 패턴 적용

  • 기존 HTTP Client에서 네트워크 장애가 발생하면, 응답 시간이 지연되거나 서버 부하가 증가하는 문제가 있었다.
  • 이를 Resilience4j서킷 브레이커 패턴을 활용해 해결했다.
  • OpenFeign을 사용할 때 Resilience4j를 적용하면, 장애 발생 시 즉시 실패 처리하고, 특정 시간 동안 API 호출을 차단하여 서버가 과부하되지 않도록 보호한다.

 


1. [Before] 기존 RestTemplate 사용 방식 (예시)

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;

@Service
public class UserService {
	
    private final RestTemplate restTemplate = new RestTemplate();
    
    public String getUserInfo(Long userId) {
    	String url = "http://localhost:8080/users/" + userId;
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        return response.getBody();
    }
}

[문제점]

- HTTP 요청을 직접 생성해야 하고, 예외 처리 및 장애 대응을 수동으로 구현해야 한다.

- API 호출 코드가 많아지고 테스트하기 어렵다.

 

2. [After] OpenFeign 적용 방식

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(name = "userClient", url = "https://api.example.com")
public interface UserClient {

    @GetMapping("/users/{id}")
    String getUserInfo(@PathVariable("id") Long userId);
}

[장점]

- API 호출 로직이 인터페이스 선언만으로 간결해진다.

- 테스트 시 이 인터페이스를 Mock 객체로 대체가 가능하다.

 

 

3. [Resilience4j 적용] 서킷 브레이커 추가

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    private final UserClient userClient;

    public UserService(UserClient userClient) {
        this.userClient = userClient;
    }

    @CircuitBreaker(name = "userService", fallbackMethod = "fallbackUserInfo")
    public String getUserInfo(Long userId) {
        return userClient.getUserInfo(userId);
    }

    public String fallbackUserInfo(Long userId, Throwable t) {
        return "Default User Info"; // 장애 발생 시 기본 응답 반환
    }
}

[서킷 브레이커 기능]

- API 요청이 반복적으로 실패하면, 일정 기간 동안 요청을 차단하여 서버 과부하를 방지한다.

- 장애 발생 시 fallbackUserInfo() 메서드를 호출하여 기본 응답을 반환한다.

- Resilience4j 덕분에 안정적인 API 호출 구조를 유지할 수 있다.

 

 

4.  결론

- 기존의 HTTP Clinet, RestTemplate을 OpenFeign으로 전환하여 코드를 간결화하고 테스트 용이성을 증가시켰다.

- OpenFeign에 Resilience4j 서킷 브레이커 패턴을 적용하여, API 장애 발생 시 즉시 실패 처리하고 서버 과부하를 방지한다.