[Spring] Service, ServiceImpl 의 관계(Feat.OCP)

김한준 Hanjun Kim·2024년 4월 5일
1

TIL(New)

목록 보기
3/9

프로젝트 코드를 보면, 패키지 명에 Service / ServiceImpl 로 나누어 작성한 모습을 볼 수 있습니다.

원래 인터페이스는 자바의 객체지향적 특징중 하나인 다형성(OCP)을 위해 사용하지만, 여기서는 심지어 1:1 관계입니다.

일반적인 토이 프로젝트에서 굳이 이렇게 나누어야 하나? 라는 생각이 들어 이 글을 작성하게 되었습니다.


인터페이스(Interface)와

구현체(Implement)

사실 굳이 이렇게 나누지 않아도 됩니다.

위에서 언급하였듯 작은 프로젝트 구조에서는 굳이 이렇게 나눌 필요가 없습니다.

그렇다면 왜 나누어서 작성하는걸까?


인터페이스와 구현체를 분리하여 얻을 수 있는 장점은 구현체 클래스를 변경하거나 확장해도, 이것을 호출하는 부분에는 영향을 주지 않는다는 것입니다.

예시

컨트롤러

// 컨트롤러
public class ClubController {
    private final ClubService clubService;

    @Operation(summary = "모든 모임 리스트 조회")
    @GetMapping
    public ApiResponse<?> getClubList(ClubPageRequestDTO pageRequestDTO) {
        return ApiResponse.ok(clubService.getAllClubs(pageRequestDTO));
    }
}

인터페이스

// 인터페이스
public interface ClubService {

    PageResponseDTO<ClubResponseDTO> getAllClubs(ClubPageRequestDTO pageRequestDTO);
}

구현체

// 구현체
public class ClubServiceImpl implements ClubService {

    @Override
    public PageResponseDTO<ClubResponseDTO> getAllClubs(ClubPageRequestDTO pageRequestDTO) {
        Page<ClubResponseDTO> result = clubRepository.findAll(pageRequestDTO);

        return PageResponseDTO.<ClubResponseDTO>withAll()
                .pageRequestDTO(pageRequestDTO)
                .dtoList(result.toList())
                .total(Long.valueOf(result.getTotalElements()).intValue())
                .build();
    }
}

이렇게 둘을 나누어서 작성한 코드 예시를 보면, (getAllClubs 메서드)

컨트롤러 : 인터페이스의 코드를 주입받음. 다른거는 상관 안함
인터페이스 : 구현체를 선언함.
구현체 : 코드의 변경이 일어남

실제로 클라이언트쪽 코드에서는 컨트롤러의 API를 가져다 쓰기 때문에, 구현체가 변경되어도 다른부분을 수정할 필요가 없다는 것입니다.

결론은

장점 : 이러한 인터페이스/구현체 구분을 이용하여, 코드의 유연성을 높이고 변화에 용이하게 만듭니다.
단점 : 코드가 복잡해져 분석하고 확인하는 부분에서 불편해질 수 있습니다.

profile
개발이 하고싶은 개발지망생

0개의 댓글