[Java] YAML 활용하기
by 배부른코딩로그💡 스프링부트에서 자주 보던 *.yml 파일을 *.properties 대신 사용해보자!
목표
- YAML 이 무엇인지 설명할 수 있다.
- SnakeYAML 라이브러리를 통해 YAML 파일을 다룰 수 있다.
- YAML 데이터를 다루는 참고 예제를 만들 수 있다.
서버에서 순수 자바로 구현된 프로세스들이 다수 존재할 수 있다.
보통 XML 혹은 Properties 파일로 관리하는 편이다. 개인적으로 각각의 장단점은 다음과 같다.
확장자 | 장점 | 단점 |
XML | 리스트 관리 편함. 명확한 계층구조. |
open, close 태그 등 내용이 불필요하게 길어짐. 프로그래밍 비교적 불편. |
Properties | 프로그래밍이 쉬운 key, value 구조. 비교적 짧은 내용. |
리스트 관리 불편. 계층구조를 위한 긴 key 값 표현. |
그래서 이번엔 YAML(YML)을 적용해보고 싶었다.
YAML 확장자는 계층구조 표현도 깔끔하고 읽기 쉬운 형태의 문법 형식을 가지고 있다고 판단했기 때문이다.
YAML 기본문법
주석 (comment)
주석은 #으로 표시한다. 예시는 다음 문법 설명에서 활용할 것이다.
들여쓰기 (indent)
들여쓰기는 기본적으로 2칸 또는 4칸을 지원한다.
# 2칸 들여쓰기(*추천)
server:
name: Apache Tomcat
rule: WAS
apps:
- test
- solution
# 4칸 들여쓰기
server:
name: Apache Tomcat
rule: WAS
apps:
- test
- solution
데이터 정의 (Map)
데이터는 key: value 형식이다. 주의할 점은 key와 value사이에는 반드시 빈칸(Whitespace)이 필요하다는 것이다.
# ok (key: value)
name: 배부른코더
# error (not key-value, string)
key:value
참/거짓
참/거짓은 [ true / false ] 및 [ yes / no ]를 인식한다.
isRunnable: true # ↔ false
isRequired: no # ↔ yes
줄바꿈 (New line)
따옴표(")를 기준으로 숫자 혹은 문자임을 인식할 수 있다.
여러 줄을 표현해야할 경우는 어떻게 해야할까?
"|" 지시어를 사용함으로써 표현이 가능하다.
description: |
newline
description test
syntax ok!
특이한 점은 "|-" 및 ">" 지시어를 통해서 조금 추가된 기능의 줄바꿈도 지원한다.
"|-" 지시어는 마지막 줄바꿈을 제외한다.
description: |-
newline
description test
syntax ok!
위의 내용은 "newline\n\ndescription test\n\nsyntax ok!" 과 동일하다.
">" 지시어는 내용 사이에 들어간 개행을 제외한다.
description: >
newline
description test
syntax ok!
위의 내용은 "newline\ndescription test\nsyntax ok!\n" 과 동일하다.
YAML 예제
openJDK를 사용했고, YAML을 load 하는 라이브러리는 SnakeYAML을 의존했다.
유틸성 함수들은 따로 분리했고, 다양한 Class type을 로드할 수 있도록 다음과 같이 구현했다.
YAML to Object
// CustomFileUtils.java
public static InputStream readFile(String parentPath, String filename) throws FileNotFoundException {
String path = parentPath + File.separator + filename;
return readFile(path);
}
public static <T> Object loadYamlObject(InputStream inputStream, Class<T> clazz) throws IOException {
Yaml yaml = new Yaml(new Constructor(clazz));
return yaml.load(inputStream);
}
public Clients loadClients(String directory, String filename) {
Clients clients = null;
try {
InputStream inputStream = FileUtils.readFile(directory, filename);
clients = (Clients) FileUtils.loadYamlObject(inputStream, Clients.class);
} catch (FileNotFoundException fe) {
logger.error("Could not find yaml file!");
} catch (Exception e) {
logger.error("Please validate the contents!", e);
}
return clients;
}
// Clients.java
public class Clients {
private List<Client> clients;
}
// Client.java
public class Client {
private String name;
private String description;
@Builder.Default
private boolean runable = false;
@Builder.Default
private Integer polling = 10;
private Source source;
private Target target;
}
전체 코드는 불필요하기 때문에 위와 같이 소스코드가 구현되어져있다고
clients:
- name: CLIENT1
description: 클라이언트 1
runable: true
polling: 5
source:
protocol: SFTP
host: 127.0.0.2
port: 10022
user: client1
password:
target:
protocol: SFTP
host: 127.0.0.1
port: 22
user: localhost
password:
- name: CLIENT2
description: 클라이언트 2
runable: true
polling: 10
source:
protocol: FTP
host: 127.0.0.3
port: 10021
user: client2
password:
target:
protocol: SFTP
host: 127.0.0.1
port: 22
user: localhost
password:
위 코드를 실행시키면, load 함수를 통해 Clients 객체로 맵핑이 되게 된다.
맵핑된 객체를 출력해보면 다음과 같다.
Client(runable=true, polling=5, name=CLIENT1, description=클라이언트 1, source=Source(protocol=SFTP, host=127.0.0.2, port=10022, user=client1, password=null), target=Target(protocol=SFTP, host=127.0.0.1, port=22, user=localhost, password=null))
Client(runable=true, polling=10, name=CLIENT2, description=클라이언트 2, source=Source(protocol=FTP, host=127.0.0.3, port=10021, user=client2, password=null), target=Target(protocol=SFTP, host=127.0.0.1, port=22, user=localhost, password=null))
※ YAML 문법 오류시, 틀린 부분도 친절하게 알려주기 때문에 쉽게 수정할 수 있다.
Object to YAML
yaml 파일로 쓰는 방법에 대한 간단한 예제이다.
Client client = Client.builder()
.name("Temp")
.description("Temp for Write Test")
.runable(true)
.polling(60)
.source(new Source())
.target(new Target())
.build();
PrintWriter writer = new PrintWriter(new File("./clients.yml"));
Yaml yaml = new Yaml();
yaml.dump(client, writer);
name: Temp
description: Temp for Write Test
runable: true
polling: 60
source:
protocol:
host:
port:
user:
password:
target:
protocol:
host:
port:
user:
password:
위와 같이 clients.yml 파일에 잘 작성되는 것을 확인할 수 있다.
간단한 예제로 의존성이 높은 객체들도 Object to Yaml 도 개인적으로 시도해볼 예정이다.
결론
어떤 포맷이든 라이브러리를 사용하면 쉽게 사용할 수 있다.
하지만, 사람이 보는 파일은 가독성이 좋은 것을 선호하게 된다.
YAML 포맷의 가독성 만큼은 인정한다 : )
가독성 면에서는 XML과 Properties 보다 월등한 느낌이다.
오히려, 열고 닫는 태그를 신경 쓰지 않다 보니 JSON 보다 더 수정 관리하기 편했다.
아직은 문법이 헷갈리지만, 앞으로 파일로 설정정보를 관리하게 된다면, yaml을 적극 활용할 것 같다.
출처
- Reading and Writing YAML Files in Java with SnakeYAML, Taimoor Choudhary, 2021-02-19
- https://subicura.com/k8s/prepare/yaml.htm, 서비큐라 기술블로그, 2022-04-01
- Best YAML Validator Online, YAML Validator (온라인 YAML 문법 검사기)
Last Updated. 2022. 05. 10.
'Java' 카테고리의 다른 글
[Java] Null Safe한 자바 컬렉션 정렬 (0) | 2022.05.24 |
---|---|
[Java] Enum 소화하기 (0) | 2022.05.09 |
[Java] @Required 직접 만들어보기 (0) | 2022.04.23 |
[Java] Array, List, Set, Map 선언과 초기화 (1) | 2021.11.05 |
[Java] Java Optional (0) | 2021.06.14 |
블로그의 정보
배부른코딩로그
배부른코딩로그