본문 바로가기

Backend/Spring

객체 지향 설계와 스프링

역할과 구현을 분리하자.

역할과 구현을 분리해서 생각해보자.

 

예를 들어서 운전자 - 자동차 관계가 있을 때, 운전자는 자동차의 내부 구조를 몰라도 운전하는데 아무 지장이 없다.

만약, 운전자가 테슬라를 몰다가 아반떼로 차를 바꿨다고 해도 전혀 문제가 되지 않는다.

이는 역할과 구현을 분리해서 생각했기 때문에 가능한 것이다.

운전자는 클라이언트고, 자동차는 역할, 테슬라나 아반떼는 구현체 정도로 생각하면 된다.

 

역할과 구현으로 분리해서 생각하면 대체 가능성이 생긴다.

따라서 변경이 용이하고 유연해져서 확장 가능성이 생기는 것이다.

 

자바 언어와 이를 연결시켜보자.

- 역할 = 인터페이스

- 구현 = 인터페이스를 구현한 클래스, 구현 객체

 

객체를 설계할 때 역할과 구현을 명확히 분리하고, 역할을 먼저 부여한 후 해당 역할을 수행하는 구현 객체를 만들어야 한다.

 

다음 그림을 보고 이해해보자.

MemberService가 클라이언트, MemberRepository가 역할, MemoryMemberRepository/JdbcMemberRepository가 구현체라고 생각하면 된다.

 

결론은 다형성이 가장 중요하다는 것이다.

이 다형성이라는 특징을 극대화해서 이용할 수 있게 해 주는 게 스프링이고, 스프링을 사용하면 구현을 편리하게 변경할 수 있게 된다.

 

좋은 객체 지향 설계의 5가지 원칙 (SOLID)

다음은 좋은 객체 지향 설계의 5가지 원칙 SOLID이다.

 

1. SRP (단일 책임 원칙)

- 한 클래스는 하나의 책임만 가져야 한다.

- 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이다.

 

2. OCP (개방-폐쇄 원칙)

- 소프트웨어 요소는 확장에는 열려 있지만 변경에는 닫혀 있어야 한다.

- 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현하는 것이 그 예이다.

 

OCP를 잘 지키지 못한 예

- MemberService 클라이언트가 구현 클래스를 직접 선택하는 경우

MemberRepository m = new MemoryMemberRepository();  // 기존 코드
MemberRepository m = new JdbcMemberRepository();  // 변경된 코드

- 구현 객체를 변경하기 위해서 위 코드에서는 클라이언트 코드를 변경했다.

- 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다.

 

3. LSP (리스코프 치환 원칙)

- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 변경할 수 있어야 한다.

 

4. ISP (인터페이스 분리 원칙)

- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.

- 자동차 인터페이스 => 운전 인터페이스, 정비 인터페이스로 분리

- 사용자 클라이언트 => 운전자 클라이언트, 정비사 클라이언트로 분리

- 이렇게 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않는다.

- 인터페이스가 명확해지고, 대체 가능성이 높아진다.

 

5. DIP (의존관계 역전 원칙)

- 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 것이다.

- OCP의 MemberService는 인터페이스에 의존하지만 구현 클래스에도 동시에 의존한다. => DIP 위반

 

정리하자면, 다형성은 객체 지향의 핵심이지만, 다형성만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경할 수밖에 없다.

따라서 다형성만으로는 OCP, DIP를 지킬 수 없다.

 

하지만 스프링DI(Dependency Injection), 즉 의존관계 주입을 통해, 그리고 DI 컨테이너를 제공함으로써 OCP, DIP를 가능하게 지원한다.

 

 

'Backend > Spring' 카테고리의 다른 글

컴포넌트 스캔  (0) 2023.08.02
싱글톤 컨테이너  (0) 2023.08.02
스프링 컨테이너와 스프링 빈  (0) 2023.08.02
스프링 예제-2  (0) 2023.08.02
스프링 예제-1  (0) 2023.08.02