
마이크로서비스 아키텍처(MSA)는 각각 독립적으로 배포 및 운영될 수 있는 서비스로 구성됩니다. 그러나 이러한 독립성에도 불구하고, MSA 환경에서는 서비스 간에 통신이 필요한 경우가 빈번히 발생합니다. 이를 통해 각 서비스가 데이터를 공유하고 협력하여 사용자의 요구를 충족시킬 수 있습니다.
MSA 간의 통신은 크게 두 가지 방식으로 나뉩니다: 동기 방식과 비동기 방식입니다.
FeignClient는 스프링 클라우드에서 제공하는 선언형 HTTP 클라이언트로, 동기 방식의 통신을 간결하고 효율적으로 구현할 수 있게 해줍니다. Feign을 사용하면 직접 RestTemplate 코드를 작성하지 않고, 인터페이스와 애노테이션만으로 HTTP 요청을 처리할 수 있습니다.
// Feign Client
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.0.2'
FeignClient를 사용하려면 스프링 부트 애플리케이션에 @EnableFeignClients 애노테이션을 추가합니다.
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class FicketUserApplication {
public static void main(String[] args) {
SpringApplication.run(FicketUserApplication.class, args);
}
}
@FeignClient(name = "ticketing-service", fallbackFactory = TicketingServiceClientFallbackFactory.class)
public interface TicketingServiceClient {
@GetMapping("/api/v1/ticketing/order/my")
List<MyTicket> getMyTickets(@RequestParam Long userId);
}
FeignClient 인터페이스를 주입받아 서비스를 호출합니다.
@Slf4j
@Service
@Transcation
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final TicketingServiceClient ticketingServiceClient;
/**
* 마이 티켓 조회 서비스
*
* @param userId 사용자 ID
* @return 마이 티켓 리스트
*/
public List<MyTicket> getMyTicket(Long userId) {
// 사용자 조회
User user = userRepository.findByUserId(userId)
.orElseThrow(() -> new BusinessException(ErrorCode.NOT_USER_FOUND));
// Feign Client를 사용하여 외부 서비스 호출
List<MyTicket> ticketInfoDtoList = ticketingServiceClient.getMyTickets(user.getUserId())
);
}
}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyTicket{
private Long orderId;
private LocalDateTime createdAt;
private LocalDateTime eventDateTime;
private String eventStageName;
private String sido;
private String eventPcBannerUrl;
private String eventMobileBannerUrl;
private String eventName;
private String companyName;
private List<MySeatInfo> mySeatInfoList;
}
FeignClient 호출 중 발생하는 에러를 처리하기 위해 ErrorDecoder를 설정합니다.
@Slf4j
@Component
public class FeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
log.error("Feign error occurred: status -> {} , methodKey -> {}", response.status(), methodKey);
switch (response.status()) {
case 400:
return new IllegalArgumentException("Invalid request for user tickets.");
case 404:
return new NotFoundException("Tickets not found for the given user.");
default:
return new Exception("General Feign Error");
}
}
}

FeignClient를 통해 ticketing-service에서 사용자 티켓 정보를 가져오는 HTTP 요청이 간단히 처리됩니다. 오류가 발생할 경우 설정된 ErrorDecoder가 동작하여 적절한 예외를 던집니다.
지금까지 FeignClient를 활용한 동기 방식의 마이크로서비스 통신 구현을 살펴보았습니다.
장애 상황에서 CircuitBreaker를 사용하면 특정 서비스가 일시적으로 문제가 있을 때 자동으로 대체 경로를 제공하거나 요청을 차단하여 시스템 전체의 안정성을 유지할 수 있습니다. 다음 단계에서는 이를 활용한 구현 방법을 다뤄보겠습니다.