자바에서 사용하는 SQL Mapper 프레임워크
📦 controller
📦 service
📦 mapper ← Mapper 인터페이스
📄 mapper.xml ← 쿼리 정의
📄 VO.java ← 결과를 담을 객체
📦 controller
└── UserController.java
📦 service
├── UserService.java ← 인터페이스
└── UserServiceImpl.java ← 구현체 (Impl)
📦 dao
├── UserMapper.java ← Mapper 인터페이스
└── user-mapper.xml ← XML Mapper
📦 vo
└── UserVO.java ← 값 객체 (DB와 매핑되는 필드 위주)
public class UserVO {
private String name;
private String email;
private int age;
// getter, setter
}
<select id="getUserById" resultType="com.example.vo.UserVO">
SELECT * FROM users WHERE id = #{id}
</select>
@Mapper
public interface UserMapper {
UserVO getUserById(Long id);
}
public interface UserService {
UserVO getUser(Long id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public UserVO getUser(Long id) {
return userMapper.getUserById(id);
}
}
| 장점 | 단점 |
|---|---|
| SQL이 명확하게 보이고 튜닝 쉬움 | XML 관리가 번거로움 |
| VO가 단순하고 직관적 | VO와 DTO가 분리되지 않아 역할이 불명확 |
| 레거시 프로젝트에서 여전히 많이 사용 | 유지보수 시 계층 분리가 부족하면 혼란 발생 |
| 성능 튜닝에 유리 (직접 쿼리) | 코드 중복, 테스트 어려움 |
값에 의미를 부여하고 불변성을 보장하고 싶을 때| 구조 요소 | 사용하는 경우 | 사용하지 않는 경우 |
|---|---|---|
| impl | • 인터페이스 기반으로 계층을 나눌 때 • 유닛 테스트 / 확장성 고려할 때 | • 간단한 프로젝트 • 임시 서비스 로직 |
| Dto | • 계층 간 데이터 전달이 많을 때 • 보안, 응답 포맷 조작이 필요할 때 • API 설계가 명확해야 할 때 | • 빠르게 만들거나 CRUD 중심의 단순한 기능 • 내부에서만 사용할 때 |
| Entity | • JPA/ Hibernate로 DB와 매핑할 때 ( 기본적으로 사용) | • 외부 API 연동만 있고 DB를 사용하지 않는 경우 추천 X |
| Vo | • 값 단위로 의미를 부여할 때 • 도메인 모델이 중요할 때 • 값의 무결성과 불변성이 중요할 때 | • 단순한 DTO처럼 쓰는 경우 • JPA 구조만으로 충분한 경우 |
💡스프링은 계층형 아키텍처를 따른다.
❌ Entity를 바로 반환하는 경우 문제점 (Entity <-> DTO)
✅DTO의 역할