ํ’€์Šคํƒ ์›น๐ŸŒ ๊ฐœ๋ฐœ์ž ์ง€๋ง์ƒ ๐Ÿง‘๐Ÿฝโ€๐Ÿ’ป
โž• ์ธ๊ณต์ง€๋Šฅ ๊ด€์‹ฌ ๐Ÿค–


Categories


Recent views

  • 1
  • 2
  • 3
  • 4
  • 5

Spring5-๊ตฌ์„ฑ ์†์„ฑ

  1. ์†์„ฑ
    • ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ
    • ํ”„๋กœํ•„

    ๊ตฌ์„ฑ ์†์„ฑ

    ๐Ÿ—ฃ๏ธ ์ถœ์ฒ˜

    _ ์ดˆ๋ณด ์›น ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์Šคํ”„๋ง 5 ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ž…๋ฌธ _์™€ ์Šคํ”„๋ง ์ธ ์•ก์…˜ ์˜ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

    ์†์„ฑ

    ์Šคํ”„๋ง์—๋Š” ๋‘ ๊ฐ€์ง€ ๊ตฌ์„ฑ์ด ํ•„์š”ํ•˜๋‹ค.

    • ๋นˆ์„ ์ƒ์„ฑํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ ๋“ฑ์— ์ƒํ˜ธ ์ฃผ์ž…๋˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ์–ธํ•˜๋Š” ๋นˆ ์—ฐ๊ฒฐ(Bean wiring)
    • ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์˜ ๋นˆ์˜ ์†์„ฑ๊ฐ’์„ ์ •ํ•˜๋Š” ์†์„ฑ ์ฃผ์ž…(Property injection)
      ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ์ด ๋‘˜์„ ์ƒ๋‹น๋Ÿ‰ ๋Œ€์‹  ํ•ด์ฃผ์ง€๋งŒ, ๊ธฐ๋ณธ ์„ค์ •์„ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด ๊ตฌ์„ฑ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

    • ์Šคํ”„๋ง ํ™˜๊ฒฝ ์ถ”์ƒํ™”(environment abstraction)
      ์†์„ฑ์˜ ๊ทผ์›์€ ์šด์˜์ฒด์ œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์˜ ์†์„ฑ ๊ตฌ์„ฑ ํŒŒ์ผ, ๋ช…๋ นํ–‰ ์ธ์ž, JVM ์‹œ์Šคํ…œ ์†์„ฑ ๋“ฑ ๋‹ค์–‘ํ•˜์ง€๋งŒ, ์ด๋ฅผ ์Šคํ”„๋ง์ด ํ•œ๋Œ€ ๋ชจ์•„ ๋นˆ๋“ค์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

    ์˜ˆ๋ฅผ ๋“ค์–ด ํฌํŠธ๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทผ์›๋“ค๋กœ ๊ฐ€๋Šฅํ•˜๋‹ค.

    • src/main/resources/application.properties์—์„œ server.port=9090
    • application.yml์—์„œ ์ง€์ •
    • java -jar tacocloud-0.0.5-SNAPSHOT.jar --server.port=9090
    • export SERVER_PORT=9090 ์šด์˜์ฒด์ œ ํ™˜๊ฒฝ๋ณ€์ˆ˜

    ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ

    ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ ์ƒ์„ฑ ๋ฐ ์œ„์น˜

    ์Šคํ”„๋ง์€ ๊ฐ„๋‹จํ•œ ์„ค์ •์œผ๋กœ ์™ธ๋ถ€์˜ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ์ด์šฉํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ db.properties ํŒŒ์ผ

    ${}๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

    db.driver=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://localhost/spring5fs?characterEncoding=utf8
    db.user=spring5
    db.password=${db.user}
    

    ๋‹ค์Œ์€ ์œ„ ๊ฐ™์€ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ์ด์šฉํ•˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค.

    โœ ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ๊ฒฝ์šฐ, ์ž๋™ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์œ„ ํŒŒ์ผ์„ src/main/resources ํด๋”์— ์œ„์น˜์‹œํ‚ค๋ฉด ๋์ด๋‹ค.
    1. PropertySourcesPlaceholderConfigurer ์ •์  ๋นˆ ํด๋ž˜์Šค ๋“ฑ๋ก
    โš ๏ธ PropertySourcesPlaceholderConfigurer ๋นˆ์€ ๋ฌด์กฐ๊ฑด static ํด๋ž˜์Šค์—ฌ์•ผ ํ•œ๋‹ค.
    ๐Ÿงพ๏ธ src/main/java/config/PropertyConfig.java
    package config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
    import org.springframework.core.io.ClassPathResource;
    
    @Configuration
    public class PropertyConfig {
    
        @Bean
        public static PropertySourcesPlaceholderConfigurer properties() {
            PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            configurer.setLocations(// ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ ๋ชฉ๋ก ์ „๋‹ฌ
                    new ClassPathResource("db.properties"),// ํด๋ž˜์Šค ํŒจ์Šค์— ์œ„์น˜ํ•œ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ 
                    new FileSytstemResources("../info.properties") // ํŒŒ์ผ ์‹œ์Šคํ…œ ํŠน์ • ํŒจ์Šค์— ์œ„์น˜ํ•œ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ
                    );
            return configurer;
        }
    }
    

    ํ”„๋กœํผํ‹ฐ ๊ฐ’ ์ „๋‹ฌ

    @Value๋ฅผ ์ด์šฉํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’ ์ „๋‹ฌ

    ์ดํ›„ ๊ตฌ์„ฑ ํด๋ž˜์Šค์—์„œ @Value("${ํ”„๋กœํผํ‹ฐํŒŒ์ผ๋ช….๊ฐ’}")์œผ๋กœ ๊ฐ’์„ ์ง€์ •ํ•ด์ค€๋‹ค.

    ๐Ÿงพ๏ธ @Value๋ฅผ ์ด์šฉํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’ ์ „๋‹ฌ
    package config;
    import org.apache.tomcat.jdbc.pool.DataSource;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration; 
    
    @Configuration
    public class DsConfigWithProp {
        @Value("${db.driver}")
        private String driver;
    
        @Value("${db.url}")
        private String jdbcUrl;
    
        @Value("${db.user}")
        private String user;
    
        @Value("${db.password}")
        private String password;
    
        @Bean(destroyMethod = "close")
        public DataSource dataSource() {
            DataSource ds = new DataSource();
            ds.setDriverClassName(driver);
            ds.setUrl(jdbcUrl);
            ds.setUsername(user);
            ds.setPassword(password);
            return ds;
        }
    }
    

    ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ๋นˆ ํด๋ž˜์Šค์—๋„ ๋นˆ ์ƒ์„ฑ์‹œ ๊ฐ’์„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ @Value ์–ด๋…ธํ…Œ์ด์…˜ ๋นˆ ํด๋ž˜์Šค ์‚ฌ์šฉ๋ก€
    package spring;
    
    import org.springframework.beans.factory.annotation.Value;
    
    public class Info {
        @Value("${info.version}")
        private String version; // ๋นˆ ํด๋ž˜์Šค์˜ version์ด ์ž๋™์œผ๋กœ info.version ๊ฐ’์œผ๋กœ ์ƒ์„ฑ
        private String author;
    
        public void printInfo() {
            System.out.println("version = " + version);
        } 
    
        public void setVersion(String version) {
            this.version = version;
        }
        
        @Value("${info.author}")
    	public void setAuthor(String author) { // setter ๋ฉ”์„œ๋“œ์—๋„ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
    		this.author = author;
    	}
    }
    

    @ConfigurationProperties๋ฅผ ์ด์šฉํ•œ ํ”„๋กœํผํ‹ฐ ๊ฐ’ ์ „๋‹ฌ

    ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์ด์šฉํ•  ๊ฒฝ์šฐ @ConfigurationProperties๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•ด๋‹น ๋นˆ์˜ ์†์„ฑ์„ ํ”„๋กœํผํ‹ฐ์—์„œ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•œ๋‹ค.

    ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์— taco.orders.pageSize: 10์ด๊ฑฐ๋‚˜ ์šด์˜์ฒด์ œ export TACO_ORDERS_PAGESIZE=10์œผ๋กœ ๊ฐ’์„ ์„ค์ •ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

    ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

    ๐Ÿงพ๏ธ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ๋งŒํผ ๋„˜๊ธฐ๊ธฐ
    //...
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.data.domain.Pageable;
    //...
    @Controller// ์ปจํŠธ๋กค๋Ÿฌ ๋นˆ ์„ค์ •
    @RequestMapping("/orders")
    @SessionAttributes("order")
    // ํ•ด๋‹น ๋นˆ์˜ ์†์„ฑ์„ ํ”„๋กœํผํ‹ฐ์—์„œ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜
    @ConfigurationProperties(prefix="taco.orders") // taco.orders์˜ ๊ฐ’๋“ค ๊ฐ€์ ธ์˜ค๊ธฐ
    public class OrderController {
    	private int pageSize = 20; // taco.orders.pageSize=10์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ๋จ
    
    	public void setPageSize(int pageSize) {
    		this.pageSize = pageSize;
    	}
    
    	//...
    
    	@GetMapping
    	public String ordersForUser(
    	@AuthenticationPrincipal User user, Model mode) {
    		Pageable pageable = PageRequest.of(0, pageSize);
    		model.addAttributes("orders",
    			orederRepo.findByUserOrderByPlacedAtDesc(user, pageable));
    		return "orderList";
    	}
    }
    

    ์œ„์˜ ๊ฒฝ์šฐ ๋ณด๋‹ค๋Š” ์ฃผ๋กœ ๊ตฌ์„ฑ ๋ฐ์ดํ„ฐ ํ™€๋”๋ฅผ ์˜๋ฏธํ•˜๋Š” Props๋ฅผ ๋ถ™์ธ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๋นˆ์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

    ๐Ÿงพ๏ธ ๊ตฌ์„ฑ ์†์„ฑ ํ™€๋” ์ •์˜

    ์†์„ฑ์˜ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•œ OrderProps ์†์„ฑ ํ™€๋”

    package tacos.web;
    
    import javax.validation.constraints.Max;
    import javax.validation.constraints.Min;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    import lombok.Data; 
    
    @Component
    @ConfigurationProperties(prefix="taco.orders")
    @Data
    @Validated
    public class OrderProps {
        @Min(value=5, message="must be between 5 and 25")
        @Max(value=25, message="must be between 5 and 25")
        private int pageSize = 20;
    }
    

    ์ด๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ OrderController ์ฝ”๋“œ ๋ณ€๊ฒฝ
    //...
    @Slf4j
    @Controller
    @RequestMapping("/orders")
    @SessionAttributes("order")
    public class OrderController {
        private OrderProps props;
        private OrderRepository orderRepo;  
    
        public OrderController(OrderRepository orderRepo, OrderProps props) {
            this.orderRepo = orderRepo;
            this.props = props;
        }
        //...
        @GetMapping
        public String ordersForUser(
                @AuthenticationPrincipal User user, Model model) {
            Pageable pageable = PageRequest.of(0, props.getPageSize());
            model.addAttribute("orders",
                    orderRepo.findByUserOrderByPlacedAtDesc(user, pageable));
            return "orderList";
        }
    }
    

    ํ”„๋กœํผํ‹ฐ ๊ตฌ์„ฑ ์˜ˆ์‹œ

    ๋ฐ์ดํ„ฐ ์†Œ์Šค ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ

    ๋ฐ์ดํ„ฐ์†Œ์Šค๋ฅผ ์ง์ ‘ ์ฝ”๋“œํ•˜์—ฌ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉด ์•„๋ž˜ ์ฒ˜๋Ÿผ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ application.yml ํŒŒ์ผ ์˜ˆ์‹œ
    spring:
    	datasource:
    		url: jdbc:mysql://localhost/tacocloud
    		usernmae: tacodb
    		password: tacopassword
    		driver-class-name: com.mysql.jdbcDriver # ์Šคํ”„๋ง ๋ถ€ํŠธ ์ด์™ธ์— ์ž๋™ JDBC ํด๋ž˜์Šค ์ง€์ •์ด ์•ˆ๋  ๊ฒฝ์šฐ ์ถ”๊ฐ€
    		
    		schema: # schema.sql, data.sql ์ด์™ธ์˜ ์ถ”๊ฐ€ sql ์‹คํ–‰์‹œํ‚ฌ ์‹œ ์ด์šฉ
    			- order-schema.sql 
    			- ingredient-schemal.sql
    		data:
    			- ingredients.sql
    		jndi-name: java:/comp/env/jdbc/tacoCloudDS # jndi๋ฅผ ์ด์šฉํ•œ ๊ตฌ์„ฑ, ์ด์šฉํ•  ๊ฒฝ์šฐ ์•ž์— ๊ฐ’๋“ค์ด ์ „๋ถ€ ๋ฌด์‹œ๋จ
    

    ์ปค๋„ฅ์…˜ ํ’€์˜ ๊ฒฝ์šฐ๋„ HikariCP, Commons DBCP 2 ๊ฐ™์€ ๊ธฐ๋ณธ ๊ฐ’์ด ์‹ซ์œผ๋ฉด ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์— ์ง€์ •ํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.
    JNDI๋Š” ๊ณต์‹ ๋ฌธ์„œ ์ฐธ์กฐ

    ๋‚ด์žฅ ์„œ๋ฒ„

    ์„œ๋ฒ„์˜ HTTPS ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ์ปจํ…Œ์ด๋„ˆ ๊ด€๋ จ ์„ค์ •์„ ์˜ˆ์‹œ๋กœ ๋ณด์ž.

    keytool -keystore mykeys.jks -genkey -alias tomcat -keyalg RSA
    
    
    1. ๋จผ์ € ํ‚ค ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด JDK์˜ keytool ์œ ํ‹ธ๋ฆฌํ‹ฐ๋กœ ํ‚ค์Šคํ† ์–ด๋ฅผ ์ƒ์„ฑํ•˜์ž.
      • ์ด๋•Œ ์•”ํ˜ธ, ์ €์žฅ ์œ„์น˜ ๋“ฑ์„ ์ž…๋ ฅํ•ด์•ผ ํ•œ๋‹ค.
    2. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ ์„ค์ •์„ ํ•ด์ฃผ์ž.
      ```yml
      server:
      port: 0 # ๋ณดํ†ต, 8443, ํฌํŠธ๋ฅผ 0์œผ๋กœ ํ•˜๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํฌํŠธ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ๊ฐ€์ ธ์˜ด
      ssl:
      key-store: file:///path/to/mykeys.jks # JAR ํŒŒ์ผ์˜ ๊ฒฝ์šฐ classpath:๋กœ URL ์ฐธ์กฐ
      key-store-password: ์ด์ „์—_์ง€์ •ํ–ˆ๋˜_์•”ํ˜ธ
      key-password: ์ด์ „์—_์ง€์ •ํ–ˆ๋˜_์•”ํ˜ธ
    #### ๋กœ๊น…
    ๊ธฐ๋ณธ์ ์œผ๋กœ ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ ์ œ๊ณต๋˜๋Š” Logback ๋กœ๊น… ๊ตฌ์„ฑ์„ ์œ„ํ•ด `logback.xml` ํŒŒ์ผ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ๋กœ๋„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
    
    ```yml
    logging:
    	path: /var/logs/
    	file: TacoCloud.log # ๋กœ๊ทธ๋ฅผ ์ €์žฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด์ฒ˜๋Ÿผ ๊ฒฝ๋กœ์™€ ํŒŒ์ผ๋ช…์„ ์ง€์ •
    	level: # ๋กœ๊น… ์ˆ˜์ค€์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ๋กœ๊ฑฐ ๋ณ„๋กœ ๋‹ค๋ฅธ ์ˆ˜์ค€์œผ๋กœ ์„ค์ •ํ•˜๊ฒŒ ํ•ด์คŒ
    		root: WARN # root๋Š” WARN
    		org.springframework: # .์„ ์ด์šฉํ•ด ํ•œ์ค„๋กœ ํ‘œํ˜„๋„ ๊ฐ€๋Šฅ
    				security: DEBUG # Spring Security ๋กœ๊ฑฐ๋Š” DEBUG
    
    

    ๊ธฐ๋ณธ์ ์ธ ๋กœ๊ทธ ํŒŒ์ผ ํฌ๊ธฐ๋Š” 10MB์ด๋ฉฐ, ๋„˜์œผ๋ฉด ์ƒˆ๋กœ์šด ๋กœ๊ทธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

    ๊ตฌ์„ฑ ์†์„ฑ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์„ ์–ธ

    ๊ตฌ์„ฑ ์†์„ฑ์„ ์ด์šฉํ•˜๋ฉด IDE์—์„œ๋Š” ์ด๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๊ฑฐ๋‚˜ ๊ฐ’์„ ๋ฐ”๋กœ ํ™•์ธํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž.

    1. ์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ์˜์กด ๋ชจ๋“ˆ์— org.springframework.boot.spring-boot-configuration-processor๋ฅผ ์ถ”๊ฐ€

    2. src/main/resources/META-INF/additional-spring-configuration-metadata.json ํŒŒ์ผ ์ƒ์„ฑ

    3. ์•„๋ž˜์™€ ๊ฐ™์ด ํŒŒ์ผ ๋‚ด์šฉ ์ถ”๊ฐ€

    ๐Ÿงพ๏ธ additional-spring-configuration-metadata.json ํŒŒ์ผ

    ๋Œ€๋ฌธ์ž์™€ - + ์†Œ๋ฌธ์ž๋Š” ์†์„ฑ ๋ช…์นญ์—์„œ ๊ฐ™์€ ์ทจ๊ธ‰ํ•œ๋‹ค.
    ex) pageSize == page-size

    {
    	"properties": [
    		{
    			"name": "taco.orders.page-size",
    			"type": "int",
    			"description": "Sets the maximum number of orders to display in a list."
    		}
    	]
    }
    

    ์ด์ œ ๋‚ด ์ปค์Šคํ…€ ์†์„ฑ ๋ช…์นญ๋งŒํผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด IDE์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋ณด์ธ๋‹ค.

    ํ”„๋กœํ•„

    ๊ฐœ๋ฐœ๊ณผ ์‹ค์ œ ์„œ๋น„์Šค ๊ฐ„์— DB, ๋กœ๊ทธ, ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋“ฑ์˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์ด ๋‹ฌ๋ผ์ง€๊ฒŒ ๋˜๋ฉฐ, ์ด ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •์„ ํ”„๋กœํ•„(Profile)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

    ์Šคํ”„๋ง์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋‹ค์–‘ํ•œ ํ”„๋กœํ•„ ๋ณ„๋กœ ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•˜๊ณ , ์ง€์ •ํ•œ ํƒœ๊ทธ์— ๋”ฐ๋ผ ํ”„๋กœํ•„ ์„ค์ •์„ ์ด์šฉํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

    ์ผ๋ถ€ ๋ฐฐํฌ์šฉ ํด๋ผ์šฐ๋“œ ์—์„œ๋Š” ํŠน์ • ํ”„๋กœํŒŒ์ผ๋ช…์„ ๊ฐ•์ œํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

    • ํด๋ผ์šฐ๋“œ ํŒŒ์šด๋“œ๋ฆฌ์—์„œ๋Š” cloud๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฐฐํฌ์šฉ ํ”„๋กœํ•„์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

    ํ”„๋กœํ•„์— ๋”ฐ๋ฅธ ๊ตฌ์„ฑ ํด๋ž˜์Šค ์ƒ์„ฑ

    @Profile ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ

    ๐Ÿงพ๏ธ ํ”„๋กœํ•„์˜ ์ƒ์„ฑ src/main/java/confi/DsDevConfig.java
    package config;
    
    import org.apache.tomcat.jdbc.pool.DataSource;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile; 
    
    @Configuration
    @Profile("dev")
    public class DsDevConfig {  
    
        @Bean(destroyMethod = "close")
        public DataSource dataSource() {
            DataSource ds = new DataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
            ds.setUsername("spring5");
            ds.setPassword("spring5");
    		// ...
            return ds;
        }
    }
    

    ํ”„๋กœํ•„ ๋ณ„ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ ์ƒ์„ฑ

    application-{ํ”„๋กœํ•„๋ช…}.yml ํ˜น์€ application-{ํ”„๋กœํ•„๋ช…}.properties๋ผ๋Š” ๋ช…์นญ์„ ํ†ตํ•ด ํŠน์ • ์ƒํ™ฉ์—๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

    ๋˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ”„๋ก ํŠธ๋งคํ„ฐ(---)๋กœ ๋‚˜๋ˆ„์–ด ๊ณตํ†ต ์†์„ฑ์„ ์ง€์ •ํ•˜๊ณ , spring.profiles ๊ฐ’์„ ํ†ตํ•ด ํ”„๋กœํ•„๋ช…์„ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ application.yml ํŒŒ์ผ
    logging:
    	level:
    		tacos: DEBUG # ๊ณตํ†ต๋œ ๋ชจ๋“  ํ”„๋กœํ•„์˜ ๊ธฐ๋ณธ ๊ฐ’
    --- # ์ƒˆ๋กœ์šด ํ”„๋กœํ•„ ์‹œ์ž‘
    spring:
    	profiles: prod # ํ”„๋กœํ•„๋ช… ์ง€์ •
    	datasource:
    		url: jdbc:mysql://localhost/tacocloud
    		username: tacouser
    		password: tacopassword
    
    logging:
    	level:
    		tacos: WARN # ๊ธฐ๋ณธ๊ฐ’ ๋ฎ์–ด์“ฐ๊ธฐ
    ---
    spring:
    	profiles: dev # ์ƒˆ๋กœ์šด ํ”„๋กœํ•„ ์‹œ์ž‘
    	datasource:
    		url: jdbc:mysql://localhost/tacocloud
    		username: tacouser
    		password: tacopassword
    

    ํ”„๋กœํ•„ ์„ ํƒ

    ๋‚ด๋ถ€ ์ฝ”๋“œ ๋ฐฉ๋ฒ•

    ๐Ÿงพ๏ธ ์„ค์ •ํ•œ ํ”„๋กœํ•„์˜ ์‚ฌ์šฉ src/main/java/main/MainProfile.java
    package main; 
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    //...
    public class MainProfile {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    		// getEnvironment: ํ”„๋กœํ•„ ํƒ์ƒ‰
    		// setActiveProfiles: ํ”„๋กœํ•„ ์„ ํƒ
    		context.getEnvironment().setActiveProfiles("dev"); //("dev", "real"); ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ”„๋กœํ•„ ์„ ํƒ ๊ฐ€๋Šฅ
    		
    		// ์ดํ›„ ์‚ฌ์šฉํ•  ๊ตฌ์„ฑ ํด๋ž˜์Šค๋ฅผ ๋“ฑ๋กํ•ด ์ค˜์•ผํ•จ. ์ˆœ์„œ ์ค‘์š”!
    		context.register(MemberConfig.class, DsDevConfig.class, DsRealConfig.class);
    
            //context.register(MemberConfigWithProfile.class);
            context.refresh();
    		//...
            context.close();
        }
    }
    

    ์œ„์ฒ˜๋Ÿผ Main ๋ฉ”์„œ๋“œ๋กœ ํ”„๋กœํ•„ ์„ ํƒํ•˜๋Š”๊ฒƒ ์ด์™ธ์— ์ถ”๊ฐ€๋กœ ์„ธ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•œ๋‹ค.

    • spring.profiles.active ์‹œ์Šคํ…œ ํ”„๋กœํผํ‹ฐ์— ์‚ฌ์šฉํ•  ํ”„๋กœํ•„ ๊ฐ’ ์ง€์ •
      • ๋‹ค์ˆ˜์˜ ๊ฒฝ์šฐ ์ฝค๋งˆ๋กœ ๊ตฌ๋ถ„ , ์šฐ์„ ์ˆœ์œ„ ์ค‘๊ฐ„
      • ex) System.setPropery("spring.profiles.active", "dev"), java -D spring.profiles.active=dev, real main.Main
    • OS ํ™˜๊ฒฝ ๋ณ€์ˆ˜ spring.profiles.active์— ์ง์ ‘ ๊ฐ’ ์„ค์ •
      • ์šฐ์„ ์ˆœ์œ„ ๊ฐ€์žฅ ๋‚ฎ์Œ
      • ex) spring.profiles.active = dev, real
    • application.yml ํŒŒ์ผ ๋‚ด์— spring.profiles.active=prod ๊ฐ™์ด ๊ฐ’ ์ง€์ •
      • ๋ณดํ†ต ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

    web.xml ์ด์šฉ

    ํ˜น์€ ์•„๋ž˜์™€ ๊ฐ™์ด web.xml์˜ spring.profiles.active ์ดˆ๊ธฐํ™” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํ”„๋กœํ•„์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค.

    <!--...-->
    <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
            <init-param>
                <param-name>spring.profiles.active</param-name>
                <param-value>dev</param-value>
            </init-param>
            <init-param>
                <param-name>contextClass</param-name>
                <param-value>
    org.springframework.web.context.support.AnnotationConfigWebApplicationContext
                </param-value>
            </init-param>
    <!--...-->
    
    

    ๋‹ค์ˆ˜ ํ”„๋กœํ•„ ์„ค์ • ๋ฐ ํ”„๋กœํ•„ ์ง‘ํ•ฉ ํด๋ž˜์Šค

    ์—ฌ๋Ÿฌ ํ”„๋กœํ•„ ํด๋ž˜์Šค๋ฅผ ํ•œ ์ค‘์ฒฉ ํด๋ž˜์Šค์— ๋ชจ์•„๋‘˜์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋•Œ ํ”„๋กœํ•„ ํด๋ž˜์Šค๋Š” ๋ฌด์กฐ๊ฑด static ํด๋ž˜์Šค์—ฌ์•ผ ํ•œ๋‹ค.

    ๋˜ํ•œ ์•„๋ž˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ ์„ค์ •์— ๋‘ ๊ฐœ ์ด์ƒ์˜ ํ”„๋กœํ•„์„ ์ฃผ๊ฑฐ๋‚˜ !๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๐Ÿงพ๏ธ ์ค‘์ฒฉ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•œ ํ”„๋กœํ•„ ๊ตฌ์„ฑ ํด๋ž˜์Šค
    //...
    @Configuration
    @EnableTransactionManagement
    public class MemberConfigWithProfile {
    	//...
    	@Configuration
        @Profile("dev, test") // dev && test ์‚ฌ์šฉ ์‹œ ํ™œ์„ฑํ™”
        // {"dev", "test"} : dev || test ์‚ฌ์šฉ์‹œ ํ™œ์„ฑํ™”
        public static class DsDevConfig {
    		@Bean(destroyMethod = "close")
            public DataSource dataSource() {
                DataSource ds = new DataSource();
                ds.setDriverClassName("com.mysql.jdbc.Driver");
                ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
                return ds;
            }
        }
      
        @Configuration
        @Profile("!real") // real์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„๋•Œ ํ™œ์„ฑํ™”
        public static class DsRealConfig {
            @Bean(destroyMethod = "close")
            public DataSource dataSource() {
                DataSource ds = new DataSource();
                ds.setDriverClassName("com.mysql.jdbc.Driver");
                ds.setUrl("jdbc:mysql://realdb/spring5fs?characterEncoding=utf8");
                ds.setUsername("spring5");
                ds.setPassword("spring5");
                return ds;
            }
        }
    }