[Spring Boot] MapStruct

2022. 12. 7. 23:33ใ†Back-End ์ž‘์—…์‹ค/Spring Framework

728x90
๋ฐ˜์‘ํ˜•

 





Source Code : https://github.com/junyharang-coding-study/JunyHarang-JAVA-EncryptionDecryption.git



 

๋ฐฑ๊ฒฌ๋ถˆ์—ฌ์ผํƒ€ ์Šคํ”„๋ง ๋ถ€ํŠธ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ with JPA:์ด์   ํ”„๋กœ์ ํŠธ๋‹ค!

COUPANG

www.coupang.com

 

 

 

React.js ์Šคํ”„๋ง ๋ถ€ํŠธ AWS๋กœ ๋ฐฐ์šฐ๋Š” ์›น ๊ฐœ๋ฐœ 101:SPA REST API ๊ธฐ๋ฐ˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ

COUPANG

www.coupang.com

 

 

 

์Šคํƒ€ํŠธ ์Šคํ”„๋ง ๋ถ€ํŠธ:์ดˆ๊ธ‰ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•œ ๊ฐ€๋ณ๊ณ  ๋„“์€ ์Šคํ”„๋ง ๋ถ€ํŠธ

COUPANG

www.coupang.com

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."







๐Ÿ—‚ ๋ชฉ์ฐจ

โ— [JAVA - Spring Boot] ์•”ํ˜ธํ™”/๋ณตํ˜ธํ™” ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ  
โ— [Spring Boot] MapStruct





 

๐Ÿš€ MapStruct ๊ฐ€์ง€๊ณ  ๋†€๊ธฐ

    ๐Ÿ”ฝ  ๊ฐœ์š”

        ๐Ÿ“ฆ ์„ค๋ช…

MapStruct๋Š” Entity ๊ฐ์ฒด์™€ DTO ๊ฐ์ฒด๋ฅผ ์ƒํ˜ธ Mapping ์ง€์›ํ•˜๋Š” Library์—์š”.

Entity์™€ DTO ๋ณ€ํ™˜์„ ์œ„ํ•ด ๋งŽ์€ ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ, ํ•ด๋‹น ์ž‘์—…์„ ์ง€์›ํ•˜๋Š” Library๋Š” ModelMapper์™€ MapStruct๊ฐ€ ๋Œ€ํ‘œ์ ์ด์—์š”.

์ฃผ๋‹ˆํ•˜๋ž‘์€ ์ด๋ฒˆ์— MapStruct๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ คํ•˜๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ModelMapper์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ, MapStruct์˜ ๊ฒฝ์šฐ Compile ์‹œ ๋ฏธ๋ฆฌ ์ƒ์„ฑ๋œ ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด Entity, DTO๋ฅผ ์ƒํ˜ธ Mapping ํ•ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํผํฌ๋จผ์Šค ์ด์ ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

๋˜ํ•œ, ModelMapper์˜ ๊ฒฝ์šฐ ๋ณ€ํ™˜ ๊ณผ์ •์—์„œ ๋ฆฌํ”Œ๋ ‰์…˜์ด ๋ฐœ์ƒํ•˜๊ณ , MapStruct๋Š” ์œ„์˜ ์ด์œ ๋กœ ๋ฆฌํ”Œ๋ ‰์…˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ์ด ์ ์ด ์žˆ๋‹ต๋‹ˆ๋‹ค.

 

 

 

    ๐Ÿ”ฝ  ์ดˆ๊ธฐ ๊ตฌ์„ฑ

        ๐Ÿ“ฆ ์˜์กด์„ฑ ์„ค์ •

build.gradle

    // MapStruct ์˜์กด์„ฑ ์ถ”๊ฐ€
    // https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor
    // ์ˆœ์„œ ์ฃผ์˜! Lombok ์‚ฌ์šฉ ์‹œ Lombok ์˜์กด์„ฑ ์„ค์ •์ด ๋จผ์ € ์œ„์น˜
    implementation 'org.mapstruct:mapstruct:1.4.2.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
    annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'



