마이크로서비스 아키텍처(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를 사용하면 특정 서비스가 일시적으로 문제가 있을 때 자동으로 대체 경로를 제공하거나 요청을 차단하여 시스템 전체의 안정성을 유지할 수 있습니다. 다음 단계에서는 이를 활용한 구현 방법을 다뤄보겠습니다.