전체 보기
🚀

Repository의 구현체를 숨겼을 때 얻을 수 있는 장점

작성일자
2024/04/27
태그
DESIGN
프로젝트
WoowaCourse
책 종류
1 more property
Repository를 인터페이스화 하여 얻는 장점은 뭘까? 특히나, db가 바뀔 일 없는 상황에선 더더욱 의문이 들 수 있다. 이에 대해 내 나름대로의 근거를 찾아간 과정을 공유해보겠다.

Repository의 구현체를 Dao로 명명

우선 내 코드의 구조를 설명하자면 domain 패키지에 Repository 인터페이스가 들어가있고, Repository의 구현체는 dao 란 이름을 가진 채로 dao 패키지에 들어가있다. 이게 무슨 뚱딴지 같은 소리야? 싶은 이들은 코드로 좀 더 내 코드의 상황을 살펴보자. 이해를 돕기 위한 부분만 남기고 간략화한 코드다. 전체 코드를 보고 싶다면 아래 링크로 들어가서 볼 수 있다.
domain 패키지엔 아래 클래스들이 들어있다. 참고로, domain 패키지에 repository 인터페이스를 넣어준 이유는 repository를 도메인 객체의 컬렉션을 관리하는 개념으로 보았기 때문이다.
public class Reservation { private Long id; private String name; private LocalDate date; private ReservationTime time; } public interface ReservationRepository { List<Reservation> findAll(); }
Java
복사
그리고 대망의 dao 패키지엔 아래 클래스가 들어있다. Repository의 구현체 이름을 Dao라 붙인 이유는 database에 접근하는 역할을 더 잘 표명할 수 있기 때문이다. 아래 클래스는 JdbcTemplate을 이용해 db에 쿼리를 날리고 있다.
@Repository public class ReservationDao implements ReservationRepository { private final JdbcTemplate jdbcTemplate; private final RowMapper<Reservation> reservationRowMapper = (resultSet, rowNum) -> new Reservation( resultSet.getLong("reservation_id"), resultSet.getString("name"), LocalDate.parse(resultSet.getString("date")), new ReservationTime( resultSet.getLong("time_id"), LocalTime.parse(resultSet.getString("time_value")) ) ); public ReservationDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Override public List<Reservation> findAll() { String sql = "SELECT r.id AS reservation_id, r.name, r.date, t.id AS time_id, t.start_at AS time_value " + "FROM reservation AS r INNER JOIN reservation_time AS t ON r.time_id = t.id"; return jdbcTemplate.query(sql, reservationRowMapper); } }
Java
복사

Repository의 구현체를 다른 패키지에 둬서 얻는 장점

위와 같은 구조로 얻을 수 있는 장점으론 service가 dao 구현체를 아예 모르게 해줄 수 있단 점이 있다. 기존엔 service가 domain과 dao 패키지를 모두 살펴봤지만, 현재는 service가 domain 패키지만 알고, 구현체가 들어있는 dao 패키지는 모른다. 이를 통해 구현체를 숨길 수 있다. 그리고 지금과 같은 계층 구조에서 구현체를 숨기는 장점이 특히 두드라진다.
web / service(application service + domain service) / domain / database
크게 위의 계층 별로 패키지를 분리해뒀다. 인터페이스를 분리하지 않는다면, service는 domain과 database에 대해 모두 알아야 한다. 허나 인터페이스를 분리한다면, service는 domain만 알면 된다.
결국 web과 application service를 한 모듈로, domain service와 domain을 한 모듈로, database를 한 모듈로 바라볼 수 있다. 모듈 별로 사람을 나눠 개발하더라도 각 개발자들이 처음에 정한 인터페이스를 기반으로 독립적으로 개발할 수 있다. 작업의 효율성이 올라가는 것이다.
인터페이스를 분리함으로써 관리 포인트가 늘어난단 단점이 생길 수 있지만, 프로그램을 모듈 별로 나눠 개발할 수 있단 장점이 그 단점을 커버해줄 수 있다 생각한다. 현재 내가 진행하고 있는 페어프로그래밍 상황에도 새 페어가 database 계층에 대한 이해가 부족한 상태에서도 service와 domain 계층만 살펴보고 비즈니스 로직을 이해할 수 있을 것이다.

Service는 인터페이스화 하지 않은 이유

service의 경우 현재 application service 와 domain service 를 나눠 작업할만한 기능이 없어 나누지 않았다. 만일 web계층에서 외부 API를 사용한다던가 해서 web계층의 dto와 service 계층의 dto를 나눠 관리해야 할 포인트가 생긴다면 나눌 거 같다.