https://prolog.techcourse.co.kr/studylogs/3648
2023. 6. 7. 오후 8:44:24
우아한테크코스 학습로그 저장소
우아한테크코스 크루들이 배운 내용을 기록하는 학습로그 저장소입니다.
prolog.techcourse.co.kr
[BE] 레벨2 - 지하철 노선도 미션
지하철 미션을 하면서 가장 고민을 많이 했던 부분은 이 부분이라고 생각한다.
Domain과 Entity를 분리해야 할까?
Repository가 필요할까?
DAO만 있어도 되지 않을까?
이런 고민의 과정과 고민을 하고 스스로 내린 결론에 대해 적어보려고 한다.
Domain & Entity
이전 미션들에서는 Domain과 Entity의 구분없이 Domain만으로 구현했었다.
public class Cart {
private Long id;
private final Long productId;
private final Long memberId;
private Quantity quantity;
...
}
지금 생각해보면 Domain보다는 Entity에 가까운 코드이지만, 정확하게 둘의 차이를 구분하지 않아서 domain이라는 패키지에 둔 것 같다.
그렇다면 Domain과 Entity는 어떤 차이가 있을까?
개인적으로 이런 아키텍쳐 관련 개념들은 정해진 규칙이 있는 기초과학 이론들과는 다르다고 생각한다.
그렇기 때문에 이름 붙이기에 따라 다르고 사람마다 이해하고 사용하기에 따라 다르다고 생각한다.
그렇지만 보통 사람들 사이에서 사용하는 용어적 해석이 있는데, 이를 바탕으로 내가 해석한 Domain과 Entity는 다음과 같다.
Domain : 객체 지향 관점에서 바라본 요구사항 해결을 위한 작은 단위의 객체
public class Section {
private final Station upStation;
private final Station downStation;
private final int distance;
...
}
Entity : Domain과 유사하지만 실제 데이터베이스에 매핑되는 객체
public class SectionEntity {
private final Long lineId;
private final Long upStationId;
private final Long downStationId;
private final int distance;
...
}
간단하게 말하자면 Entity는 DB 테이블을 객체로 표현한 것, Domain은 이를 객체 지향 관점에서 바라보고 만든 객체라고 해석했다.
물론 여기서 순서는 닭이 먼저냐 달걀이 먼저냐와 같을 것이다.
DB 설계를 먼저한다면 Entity부터 생각할 것이고, 도메인 설계부터 한다면 Domain부터 나오게 될 것이다.
이에 대해서는 각자 선호하는 바가 다를 것이기 때문에, 직접 해보고 자신에게 적합한 방식을 찾으면 된다고 생각한다.
DAO & Repository
DAO를 통해 원하는 객체를 DB에 추가하거나 조회, 수정, 삭제할 수 있다.
그렇다면 Repository는 뭘까??
우선 앞서 말했듯이 Entity는 Domain보다 더 DB에 가까운, 실제 DB에 매핑되는 객체로 사용된다.
그렇기 때문에 Domain 객체를 DAO에 직접 전달하지 않고, Entity를 전달하여 Domain과 DAO의 의존성을 분리하는 것이 좋다.
그래서 Service에서 DAO를 호출할 때마다 객체를 Domain → Entity
, Entity → Domain
으로 변환해주는 과정이 필요하다.
하지만 이렇게 되면 한 가지 이상한 점을 찾을 수 있을 것이다.
Entity는 데이터베이스에 객체를 전달하기 위해서만 사용되는데, 이 Entity를 Service가 알고 있으면 불필요한 의존 관계가 생기는 게 아닐까??
이런 고민 끝에 Repository를 두기로 결정했다.
@Repository
public class JdbcSectionRepository implements SectionRepository {
private final SectionDao sectionDao;
public JdbcSectionRepository(final SectionDao sectionDao) {
this.sectionDao = sectionDao;
}
@Override
public void insertAll(final Long lineId, final Sections sections) {
final List<SectionEntity> sectionEntities = sections.getSections().stream()
.map(it -> SectionEntity.of(lineId, it))
.collect(Collectors.toList());
sectionDao.insertAll(sectionEntities);
}
@Override
public Sections findByLineId(final Long lineId) {
final List<Section> sections = sectionDao.findByLineId(lineId).stream()
.map(SectionStationEntity::toDomain)
.collect(Collectors.toList());
return new Sections(sections);
}
@Override
public void deleteAllByLineId(final Long lineId) {
sectionDao.deleteAllByLineId(lineId);
}
}
Domain → Entity
, Entity → Domain
으로 변환하는 과정을 Repository에서 해결하도록 하는 것이다.
Repository는 Domain 객체를 전달받아서 Entity로 변환 후, 해당 DAO를 호출하고
DAO의 반환 값은 다시 Domain으로 변환되어 반환된다.
그렇다면 Service는 Entity나 DAO의 존재 유무도 알 필요없이 Repository만 호출하면 되고, persistence layer와 서비스 로직을 분리할 수 있다.
'우아한테크코스' 카테고리의 다른 글
[학습 로그] Stack vs Deque (0) | 2023.04.21 |
---|---|
[미션 회고] Level 1 - 블랙잭 미션 회고 (0) | 2023.04.21 |
[글쓰기 미션] Level 1 - 우아한테크코스 한 달 생활기 (0) | 2023.04.20 |
[학습 로그] 요구사항과 확장성은 어디까지 고려해야 할까 (0) | 2023.04.19 |
[미션 회고] Level 1 - 사다리 타기 미션 회고 (0) | 2023.04.19 |