Repository는 도메인 계층일까, 영속성 계층일까?

hongo·2023년 5월 22일
0

Repository는 도메인 계층일까, 영속성 계층일까?

이번 미션에서 DB에 Station 객체들을 저장하기 위해 다음과 같은 클래스를 만들었다.

  • DbStationRepository
@Repository
public class DbStationRepository {
    private final StationDao stationDao;

    public DbStationRepository(StationDao stationDao) {
        this.stationDao = stationDao;
    }

    public long create(Station station) {
        return stationDao.insert(new StationEntity(station.getName()));
    }

    public Station findById(Long id) {
        StationEntity stationEntity = stationDao.findById(id);
        return new Station(stationEntity.getId(), stationEntity.getName());
    }

    ...
}

그럼 이 DbStationRepository는 어떤 계층에 속해야 할까?

Domain-Driven Design (Evans, 2003)에서는 Repository를 다음과 같이 설명하고 있다.

"a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects"

Repository는 객체 collection의 상태를 관리하는 저장소라고 볼 수 있다.

객체 collection에 객체를 저장하고, 탐색하는 기능을 캡슐화한 것이 Repository이다.

여기서 분명한 것은 Repository객체 collection에 대한 관리를 하므로, 도메인 계층에 대해 알고있어야 한다는 것이다. 하지만, DbStationRepository를 보면 Dao를 사용해 영속성 계층에 접근하는 것을 볼 수 있다.

그럼 Repository는 도메인 계층과 영속성 계층 둘 모두에 접근하고 있는 걸까?

레이어드 아키텍처 구조에 따르면, 상위 계층은 하위 계층에 대한 정보를 알고 있지만, 하위 계층에 상위 계층에 대한 정보를 알지 못한다. 의존성의 흐름이 한 방향으로 흘러야하는 것이다.

하지만 Repository가 도메인 계층과 영속성 계층 둘 모두를 알고있다면 이 구조가 깨지게 된다.

여기서, Repository에 의존 역전 원칙을 사용하면 의존성의 방향을 일정하게 유지할 수 있다.

의존 역전 원칙

  1. 고수준 모듈(high level module)은 저수준 모듈(low level module)에 의존하면 안된다. 또한, 두 모듈은 추상화된 것(abstarctions)에 의존해야 한다.
  2. 추상화된 것은 상세한 것(details)을 의존하면 안된다. 상세한 것은 추상화된 것을 의존해야 한다.

Repository 인터페이스 생성

추상화 객체인 StationRepository를 생성해서 도메인 계층과 영속성 계층간의 의존을 끊는 것이다.

public interface StationRepository {
    long create(Station station);

    Station findById(Long id);

    List<Station> findAll();

    void update(Station station);

    void deleteById(Long id);
}
  • 객체 collection에 대한 관리 책임을 가지고 있는 StationRepository를 생성한다.

StationRepository는 영속성 계층에 대한 정보를 가지고 있지 않는다. 온전히 객체 collection 관리에 대한 책임만을 가진다.

Repository 구현체 생성

@Repository
public class DbStationRepository implements StationRepository {
    private final StationDao stationDao;

    public DbStationRepository(StationDao stationDao) {
        this.stationDao = stationDao;
    }

    @Override
    public long create(Station station) {
        return stationDao.insert(new StationEntity(station.getName()));
    }

    @Override
    public Station findById(Long id) {
        StationEntity stationEntity = stationDao.findById(id);
        return new Station(stationEntity.getId(), stationEntity.getName());
    }

    ...
}
  • 앞서 생성한 StationRepository를 구현하는 DbStationRepository를 만든다.

DbStationRepository는 Dao를 사용해 객체를 관리하는 책임을 가지므로 영속성 계층에 속한다.

하지만, StationRepository 자체는 구현체인 DbStationRepository가 영속성 계층에 접근한다는 사실을 알지 못한다. StationRepository는 단순히 객체 collection에 대한 관리를 추상화한 객체이며, DbStationRepository는 객체 collection을 관리하기 위한 방법으로 객체를 DB에 저장하는 방식을 선택했을 뿐이다.

구조를 그리면 다음과 같다.

StationRepository라는 추상화 객체를 사용해 도메인 계층과 영속성 계층간의 의존성을 역전함으로써, StationRepository가 영속성 계층에 의존하지 않도록 관리할 수 있다.

2개의 댓글

comment-user-thumbnail
2023년 5월 30일

오 글 좋은데요!!

1개의 답글