์œ„์™€ ๊ฐ™์ด MapStruct์˜ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์–ด์š”.





        ๐Ÿ“ฆ Interface ๊ตฌ์„ฑ

MapStruct๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Generic์„ ์ด์šฉํ•˜์—ฌ ๋จผ์ € Interface๋ฅผ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•ด์š”.

GenericMapper<DTO, Entity>

๋ฐ˜์‘ํ˜•


์œ„์™€ ๊ฐ™์ด GenericMapper๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์–ด์š”.

์œ„ Interface์—์„œ toDTO์™€ toEntity๋Š” ๊ฐ๊ฐ DTO๊ฐ€ ๋“ค์–ด์˜ค๋ฉด Entity๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๊ณ ,
Entity๊ฐ€ ๋“ค์–ด์˜ค๋ฉด DTO๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์ถ”์ƒ Method์—์š”.

๊ทธ ์•„๋ž˜ List Method๋“ค์€ List๋กœ ์ž‘์—…์„ ํ•  ๋•Œ ์“ฐ๊ธฐ ์œ„ํ•ด ์„ ์–ธํ•ด ์ฃผ์—ˆ์–ด์š”.


16๋ฒˆ์งธ Annotaion๊ณผ ๊ฐ™์ด ์„ค์ •์„ ๋„ฃ๊ฒŒ ๋˜๋ฉด nullValuePropertyMappingStrategy๋กœ ์ธํ•ด
Null ๊ฐ’์ด ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ๋ณ€ํ™” ์‹œ์ผœ์ฃผ์ง€ ์•Š๋„๋ก ์„ค์ •์„ ํ•˜์—ฌ ์ฃผ์—ˆ์–ด์š”.

updateFromDTO()๋Š” ๊ธฐ์กด ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” Entity๋ฅผ Updateํ•˜๊ณ  ์‹ถ์„ ๋•Œ,
Null์ด ์•„๋‹Œ ๊ฐ’๋งŒ Updateํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ค€ ์ถ”์ƒ Method์—์š”.


๐Ÿ’ก ์ฐธ๊ณ  ์‚ฌํ•ญ
@MappingTarget : ๋ณ€ํ™˜ํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋งค๊ฐœ ๋ณ€์ˆ˜(์ธ์ž)๋กœ ๋ฐ›์•„ Updateํ•  Target ์„ค์ •.
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) : Source Field๊ฐ€ Null์ด๋ผ๋ฉด Null ๊ฐ’ ๋ฌด์‹œ.

 

 







    ๐Ÿ”ฝ ์ฝ”๋“œ ๊ตฌํ˜„

        ๐Ÿ“ฆ BoardMapper

์‹ค์ œ๋กœ MapStruct๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ค˜์•ผํ•ด์š”.

TestBoardMapper


์œ„์™€ ๊ฐ™์ด GenericMapper๋ฅผ ์ƒ์†๋ฐ›๋Š”๋ฐ, GenericMapper์— Generic Type์œผ๋กœ Mapping ํ•˜๊ณ ์žํ•˜๋Š” DTO์™€ Entity๋ฅผ ๋ช…์‹œํ•ด ์ฃผ๋ฉด ๋˜์š”.

๊ทธ๋ฆฌ๊ณ , @Mapper๋ฅผ ํ†ตํ•ด mapstruct๊ฐ€ ์ธ์‹๋˜๋„๋ก ํ•˜์—ฌ์ฃผ์—ˆ์–ด์š”.



๐Ÿ’ก ์ฐธ๊ณ  ์‚ฌํ•ญ
@Mapper : MapStruct Code Generator๊ฐ€ ํ•ด๋‹น Interface์˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์คŒ.
componentModel = "spring" : Spring ํ™˜๊ฒฝ์— ๋งž๊ฒŒ Bean ๋“ฑ๋ก

 

