Skip to content

Latest commit

ย 

History

History
93 lines (72 loc) ยท 7.5 KB

File metadata and controls

93 lines (72 loc) ยท 7.5 KB

Map Struct

ํ˜„์žฌ๊นŒ์ง€ entity -> dto, dto -> entity, dto -> dto ๋งคํ•‘์ž‘์—…์„ ์ƒ์„ฑ์ž๋‚˜ ๋นŒ๋”๋ฅผ ์ด์šฉํ•ด์„œ ์ž‘์—…์„ ํ•ด์™”๋‹ค. ์‚ฌ์‹ค๋Œ€๋กœ ๋งํ•˜๋ฉด ๊ณ„์ธต(layer)์— ๋”ฐ๋ฅธ dto๋ฅผ ๋”ฐ๋กœ ๋‘์ง€ ์•Š๊ณ  entity๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๋‹ค. ์–ด๋””์„œ๋ถ€ํ„ฐ ์ž˜๋ชป๋˜์–ด์˜จ ๊ฒƒ์ธ์ง€๋Š” ๋ชฐ๋ผ๋„ ๋ชจ๋“  ๊ณ„์ธต์—์„œ entity๋ฅผ ์ง์ ‘ ์ฐธ์กฐํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์˜€๋‹ค.
๊ทธ๋ ‡๊ฒŒ ์ˆ˜ ๋งŽ์€ entity์™€ ๊ฐ ๊ณ„์ธต๋งˆ๋‹ค ์‚ฌ์šฉํ•˜๋Š” dto๋ฅผ ๋”ฐ๋กœ ๋‘๊ณ  ๋งคํ•‘์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋ ค๊ณ  ํ–ˆ๋‹ค. ๋ฌธ๋“ 1~2๋…„์ฐจ ๋•Œ, ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์‚ฌ์šฉํ–ˆ๋˜ Model Mapper๊ฐ€ ์ƒ๊ฐ๋‚ฌ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด์ „์— ๋ฌด์‹ฌ์ฝ” ์ฝ์—ˆ๋˜ ๋ธ”๋กœ๊ทธ ๊ธ€์ด ๊ธฐ์–ต๋‚ฌ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ธ”๋กœ๊ทธ ์ฝ”๋ฉ˜ํŠธ ์ค‘ Map Struct๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

Map Struct๋ฅผ ์„ ํƒํ•œ ์ด์œ 

์—ฌ๋Ÿฌ ๋ธ”๋กœ๊ทธ์—์„œ ๋ณด๋ฉด ์ธ๊ธฐ๋„, ์„ฑ๋Šฅ์— ๋Œ€ํ•œ ๊ธ€์ด ์ ์ง€ ์•Š๋‹ค. ๋ช‡ ๊ฐœ๋งŒ ์ฝ์–ด ๋ณด์•„๋„ ์ถฉ๋ถ„ํžˆ Map Struct๊ฐ€ ์ข‹์€ ์„ ํƒ์ง€๋ผ๊ณ  ๋А๋‚„์ˆ˜ ์žˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์„ค์ •์œผ๋กœ Spring Framework์—์„œ ์‚ฌ์šฉํ•˜๋„๋ก bean์œผ๋กœ ์Šค์บ๋‹ํ•  ์ˆ˜ ์žˆ์–ด ์ข‹์•˜๋‹ค. ๋˜ํ•œ ๋กฌ๋ณต(lombok)์ฒ˜๋Ÿผ ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์ปดํŒŒ์ผ ์‹œ์ ์— ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

Map Struct๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ฒช์—ˆ๋˜ ๊ฒƒ๋“ค

Spring Framework์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

๊ณต์‹ ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด componentModel๋ฅผ ' springโ€™์œผ๋กœ ์ง€์ •ํ•˜๋ฉด โ€˜@Autowiredโ€™๋ฅผ ๋„ฃ์–ด์„œ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

Lombok์˜ Builder์‚ฌ์šฉํ•˜๊ธฐ

