카테고리 없음

YAML으로 마스터데이터 마이크로서비스 만들기

msna 2019. 2. 2. 15:35

배경

 지금 현장은 새로 만드는 기능은 마이크로서비스로 구현하려고 하고 있다. 안드로이드 어플과 그외 관리서비스에서 쓸 마스터데이터까지 마이크로서비스로 만들어서 JSON으로 넘겨주란다. 이렇게 하면 어플을 업데이트 하지 않아도 초기치나 표시되는 라벨등등을 변경할 수 있다. 그래서 데이터 샘플을 보는데...


{
"process_status" : {
"version" : "2019-01-01T00:00:00",
"list" : [
{
"code" : "01",
"name" : "미처리"
},
{
"code" : "02",
"name" : "처리중"
},
{
"code" : "03",
"name" : "처리완료"
}
]
},
"action_list" : {
"version" : "2019-01-01T00:00:00",
"list" : [
{
"action" : "01",
"name" : "조회",
"init" : {
"disp" : true,
"image_path" : [
"img/action01.png"
, "img/action01_320px.png"
]
}
},
{
"action" : "02",
"name" : "삭제",
"init" : {
"disp" : false,
"image_path" : [
"img/action02.png"
, "img/action02_340px.png"
]
}
}
]
}
}
view raw masterData.json hosted with ❤ by GitHub

대충 이러하단다.


어떻게할까?

샘플 데이터를 보기 전에는 마스터데이터니까 그냥 key:value만일거라고 믿었었는데, action_list처럼 init의 값이 오브젝트이고 image_path는 리스트이다. 게다가 앞으로 어떤 구조의 데이터를 넣을지도 모르는 상황. 그래서 테이블을 나누고 필요한 컬럼을 추가해서 아래와 같은 테이블 구조를 만들었다.

master_data

master_name version
'action_list' 2019-01-01T00:00:00

master_data_values

master_name depth upper_key key value type
'action_list' 1 'action' '01' 'String'
'action_list' 1 'name' '조회' 'String'
'action_list' 1 'init' 'Object'
'action_list' 2 'init' 'disp' true 'Boolean'
'action_list' 2 'init' 'image_path' 'List'
'action_list' 3 'image_path' 'img/action01.png' 'String'
'action_list' 3 'image_path' 'img/action01_320px.png' 'String'

테스트용 DB가 없어서 실제로는 안해봤지만 대충 자기 자신보다 작은 depth의 key가 자신의 upper_key라면 우선은 될 것 같다. upper_key가 중복이 될 수도 있겠지만 master_name이 같은데 같은 이름으로 키를 쓰지는 않을거라고 믿는다.

 JSON자체를 저장해버리는 방법도 생각했었는데, 쓰는 DB가 MySQL5.6인데 JSON저장은 5.7부터란다. 버전업을 요청할까도 생각했지만... 했지만...


YAML으론 안될까?

 뭔가 잘못 만든 부분은 없을까? 더 나은 방법은 없나?라며 샘플 데이터를 다시 살펴보던 중 YAML쓰면 안되나? 라는 생각이 머리를 스쳤다.

 이 현장의 마이크로 서비스는 기본셋팅이 있고 db명과 기본테이블명도 통일되어 있어서 습관적으로 DB로 했는데, 이건 마스터니까 수정이 그리 많겠어?라는 핑계거리가 생겨서 YAML으로 구현해보았다.


YAML으로 값 읽어서  JSON으로 출력하는 코드

라이브러리는 

SnakeYAML( https://mvnrepository.com/artifact/org.yaml/snakeyaml/1.8 )

GSON( https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5 )

을 사용하였다.


public class Yaml2Json {
public static String toJson( String yamlString ){
Yaml yaml = new Yaml();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
return gson.toJson( yaml.load( yamlString ).getClass().getName() );
}
}
view raw Yaml2Json.java hosted with ❤ by GitHub

입출력결과

process_status :
version : 2019-01-01T00:00:00
list :
-
code : 01
name : 미처리
-
code : 02
name : 처리중
-
code : 03
name : 처리완료
action_list :
version : 2019-01-01T00:00:00
list :
-
action : 01
name : 조회
init :
disp : true
image_path :
- img/action01.png
- img/action01_320px.png
-
action : 02
name : 삭제
init :
disp : false
image_path :
- img/action02.png
- img/action02_340px.png
{
"process_status": {
"version": "Jan 1, 2019 9:00:00 AM",
"list": [
{
"code": 1,
"name": "미처리"
},
{
"code": 2,
"name": "처리중"
},
{
"code": 3,
"name": "처리완료"
}
]
},
"action_list": {
"version": "Jan 1, 2019 9:00:00 AM",
"list": [
{
"action": 1,
"name": "조회",
"init": {
"disp": true,
"image_path": [
"img/action01.png",
"img/action01_320px.png"
]
}
},
{
"action": 2,
"name": "삭제",
"disp": false,
"image_path": [
"img/action02.png",
"img/action02_340px.png"
]
}
]
}
}


실제로 추가된 코드 자체는 없다. 프린트해서 보기위해서 Gson에 setPrettyPrinting만 설정해주었다.

yaml.load()에서 리턴된 값은 LinkedHashMap이다.

version의 날짜표시 부분은 원하는대로 안 나왔는데, 그건 다음 포스트에서 다루겠다.


결론

  • 약간 복잡한 데이터 구조도 YAML이면 좀 더 자유도 있게 다룰 수 있다.
  • JSON/YAML간의 변환은 매우 간편하다.
  • 어차피 DB안쓰고 파일로 처리할거면 굳이 변환할 필요없이 json파일로 저장했어도 되지 않았나? 하는 생각이 드는데, YAML이 사람이 고치기 더 편하니 YAML을 쓰도록 하자.