ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • MapStruct 의 다양한 사용에 대해 알아보자
    Server/Spring Boot 2025. 4. 16. 13:08
    728x90
    반응형

    🚀 MapStruct 고급 매핑 예제

    이번엔 MapStruct를 좀 더 깊이 있게 사용하는 예제들을 소개합니다.
    List 매핑, @AfterMapping, @Named, @InheritInverseConfiguration 등 실제 프로젝트에서도 매우 유용한 기능들이에요.


    1️⃣ List 매핑

    컬렉션 타입도 자동 매핑 가능합니다.

    // 단일 DTO 매핑 메서드
    UserDto toDto(User user);
    
    // 리스트 매핑
    List<UserDto> toDtoList(List<User> users);
    

    단, 단일 객체 매핑 메서드가 정의되어 있어야 리스트 매핑도 동작합니다.

    ---

    2️⃣ @AfterMapping - 매핑 후 추가 작업 처리

    매핑이 완료된 후 후처리를 하고 싶을 경우 @AfterMapping을 사용합니다.

    @Mapper(componentModel = "spring")
    public interface UserMapper {
    
        UserDto toDto(User user);
    
        @AfterMapping
        default void setCustomFields(@MappingTarget UserDto dto, User user) {
            dto.setUsername(dto.getUsername().toUpperCase());
        }
    }
    
    • @MappingTarget: 결과 객체를 참조합니다.
    • 위 예시에서는 매핑된 결과 중 username 필드를 대문자로 수정합니다.

    ---

    3️⃣ @Named - 재사용 가능한 매핑 정의

    @Named는 재사용 가능한 변환 메서드를 만들고, qualifiedByName으로 명시적으로 사용할 때 유용합니다.

    @Mapper(componentModel = "spring")
    public interface UserMapper {
    
        @Mapping(source = "email", target = "email", qualifiedByName = "maskEmail")
        UserDto toDto(User user);
    
        @Named("maskEmail")
        static String maskEmail(String email) {
            if (email == null || !email.contains("@")) return email;
            return "***@" + email.substring(email.indexOf("@") + 1);
        }
    }
    

    포인트: 민감 정보를 가릴 때, 포맷을 바꿀 때 유용하게 사용됩니다.

    ---

    4️⃣ @InheritInverseConfiguration - 양방향 매핑 간소화

    @InheritInverseConfiguration기존 매핑 설정을 반대로 재사용할 수 있게 해줍니다.

    @Mapper(componentModel = "spring")
    public interface UserMapper {
    
        @Mapping(source = "name", target = "username")
        UserDto toDto(User user);
    
        @InheritInverseConfiguration
        User toEntity(UserDto dto);
    }
    

    장점: 중복되는 @Mapping을 줄이고, 실수를 방지할 수 있어요.

    ---

    5️⃣ 여러 기능을 조합한 예제

    @Mapper(componentModel = "spring")
    public interface UserMapper {
    
        @Mapping(source = "name", target = "username")
        @Mapping(source = "email", target = "email", qualifiedByName = "maskEmail")
        UserDto toDto(User user);
    
        @InheritInverseConfiguration
        @Mapping(target = "id", ignore = true)
        User toEntity(UserDto dto);
    
        List<UserDto> toDtoList(List<User> users);
    
        @Named("maskEmail")
        static String maskEmail(String email) {
            if (email == null || !email.contains("@")) return email;
            return "***@" + email.substring(email.indexOf("@") + 1);
        }
    
        @AfterMapping
        default void afterMapping(@MappingTarget UserDto dto, User user) {
            dto.setUsername(dto.getUsername().toUpperCase());
        }
    }
    

    ---

    🧠 마무리 정리

    • List 매핑은 단일 매핑 메서드가 있을 때 자동 지원됨
    • @AfterMapping은 후처리 로직 작성에 유용
    • @Named + qualifiedByName은 커스텀 메서드 재사용 시 필수
    • @InheritInverseConfiguration은 양방향 매핑을 편리하게 관리

    이렇게 MapStruct의 기능을 적절히 조합하면, 반복 코드를 줄이면서도 확장성과 가독성을 높일 수 있습니다 😎

    728x90
    반응형

    댓글

Designed by Tistory.