์ด์ œ ์ด ์ƒํƒœ์—์„œ Spring Boot๋ฅผ ๊ธฐ๋™ํ•˜๊ฒŒ ๋˜๋ฉด MapperImpl์ด ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๊ฒŒ ๋˜์š”.



Package Path

728x90
package com.junyharang.endecrypttest.common.mapper;

import com.junyharang.endecrypttest.model.dto.request.BoardRequestDTO;
import com.junyharang.endecrypttest.model.dto.request.BoardRequestDTO.BoardRequestDTOBuilder;
import com.junyharang.endecrypttest.model.entity.TestBoard;
import com.junyharang.endecrypttest.model.entity.TestBoard.TestBoardBuilder;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.processing.Generated;
import org.springframework.stereotype.Component;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-12-07T22:50:19+0900",
    comments = "version: 1.4.2.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-7.5.1.jar, environment: Java 11.0.16 (Azul Systems, Inc.)"
)
@Component
public class TestBoardMapperImpl implements TestBoardMapper {

    @Override
    public BoardRequestDTO toDTO(TestBoard entity) {
        if ( entity == null ) {
            return null;
        }

        BoardRequestDTOBuilder boardRequestDTO = BoardRequestDTO.builder();

        boardRequestDTO.title( entity.getTitle() );
        boardRequestDTO.content( entity.getContent() );

        return boardRequestDTO.build();
    }

    @Override
    public TestBoard toEntity(BoardRequestDTO dto) {
        if ( dto == null ) {
            return null;
        }

        TestBoardBuilder testBoard = TestBoard.builder();

        testBoard.title( dto.getTitle() );
        testBoard.content( dto.getContent() );

        return testBoard.build();
    }

    @Override
    public List<BoardRequestDTO> toDTOList(List<TestBoard> entityList) {
        if ( entityList == null ) {
            return null;
        }

        List<BoardRequestDTO> list = new ArrayList<BoardRequestDTO>( entityList.size() );
        for ( TestBoard testBoard : entityList ) {
            list.add( toDTO( testBoard ) );
        }

        return list;
    }

    @Override
    public List<TestBoard> toEntityList(List<BoardRequestDTO> dtoList) {
        if ( dtoList == null ) {
            return null;
        }

        List<TestBoard> list = new ArrayList<TestBoard>( dtoList.size() );
        for ( BoardRequestDTO boardRequestDTO : dtoList ) {
            list.add( toEntity( boardRequestDTO ) );
        }

        return list;
    }

    @Override
    public void updateFromDTO(BoardRequestDTO dto, TestBoard entity) {
        if ( dto == null ) {
            return;
        }
    }
}



์œ„์™€ ๊ฐ™์ด ์ž๋™์œผ๋กœ ๊ตฌํ˜„์ฒด Class๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.










    ๐Ÿ”ฝ ์ฝ”๋“œ ์‚ฌ์šฉ

        ๐Ÿ“ฆ Service Layer

BoardServiceImpl.insertBoard() - ์ˆ˜์ • ์ „


์›๋ž˜๋Š” ์œ„์™€ ๊ฐ™์ด Entity์˜ Builder Pattern์„ ํ†ตํ•ด DTO๋ฅผ Entity๋กœ ๋ฐ”๊พธ๋Š” Logic์ด์˜€๋˜ ๊ฒƒ์„
MapStruct๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ณ€๊ฒฝํ•ด ๋ณผ๊ฒŒ์š”.



BoardServiceImpl.insertBoard() - ์ˆ˜์ • ํ›„


์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •์„ ์™„๋ฃŒ ํ•ด ์ฃผ์—ˆ์–ด์š”.

์ตœ์ดˆ content ๊ฐ’์„ ์•”ํ˜ธํ™” ํ•ด์ฃผ๋Š” Logic์ด ๊ตฌํ˜„๋˜์–ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— RequestDTO์— setContent()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•”ํ˜ธํ™” Logic์„ ํƒ„ ๋’ค ๋ฐ˜ํ™˜๋˜๋Š” ์•”ํ˜ธ๊ฐ’์ด content Field์— ์ €์žฅ๋˜๋„๋ก ํ•˜์—ฌ์ฃผ์—ˆ์–ด์š”.

