๐Ÿ“š ์‹ค๋ฌด์—์„œ DTO โ†” Domain โ†” Entity Mapper ์ฑ…์ž„ ์œ„์น˜ ์ •๋ฆฌ (ํ—ฅ์‚ฌ๊ณ ๋‚  + DDD ์ ์šฉ ๊ฒฝํ—˜ ๊ธฐ๋ฐ˜)

๋ฐ•์ค€ํ˜•ยท2025๋…„ 8์›” 17์ผ

์Šคํ”„๋ง ๊ฐœ๋ฐœ

๋ชฉ๋ก ๋ณด๊ธฐ
12/20
post-thumbnail

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜์™€ DDD๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋ฉด์„œ,
๊ฐ€์žฅ ํฌ๊ฒŒ ๋ถ€๋”ชํžŒ ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋Š” DTO โ†” Domain โ†” Entity ๋ณ€ํ™˜ ์ฑ…์ž„์„ ์–ด๋””์— ๋‘˜ ๊ฒƒ์ธ๊ฐ€์˜€๋‹ค.

์ฒ˜์Œ์—๋Š” Service๋‚˜ Controller ์•ˆ์—์„œ ๋ฌด์‹ฌ์ฝ” ๋ณ€ํ™˜์„ ์ฒ˜๋ฆฌํ–ˆ๋Š”๋ฐ, ์‹œ๊ฐ„์ด ์ง€๋‚ ์ˆ˜๋ก ๋ ˆ์ด์–ด ๊ฐ„ ๊ฒฝ๊ณ„๊ฐ€ ๋ฌด๋„ˆ์ง€๊ณ , ๋„๋ฉ”์ธ ์ˆœ์ˆ˜์„ฑ์ด ์˜ค์—ผ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋˜์—ˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋ ˆ์ด์–ด ๊ฐ„ ๋ณ€ํ™˜ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ธฐ์ค€์„ ๋ช…ํ™•ํžˆ ์žก์•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ ๊ตฌ์กฐ์  ์•ˆ์ •์„ฑ๊ณผ ๋ณ€๊ฒฝ ๋‚ด์„ฑ์ด ํฌ๊ฒŒ ์ข‹์•„์ง€๊ฒŒ ๋˜์—ˆ๋‹ค.

์•„๋ž˜๋Š” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ์—์„œ ์ ์šฉํ•œ ๊ตฌ์กฐ์ด๋ฉฐ board ๋„๋ฉ”์ธ์— ๊ฒŒ์‹œ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ์„ ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž.


โœ… 1. Web DTO โ†” Application DTO

  • ์œ„์น˜: adapter/web/mapper/

๐Ÿ“Œ ๋‚ด๊ฐ€ ์ด๋ ‡๊ฒŒ ํ•œ ์ด์œ 

  • ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜ ๊ด€์ ์—์„œ Web ๊ณ„์ธต์€ ๋‹จ์ˆœํžˆ ์™ธ๋ถ€ ์š”์ฒญ์„ ๋ฐ›์•„ UseCase(Application Service)๋กœ ์ „๋‹ฌํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ์ผ ๋ฟ์ด๋‹ค.
  • API์— ๋งž์ถ˜ DTO(Web DTO)๋Š” Swagger ๋ฌธ์„œ, Validation, ํ•„๋“œ๋ช… ๋“ฑ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•ด์•ผ ํ•˜๊ณ ,
    ๋‚ด๋ถ€ Application DTO๋Š” ์˜ค์ง ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋งŒ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ WebMapper๋ฅผ ๋‘์–ด Web DTO โ†” Application DTO ๋ณ€ํ™˜์„ ๋‹ด๋‹นํ•˜๊ฒŒ ํ•˜๋ฉด,
    ์›น ๊ณ„์ธต๊ณผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต์ด ์„œ๋กœ ์นจ๋ฒ”ํ•˜์ง€ ์•Š๋Š”๋‹ค.
// ๐Ÿ“ board/adapter/web/mapper/BoardWebMapper.java
@Component
public class BoardWebMapper {

    public CreateBoardRequest toApplicationDto(CreateBoardWebRequest request, Long userId) {
        return new CreateBoardRequest(request.title(), request.content(), userId);
    }

    public BoardWebResponse toWebDto(CreateBoardResponse response) {
        return new BoardWebResponse(response.boardId());
    }
}


โœ… 2. Application DTO โ†” Domain Model

  • ์œ„์น˜: application/mapper/

๐Ÿ“Œ ๋‚ด๊ฐ€ ์ด๋ ‡๊ฒŒ ํ•œ ์ด์œ 

  • ApplicationService๋Š” ์œ ์Šค์ผ€์ด์Šค ์กฐ๋ฆฝ๊ณผ ํŠธ๋žœ์žญ์…˜ ๊ฒฝ๊ณ„ ๊ด€๋ฆฌ์— ์ง‘์ค‘ํ•ด์•ผ ํ•œ๋‹ค.
  • Domain์€ DTO๋ผ๋Š” ์™ธ๋ถ€ ๊ตฌ์กฐ๋ฅผ ์ „ํ˜€ ๋ชฐ๋ผ์•ผ ์ˆœ์ˆ˜์„ฑ์ด ๋ณด์žฅ๋œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ค‘๊ฐ„์— Mapper๋ฅผ ๋‘์–ด Application DTO โ†” Domain ๋ณ€ํ™˜์„ ์ฑ…์ž„์ง€๊ฒŒ ํ–ˆ๋‹ค.
  • ์ด๋•Œ ๋ณ€ํ™˜์€ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ํ•„์š”ํ•˜๋‹ค.
    • Application Request DTO โ†’ Domain Model
    • Domain Model โ†’ Application Response DTO
