https://tes1194.tistory.com/100
무작정 구글링을 통해 이메일 인증 기능을 구현하는데 성공했습니다.
이메일 인증 기능에서 properties 설정을 해주는데,
properties가 무엇인며 왜-언제 사용하고, 어떻게 사용하는지에 대해 알아봤습니다
Properties란 무엇이고 언제 사용될까요?
Properties(Java 속성 파일)은 프로젝트 구성 데이터 또는 설정을 저장하는 데 사용됩니다.
그렇다면 왜 설정을 수정하는 일이 필요할까요?
로컬서버의 properties에는 로컬 DB정보를, dev서버의 properties에는 공용 DB정보를,
실제 운영 서버의 properties에는 실제 사용자들의 데이터를 담는 DB정보를 저쟝해야합니다.
즉 동일한 소스코드에 실행하는 환경에 따라서 여러가지 설정정보(properties)를 동적으로 변경하고 싶을 때 사용할 수 있어요.
properties 파일이 여러 개가 될 거고 그 중 하나를 고르는게 Spring profile 입니다.
만약 A, B properties 파일을 만들어 놨다면, 동일한 소스코드를 실행할 때 Spring profile 으로 A 를 주면 A properties 가 사용되고, B 를 주면 B properties 가 사용되는 것이라고 이해할 수 있습니다.
properties 설정 방법
- java.util.Properties 클래스는 프로그램 설정정보를 개발코드에 불러오거나 새로운 정보를 추가, 수정, 저장 할 수 있게 해줍니다.
Properties 클래스는 Map의 속성인 key와 values 를 String 형태로 가지고 있습니다.
즉 (String, String) 형태입니다. get, set, put 메서드를 제공합니다.
public class PropertiesEx1 {
public static void main(String[] args) {
Properties prop = new Properties();
// prop에 키와 값(key,value)를 저장
prop.setProperty("timeout", "30");
prop.setProperty("language", "kr");
prop.setProperty("size", "10");
prop.setProperty("capacity", "10");
// prop 저장된 요소들을 출력
Enumeration enumeration = prop.propertyNames();
while (enumeration.hasMoreElements()) {
String element = (String) enumeration.nextElement();
System.out.println(element + "=" + prop.getProperty(element));
}
System.out.println();
prop.setProperty("size", "20"); // size의 값을 20으로 변경
System.out.println("size=" + prop.getProperty("size"));
System.out.println("capacity=" + prop.getProperty("capacity", "20"));
System.out.println("loadfactor=" + prop.getProperty("loadfactor", "0.75"));
System.out.println(prop); // prop에 저장된 요소들을 Map 형태로 출력
}
}
출력값입니다.
- 데이터를 저장하는데 사용되는 setProperty()는 단순히 Hashtable의 put메서드를 호출합니다.
- setProperty()는 기존에 같은 키로 저장된 값이 있는 경우 그 값을 Object타입으로 반환하며 그렇지 않을 경우 null을 반환합니다.
- prop.setProperty("size", "10");는 null을 반환하고,
- prop.setProperty("size", "20");는 Object 타입의 10 을 반환합니다. - getProperty()는 properties에 저장된 값을 가져옵니다. 이미 저장된 키-벨류가 없다면 getProperty()를 호출할 때 지정한 기본값(default: 0.75)을 반환합니다.
- Properties는 컬렉션프레임워크 이전의 구버전이기 때문에 Iterator가 아닌 Enumeration을 사용합니다.
- @ConfigurationProperties
1. properties 파일에서 설정 정보를 @ConfigurationProperties 에노테이션이 붙은 클래스로 가져오기
@Configuration
@ConfigurationProperties(prefix = "mail")
@Getter
@Setter
public class ConfigProperties {
private String hostName;
private int port;
private String from;
}
#Simple properties
mail.hostname=host@mail.com
mail.port=9000
mail.from=mailer@mail.com
이렇게 설정하면 Spring 에서 변수에 맞는 값을 바인딩 해줍니다.
2. @ConfigurationProperties 이 붙은 클래스에서 Validation
@NotBlank
private String hostName;
@Length(max = 4, min = 1)
private String authMethod;
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;
3. Bean 메서드에 @ConfigurationProperties 사용하기
@Configuration
public class ConfigProperties {
@Bean
@ConfigurationProperties(prefix = "item")
public Item item() {
return new Item();
}
}
https://tes1194.tistory.com/100
위 포스팅에 있는 코드를 바꿔보겠습니다.
EmailConfig 에 properties 가져오기
@Configuration
@ConfigurationProperties(prefix = "spring.mail")
@Getter
@Setter
public class EmailConfig {
private String host;
private int port;
private String username;
private String password;
private boolean auth;
private boolean starttlsEnable;
private int timeout;
@Bean
public JavaMailSender javaMailService() {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(this.host);
javaMailSender.setPort(this.port);
javaMailSender.setUsername(this.username);
javaMailSender.setPassword(this.password);
javaMailSender.setJavaMailProperties(getMailProperties());
return javaMailSender;
}
private Properties getMailProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", String.valueOf(auth));
properties.setProperty("mail.smtp.starttls.enable", String.valueOf(starttlsEnable));
properties.setProperty("mail.smtp.timeout", String.valueOf(timeout));
properties.setProperty("mail.transport.protocol", "smtp");
properties.setProperty("mail.debug", "true");
properties.setProperty("mail.smtp.ssl.trust","smtp.gmail.com");
properties.setProperty("mail.smtp.ssl.enable","false");
return properties;
}
}
이를 SRP(단일 책임 원칙, Single Responsibility Principle) 적용하여 EmailProperties 만들기.
@Component
@ConfigurationProperties(prefix = "spring.mail")
@Getter
@Setter
public class EmailProperties {
private String host;
private int port;
private String username;
private String password;
private boolean auth;
private boolean starttlsEnable;
private int timeout;
private String protocol;
private boolean debug;
private String trust;
private boolean sslEnable;
public Properties toProperties() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", String.valueOf(auth));
properties.setProperty("mail.smtp.starttls.enable", String.valueOf(starttlsEnable));
properties.setProperty("mail.smtp.timeout", String.valueOf(timeout));
properties.setProperty("mail.transport.protocol", String.valueOf(protocol));
properties.setProperty("mail.debug", String.valueOf(debug));
properties.setProperty("mail.smtp.ssl.trust", String.valueOf(trust));
properties.setProperty("mail.smtp.ssl.enable",String.valueOf(sslEnable));
return properties;
}
}
@Configuration
public class EmailConfig {
private final EmailProperties emailProperties;
@Autowired
public EmailConfig(EmailProperties emailProperties) {
this.emailProperties = emailProperties;
}
@Bean
public JavaMailSender javaMailService() {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(emailProperties.getHost());
javaMailSender.setPort(emailProperties.getPort());
javaMailSender.setUsername(emailProperties.getUsername());
javaMailSender.setPassword(emailProperties.getPassword());
javaMailSender.setJavaMailProperties(emailProperties.toProperties());
return javaMailSender;
}
}
튜터님의 조언을 듣고 아래와 같이 수정했습니다.
@Configuration
public class EmailConfig {
private final EmailProperties emailProperties;
@Autowired
public EmailConfig(EmailProperties emailProperties) {
this.emailProperties = emailProperties;
}
@Bean
public JavaMailSender javaMailService() {
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost(emailProperties.getHost());
javaMailSender.setPort(emailProperties.getPort());
javaMailSender.setUsername(emailProperties.getUsername());
javaMailSender.setPassword(emailProperties.getPassword());
javaMailSender.setJavaMailProperties(setProp());
return javaMailSender;
}
private Properties setProp() {
Properties properties = new Properties();
properties.setProperty("mail.smtp.auth", String.valueOf(emailProperties.isAuth()));
properties.setProperty("mail.smtp.starttls.enable", String.valueOf(emailProperties.isStarttlsEnable()));
properties.setProperty("mail.smtp.timeout", String.valueOf(emailProperties.getTimeout()));
properties.setProperty("mail.transport.protocol", emailProperties.getProtocol());
properties.setProperty("mail.smtp.ssl.trust", emailProperties.getTrust());
return properties;
}
}
@Component
@ConfigurationProperties(prefix = "spring.mail")
@Getter
@Setter
public class EmailProperties {
private String host;
private int port;
private String username;
private String password;
private boolean auth = true;
private boolean starttlsEnable = true;
private int timeout = 5000;
private String protocol;
private String trust;
}
이렇게 하면 EmailProperties는 설정 정보를 바인딩하기 위한 객체로서 남고,
EmailConfig는 메일에 관한 설정 정보를 set하여 반환하는 책임을 갖습니다.
위와 같이 바꾸는 것이 단일 책임 원칙에 더 맞는 코드인 것 같습니다.
참고 : https://www.baeldung.com/configuration-properties-in-spring-boot
Guide to @ConfigurationProperties in Spring Boot | Baeldung
A quick and practical guide to @ConfigurationProperties annotation in Spring Boot.
www.baeldung.com
'Spring > Spring 문법' 카테고리의 다른 글
QueryDSL이란 무엇일까?? (0) | 2024.11.14 |
---|---|
@RequestParam 에서 매개 변수에 null 넣기 (0) | 2024.11.14 |
Spring boot 에서 이메일 인증 구현하기 (googleEmail) - Bean 만들어서 주입하기 (0) | 2024.10.24 |
Spring boot 에서 이메일 인증 구현하기 (googleEmail) - JavaMailSender 자동 주입 (2) | 2024.10.24 |
ResponseEntity란 무엇일까? (2) | 2024.10.24 |