๊ทธ๋Ÿฐ ๋’ค 43๋ฒˆ์งธ ์ค„์— BoardReqeustDTO ๊ฐ์ฒด๋ฅผ Entity๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” Method๋ฅผ ํ†ตํ•ด Entity๋ฅผ ์–ป๊ฒŒํ•˜๊ณ , ๊ทธ๊ฒƒ์„ Repository๋กœ ๋ณด๋‚ด๊ฒŒ ๊ตฌํ˜„ํ•ด ์ฃผ์—ˆ์–ด์š”.





์œ„์™€ ๊ฐ™์ด ๊ธ€ ์ž‘์„ฑ์„ ์„ฑ๊ณตํ•˜์˜€์–ด์š”.


์ƒ์„ธ ์กฐํšŒ ๊ธฐ๋Šฅ์„ ์ด์šฉํ–ˆ์„ ๋•Œ๋„ ์ •์ƒ์ ์œผ๋กœ ๋ณตํ˜ธํ™”๊ฐ€ ๋˜๋ฉด ๊ฐ’์„ ๋ฐ˜ํ™˜๋ฐ›์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.





๐Ÿง ์ฐธ๊ณ  ์ž๋ฃŒ

 

[Spring] MapStruct๋ฅผ ์ด์šฉํ•œ Entity, Dto ๋ฐ˜ํ™˜ ๋ฐ ๊ณ ์ฐฐ

๊ทธ ๋™์•ˆ View layer์—์„œ Entity์— ์ง์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์งฐ๋˜ ๋‚˜์—๊ฒŒ, ์ด๋ฒˆ DTO ์ ์šฉ์€ ์ƒ๋‹นํžˆ ๊ณ ๋œ ์ผ์ด์—ˆ๋‹ค. ์‚ฌ์‹ค dto๋Š” ๋‹จ์ˆœํ•œ entity์˜ ํด๋ก  ๋Š๋‚Œ์ด๋ผ ์ ์šฉ์ด ํฌ๊ฒŒ ์–ด๋ ต์ง€ ์•Š์„ ์ค„ ์•Œ์•˜๋Š”๋ฐ,

kth990303.tistory.com

 

 

 

 

๋ฐฑ๊ฒฌ๋ถˆ์—ฌ์ผํƒ€ ์Šคํ”„๋ง ๋ถ€ํŠธ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ with JPA:์ด์   ํ”„๋กœ์ ํŠธ๋‹ค!

COUPANG

www.coupang.com

 

 

 

React.js ์Šคํ”„๋ง ๋ถ€ํŠธ AWS๋กœ ๋ฐฐ์šฐ๋Š” ์›น ๊ฐœ๋ฐœ 101:SPA REST API ๊ธฐ๋ฐ˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ

COUPANG

www.coupang.com

 

 

 

์Šคํƒ€ํŠธ ์Šคํ”„๋ง ๋ถ€ํŠธ:์ดˆ๊ธ‰ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ„ํ•œ ๊ฐ€๋ณ๊ณ  ๋„“์€ ์Šคํ”„๋ง ๋ถ€ํŠธ

COUPANG

www.coupang.com

"์ด ํฌ์ŠคํŒ…์€ ์ฟ ํŒก ํŒŒํŠธ๋„ˆ์Šค ํ™œ๋™์˜ ์ผํ™˜์œผ๋กœ, ์ด์— ๋”ฐ๋ฅธ ์ผ์ •์•ก์˜ ์ˆ˜์ˆ˜๋ฃŒ๋ฅผ ์ œ๊ณต๋ฐ›์Šต๋‹ˆ๋‹ค."

 

 

 

 

 

 

 

 

728x90
๋ฐ˜์‘ํ˜•