// ๐Ÿ“ board/application/mapper/BoardMapper.java
@Component
public class BoardMapper {

    // Application Request DTO โ†’ Domain Model
    public Board toDomain(CreateBoardRequest request) {
        return Board.of(request.title(), request.content(), request.userId());
    }

    // Domain Model โ†’ Application Response DTO
    public CreateBoardResponse toResponse(Board board) {
        return new CreateBoardResponse(board.getId());
    }
}


โœ… 3. Domain Model โ†” JPA Entity

  • ์œ„์น˜: adapter/jpa/mapper/

๐Ÿ“Œ ๋‚ด๊ฐ€ ์ด๋ ‡๊ฒŒ ํ•œ ์ด์œ 

  • JPA Entity๋Š” DB์™€์˜ ์ €์žฅ/์กฐํšŒ์— ํŠนํ™”๋œ Persistence ๋ชจ๋ธ์ด๋‹ค.
  • Domain Model์€ ์ˆœ์ˆ˜ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™ ํ‘œํ˜„์— ์ง‘์ค‘ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋‘ ๋ชจ๋ธ์„ ์„ž์–ด ์“ฐ๋ฉด ๋„๋ฉ”์ธ ๋ชจ๋ธ์ด JPA ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์˜ค์—ผ๋œ๋‹ค.
  • ๋”ฐ๋ผ์„œ JPA Adapter ๋‚ด๋ถ€์—์„œ๋งŒ ๋งคํ•‘์„ ํ—ˆ์šฉํ–ˆ๊ณ , ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋„๋ฉ”์ธ ๊ณ„์ธต์€ JPA ์กด์žฌ ์ž์ฒด๋ฅผ ๋ชจ๋ฅด๊ฒŒ ๋œ๋‹ค.
// ๐Ÿ“ board/adapter/jpa/mapper/BoardJpaMapper.java
@Component
public class BoardJpaMapper {

    public BoardEntity toEntity(Board board) {
        return BoardEntity.of(board.getId(), board.getTitle(), board.getContent(), board.getUserId());
    }

    public Board toDomain(BoardEntity entity) {
        return Board.of(entity.getId(), entity.getTitle(), entity.getContent(), entity.getUserId());
    }
}


๐Ÿ“ ์ข…ํ•ฉ ์š”์•ฝ (๊ตฌ์กฐ์  ์œ„์น˜ ์ •๋ฆฌ + ์ด์œ )

๋ณ€ํ™˜ ์ฑ…์ž„์œ„์น˜์ด์œ 
Web DTO โ†” Application DTOadapter/web/mapper/API ํ‘œํ˜„๊ณผ ๋‚ด๋ถ€ DTO๋ฅผ ๋ถ„๋ฆฌ โ†’ ํ—ฅ์‚ฌ๊ณ ๋‚  ๊ฒฝ๊ณ„ ๋ช…ํ™•ํ™”
Application DTO โ†” Domainapplication/mapper/Domain์€ ์™ธ๋ถ€ DTO๋ฅผ ๋ชฐ๋ผ์•ผ ํ•จ โ†’ ์ˆœ์ˆ˜์„ฑ ์œ ์ง€. Request/Response ์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ํ•„์š”
Domain โ†” JPA Entityadapter/jpa/mapper/Persistence ์ „์šฉ, JPA ์˜์กด์„ฑ ์ฐจ๋‹จ โ†’ ๋„๋ฉ”์ธ ์˜ค์—ผ ๋ฐฉ์ง€


๐Ÿš€ ๊ฒฐ๋ก 

ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„ํ‚คํ…์ฒ˜ + DDD๋ฅผ ์‹ค๋ฌด์— ์ ์šฉํ•˜๋ฉด์„œ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋ฐฐ์šด ์ ์€
โ€œ๋„๋ฉ”์ธ ์ˆœ์ˆ˜์„ฑ์„ ์ง€ํ‚ค๋ ค๋ฉด, ๋ณ€ํ™˜ ์ฑ…์ž„์„ ๋ฐ˜๋“œ์‹œ ๊ฒฝ๊ณ„์— ๋‘์–ด์•ผ ํ•œ๋‹คโ€๋Š” ๊ฒƒ์ด๋‹ค.

  • Web โ†” Application: ํ‘œํ˜„๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋ถ„๋ฆฌ
  • Application โ†” Domain: Request DTO์—์„œ ๋„๋ฉ”์ธ์œผ๋กœ ๋ณ€ํ™˜, ๋„๋ฉ”์ธ์—์„œ Response DTO๋กœ ๋ณ€ํ™˜
  • Domain โ†” JPA Entity: Persistence์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋ถ„๋ฆฌ

์ด๋ ‡๊ฒŒ ๊ฐ ๊ณ„์ธต์˜ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊ตฌ๋ถ„ํ–ˆ๋”๋‹ˆ,
์ฝ”๋“œ ํ’ˆ์งˆ์ด ์œ ์ง€๋˜๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ๋‹จ์ˆœํ•ด์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ๊ณ„์ธต์˜ ์˜๋ฏธ๋ฅผ ๋”์šฑ ๋ช…ํ™•ํ™” ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค!

profile
๋งค์ผ ๋งค์ผ ์„ฑ์žฅํ•˜๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€