Spring Configuration을 통한 설정

Kan9hee·2024년 4월 7일
0

컨테이너에 미리 담아놓자

@Configuration은 스프링에서 클래스를 통해 값, 또는 @Bean을 이용한 함수를 설정하여 지정된 객체에 의존성 주입을 할 수 있는 어노테이션이다. 즉 객체를 미리 생성시켜 두는 건데, 이는 객체 사이의 의존도를 낮추고 스프링 컨테이너에서 객체의 생명주기와 의존관계를 관리하기에 상당히 유연한 코드를 작성할 수 있다는 장점이 있다.

예를 들어, 다음과 같이 SMTP를 통해 메일을 발송하는 코드가 있다고 가정해보자.

예시

@Service
public class EmailService {
    public void sendMail(MailInfoDTO mailInfoDTO) throws MessagingException, IOException {
        MimeMessagePreparator preparator = mimeMessage -> {
            final MimeMessageHelper message = new MimeMessageHelper(mimeMessage,true,"UTF-8");

            message.setTo(mailInfoDTO.getReceiver());
            message.setFrom("example@gmail.com");
            message.setSubject(mailInfoDTO.getTitle());
            message.setText(mailInfoDTO.getContents()));
        };

		JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost("smtp.gmail.com");
        mailSender.setPort(465);
        mailSender.setUsername("example@gmail.com");
        mailSender.setPassword("examplePassword");

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.smtp.auth", true);
        props.put("mail.smtp.starttls.enable", true);
        mailSender.send(preparator);
    }
}

해당 코드는 JavaMailSenderImpl을 통해 정해진 계정으로 타인에게 메일을 전송하는데, sendMail을 실행할 때마다 mailSender 객체를 생성하여 리소스가 낭비되고, mailSender와 message.setFrom()을 설정하는 값이 하드코딩되어 가독성과 유지보수성이 낮다.

이를 @Configuration을 통해 미리 객체와 값을 설정하여 해결할 수 있다.


값 설정

먼저 하드코딩된 값들을 리소스 파일을 통해 설정하는 방법을 알아보자.
Configuration으로 선언된 클래스 내에 값을 직접 설정하면, 그 또한 하드코딩이기에 yml 설정 파일을 생성하여 설정한다.
해당 파일을 Spring Boot 프로젝트 내 resources폴더에 생성하고, application.properties에서 resources폴더 내에 생성한 yml 설정 파일 내의 값들을 가져온다.

values.yml

spring:
  mail:
    host: smtp.gmail.com
    port: 587
    username: example@gmail.com
    password: appPasswordFromGmail 
    encoding: UTF-8
    propString:
      auth: mail.smtp.auth
      enable: mail.smtp.enable
    smtp:
      auth: true
      starttls:
        enable: true

application.properties

spring.config.import=classpath:values.yml

이후, @Configuration과 @ConfigurationProperties를 통해 application.properties내에서 spring.mail 필드에 해당되는 값들을 불러온다. 불러온 값들은 @Getter를 통해 차후 호출할 수 있도록 한다. spring.mail 필드에서 파생되는 필드들에 대해서는 내부에 별도로 클래스를 생성하여 이를 매핑한다.

MailConfig

@Configuration
@ConfigurationProperties(prefix = "spring.mail")
@Data
public class MailConfig {
    private String host;
    private Integer port;
    private String username;
    private String password;
    private String encoding;
    private PropString propString; //파생 필드
    private Smtp smtp; //파생 필드

	@Data
    public static class PropString{
    	private String auth;
        private String enable;
    }

    @Data
    public static class Smtp {
        private boolean auth;
        private Starttls starttls; //파생 필드

        @Data
        public static class Starttls {
            private boolean enable;
        }
    }
}

객체 설정

다음은 객체를 미리 설정하는 방법이다.
JavaMailSender 구현체를 반환하는 javaMailSender 매서드를 빈으로 등록하여 애플리케이션이 시작될 때 JavaMailSender 빈이 필요할 때마다 새로운 인스턴스를 생성하는 것이 아니라, 미리 생성된 인스턴스를 사용하도록 한다.
다만 MimeMessageHelper는 메일의 내용을 설정하는데 사용되는데, 메일 전송 후에도 내용이 메모리에 남아있을 수 있어, 이전 메일의 내용이 다음 메일에 영향을 주지 않도록 각각의 메일마다 새로운 MimeMessageHelper 인스턴스를 생성해야 하므로 설정하지 않는다.

MailSenderConfig

@Configuration
public class MailSenderConfig {
    @Autowired
    private MailConfig mailConfig;

    @Bean
    public JavaMailSender javaMailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(mailConfig.getHost());
        mailSender.setPort(mailConfig.getPort());
        mailSender.setUsername(mailConfig.getUsername());
        mailSender.setPassword(mailConfig.getPassword());

        Properties props = mailSender.getJavaMailProperties();
        props.put(mailConfig.getPropString().getAuth(), mailConfig.getSmtp().isAuth());
        props.put(mailConfig.getPropString().getEnable(), mailConfig.getSmtp().getStarttls().isEnable());

        return mailSender;
    }
}

결과물

EmailService

@Service
@RequiredArgsConstructor
public class EmailService {

	private final MailSenderConfig mailConfig
    private final JavaMailSender mailSender;

    public void sendMailWithCurrentInfo(CurrentNewsDTO currentNewsDTO) throws MessagingException, IOException {
        MimeMessagePreparator preparator = mimeMessage -> {
            final MimeMessageHelper message = new MimeMessageHelper(mimeMessage,true,mailConfig.getEncoding());

            message.setTo(currentNewsDTO.getReceiver());
            message.setFrom(mailConfig.getUsername());
            message.setSubject(currentNewsDTO.getTitle());
            message.setText(currentNewsDTO.getNewsUrl());
        };

        mailSender.send(preparator);
    }
}

0개의 댓글