์Šคํ”„๋ง ๋ถ€ํŠธ Auto Configuration

2023. 4. 25. 09:36ใ†์ธํ”„๋Ÿฐ/์Šคํ”„๋ง ๋ถ€ํŠธ - ํ•ต์‹ฌ ์›๋ฆฌ์™€ ํ™œ์šฉ

728x90

 

0๏ธโƒฃ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    //ํ…Œ์ŠคํŠธ์—์„œ lombok ์‚ฌ์šฉ
    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}

์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ Lombok, Spring Web, H2 Database, JDBC API ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ dependencies๋ฅผ ์ถ”๊ฐ€ํ•ด์คฌ๋‹ค.

 

 

Member

@Data
public class Member
{
   private String memberId;
   private String name;
   
   public Member()
   {
   }
   
   public Member(String memberId, String name)
   {
      this.memberId = memberId;
      this.name = name;
   }
}

์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ ํšŒ์›์„ ์ƒ์„ฑํ•˜๊ณ  ์ €์žฅํ•˜๋ฉฐ ์กฐํšŒํ•˜๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ๋กœ Member ํšŒ์›์—๋Š” memberId์™€ name ํ•„๋“œ๊ฐ€ ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค. 

 

 

DbConfig

@Slf4j
@Configuration
public class DbConfig
{
   
   @Bean
   public DataSource dataSource()
   {
      log.info("dataSource ๋นˆ ๋“ฑ๋ก");
      HikariDataSource dataSource = new HikariDataSource();
      dataSource.setDriverClassName("org.h2.Driver");
      dataSource.setJdbcUrl("jdbc:h2:mem:test");
      dataSource.setUsername("sa");
      dataSource.setPassword("");
      
      return dataSource;
   }
   
   @Bean
   public TransactionManager transactionManager()
   {
      log.info("transactionManager ๋นˆ ๋“ฑ๋ก");
      return new JdbcTransactionManager(dataSource());
   }
   
   @Bean
   public JdbcTemplate jdbcTemplate()
   {
      log.info("jdbcTemplate ๋นˆ ๋“ฑ๋ก");
      return new JdbcTemplate(dataSource());
   }
   
   
}

์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋Š” jdbcTemplate๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํšŒ์› ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ์—ฌ๊ธฐ์„œ๋Š” ์ง์ ‘ DataSource, TransactionManager, JdbcTemplate ์„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ง์ ‘ ๋“ฑ๋กํ•œ๋‹ค. 

(JdbcTanscationManager๋Š” DataSoureTransactionManager ์™€ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๋ณด๋ฉด ๋˜๋Š”๋ฐ JdbcTransactionManager๋Š” ๊ธฐ์กด์—์„œ ์˜ˆ์™ธ ๋ณ€ํ™˜ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.) 

 

 

MemberRepository

@Repository
public class MemberRepository
{
   
   public final JdbcTemplate template;
   
   public MemberRepository(JdbcTemplate template)
   {
      this.template = template;
   }
   
   public void initTable()
   {
      template.execute("create table member (member_id varchar primary key , name varchar)");
   }
   
   public void save(Member member)
   {
      template.update("insert into member(member_id, name) values (?,?)", member.getMemberId(), member.getName());
   }
   
   public Member find(String memberId)
   {
      return template.queryForObject(
            "select member_id , name from member where member_id = ? ", BeanPropertyRowMapper.newInstance(Member.class), memberId);
   }
   
   public List<Member> findAll()
   {
      return template.query("select member_id, name from member", BeanPropertyRowMapper.newInstance(Member.class));
   }
}

JdbcTemplate๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํšŒ์›์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์ด๋‹ค. 

 

*initTable : ๋ณดํ†ต ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋Š” ๋„ฃ์–ด๋‘์ง€ ์•Š๋Š”๋ฐ ์˜ˆ์ œ ํ”„๋กœ์ ํŠธ๋ผ์„œ ์—ฌ๊ธฐ์„  ๋‹จ์ˆœํžˆ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์— ๋„ฃ์–ด๋’€๋‹ค. 

 

 

MemberRepositoryTest

@SpringBootTest
class MemberRepositoryTest
{
   
   @Autowired
   MemberRepository memberRepository;
   
   @Transactional
   @Test
   void memberTest()
   {
      Member member = new Member("idA", "memberA");
      memberRepository.initTable();
      memberRepository.save(member);
      Member findMember = memberRepository.find(member.getMemberId());
      Assertions.assertThat(findMember.getMemberId()).isEqualTo(member.getMemberId());
      Assertions.assertThat(findMember.getName()).isEqualTo(member.getName());
   }
   
}

๊ทธ๋ฆฌ๊ณ  ๋งŒ๋“  ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ํ…Œ์ŠคํŠธํ•ด๋ณผ ๊ฒƒ์ธ๋ฐ ctrl+ shift + T ๋ˆ„๋ฅด๋ฉด ์‰ฝ๊ฒŒ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜์žˆ๋‹ค. (์ธํ…”๋ฆฌ์ œ์ด ๋‹จ์ถ•ํ‚ค ใ…Žใ…Ž) 

 

