아래 코드에 대해 Dao인데 Repository 어노테이션을 사용한 이유에 대해 질문 받았다.
@Repository
public class ReservationMemoryDao implements ReservationDao {
private final List<Reservation> reservations = new ArrayList<>();
private final AtomicLong counter = new AtomicLong();
@Override
public List<Reservation> findAll() {
return reservations;
}
@Override
public Optional<Reservation> findById(Long id) {
return reservations.stream()
.filter(reservation -> reservation.getId().equals(id))
.findFirst();
}
@Override
public void save(Reservation reservation) {
reservation.setId(counter.incrementAndGet());
reservations.add(reservation);
}
@Override
public void delete(Reservation reservation) {
reservations.remove(reservation);
}
}
Java
복사
일단 왜 위의 코드가 Dao인지부터 궁금할 수 있는데, 추후 save, delete, find 동작이 List 콜렉션에 대해 동작하는 게 아니라 database에 대해 동작하게 리팩토링할 계획이라 Dao라고 이름 붙여뒀다.
Repository 어노테이션의 역할
스프링 빈으로 등록하고 싶어서 별 고민없이 사용했었는데, @Repository 어노테이션의 역할을 살펴보니 현재 코드에선 불필요하단 점을 깨달아 @Component 어노테이션으로 변경해주었다. 현재 코드에선 database와 관련한 예외를 변환할 일이 없기 때문이다. 스프링 빈으로 등록시키는 건 @Component 어노테이션으로 충분하다.
•
@Repository 의 역할
◦
database와 관련된 예외를 스프링의 DataAccessException으로 변환해준다.
◦
스프링 빈으로 등록시킨다.
◦
Repository 레이어에 대한 스테레오 타입으로 쓰인다.
Dao와 Repository 어노테이션 (with 공식문서)
다만, 후에 database를 적용한다면 Dao여도 @Repository을 붙이는 게 말이 아예 안되진 않을 거 같다.
공식문서를 찾아보니 아래와 같이 명시하고 있다.
Teams implementing traditional Jakarta EE patterns such as "Data Access Object" may also apply this stereotype to DAO classes, though care should be taken to understand the distinction between Data Access Object and DDD-style repositories before doing so. This annotation is a general-purpose stereotype and individual teams may narrow their semantics and use as appropriate.
요약해보자면, dao 패턴을 사용하는 팀들은 @Repository을 DAO 클래스에 적용할 수 있으나, @Repository를 사용할 땐 해당 클래스가 누군가에겐 도메인 중심의 Repository 개념으로 간주될 수도 있단 점을 주의하고 사용하라 명시하고 있다. DAO와 Repository의 개념은 명백히 다르기에 조심해야 한다.
만일 DAO에 @Repository 를 붙이고 싶다면, 팀 내 규칙으로 @Repository 애노테이션의 의미를 좁혀서 적절하게 사용해야 할 것이다. @Repository은 Repository 레이어를 나타내는 스테레오 타입이긴 하지만, 각 팀이 그 의미를 좁혀서 적절하게 사용할 수 있다고 공식문서가 명시하고 있기 때문이다.