Gradle ์„ค์ •(build.gradle)

// To use Map Struct and Lombok together,
// Refer to this: https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-lombok
implementation 'org.projectlombok:lombok'
implementation 'org.mapstruct:mapstruct:1.4.2.Final'

annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

์‚ฌ์šฉ ์˜ˆ์‹œ

Entity ๊ฐ์ฒด์—์„œ DTO ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•˜๊ธฐ

All arguments constructor(ctor)๋ฅผ ์ ‘๊ทผ ์ œํ•œ์„ ๋‘์–ด ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  builder๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ ‘๊ทผ ์ œํ•œ์„ ํ•˜์ง€ ์•Š์•˜๋‹ค. Mapper์˜ ๊ตฌํ˜„์ฒด ์—ญ์‹œ๋„ builder๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
๊ตฌํ˜„์ฒด๋Š” MapperNameImpl์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.
MSE-001-basic-usage

Person entity๋ฅผ PersonResponse dto๋กœ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ถ”๊ฐ€์ ์œผ๋กœ ์Šคํ”„๋ง์˜ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด @Mapper annotation์— componentModel์˜ ๊ฐ’์„ โ€˜springโ€™์œผ๋กœ ์ฃผ์—ˆ๋‹ค. ์ด ์„ค์ •์€ ๊ตฌํ˜„์ฒด์— @Component annotation์ด ์ƒ์„ฑํ•œ๋‹ค.

์ƒ์† ๊ด€๊ณ„์—์„œ ๋งคํ•‘ํ•˜๊ธฐ

public class BaseDatetime {
  @CreatedDate
  private LocalDateTime createdAt;
  @LastModifiedDate
  private LocalDateTime lastModifiedAt;
}

Entity ๋งˆ๋‹ค ๊ณตํ†ต์œผ๋กœ ๋“ค์–ด๊ฐ€๋Š” ๋‚ ์งœ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋”ฐ๋กœ ์ถ”์ถœํ•˜๊ณ  entity ๊ฐ์ฒด๋Š” ์ด๋ฅผ ์ƒ์†ํ•˜๊ณ  ์žˆ๋‹ค. ๋ถ€๋ชจ ๊ฐ์ฒด์˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋„ mapper๊ฐ€ ์ž๋™์ ์œผ๋กœ ์ž˜ ๋งคํ•‘ํ•ด์ค€๋‹ค.
MSE-002-inheritance-usage

ํ•ฉ์„ฑ ๊ด€๊ณ„์—์„œ ๋งคํ•‘ํ•˜๊ธฐ

ํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง„ ์ƒํ™ฉ์ด๋‹ค. ๋ณ„๋‹ค๋ฅธ ์ž‘์—…์—†์ด mapper๊ฐ€ ์ž๋™์ ์œผ๋กœ ๋งคํ•‘ํ•ด์ค€๋‹ค.
MSE-003-composition-usage

๊ทธ๋Ÿฌ๋‚˜ ๊ฐ์ฒด์˜์˜ ๋ณ€์ˆ˜๋ช…์ด ๋‹ฌ๋ผ์ง„ ๊ฒฝ์šฐ๋Š” @Mapping annotation์„ ์ด์šฉํ•ด์„œ source์™€ target์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
MSE-003-composition-usage-diff-name

๋˜ํ•œ, ์ถ”๊ฐ€์ ์ธ ๋งคํ•‘ ๋กœ์ง์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ณ„๋„์˜ mapper๋ฅผ ๋‘์–ด์„œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ•œ mapper๋ฅผ ๊ฐ€์ง€๊ณ  ์™€์„œ ์‚ฌ์šฉํ•œ๋‹ค.
๋ฌธ์ œ๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋ณ„๋„์˜ mapper๋ฅผ Mappers.getMapper()๋กœ ๊ฐ€์ง€๊ณ  ์˜ฌ ์ˆ˜ ์—†๋‹ค. ๋ณ„๋„์˜ mapper๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ฃผ์ž…ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์„ ๊ณ ๋ คํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ์ด์ฒ˜๋Ÿผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ mapper์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋นˆ(bean)์œผ๋กœ ๊ฐ€์ ธ์™€์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
MSE-003-composition-usage-another-mapper
How to Get Mapper as Spring Bean

๋‚ ์งœ ํ˜•์‹ ์ง€์ •ํ•ด์„œ ๋งคํ•‘ํ•˜๊ธฐ

๊ธฐ๋ณธ์ ์œผ๋กœ mapper๋Š” ์ž๋ฐ” 8์˜ ๋‚ ์งœ ํด๋ž˜์Šค๋ฅผ ์ง€์›ํ•œ๋‹ค. ( ์ฐธ๊ณ : link)
๋”ฐ๋กœ ํ˜•์‹์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด default ํ˜•์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๋งŒ์•ฝ ํ˜•์‹์„ ์ง€์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด @Mapping annotation์˜ dateFormat ๊ฐ’์„ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.
MSE-004-datetime-format-usage

JSON์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งคํ•‘ํ•˜๊ธฐ

๊ฐ์ฒด ๋ฐ์ดํ„ฐ๋ฅผ json value ๋˜๋Š” json value๋ฅผ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋”ฐ๋กœ ์žˆ์ง€๋Š” ์•Š์•„ ๋ณด์—ฌ์„œ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋งคํ•‘ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.
MSE-005-json-usage

๋‘ ๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ํ•œ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•˜๊ธฐ

๋‘ ๊ฐ์ฒด์˜ ๋ฐ์ดํ„ฐ๋กœ ํ•œ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ„๋„์˜ ๋กœ์ง ์—†์ด ๋ฐ”๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ•œ ๊ฐ€์ง€ ์œ ์˜ํ•  ์ ์€ ๋‘ ๊ฐ์ฒด ์•ˆ์˜ ๋™์ผํ•œ ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋Š” source์™€ target์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ๋งŒ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
MSE-006-objects-to-a-object

๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜๋กœ ๋งคํ•‘ํ•˜๊ธฐ

๋‘ ๊ฐ์ฒด์˜ ๊ฐ๊ฐ์˜ ๋ณ€์ˆ˜๋Š” ํ•œ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•  ๋•Œ, ๋ณ„๋„์˜ ๋กœ์ง ๊ตฌํ˜„์ด ํ•„์š”์—†๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜๋กœ ๋งคํ•‘ํ•  ๋•Œ์—๋Š” ๋ณ„๋„์˜ ๋กœ์ง ๊ตฌํ˜„์ด ํ•„์š”ํ•˜๋‹ค.
MSE-007-fields-to-a-field

๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋งคํผ๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๋งคํ•‘ํ•˜๊ธฐ

์•ž์„œ ๋งํ–ˆ๋“ฏ์ด entity์˜ ๋‚ ์งœ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋Š” ๋”ฐ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. ๋‹ค์ˆ˜์˜ entity ๊ฐ์ฒด์—์„œ ๋™์ผํ•œ ํ˜•์‹์œผ๋กœ ๋‚ ์งœ๋ฅผ ๋งคํ•‘ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜๋กœ ํ†ต์ผํ•˜๋„๋ก ํ•œ๋‹ค. ํ†ต์ผํ•˜๊ธฐ ์œ„ํ•ด ๋‚ ์งœ ๊ด€๋ จํ•ด์„œ ๋งคํ•‘์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธ ๋งคํผ๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ๊ฐ๊ฐ์˜ ๋งคํผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ํ•œ ๊ฐ€์ง€ ์œ ์˜ํ•  ์ ์€ ๋‹ค์ˆ˜์˜ ๊ฐ์ฒด๋ฅผ ํ•œ ๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•  ๋•Œ, createdAt์ฒ˜๋Ÿผ ๋™์ผํ•œ ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋Š” ์ž๋™์œผ๋กœ ๋งคํ•‘ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— source์™€ target์„ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
MSE-008-common-fields-usage