1. mailgun 가입 및 API key 발급
Transactional Email API Service For Developers | Mailgun
Powerful Transactional Email APIs that enable you to send, receive, and track emails, built with developers in mind. Learn more today!
www.mailgun.com
- 대시보드에서 왼쪽 Send-Sending-Domains에서 sandbox 확인
- 오른쪽에 이메일 전달받을 테스트 이메일 Verified 받아두기
- API Keys 접속 후, Mailgun API key 발급받기 (잘 메모해 두기!)
2. user-api 모듈 추가
- 루트 프로젝트의 Application.java 파일 삭제, build.gradle 내용 지우기
settings.gradle
rootProject.name = 'healthnewbie'
include 'user-api'
2. 의존성 추가
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.6'
id 'io.spring.dependency-management' version '1.1.5'
}
group = 'me.progfrog'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
ext {
set('springCloudVersion', "2023.0.1")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
dependencyManagement {
imports{
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
핵심은 이 2개의 의존성
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
spring cloud 2023.0.1 버전을 사용하기 위해 스프링 부트의 버전을 3.2.6으로 맞춰줬다.
Spring Cloud Train Reference Documentation :: Spring Cloud Release
Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus). Coordination of distributed
docs.spring.io
3. UserApplication 생성
package me.progfrog.healthnewbie.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
4. application.properties 수정
server.port = 8081
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
feign.okhttp.enabled=true
# profile
spring.profiles.include=secret
5. application-secret.properties 파일 생성
application-secret.properties
- 1에서 발급받은 mailgun key 작성하기
- 해당 파일은 깃허브 등에 업로드되지 않도록 주의
mailgun.key=mailgun key 작성
.gitignore 파일 수정
### etc ###
user-api/src/main/resources/application-secret.properties
캐시 삭제
git rm --cached user-api/src/main/resources/application-secret.properties
6. Config 추가
SwaggerConfig
package me.progfrog.healthnewbie.user.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import org.springframework.context.annotation.Configuration;
// http://localhost:8081/swagger-ui/index.html
@OpenAPIDefinition(
info = @Info(title = "API 명세서", description = "운동 좋아하는 사람 모여라 <헬린이>의 API 명세서", version = "1.0")
)
@Configuration
public class SwaggerConfig {
}
FeignConfig
package me.progfrog.healthnewbie.user.config;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Value(value = "${mailgun.key}")
private String mailgunKey;
@Qualifier(value = "mailgun")
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("api", mailgunKey);
}
}
- Feign 클라이언트의 설정을 정의하는 클래스
- @Configuation
- 이 클래스가 설정 클래스임을 나타냄
- 이 클래스는 빈을 정의하고 구성함
- @EnableFeginClients
- Feign 클라이언트를 활성화
- 이 애노테이션은 Feign 클라이언트를 스캔하고 구성하여 사용할 수 있도록 한다.
- @Value(value = "${mailgun.key}")
- application-secret.properties에서 mailgun.key라는 프로퍼티의 값을 가져와 mailgunKey 변수에 주입
- 이 변수는 mailgun API의 인증에 사용
- @Qualifier(value = "mailgun")
- 여러 개의 BasicAuthRequestInterceptor* 빈이 있을 때, mailgun이라는 이름으로 이 빈을 식별할 수 있도록 한다.
- @Bean
- 이 메서드가 스프링 컨텍스트의 빈으로 등록됨을 나타냄
- 이 메서드는 mailgunKey를 사용하여, BasicAuthRequestInterceptor 객체를 생성하고, 생성된 인터셉터는 Feign 클라이언트가 mailgun API를 호출할 때 인증 정보를 포함하도록 한다.
* BasicAuthRequestInterceptor
Feign 클라이언트가 HTTP 요청을 보낼 때, 기본 인증 헤더를 추가하는 인터셉터
7. MailgunClient
SendMailForm
package me.progfrog.healthnewbie.user.client.mailgun;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Builder
public class SendMailForm {
private String from;
private String to;
private String subject;
private String text;
}
MailgunClient
package me.progfrog.healthnewbie.user.client;
import feign.Response;
import me.progfrog.healthnewbie.user.client.mailgun.SendMailForm;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.PostMapping;
@FeignClient(name = "mailgun", url = "https://api.mailgun.net/v3/")
@Qualifier("mailgun")
public interface MailgunClient {
@PostMapping("sandbox18ce11a1f42a441e8183e7c255644a6e.mailgun.org/messages")
Response sendEmail(@SpringQueryMap SendMailForm form);
}
Feign 클라이언트
- Java의 HTTP 클라이언트 라이브러리로, 원격 서비스 호출을 추상화하고 쉽게 사용할 수 있도록 도와준다.
- Spring Cloud Netflix 프로젝트의 일부로서, RESTful 웹 서비스를 호출하기 위해 인터페이스 기반의 접근 방식을 제공
- Feign 클라이언트는 개발자가 RESTful 서비스와 상호작용할 때, 복잡한 HTTP 클라이언트 코드를 작성하지 않도록 도와준다.
- 인터페이스와 애노테이션을 사용하여 원격 서비스 호출을 선언적으로 정의할 수 있기 때문에, 코드의 가독성과 유지 보수성을 크게 향상시킨다.
특징 및 장점
1. 인터페이스 기반
- Feign 클라이언트는 RESTful 웹 서비스 호출을 위한 인터페이스를 정의하여 사용할 수 있다.
- 즉, HTTP 요청을 메서드 호출로 추상화한다.
@FeignClient(name = "example", url = "http://example.com")
public interface ExampleClient {
@GetMapping("/resource")
Resource getResource();
}
2. 선언적 접근
- 인터페이스에 애노테이션을 사용하여 요청 매핑을 정의한다.
- Spring MVC 애노테이션인 @GetMapping, @PostMapping 등을 사용할 수 있다.
3. 자동 구성
- Spring Boot와 함께 사용하면, 애플리케이션이 시작될 때 Feign 클라이언트가 자동으로 구성되고 빈으로 등록된다.
- @EnableFeiginClients 애노테이션을 사용하여 이를 활성화할 수 있다.
4. 쉽고 간결한 코드
- 복잡한 HTTP 요청 처리 코드 없이 간결하고 명확한 인터페이스로 REST API를 호출할 수 있다,
8. EmailSendService
package me.progfrog.healthnewbie.user.service;
import feign.Response;
import lombok.RequiredArgsConstructor;
import me.progfrog.healthnewbie.user.client.MailgunClient;
import me.progfrog.healthnewbie.user.client.mailgun.SendMailForm;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class EmailSendService {
private final MailgunClient mailgunClient;
public Response sendEmail() {
SendMailForm form = SendMailForm.builder().
from("healthnewbie@email.com")
.to("happyprogfrog@gmail.com")
.subject("Test email from healthnewbie")
.text("Hello, World!").build();
return mailgunClient.sendEmail(form);
}
}
EmailSendServiceTest
package me.progfrog.healthnewbie.user.service;
import feign.Response;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class EmailSendServiceTest {
@Autowired
private EmailSendService emailSendService;
@Test
void sendEmail() {
Response response = emailSendService.sendEmail();
System.out.println(response);
}
}
9. 마무리
테스트가 통과되고, 1에서 세팅해 둔 테스트 이메일에 이메일이 잘 전달되는 것을 확인! 메일이 확인되지 않는다면 스팸함 확인해 보기~~발송자에 임시 메일주소를 작성했더니 구글 메일이 귀신 같이 경고해주는 것을 알 수 있다ㅋㅋ똑똑하누...