2022. 7. 31. 17:16γBackend/πΏ Spring
λͺ©μ°¨
- μλ‘
- λμ
- κΈ°λ₯ μ건
- λ¬Έμ μ
- λ³Έλ‘
- μ΄κΈ° κ°μ²΄ ꡬ쑰(Map) - Bad
- μ΅μ’ κ°μ²΄ ꡬ쑰 (DTO) - Good
- κ²°λ‘
μλ‘
λμ
μ¬μ΄λ νλ‘μ νΈμμ "μ λ‘μ¨μ΄μ€νΈ κ΄λ ¨ μ₯μ"λ₯Ό μ§λμ λμ°λ μμ μ λ΄λΉνλ€. "μ λ‘μ¨μ΄μ€ κ΄λ ¨ μ₯μ" (μ΄ν place) λ λ€μν μΉ΄ν κ³ λ¦¬λ‘ λΆλ₯λ μ μλλ°, κΈ°ν λ¨κ³μμ μλ μ΄λ―Έμ§μ νν° λΆλΆ μ²λΌ μ μνμ¬ μΉ΄ν κ³ λ¦¬ν νμλ€.
κΈ°λ₯ μ건
μ¬μ©μκ° μνλ μΉ΄ν κ³ λ¦¬μ μμ μ μ νν μ μλλ‘ 'νν°'λ₯Ό κΈ°λ₯μ μ 곡νλ κ²μ΄ λͺ©νμλ€.
- ν° μΉ΄ν κ³ λ¦¬μ ν΄λΉλλ μλΉλ₯Ό λλ, μνμ λλ, 보μμ μ£Όλ μΉ΄ν κ³ λ¦¬λ₯Ό μ°μ λ§λ λ€.
- κ° μΉ΄ν κ³ λ¦¬μ μνλ μ¬λ¬ κ°μ νν°λ₯Ό λ£λλ€.
- ν΄λΌμ΄μΈνΈ λ¨μμ κ°κ°μ κ°μ μ μ μλλ‘ key, value νμμΌλ‘ μ μ‘νλ€. key κ°μ μ‘°ννλ©΄ ν΄λΉ μΉ΄ν κ³ λ¦¬μ μλ¬Έ μ½λκ°, value λ₯Ό μ‘°ννλ©΄ ν΄λΉ μΉ΄ν κ³ λ¦¬μ νκΈ μ½λλ₯Ό μ‘°νν μ μλλ‘ νλ€.
λ¬Έμ μ
λ°±μλ κ°λ°μμΈ νμλ μ΄ 'νν°' λ₯Ό μ½λν νμ¬ νλ©΄λ¨μ 보λ΄μ£Όμ΄μΌ νλ€. μ΄ κ³Όμ μμ νμλ νν°λ₯Ό map ννλ‘ κ΅¬μ±νμ¬ ν΄λΌμ΄μΈνΈλ‘ μ μ‘ν μ€μλ₯Ό λ²νλλ°, 1) μ΄κ² μ μλͺ»λ λ°©μμΈμ§,
2) map λμ Dto λ₯Ό μ¬μ©ν΄μΌ νλ μ΄μ
κ° λ¬΄μμΈμ§ λ₯Ό μ€μ¬μΌλ‘ κΈμ νμ΄λ³΄κ² λ€.
λ³Έλ‘
μ΄κΈ° κ°μ²΄ ꡬ쑰(Map) - Bad
μλ κ°μ²΄ ꡬ쑰λ νμκ° μ²μ μ€κ³ν λ°©μμΌλ‘, Java μ Map μ μ΄μ©ν΄ ꡬμ±νλ€.
μ΅μμ key κ°μΌλ‘ RECYCLE, COMPENSATION, CONSUME
μ κ°μ§λλ‘ νκ³ , κ°κ°μ key μ λμλλ value λ λλ€λ₯Έ Key-value ꡬ쑰λ₯Ό 리μ€νΈλ‘ λ°λλ‘ νλ€.
{
"RECYCLE": {
"name": [
"무ν΄ν μνμ λλ"
],
"filters": [
"μμ΄μ€ν©μκ±°ν¨",
"μνκ°μ μκ±°ν¨",
"λμ¬λ¬΄μ"
]
},
"COMPENSATION": {
"name": [
"보μμ μ£Όλ"
],
"filters": [
"μνΌλΉ",
"λΆλ¦¬μκ±°"
]
},
"CONSUME": {
"name": [
"무ν΄ν μλΉλ₯Ό λλ"
],
"filters": [
"μ λ‘μ¨μ΄μ€νΈμ΅",
"리νμ€ν
μ΄μ
",
"μ±μμλΉ"
]
}
}
μ¬μ€ μ§κΈ 보면 μ΄μ²κ΅¬λ μλ μ½λμΈλ°, λΉμμλ λ¬΄μ¨ κ·Όκ±°λ‘ μ΄λ κ² κ°μ²΄λ₯Ό ꡬμ±νλμ§ λͺ¨λ₯΄κ² λ€.
Map μ μ¬μ©ν΄ μ κ°μ²΄λ₯Ό μ΄λ»κ² ꡬμ±νλμ§ μ΄ν΄λ³΄μ.
μ°μ μ΅μμ key μ λμλλ value μ νμ λ Map μ΄ λΌμΌνλ€. (μ΄λ―Έ μ¬κΈ°μλΆν° 볡μ‘νλ€)
μλνλ©΄ κ°κ°μ κ°μ²΄ ꡬ쑰λ (name κ³Ό filters λ λΌλ) String key μ λμνλ λ¬Έμμ΄ λ¦¬μ€νΈλ₯Ό value λ‘ λ°κΈ° λλ¬Έμ΄λ€.
μ½λλ‘ νννλ©΄ λκ° μ΄λ° λͺ¨μ΅μ΄λ€.
public Map<String, Map<String, List<String>>> category = new HashMap<>();
λΉμ°ν μ½λ리뷰 λ νμμΌλ‘ λΆν° μλμ κ°μ νΌλλ°±μ λ°μλ€.
νμλΆμ λ§μ§λ§ μ€λ λλ₯Ό λ³΄κ³ , λ΄κ° μ§ κ°μ²΄ μ€κ³μ λ¬Έμ μ μ΄ μ΄ν΄λλ€.
μ μ²λΌ μ€κ³ν κ²μ λ¬Έμ μ
- ν΄λΌμ΄μΈνΈ κ°λ°μκ° κ³Όμ°
RECYCLE, COMPENSATION, CONSUME
μ΄λ key κ°μ λ€ μκ³ μμκΉ? - μ§κΈμ μ 체 μΉ΄ν κ³ λ¦¬κ° 3κ° λΏμ΄μ§λ§, μΆνμ μΉ΄ν κ³ λ¦¬κ° μμ, μλ°±κ°λ‘ λμ΄λλ€λ©΄? κ·Έ λλ ν΄λΌμ΄μΈνΈ κ°λ°μκ° μΌμΌμ΄ key κ°μ ν΄λΉλλ κ°μ λͺ¨λ νμ ν μ μμκΉ?
λλ¬Έμ value μ ν΄λΉλλ RECYCLE, COMPENSATION, CONSUME κ°μ κ°λ€μ keyκ° μλ, value μ μμΉμ λλ κ²μ΄ μ³λ€.
μ΄λ° μ μ μΌλνμ¬ κ°μ²΄ ꡬ쑰λ₯Ό map μμ DTO λ‘ λ¦¬ν©ν λ§ ν΄λ³΄μ.
μ΅μ’ κ°μ²΄ ꡬ쑰 (DTO) - Good
{
"categoryGroup": [
{
"key": "CONSUME",
"value": "무ν΄ν μλΉλ₯Ό λλ",
"filters": [
{
"value": "μ λ‘μ¨μ΄μ€νΈμ΅",
"key": "ZEROWASTESHOP"
},
{
"value": "리νμ€ν
μ΄μ
",
"key": "REFILLSTATION"
},
{
"value": "μ±μμλΉ",
"key": "VEGANSHOP"
}
]
},
{
"key": "RECYCLE",
"value": "무ν΄ν μνμ λλ",
"filters": [
{
"value": "μμ΄μ€ν©μκ±°ν¨",
"key": "ICEPACK"
},
{
"value": "μνκ°μ μκ±°ν¨",
"key": "APPLIANCES"
},
{
"value": "νμ 볡μ§μΌν°",
"key": "DONG"
}
]
},
{
"key": "COMPENSATION",
"value": "보μμ μ£Όλ",
"filters": [
{
"value": "μνΌλΉ",
"key": "SUPERBEAN"
}
]
}
]
}
리ν©ν λ§ν κ°μ²΄λ DTO ννλ‘ μ μνλ€.
categoryGroup μ΄λ key μ λμλλ value λ λμΌν DTO λ₯Ό 리μ€νΈ ννλ‘ λ°λλ€. μ΄ DTO λ μλ μ½λμμ CategoryDto μ inner class μΈ Response μ ν΄λΉλλ€. Response ν΄λμ€λ key, value, filters λΌλ μΈκ°μ§ νλλ₯Ό κ°μ§λ©°, filters λ Map μ μ λλ¦μΌλ‘ λ°λ 리μ€νΈλ‘, μ¦ μΉ΄ν κ³ λ¦¬μ νμμ μνλ λ€μμ νν° κ°λ€μ΄ key-value μ 맡 ννλ‘ filters μ ν¬ν¨λλ ꡬ쑰λ€.
CategoryDto ν΄λμ€
@Data
@AllArgsConstructor
public class CategoryDto {
private List<Response> categoryGroup;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Response {
private CategoryGroups key;
private String value;
private List<Map<String, String>> filters;
public static Response of(CategoryGroups categoryGroups) {
List<Category> categoryList = CategoryGroups.getFilterList(categoryGroups);
List<Map<String, String>> filters = new ArrayList<>();
for (Category category : categoryList) {
Map<String, String> map = new HashMap<>();
map.put("value", category.getCategory());
map.put("key", category.toString());
filters.add(map);
}
return Response.builder()
.key(categoryGroups)
.value(categoryGroups.getCategory())
.filters(filters)
.build();
}
}
public static CategoryDto response(List<Response> categoryGroup) {
return new CategoryDto(categoryGroup);
}
}
CategoryGroups Enum ν΄λμ€
Category Enum ν΄λμ€
Category νΈμΆ API
CategoryDto ν΄λμ€ version 2
μ²μ μ§ CategoryDto ν΄λμ€μ νκ°μ§ λ¬Έμ κ° μλλ°, λ°λ‘ filters 리μ€νΈκ° map νμ μ μ λλ¦μΌλ‘ λ°λλ€. κ²μ DTO ννλ‘ λ°μμ§λΌλ, κ·Έ λ΄λΆμ κ°μ map μΌλ‘ λ°λ κΈ°μ΄ν ννμμ κΉ¨λ¬μκ³ , μλ μ½λμ²λΌ 리ν©ν λ§νλ€. 그리νμ¬ filters 리μ€νΈμ μ λλ¦ νμ λ FilterResponse λΌλ DTO λ₯Ό λ°λλ‘ λ¦¬ν©ν λ§ν μ μμλ€.
@Data
@AllArgsConstructor
public class CategoryDto {
private List<Response> categoryGroup;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
private static class FilterResponse{ // μΆκ°λ λΆλΆ
private Category key;
private String value;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Response {
private CategoryGroups key;
private String value;
private List<FilterResponse> filters; // λ³κ²½λ λΆλΆ
public static Response of(CategoryGroups categoryGroups) {
List<Category> categoryList = CategoryGroups.getFilterList(categoryGroups);
List<FilterResponse> filters2 = new ArrayList<>();
for (Category category : categoryList) {
// μΆκ° λ° λ³κ²½λ λΆλΆ
FilterResponse build = FilterResponse.builder()
.key(category)
.value(category.getCategory())
.build();
filters.add(build);
}
return Response.builder()
.key(categoryGroups)
.value(categoryGroups.getCategory())
.filters(filters)
.build();
}
}
}
κ²°κ³Ό
μ΄λ κ² νμ¬ κΈ°μ‘΄μ map ννμμ DTO λ‘ Response λ₯Ό 리ν©ν λ§ ν μ μμλ€.
map λμ DTO λ₯Ό μ¬μ©νμ¬ μ»μ μ μλ μ₯μ μ 무μμ΄ μμκΉ?
1. κ°λ
μ±μ΄ ν¬κ² κ°μ λλ€
. μμμ μΈκΈνλ―μ΄ μ€μ²©λ mapμ ννλ₯Ό 보면 . . . κ·Έ λ΄λΆλ₯Ό νμ
νλ κ²μ΄ κ½€λ 볡μ‘νλ€. μλ μ½λμΌ Map λ΄λΆμ map μ΄ νλλ°μ μΆκ°λμ§ μμ κ°λ¨ν μΌμ΄μ€μ§λ§, μ€μ²© λ λ²¨μ΄ κΉμ΄μ§λ€λ©΄ μ½λ νΈλνΉνλλ° λ λ§μ μκ°μ΄ μλͺ¨λ κ²μ΄λ€.
2. key κ°μ String λμ νΉμ νμ
μ μ¬μ©ν¨μΌλ‘ νμ
μμ μ±μ λμΌ μ μλ€
. μ μ½λμμλ DTO μ¬μ©μ enum μ key λ‘ μ¬μ©νκΈ°μ, μ€νλ μλͺ»λ λ¬Έμμ΄ μ
λ ₯μ 곧λ°λ‘ μ»΄νμΌ μλ¬λ‘ λ¬Έμ λ₯Ό νμ
ν μ μλ€. -> νμ§λ§ μ΄ λΆλΆμ, map μ μ¬μ©ν λλ key λΆλΆμ String μ΄ μλ νΉμ λ°μ΄ν° νμ
μ λ£μ΄ νμ
μμ μ±μ κ°νν μ μλ€κ³ μκ°νλ€. μ΄κ² κΌ DTO λ₯Ό μ¬μ©νμ μμ μ₯μ μΈμ§λ μλ¬Έμ΄λ€. (λκΈλ‘ λ€μν μ견 λΆνλλ¦Όλ€)
3. κ°λ
μ±κ³Ό μ°κ΄λ λΆλΆμΌ μλ μλλ°, ν΄λΌμ΄μΈνΈλ¨μμ μνλ λ°μ΄ν°κ° 무μμΈμ§ μ½κ² νμ
ν μ μλ€.
DTO ν΄λμ€ λ΄λΆμ μ μλ λ©€λ² λ³μλ₯Ό 보면 ν΄λΌμ΄μΈνΈ λ¨μΌλ‘ 보λ΄μΌν κ°μ΄ μ΄λ€κ²μΈμ§ μ½κ² νμ
ν μ μλ€. API μ λͺ
μΈκ° λ³κ²½λ λμλ, ν΄λΉ νλλ₯Ό λ³κ²½νλ©΄ λκΈ° λλ¬Έμ λ³κ²½μλ μ μ°ν κ²μ΄λΌ μκ°νλ€.
κ²°λ‘
map λμ DTO λ₯Ό μ°μ. λ¬Όλ‘ μ½λμμ΄ λμ΄λκ³ map μ μ¬μ©ν λ λ³΄λ€ λ³΅μ‘ν μ½λ ꡬ쑰λ₯Ό κ°κ² λλ κ²μ΄ λ¨μ μΌλ‘ λ°μλ€μ¬μ§ μ λ μλ€. νμ§λ§ μ΄λ° λΆνΈν¨μ κ°μν΄μλΌλ, κ°λ°μ μμ μ±κ³Ό ν΄λΌμ΄μΈνΈ κ°λ°μμμ νμ μΈ‘λ©΄μμλ DTO λ₯Ό μ¬μ©νμ¬ μλ‘ νμλ ννλ‘ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λ κ²μ΄ μ’λ€κ³ μκ°νλ€.
'Backend > πΏ Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
IntelliJ μ€νλ§λΆνΈ μλ² 2λ μ΄μ μ€ννλ λ² (0) | 2022.08.14 |
---|---|
[Docker, Springboot] java.sql.SQLSyntaxErrorException: Unknown database (4) | 2022.08.03 |
[JPA] API κ°λ° - μ§μ°λ‘λ©κ³Ό μ±λ₯ μ΅μ ν (feat.Fetch μ‘°μΈ) (0) | 2022.06.16 |
[Spring] @Aspect μ AOP νΊμ보기 (0) | 2022.06.05 |
[Spring] λΉ νμ²λ¦¬κΈ°, Bean Postprocessor (0) | 2022.06.04 |