새소식

Java

[Spring] feign 에 대하여

  • -
728x90
프로젝트를 MSA 구조로 진행하며, 서비스 로직에서 다른 서비스의 API 를 호출해야 하는 경우가 빈번하게 생겼다. 이를 RestTemplate 을 통해 해결할 수도 있지만 보다 더 나은, 간편한 기능을 통해 풀어본 내용들을 기록하고 공유하고자 이 글을 작성한다.

 

Feign 은 Netflix 에서 개발된 Http client binder다. Feign 을 사용하면 웹 서비스 클라이언트를 보다 쉽게 작성할 수 있다. Feign 을 사용하기 위해서는 interface 를 작성하고 annotation 을 선언 하기만 하면 된다. 마치 Spring Data JPA 에서 실제 쿼리를 작성하지 않고 Interface 만 지정하여 쿼리실행 구현체를 자동으로 만들어주는 것과 유사하다. 

 

사용법

feign 을 사용하기 위한 준비도 그렇게 많지 않다.

 

의존성

ext {
	set('springCloudVersion', "2023.0.3")
}

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

 

build.gradle 에 위의 의존성을 추가해 주어야 한다. 

 

어노테이션

import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class CatalogServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(CatalogServiceApplication.class, args);
	}
}

 

 

1. @EnableFeignClients 을 사용해야 한다.
root package 에 있어야 하며, 그렇지 않은 경우 basePackages 또는 basePackageClasses 를 지정해주어야 한다.

 

2. @EnableFeignClients 은 지정된 package 를 돌아다니면서 @FeignClient 를 찾아 구현체를 만들어 준다.

 

예제 코드

CatalogService, 상품 서비스(package)에서 아래의 2가지 기능이 있다.

 

1. 상품 등록

2. 상품 삭제

 

상품을 등록할 때 List<String> 형식의 tag 를 추가로 넣어주는데, 이는 검색 서비스(package) 에서 해당 tag로 검색이 가능하게 되어야 하며, 이는 Cache 에 저장되는 형식이다. 그렇기에 상품을 등록하는 동시에 검색 서비스의 Cache 를 추가하는 API 를 호출해야 한다. 아래 코드를 통해 설명을 구체화 해보겠다.

 

먼저 인터페이스를 생성해 준다.

@FeignClient(name = "searchClient", url = "http://search-service:8080")
public interface SearchClient {

    @PostMapping(value = "/search/addTagCache")
    void addTagCache(@RequestBody ProductTagsDto dto);

    @PostMapping(value = "/search/removeTagCache")
    void removeTagCache(@RequestBody ProductTagsDto dto);
}

 

name: FeignClient의 bean name (다른 FeignClient의 name과 겹치면 안됨)
url: 해당 client의 base url
@GetMapping(value = “/api/”): RequestMethod와 api Path

 

통신해야 하는 API 는 addTagCache, removeTagCache 2개이다. 각각에 해당하는 Request Method Mapping 을 해주고 value 에 api Path 를 지정해준다. 

@Service
public class CatalogService {

    // MySQL
    @Autowired
    SellerProductRepository sellerProductRepository;

    // Cassandra
    @Autowired
    ProductRepository productRepository;

    @Autowired
    SearchClient searchClient;

    // 상품 등록
    public Product registerProduct(
        Long sellerId,
        String name,
        String description,
        Long price,
        Long stockCount,
        List<String> tags
    ) {
        // 등록
        var SellerProduct = new SellerProduct(sellerId);
        sellerProductRepository.save(SellerProduct);

        Product product = new Product(
                SellerProduct.id,
                sellerId,
                name,
                description,
                price,
                stockCount,
                tags
        );

        // Open feign
        var dto = new ProductTagsDto();
        dto.tags = tags;
        dto.productId = product.id;

        searchClient.addTagCache(dto);

        return productRepository.save(product);
    }

 

이제 실제 api 를 호출해야 하는 부분에 dto 를 생성하여 interface 에 작성한 메서드를 호출하기만 하면 된다.

 

이번 프로젝트에 꽤 많은 시간을 들이고 있다. 실제 회사에서 다루던 결제 서비스를 다른 언어, MSA 구조로 설계해 나가는 과정을 통해 꽤 많은 것들을 느끼며 재미있는 경험을 하고 있다. 앞으로도 더 많은 포스팅을 가지고 오겠다!

728x90
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.