chap05 구성속성

ChapJun·2022년 1월 5일
0

1. 스프링의 구성 속성

스프링에는 2가지 구성이 있습니다.

  • 빈 연결 : 스프링 애플리케이션 컨텍스트에서 빈으로 생성되는 컴포넌트 및 상호 간에 빈이 주입되는 방법을 선언하는 구성
  • 속성 주입 : 스프링 애플리케이션 컨텍스트에서 빈의 속성값을 설정하는 구성
@Bean
public DataSource dataSource() {
	return new EmbeddedDatabaseBuilder()  //내장데이터베이스 구성 클래스
		.setType(EmbeddedDataType.H2)      //h2가 준비되면
		.addScript("schema.sql")           //sql 스크립트 실행되어 db에 적용
		.addScript("user_data.sql","ingredient_data.sql")
		.build();
	}

1.1 스프링 환경 추상화

  • 구성 가능한 모든 속성을 한 곳에서 관리하는 개념

  • 속성을 주입하는 방법
#JVM 시스템 속성 (JVM VM arguments  -Dserver.port=8080)
System.getProperty("server.port")

#운영체제 환경 변수
$ export SERVER_PORT=8080

#명령행인자
java -jar tacocloud-0.0.1-SNATSHOT.jar --server.port=8080

#application.properties
server.port = 8080

#application.yml
server:
	port: 8080

1.2 데이터 소스 구성하기

현재 타코 애플리케이션은 내장 h2 데이터베이스를 사용합니다.

⇒ 만일 운영으로 반영하여 db를 MySql로 변경하게된다면??? 🤔

spring:
	datasource:
		url: jdbc:mysql://localhost/tacocloud            //(db주소)
		username: tacodb                                 //(db사용자 이름)
		password: tacopassword                           //(db사용자 패스워드)
        driver-class-name: com.mysql.jdbc.Driver 		 //(JDBC Driver)
    	schema:
        	- order-schema.sql
            	- ingredient-schema.sql
        data:
        	- ingredients.sql

이러한 속성 설정이 DataSource 빈을 자동구성할 때 연결 데이터로 사용된다.

1.3 내장 서버 구성하기

1.포트

# application.yml

server:
	port: 0  // 랜덤포트 (MSA에서 주로 사용)
  1. HTTPS
# 키스토어 생성

$ keystore -keystore mykeys.jks - genkey -alias tomcat -keyalg RSA
# HTTPS를 활성화 하기위한 속성 설정 (8443 포트의 HTTPS 요청을 기다린다.)

server: 
	port: 8443
ssl:
	key-store: file:///path/to/mykeys.jks                //keystore파일이 생성된 경로
	key-store-password: letmein                          
	key-password: letmein

1.4 로깅 구성하기

로깅구성을 제어할 때는 src/main/resources/logback.xml 파일을 생성하여 작성해야한다.
logback.xml 파일을 수정하여 원하는 형태로 로그 파일을 제어할 수 있지만 가장 많이 변경하는
로깅 수준과 로그파일은 스프링부트의 구성 속성을 사용하여 변경할 수 있습니다.

# logback.xml

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>
    <logger name="root" level="INFO"/>
        <root level="INFO">
    <appender-ref ref="STDOUT" />
    </root>
</configuration>
  • logging 설정
logging:
	path: /var/logs/					// 로그파일 저장경로
	file: TacoCloud.log					// 파일명
	level:
		root: WARN						// 로깅수준 WARN
		org:
			springframework:
				security: DEBUG			// 시큐리티의 로그는 DEBUG

1.5 다른 속성의 값 가져오기

다른 속성 값은 다음과 같이 ${} 을 사용하여 가져올 수 있습니다.

greeting:
	welcome: you are using ${spring.application.name}:${spring.application.instance_id:${random.value}}.    

2. 우리의 구성 속성 생성하기

구성속성의 올바른 주입을 위해 스프링부트는 @ConfigurationProperties 어노테이션을 제공한다.

2.1 구성 속성 홀더 정의하기

@ConfigurationProperties는 반드시 특정 빈에만 사용되는 것은 아니며 실제로 데이터의 홀더로 사용되는 경우가 많습니다. (관리 용이)

taco:
  orders:
    pageSize: 20
    
@Value("${taco.orders.pageSize}")
private int pageSize2;    
@Component
@ConfigurationProperties(prefix = "taco.orders")
@Data
@Validated
public class OrderProps {

    private int pageSize = 100;

