티스토리 뷰
DB에 연결해서 데이터를 가져오는 것에 아무 생각 없이 @Repository 어노테이션을 붙여서 개발을 하고 있었다.
그러던 중 지인이 @Mapper와 @Repository의 차이에 물어왔고 생각해보니 그 둘의 차이점을 몰라 구글링을 해보다보니 두 어노테이션은 크게 차이가 없지만 Repository와 Mapper 간에는 차이가 있다는 것을 알고 정리를 해보려한다.
애초에 구글링해서 나오는 글들은 javadoc을 그대로 번역하거나 뭔가 내 기준으로 와닿지 않아서 내 말로 정리하는게 필요할 것 같다.
Mapper란
우선 repository와 Mapper를 비교할 때 mapper가 작은 단위이다.
밑에서도 설명할테지만 repository는 mapper를 포함하고 있다.
mapper는 00.xml과 같이 sql문을 정의해놓은 파일과 많이 사용한다. SQL문을 정의하고 그 결과를 정의해놓은 모델에 매핑시키는 ibatis(mybatis) 방식에서 사용하는 것으로 mapper는 매핑이라는 단어에서 유추할 수 있듯이 sql문(xml)을 메소드(java)로 매핑 시켜주는 것을 의미한다.
즉, 우리가 정의해놓은 sql와 개발할 때 사용하는 메소드를 연결하고 결과 값을 정의해놓은 타입으로 매핑 시켜주는 것이다.
그래서 우리는 sql문을 정의해놓고 namespace와 sql id에 맞는 메소드를 호출해 DB의 데이터를 조회 및 조작할 수 있는 것이다.
@Mapper
그렇다면 @Mapper 어노테이션은 무엇인가?
@Mapper 어노테이션을 까서 javadoc의 내용을 보면 아래와 같다.
// Marker interface for MyBatis mappers.
의미를 보면 @Mapper는 마커 인터페이스라는 것이다.
* 마커 인터페이스: 기능이 있는게 아니라 마커, 즉 무언가 표시를 하기 위한 인터페이스를 의미한다.
즉, @Mapper는 단순히 '이것은 매퍼입니다!!'라는 것을 표시하기 위한 어노테이션이라는 것이다.
중요한 것은 @Mapper와 같이 쓰이는 @MapperScan이지 굳이 @Mapper를 쓰지 않고 커스텀 어노테이션을 생성해서 사용해도 된다.
// @Mapper 사용
@MapperScan(annotationClass = Mapper.class)
public class MapperConfig {
...
}
// 커스텀 어노테이션 사용
@MapperScan(annotationClass = CustomMapper.class)
public class CustomMapperConfig {
...
}
Repository
그렇다면 repository는 무엇인가? 이 부분이 제일 와닿지 않아서 계속 구글링을 했던 부분이다. mapper는 sql과 메소드를 매핑해서 사용할 수 있게 해주는 것이라고 이해가 가는데 그렇다면 repository는 무엇이고 왜 mapper와 구분짓는 것인가?
우선 repository는 위에 mapper에서 설명했듯이 mapper를 포함하고 있다.
repository에 대해 찾아보면 다들 하는 얘기가 repository는 dao라고 한다.
* DAO(Data Access Object): DB에 접근해서 데이터를 조회 및 조작하는 객체
어디서 많이 본 개념 같다. mapper와 매우 비슷하다. 이래서 mapper와 repository 차이를 보는데 정말 와닿지 않아서 계속 구글링 했다.
일단 이해한바로 정리하면 아래와 같다.
mapper는 위에서 설명한 것처럼 sql을 메소드로 쓰기 위해, sql 결과를 정의해놓은 모델로 매핑하기 위한 이름 그대로의 매퍼이다.
repository는 위의 매퍼들을 포함해서 mapper처럼 sql을 메소드랑 매핑해서 쓰든 아니든 db를 조회 및 조작하는 것에 중점을 둔 개념이다.
그래서 repository는 mapper를 포함하는 것이다.
repository(dao)는 비즈니스로직에서 db의 데이터를 조회 및 조작하는 것을 비즈니스 로직과 분리하기 위한 것으로 db랑 연결하는 것이 강한 mapper와 달리 db의 데이터를 조회 및 조작하는 것에 중점을 뒀다는 것이 제일 큰 개념이다.
@Repository
그렇다면 @Repository 어노테이션은 무엇인가.
어노테이션을 까보면 아래와 같이 생겼다.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
Target도 Mapper와 차이가 있긴 하지만 다른 것들을 살펴보면, 우선 @Repository에는 @Component가 붙어있다. 즉, @Repository를 붙이면 해당 객체는 자동으로 빈 등록이 되고 DI에 쓰일 수 있다는 것이다.
이는 repository는 mapper를 포함하는 개념이므로 mapper를 호출해서 써 repository에 @MapperScan을 할 필요 없이 사용할 수 있기 떄문으로 보인다.
그리고 @Repository는 value라는 값을 하나 받는다. value에 대한 javadoc 설명을 보면 아래와 같다. 여기서 볼거는 'component name'인데 즉 해당 객체가 빈으로 등록되었을 때의 이름을 의미하게 된다는 것이다. 이 값은 mapper.xml의 namespace를 repository랑 매칭 시킬 때 유용하다.
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
보통 mapper.xml의 namespace는 패키지명을 포함한 주소가 된다. 하지만 @Repository의 value 값을 설정하면 그럴 필요가 없다. value값과 mapper.xml의 namespace의 이름이 일치하면 되는 것이다.
@Repository("test")
public void TestRepository {
...
}
<mapper namespace="test">
...
</mapper>
Mapper와 Repository의 차이 정리
MVC에서 repository, mapper를 적용해보면 아래와 같이 구현하고자 하는 구조에 따라서 유동적으로 선택해서 사용하면 된다. Mapper만 썼으니 잘못됐어! Mapper 클래스 없이 Repository만 썼으니 잘못됐어! 이런건 없다.
- Controller -> Service -> Repository -> mapper.xml
- Controller -> Service -> Repository -> Mapper -> mapper.xml
- Controller -> Service -> Mapper -> mapper.xml
하지만 그래도 repository, mapper가 다른 것이고 각각 어떤 것을 의미하는지는 알아야겠다.
✋ What exactly is the difference between a data mapper and a repository?
'Java' 카테고리의 다른 글
Mockito로 static method mock 하기 (0) | 2022.03.17 |
---|---|
빌더 패턴(Builder pattern)을 써야하는 이유, @Builder (2) | 2022.03.02 |
어노테이션 중복 정의를 가능하게 하는 @Repeatable (0) | 2022.02.17 |
Build Gradle vs IntelliJ IDEA (2) | 2022.02.10 |
자바의 function interface (0) | 2022.02.04 |
- Total
- Today
- Yesterday
- eclipse
- k8s
- rabbitmq
- postgres
- MAC
- springboot
- 데이터베이스
- 캐싱
- 자바
- DB
- 캐시
- DATABASE
- enum
- Caching
- 메시지큐
- Spring
- HttpClient
- Intellij
- cache
- Java
- mockito
- JPA
- 스프링부트
- ssh
- 이클립스
- PostgreSQL
- 역직렬화
- 어노테이션
- 공간데이터
- annotation
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |