Open Yg-Hong opened 1 year ago
먼저 .properties
나 .ymal
파일을 알아보기 전 XML
으로 DB
관련 환경 설정을 진행해보겠습니다.
먼저 환경 설정 XML
파일을 생성합니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
생성한 XML
파일이며 여기서 DB
관련 환경 설정을 진행하도록 하겠습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg>
<bean class="com.zaxxer.hikari.HikariConfig">
<property name="jdbcUrl" value="jdbc:h2:tcp://localhost/~/code/study/db/config"/>
<property name="username" value="sa"/>
<property name="password" value="1234"/>
<property name="driverClassName" value="org.h2.Driver"/>
</bean>
</constructor-arg>
</bean>
</beans>
다음과 같이 XML
파일 안에 DB
관련 환경 설정을 하고 추가적으로 @ImportResource
에다가 해당 XML
파일을 등록해줍니다.
@SpringBootApplication
@ImportResource("classpath:application.xml") // XML 파일을 임포트
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
하지만 .. 실행이 정상적으로 되지 않았습니다. 뭔가 더 해야하는 것이 있는것을 추후 발견했습니다만 번거로운 작업이 필요합니다.
대략 30분 동안 XML
파일을 가지고 Spring
환경 설정을 해보려고 했지만 가독성도 매우 떨어지고 환경설정 방식도 매우 어려웠습니다.
먼저 XML
, yaml
, propreties
와 같은 파일 포맷에 대한 간단한 설명을 하겠습니다.
아래의 코드들은 각각 Spring
에서 DB
와 관련된 설정을 하기 위한 설정입니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg>
<bean class="com.zaxxer.hikari.HikariConfig">
<property name="jdbcUrl" value="jdbc:h2:tcp://localhost/~/code/study/db/config"/>
<property name="username" value="sa"/>
<property name="password" value="1234"/>
<property name="driverClassName" value="org.h2.Driver"/>
</bean>
</constructor-arg>
</bean>
</beans>
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:tcp://localhost/~/code/study/db/config
password: 1234
username: sa
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:tcp://localhost/~/code/study/db/config
spring.datasource.username=sa
spring.datasource.password=1234
각각의 파일에 따른 설정들이며 공통된 점으로는 key-Value
형식으로 이루어져 있습니다. 이러한 이유는 타 시스템 간에 데이터를 주고 받을 때 데이터 포맷에 대한 약속이 필요하기 때문입니다.2)
과거에 Spring
에서는 XML
을 사용하여 환경 설정과 같은 작업을 하였는데 현재 Spring
에서 XML
대신에 다른 포맷을 사용하는 이유 다음과 같습니다.
Properties
파일 및 YAML
파일은 XML
보다 더 간결하고 가독성이 좋습니다.
XML
은 태그 기반으로 작성되고 여는 태그와 닫는 태그가 필요하며 이로 인해서 불필요한 장황함이 발생할 수 있습니다.
위의 3가지 코드를 봐도
XML
이 가장 가독성이 좋지 않다는 것을 확인할 수 있습니다.
Properties
파일 및 YAML
파일은 리스트와 맵을 나타내기 위한 간단한 표기법을 제공합니다. 예를 들면 YAML
에서는 들여쓰기를 사용하여 리스트 및 맵을 정의할 수 있습니다.
2)
XML
에서는 복잡한 태그 구조를 사용하며 리스트와 맵을 나타내어야 하므로 번거롭고 복잡할 수 있습니다.
Properties
파일은 다양한 프로그래밍 언어와 플랫폼에서 사용 가능하며, YMAL
도 널리 사용됩니다.
현재는
YAML
이 더 많이 사용하는 것 같습니다.
XML
은 주로 Java
생태계에서 사용되며, 다른 환경에서는 해석하기가 어렵고 불편할 수 있습니다.
이러한 이유로
XML
은 점점 주류에서 벗어나게 되었습니다.
이제 Spring Boot
는 Properties
와 YAML
파일을 기본으로 지원하고 설정을 더 쉽게 관리할 수 있습니다.
XML
을 사용하려면 추가 설정이 필요하며, Spring Boot
의 자동 설정과 통합이 어렵습니다.
Spring
에서XML
을 사용하지 않는 가장 큰 이유라고 생각하고있습니다.
Properties
와 YAML
파일은 Spring
프로젝트에서 설정을 더 간편하게 관리하고 가독성을 높일 수 있는 선택입니다.
XML
은 특별한 경우나 레거시 시스템과의 통합 등 특수한 상황에서 사용될 수 있지만, 주로 Properties
나 YAML
을 선호하는 추세입니다.
추가적으로 요청했던 .properties
, .yaml
등 이런 파일이 스프링에서 설정 정보를 보관할 수 있도록 만든 원리는 무엇일까? 에 대한 내용에 대해서 찾아보고 정리합니다.
실제로 개발을 진행할 때 ymal
파일을 자주 사용하는데 관심이 있었던 주제이기 때문에 자세하게 찾아보며 코드도 찾아봅니다.
기존에 Spring
에서는 XML
로 모든 설정을 관리했는데 Spring Boot
에서는 정적인 값을 key-value
형식으로 관리합니다.
Properties
,YMAL
그러면 Spring Boot
는 어떻게 해당 값들을 사용하는 것 일까요?
해답은 @SrpingBootApplication
어노테이션에 있습니다.
@SpringBootApplication // 이 어노테이션
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
}
해당 어노테이션이 어떻게 구성되어 있는지 확인하면 다음과 같습니다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
위의 어노테이션 중 @EnableAutoConfiguration
이 자동 환경 설정을 도와줍니다.
Spring Boot
에서 개선된 점이며 Spring Boot
가 가지는 가장 큰 장점입니다.
자동으로 환경을 설정해주기 때문에 번거롭게 설정을 할 필요가 없어져 개발자들은 개발에만 집중할 수 있게 됩니다.
이 어노테이션 하나로 Web
, H2
, JDBC
를 비롯한 수 많은 자동 설정을 제공합니다.
만약,
H2 DB
의 의존성이 클래스 경로에 존재한다면 자동으로In-Memory DB
에 접근하게 됩니다. 이러면 개발자가H2 DB
의 설정을 파일에 따로 입력하지 않아도 해당 애플리케이션이In-Memory DB
에 접근합니다.
혹시나 더 자세한 코드를 확인하고 싶은 분들은 AutoConfigurationPackages.java
관련 추상 클래스를 확인해보시면 좋을 것 같습니다. 설정 파일이 존재하지 않으면 예외를 던지고 있으며 설정파일을 등록, 추가 하는 기능이 존재합니다.
Embedded Tomcat
에서 기본 설정 값으로 8080
포트를 사용하게 되는데 이것도 @EnableAutoConfiguration
의 영향 때문 입니다.
{
"name": "server.port",
"type": "java.lang.Integer",
"description": "Server HTTP port.",
"sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties",
"defaultValue": 8080
},
해당 설정은
IntelliJ IDEA
기준으로외부 라이브러리 -> Gradle: org.springframework.boot:spring-boot-autoconfigure:${spring_boot_version} -> META-INF -> spring-configuration-metadata.json
에서 확인할 수 있습니다.
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations); // 중복되는 설정 제거
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
Spring Boot
에서는 자동 설정할 클래스들을 먼저 불러오는데 만약 중복되는 Bean
이 설정될 경우가 생기는데 이를 대비하여 처리하는 로직이 있습니다.
바로 Set
을 이용하여 제외할 설정을 저장합니다. 여기서 제외할 설정들은 중복된 설정 removeDuplicates
메소드를 이용해 추려지게 됩니다. 마지막으로 이 중에서 프로젝트에 사용 되는 Bean
만 Import
할 자동 설정 대상으로 선택됩니다.
더 자세한 코드는
AutoConfigurationImportSelector.java
파일에서 확인할 수 있습니다.
위의 글에서는 Properties
를 예시로 들었습니다. 하지만 저는 YAML
을 더 많이 사용하고 있고 Spring Project
팀에서도 YAML
을 사용하고 있다고 합니다.
원래 YAML
을 사용하려면 SnakeYAML
모듈을 별도로 설치해야 하지만, 이제는 Spring Boot Starter
에 이 모듈이 기본으로 내장되어 있기 때문에 별도로 의존성을 추가할 필요 없이 application.properties
를 application.yml
로 이름을 바꾸면 됩니다.
만약
properties
와ymal
파일이 두 개 다 존재하면ymal
파일만 오버라이드 되어 적용이됩니다.
👍 문제
Spring은 XML을 중심으로 설정 정보를 보관하던 때가 있었다. 현재는 XML 설정을 완전히 배제한 채로 처리하도록 장려하고 있다. 그 대안으로는 .properties나 .yaml, .yml 파일이 있는데 이렇게 바뀐 이유는 무엇일까?
또, .properties, .yaml 등 이런 파일이 스프링에서 설정 정보를 보관할 수 있도록 만든 원리는 무엇일까? <- 이건 어려우면 패스하자..ㅎ
✈️ 선정 배경
지난주 암살주제 때문에 이슈 난이도를 좀 낮추고자 서버 개발자에게 친숙한 Spring을 가지고 오고 싶었다.
📺 관련 챕터 및 레퍼런스
story. 13 XML과 JSON도 잘 쓰자.
🐳 비고
서버 개발자가 되고 싶은 사람이 이 주제를 다루면 찰떡일 거 같아요!