    @Min(value = 10, message = "must be between 10 and 50")
    @Max(value = 50, message = "must be between 10 and 50")
    private int imgSize = 50;
}
@Slf4j
@Controller
@RequestMapping("/orders")
@SessionAttributes("order")
public class OrderController {

    @Autowired
    private OrderProps orderProps;

    private final Environment env;
    private final OrderRepository orderRepository;

    public OrderController(Environment env, OrderRepository orderRepository) {
        this.env = env;
        this.orderRepository = orderRepository;
    }

    @GetMapping()
    @ResponseBody
    public List<Order> ordersForUser(@AuthenticationPrincipal User user, Model model) {

        int pageSize = Integer.parseInt(env.getProperty("taco.orders.pageSize"));
        
        // .yml 파일에 있는 pageSize로 덮어 씌워짐
        log.info("PAGE SIZE : " + pageSize + " <-> PROP PAGE SIZE : " + orderProps.getPageSize()); 
        
        log.info("PROPS SIZE : " + orderProps.getImgSize());
        
        Pageable pageable = PageRequest.of(0, pageSize);
//        model.addAttribute("orders", orderRepository.findByUserOrderByPlacedAtDesc(user, pageable));

        return orderRepository.findByUserOrderByPlacedAtDesc(user, pageable);
    }
}
  • 구성속성의 우선순위
  1. 유저 홈 디렉토리에 있는 spring-boot-dev-tools.properties
  2. 테스트에 있는 @TestPropertySource
  3. @SpringBootTest 애노테이션의 properties 애트리뷰트
  4. 커맨드 라인 아규먼트
  5. SPRING_APPLICATION_JSON (환경 변수 또는 시스템 프로티) 에 들어있는 프로퍼티
  6. ServletConfig 파라미터
  7. ServletContext 파라미터
  8. java:comp/env JNDI 애트리뷰트
  9. System.getProperties() 자바 시스템 프로퍼티
  10. OS 환경 변수
  11. RandomValuePropertySource
  12. JAR 밖에 있는 특정 프로파일용 application properties / yml
  13. JAR 안에 있는 특정 프로파일용 application properties / yml
  14. JAR 밖에 있는 application properties / yml
  15. JAR 안에 있는 application properties / yml
  16. @ConfigurationProperties
  17. 기본 프로퍼티 (SpringApplication.setDefaultProperties)

2.2 구성 속성 메타데이터 선언하기

  • pom.xml
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
</dependency>
# /resources/META-INF/additional-spring-configuration-metadata.json

  "properties": [
    {
      "name": "taco.orders.page-size",
      "type": "java.lang.Integer",
      "description": "Description for taco.orders.pageSize.",
      "defaultValue": "20"
    }
  ]
}

2.3 프로파일 사용해서 구성하기

로컬/개발/운영 환경에 따른 속성 파일(.properties or .yml)을 정의할 수 있습니다.

  • application-{프로파일 이름}.yml(또는 properties)
  • application-dev.yml
  • application-stage.yml
  • application-prod.yml
spring:
  profiles:
    active: 
    	- dev		# 하나이상의 활성화 프로파일 지정 가능
        - audit
        - ha

---

# application-dev.yml

spring:
  config:
    activate:
      on-profile: dev
      
server:
  port: 7777

taco:
  orders:
    pageSize: 20

---

# application-test.yml

spring:
  config:
    activate:
      on-profile: test

server:
  port: 8888

2.4 프로파일을 사용해서 조건별로 빈 생성하기

  • 특정 프로파일이 활성화될 때만 생성되어야 하는 빈이 있다면 @Profile 을 사용해 적합한 빈들을 생성할 수 있습니다.
// dev 프로파일이 활성화 될때에만 빈 생성

@Bean
@Profile("dev")
public commandLineRunner dataLoader (IngredientRepository repo, UserRepository userRepo
, PasswordEncoder encoder){
		...
}

dev 프로파일이나 qa프로파일 중 하나가 활성화될 때 생성된다면 ?

→ @Profile({”dev”, “qa”})

prod 프로파일이 활성화되지 않을 때 생성된다면 ?

→ @Profile(”!prod”)

  • 클래스 전체에도 사용이 가능
@Profile({"!prod", "!qa"})
@Configuration
public class DevelopmentConfig {

	@Bean
    public commandLineRunner dataLoader (IngredientRepository repo, UserRepository userRepo,
    PasswordEncoder encoder) {
		...
	}

}
profile
Chap Chap

0개의 댓글