OOP란 뭔가? 객체 중심으로 사고한다는 그런 개념적인 풀이 말고, OOP의 핵심 개념인 추상화, 캡슐화, 다형성, 상속 네 가지 개념을 짬통하면 뭐가 나오는지 감이 올듯 말듯 해서 정리하는 글이다.
예시1) DI + 인터페이스 (추상화, 다형성)
스프링은 Controller Service Repository 세 계층으로 나뉘어 있는데, 보통 서비스는 리포지토리를 인터페이스 타입으로 받아 사용하라고 가르친다. (예시2에 후술) 아래 예시는 DI와 함께 인터페이스에 의존함으로써 서비스 레이어와 리포지토리 레이어를 느슨하게 결합한 사례이다.
public interface Repository {
public Response save(Request request);
}
@RequiredArgsConstructor
public class InmemoryRepository implements Repository {
private final Map<String, String> store = new HashMap<>();
@Override
public Response save(Request request) {
store.put(request.getKey(), request.getValue());
return new Response("Inmemory 저장 완료");
}
}
@RequiredArgsConstructor
public class JdbcRepository implements Repository {
private final DataSource dataSource;
@Override
public Response save(Request request) {
// jdbc 통신 코드
return new Response("db 저장 완료");
}
}
@Service
@RequiredArgsConstructor
public class Service {
private final Repository repository;
public String save() {
repository.save();
}
}
서비스가 내부 구현을 전혀 모르게 되면 다음 이점이 생긴다.
설정 파일에서 인메모리 저장 클래스를 사용하든, Jdbc 저장 클래스를 사용하든 서비스 클래스는 한 줄 변경없이 그대로 동작한다(DI가 없었다면 new() 한 줄은 수정 필요). 앞으로도 여러 구현체를 추가할 수 있고(확장에 열려있음) 목킹이 가능하므로 테스트에도 용이하다.
예시2) 프록시 (상속, 다형성)
대부분 우리는 스프링 빈을 등록할 때 아래와 같이 new 키워드를 사용한다.
@Bean
public ExampleBean exampleBean() {
return new ExampleBean();
}