개인적으로 신규 프로젝트가 좋은 이유는 코드 구조를 바꿔볼 수 있기 때문이다.
기존 프로젝트의 코드를 리팩토링하기란 촉박한 일정에 맞춰 많은 기능을 구현해야 하는 업무 상황상 현실적으로 쉽지 않다.
이 기회를 노려 구조를 바꿔보던 중 Spring Service단에 Interface가 필요한가? 라는 질문을 받게 되었다.
1. 기존에 접하던 구조
- Controller단에서 비즈니스 로직 처리 후 바로 DAO 호출하는 코드가 많음
- 즉 Controller단과 Service단의 분리가 되어있지 않음
- 특정 조건에 따라 데이터를 가공하는 로직을 이해하는데 시간이 너무 많이 소모된다
- 중복 로직이 생길 경우 코드는 미친듯이 늘어난다
이번 프로젝트에 REST API를 적용하게 되었고, 그 정신에 알맞게 Controller와 Service를 제대로 분리해보자고 했다.
2. 첫번째 구현
- 부서 관리
- 데이터를 가공하는 로직은 없음
- DB 조작 시 부서 테이블과 부서 계층 테이블에 동시에 조작해줘야 하는 경우가 있어 트랜잭션 처리 필요
- DepartmentService(interface), DepartmentServiceImpl(class)로 구현
코드를 보신 xx님이 왜 서비스에다 인터페이스를 사용했냐고 물어봤다. (그러니까 더 공부해보란 말씀이셨음)
다형성을 위해서.. 예를 들면 DB 구현체가 다양한 경우에 사용합니다.. 관습적으로 사용하는 경우도 있습니다.... (대답하면서 아차했다..)
네.. 저는 이 부분에서 관습적으로 사용한 것 같습니다..
3. Interface 사용하는 이유?
- 관습적 사용
- 과거 *Spring은 프록시를 사용할 때 인터페이스 기반의 JDK Dynamic Proxy만 사용
- 인터페이스가 있어야만 사용할 수 있었기 때문에 인터페이스를 만들어 주는 관습이 생김
- Spring Boot 2.0 버전부터 클래스 기반의 CGLIB를 기본적으로 사용하며 JDK Dynamic Proxy 중 선택하여 사용 가능함
- 클래스만 있어도 프록시 관련 기능을 사용할 수 있으므로 관습적인 이유만으로 인터페이스 구조를 사용할 필요는 없음
- 확장성 고려
- 확장성을 고려한다고 무작정 생성하지 말고 이게 정말 확장성이 필요한 기능인가 생각해봐야 함
- 여러 가지 구현체가 필요할 때 확장성을 위해 Interface를 사용하면 적절함
- ex. 예전에 특정 기능만 운영 DB에 붙어서 개발해야 했던 적이 있다. 그 때 임시로 DB 연결 인터페이스를 구현하여 운영 DB용 클래스를 만들었고 @Qualifier를 사용하여 주입해줌
- ex. DB oracle, postgresql 여러 개 DB를 사용할 경우라든가..
- 서비스 클래스 간 의존성이 너무 높을 때 의존성을 느슨하게 해주기 위한 방안으로 적절
- 테스트 용이
*Spring 프록시 사용? 낯선 내용 같아보이지만 Spring이 @Transactional 같은 어노테이션을 구현할 때 AOP를 사용했고 이 AOP를 사용할 때 프록시 패턴 이용함
4. You Aren't Gonna Need It
찾아보니까 YAGNI(You Aren't Gonna Need It) 원칙이라는 게 있다.
"실제로 필요할 때 무조건 구현하되, 그저 필요할 것이라고 예상할 때에는 절대 구현하지 말라."
5. 두번째 구현
- 부서 관리의 기능은 추가, 수정, 삭제, 읽기가 있다. 현재 시점에서 이 네 가지 기능이 심화될 여지는 없다고 판단
- DepartmentService(interface), DepartmentServiceImpl(class) -> DepartmentService(class)로 변경
그래서 처음의 그 질문에 대해 필요할 수도, 필요하지 않을 수도 있다. 필요할 때 만들고, 필요하지 않으면 만들지 않아도 된다. 라고 스스로 답을 내려봤다.
'Study > Spring' 카테고리의 다른 글
Spring과 Spring Boot 차이 한 줄 요약 (0) | 2023.03.10 |
---|---|
트랜잭션 이해 (0) | 2023.01.18 |