Spring/Spring 문법

Java Spring properties

열심히 해 2024. 10. 26. 11:16

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