์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— @SpringbootTest ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ–ˆ๊ณ , 

@Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์„œ ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋Šฅ์„ ์ ์šฉํ–ˆ๋‹ค.  (์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด TransactionManager๊ฐ€ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.) 

 

 

๐Ÿ“š ์œ„์— ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ณ  ์ •์ƒ ๋™์ž‘ํ•˜๋ฉด ๋œ ๊ฒƒ์ธ๋ฐ... 

์ง€๊ธˆ ๋ณด๋ฉด ์ง์ ‘ DataSource, TransacionManager, JdbcTemplate๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์คฌ๋Š”๋ฐ.. 

DB๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋˜ ํ•œ๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋“ค์„ ๋ฐ˜๋ณตํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.. 

 

 

 

1๏ธโƒฃ ์Šคํ”„๋ง ๋ถ€ํŠธ ์ž๋™ ๊ตฌ์„ฑ Auto Configuration 

์‚ฌ์‹ค DbConfig์˜ @Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ์ œ๊ฑฐํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋„ ์ •์ƒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜์ง€ ์•Š์•„๋„ ์‚ฌ์‹ค ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ด์ค€๋‹ค. 

 

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์ž๋™ ๊ตฌ์„ฑ Auto Configuration ์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ˆ˜๋งŽ์€ ๋นˆ๋“ค์„ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.  ์•ž์—์„œ ๋ดค๋˜ JdbcTemplate, DataSource, TransactionManager ๋ชจ๋‘ ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ž๋™ ๊ตฌ์„ฑ(Auto Configuration) ์„ ์ œ๊ณตํ•ด์„œ ์ž๋™์œผ๋กœ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ค€๋‹ค. 

 

 

JdbcTemplateAutoConfiguration 

@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(JdbcProperties.class)
@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
      NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {

}

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” spring-boot-autoconfiguration ์ด๋ผ๋Š” ํ”„๋กœ์ ํŠธ ์•ˆ์—์„œ ์ˆ˜๋งŽ์€ ์ž๋™ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. 

@AutoConfiguration :  ์ž๋™ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. 

@ConditionalOnClass ({DataSource.class, JdbcTemplate.class}) 

: if ๋ฌธ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ๋˜๋Š”๋ฐ ์œ„์— ์ง€์ •ํ•œ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์„ค์ •์ด ๋™์ž‘ํ•˜๋„๋ก ์„ค์ •ํ•œ๋‹ค. ๋งŒ์•ฝ ์ด ํด๋ž˜์Šค๋“ค์ด ์—†๋‹ค๋ฉด ์—ฌ๊ธฐ ์žˆ๋Š” ์„ค์ •์„ ํ•˜์ง€ ์•Š๋Š”๋‹ค. 

 

 

JdbcTemplateConfiguration

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {

   @Bean
   @Primary
   JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
      JdbcProperties.Template template = properties.getTemplate();
      jdbcTemplate.setFetchSize(template.getFetchSize());
      jdbcTemplate.setMaxRows(template.getMaxRows());
      if (template.getQueryTimeout() != null) {
         jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
      }
      return jdbcTemplate;
   }

}

@Configuartion : ์ž๋ฐ” ์„ค์ • ํŒŒ์ผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. 

@ConditionalOnMissinigBean (JdbcOperationis.class)

: JdbcOperation ๋นˆ์ด ์—†์„ ๋•Œ ๋™์ž‘ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์œผ๋กœ JdbcOperations๋Š” JdbcTemplate์˜ ๋ถ€๋ชจ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ฆ‰, JdbcTemplate ๊ฐ€ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋™์ž‘ํ•œ๋‹ค. 

-> ์ฆ‰, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ JdbcTemplate ์„ ๋“ฑ๋กํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ๋“ฑ๋กํ•œ ๋นˆ์„ ์‚ฌ์šฉํ•˜๊ณ , ์ž๋™ ๊ตฌ์„ฑ์€ ๋™์ž‘ํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค. 

 

์ด๋Ÿฐ์‹์œผ๋กœ ์ž๋™ ๊ตฌ์„ฑ ๊ธฐ๋Šฅ๋“ค์ด ํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ค€๋‹ค. 

DataSource -> DataSourceAutoConfiguration 

TransactionManager -> DataSourceTransactionManagerAutoConfigurationi 

JdbcTemplate -> JdbcTemplateAutoConfiguration 

 

 

 

๐Ÿ’Œ Auto Configuration 

์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์ˆ˜ ๋งŽ์€ ์ž๋™ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•˜๊ณ , spring-boot-autoconfigure ์— ์ž๋™ ๊ตฌ์„ฑ์„ ๋ชจ์•„๋‘”๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ์Šคํ”„๋ง ๋ถ€ํŠธ ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด spring-boot-autoconfigure ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90