Feign은 원래 넷플릭스(Netflix)에서 개발한 HTTP 클라이언트 바인더입니다. Spring Cloud는 이 Feign이라는 도구를 통합해서 Spring과 함께 사용할 수 있도록 지원하는 기능을 제공합니다. 클라우드에서 제공하는 Spring Cloud OpenFeign이라는 형태의 도구를 사용하면, Spring Boot와 자연스럽게 연동하여 REST API 호출을 간편하게 처리할 수 있습니다.
@FeignClient 어노테이션으로 간단하게 외부 API 클라이언트를 정의할 수 있습니다.application.yml 또는 application.properties 파일에서 쉽게 환경 설정을 조정할 수 있습니다.build.gradle 파일에 Feign 의존성을 추가합니다.
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}
@EnableFeignClients 어노테이션 설정@EnableFeignClients를 사용해 Feign을 활성화합니다. Spring Boot 애플리케이션의 메인 클래스에 추가합니다.
@SpringBootApplication
@EnableFeignClients
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
이메일 전송을 처리하는 외부 API로 Mailgun을 이용해 보겠습니다.
Mailgun Open API란?
이메일 전송, 수신, 추적 기능을 제공하는 이메일 API 서비스입니다. 특히 대량 이메일 발송과 인증 메일 전송에 적합합니다. 복잡한 SMTP 설정 없이 REST API로 쉽게 전송 기능을 사용할 수 있습니다. 하루에 메일 전송이 100개 이하라면 무료 플랜으로 사용이 가능합니다.
Mailgun에서는 사용자에게 제공한 API키와 특정 도메인을 조합해서 이메일을 전송할 수 있는 엔드포인트를 제공합니다. 이를 Feign Client로 호출할 수 있게 설정합니다.
Mailgun API 키는 보안 상 민감한 정보이므로, Spring Boot의 application.yml 또는 환경 변수에 설정하는 것이 좋습니다.
# properties 파일
mailgun.key=YOUR_MAILGUN_API_KEY # Mailgun에서 받은 API key 값
mailgun.domain=YOUR_DOMAIN_ADDRESS # 호출할 domain 주소 (예: sandboxXXXXXX.mailgun.org)
FeignClient에서는 어떤 API를 호출할지 설정합니다. Feign을 통해 특정 API와 통신할 수 있는 인터페이스입니다. 아래 예시는 Mailgun 외부 API를 호출하는 코드입니다.
@FeignClient(name = "mailgun", url = "https://api.mailgun.net/v3")
public interface MailgunClient {
@PostMapping("/{domain}/messages")
void sendEmail(
@RequestHeader("Authorization") String authorization,
@PathVariable("domain") String domain,
@RequestBody SendMailForm emailRequest); // DTO를 사용해 Body 작성
}
FeignConfig에서는 특정 API를 호출할 때 어떻게 동작할지를 설정합니다. FeignClient가 작동할 때 필요한 설정을 정의하는 클래스입니다.
예시 코드에는 아래 설정 내용을 포함합니다.
@Configuration
public class FeignConfig {
// Mailgun API 키를 불러오기 위한 @Value 어노테이션
@Value("${mailgun.key}")
private String mailgunKey;
// Feign 클라이언트에 Mailgun 인증 정보를 추가하는 인터셉터
@Bean
@Qualifier("mailgun")
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("api", mailgunKey); // Mailgun은 기본적으로 api 키로 인증
}
// Feign 클라이언트의 타임아웃 설정 (연결 타임아웃: 5초, 읽기 타임아웃: 10초)
@Bean
public Feign.Builder feignBuilder() {
return Feign.builder()
.options(new Request.Options(5000, 10000)); // 연결 타임아웃 5초, 읽기 타임아웃 10초
}
// 예외 처리를 위한 커스텀 ErrorDecoder
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder(); // API 실패에 대한 맞춤형 예외 처리
}
// 리트라이 정책 설정 (100ms 대기 후 최대 3번까지 재시도)
@Bean
public Retryer retryer() {
return new Retryer.Default(100, 1000, 3); // 리트라이: 최대 3번 시도, 100ms부터 시작
}
}
// 커스텀 예외 처리를 위한 ErrorDecoder 구현
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() == 404) {
return new NotFoundException("리소스를 찾을 수 없습니다.");
} else if (response.status() >= 500) {
return new ServerErrorException("서버에 오류가 발생했습니다.");
}
return new Exception("알 수 없는 오류가 발생했습니다.");
}
}
발송 서비스 메소드에서 메일 데이터를 작성할 때 사용할 DTO를 만듭니다.
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Builder
public class SendMailForm {
private String from;
private String to;
private String subject;
private String text;
}
이제 실제 발송을 위한 서비스 메소드를 작성합니다.
@Service
@RequiredArgsConstructor
public class EmailService {
private final MailgunClient mailgunClient;
@Value("${mailgun.domain}")
private String domain; // application.properties에서 가져온 도메인
public void sendVerificationEmail(String email, String name, UserType type, String code) {
// 이메일 본문 생성
String emailBody = getVerificationEmailBody(email, name, type, code);
// DTO 사용해서 이메일 데이터 작성
SendMailForm emailForm = SendMailForm.builder()
.from("no-reply@yourdomain.com")
.to(email)
.subject("이메일 인증을 완료해 주세요")
.text(emailBody) // 생성한 이메일 본문을 삽입
.build();
// Mailgun API 호출하여 이메일 전송 (Authorization은 FeignConfig에서 자동으로 처리)
mailgunClient.sendEmail(domain, emailForm);
}
// 이메일 본문 생성 메소드 (서버 도메인 작성)
private String getVerificationEmailBody(String email, String name, UserType type, String code) {
return "안녕하세요, " + name + "님! 아래 링크를 클릭해서 인증을 완료해 주세요. \n\n" +
"http://localhost:8080/signUp/" + type + "/verify?email=" + email + "&code=" + code;
}
}
참고 공식 문서
Mailgun API Authentication
Mailgun Where can I find my API keys and SMTP credentials?