VO ↔ DTO 변환 라이브러리 MapStruct 사용법
MapStruct 라이브러리 추가 방법
pom.xml 수정
<dependencies>
<!-- MapStruct 라이브러리 의존성 추가 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
</dependencies>
<build>
<!-- 생략 -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<!-- 항상 전체 컴파일 설정 : DTO, VO 필드 변경 시 MapStruct impl 갱신 -->
<useIncrementalCompilation>false</useIncrementalCompilation>
<annotationProcessorPaths>
<!-- Lombok annotationProcessor -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
<!-- MapStruct annotationProcessor 추가 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
pom.xml에 MapStruct 라이브러리 및 어노테이션 프로세서를 추가하고, Maven을 리로드하여 반영해줍니다.
Lombok으로 VO 및 DTO Getter, Setter 함수가 생성된 이후 사용되어야 하므로, Lombok 아래에 추가합니다.
VO → DTO 변환 담당 ResponseMapper 생성
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface AiLrnProfClasStnsResponseMapper {
// VO → DTO 변환 (필드명이 서로 다른 경우만 명시)
@Mapping(source = "DTO필드명1", target = "VO필드명1")
@Mapping(source = "DTO필드명2", target = "VO필드명2")
AiLrnProfClasStnsResponseDto voToDto(AiLrnProfClasStns vo);
// VO 리스트 → DTO 리스트 변환
// MapStruct가 내부적으로 voToDto를 호출하여 자동 매핑
List<AiLrnProfClasStnsResponseDto> voListToDtoList(List<AiLrnProfClasStns> voList);
}
DB 쿼리 조회용 Mapper 폴더 안에 dto 폴더 생성 후, DTO 변환용 Mapper를 추가 생성합니다.
서비스에서 Mapper 생성자 주입 후 사용 예시
@Service ("AiLrnProfLrnnService")
public class AiLrnProfLrnnServiceImpl extends EgovAbstractServiceImpl implements AiLrnProfLrnnService {
private final AiLrnProfLrnnMapper aiLrnProfLrnnMapper;
private final AiLrnProfClasStnsResponseMapper aiLrnProfClasStnsResponseMapper;
private final Ehcache ehCache;
// 생성자 주입
public AiLrnProfLrnnServiceImpl(
AiLrnProfLrnnMapper aiLrnProfLrnnMapper,
AiLrnProfClasStnsResponseMapper aiLrnProfClasStnsResponseMapper,
Ehcache ehCache
) {
this.aiLrnProfLrnnMapper = aiLrnProfLrnnMapper;
this.aiLrnProfClasStnsResponseMapper = aiLrnProfClasStnsResponseMapper;
this.ehCache = ehCache;
}
public List<AiLrnProfClasStnsResponseDto> selectProfClasStnsList(AiLrnClassStnsCondition condition) throws Exception {
// 클래스 ID 리스트 세팅
IMLoginVO user = (IMLoginVO) EgovUserDetailsHelper.getAuthenticatedUser();
List<ClassInfo> classList = IMLoginAPIUtil.classList(ehCache, user.getId());
condition.setClassInfos(classList);
List<AiLrnProfClasStns> voList = aiLrnProfLrnnMapper.selectProfClasStnsList(condition);
return aiLrnProfClasStnsResponseMapper.voListToDtoList(voList);
}
}
@Autowired, @Resources 대신 생성자 주입으로 Mapper Bean을 주입받아 사용하는 것이 권장됩니다.
MapStruct 라이브러리가 적용된 Mapper를 통해 DB에서 조회한 VO를 DTO로 변환할 수 있습니다.
MapStruct 정상 적용 확인
package com.intermorph.lrn.mapper.dto;
import com.intermorph.lrn.domain.AiLrnProfClasStns;
import com.intermorph.lrn.dto.AiLrnProfClasStnsResponseDto;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-11-25T09:16:14+0900",
comments = "version: 1.4.2.Final, compiler: javac, environment: Java 1.8.0_401 (Oracle Corporation)"
)
@Component
public class AiLrnProfClasStnsResponseMapperImpl implements AiLrnProfClasStnsResponseMapper {
@Override
public AiLrnProfClasStnsResponseDto voToDto(AiLrnProfClasStns vo) {
if ( vo == null ) {
return null;
}
AiLrnProfClasStnsResponseDto aiLrnProfClasStnsResponseDto = new AiLrnProfClasStnsResponseDto();
aiLrnProfClasStnsResponseDto.setClasId( vo.getClasId() );
aiLrnProfClasStnsResponseDto.setShcYear( vo.getShcYear() );
aiLrnProfClasStnsResponseDto.setShcTrm( vo.getShcTrm() );
aiLrnProfClasStnsResponseDto.setRcmCtareaCd( vo.getRcmCtareaCd() );
aiLrnProfClasStnsResponseDto.setRcmCtareaNm( vo.getRcmCtareaNm() );
return aiLrnProfClasStnsResponseDto;
}
@Override
public List<AiLrnProfClasStnsResponseDto> voListToDtoList(List<AiLrnProfClasStns> voList) {
if ( voList == null ) {
return null;
}
List<AiLrnProfClasStnsResponseDto> list = new ArrayList<AiLrnProfClasStnsResponseDto>( voList.size() );
for ( AiLrnProfClasStns aiLrnProfClasStns : voList ) {
list.add( voToDto( aiLrnProfClasStns ) );
}
return list;
}
}
톰캣 실행 시 프로젝트폴더/target/generated-sources/annotations 이하에 생성된 MapperImpl.java 파일입니다.
VO 내 각 필드 값을 DTO 내 각 필드에 매핑해주는 로직이 자동 구현된 것을 확인할 수 있습니다.
만약, 필드 매핑 로직이 생성되지 않았다면 프로젝트 Java 버전에 맞게 MapStruct 버전을 변경하면 됩니다.