[스프링 핵심원리] - 1.객체지향 설계와 스프링

Chooooo·2022년 10월 5일
0
post-thumbnail

이 글은 강의 : 김영한님의 - "스프링 핵심원리 - 기본편"을 듣고 정리한 내용입니다. 😁😁


🏈 스프링의 진짜 핵심

스프링은 자바 언어 기반의 프레임워크다.(자바의 가장 큰 특징은 객체지향언어라는 것.)

스프링은 좋은 객체지향 애플리케이션을 개발할 수 있도록 도와주는 프레임워크다.

좋은 객체 지향 프로그래밍이란?

객체지향 프로그래밍

객체지향 프로그래밍은 컴퓨터 프로그램을 여러개의 독립된 단위 즉, 객체들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고 받고 데이터를 처리한다.(협력)
프로그램을 유연하고 변경이 용이하게 만들어 대규모 SW 개발에 많이 사용된다.

⚽ 유연하고, 변경이 용이하다

컴포넌트를 쉽고 유연하게 변경하면서 개발한다는 뜻이다.

다형성의 실세계 비유

역할구현으로 세상을 구분한다. (역할은 Interface, 구현은 Interface를 구현한 Class)
역할과 구현으로 세상을 분리했기 때문에, client 에 영향을 주지 않고 새로운 기능을 제공할 수 있다.

새로운 자동차가 출시되어도 클라이언트에 영향을 주지 않으므로 클라이언트를 바꿀 필요가 없다.

로미오 역할이 바뀐다고 해서 줄리엣 역할에 영향을 주지 않는다.

😀 역할과 구분을 분리

역할과 구현으로 구분하면 세상이 단순해지고 유연해지며 변경도 편리해진다.

<장점>

  • 클라이언트는 대상의 역할(인터페이스)만 알면 된다.

  • 클라이언트는 구현 대상의 내부 구조를 몰라도 된다.

  • 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.

  • 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.

자바 언어의 다형성 활용

역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스, 구현 객체
객체를 설계할 때 역할과 구현을 명확히 분리
객체 설계시 역할(인터페이스)를 먼저 부여하고 그 역할을 수행하는 구현 객체 만들기

객체의 협력이라는 관계부터 생각

클라이언트 : 요청 서버 : 응답
수많은 객체 클라이언트와 객체 서버는 서로 협력 관계를 가진다.

자바 언어의 다형성

  • 실제로 MemberService가 save() 호출하면 오버라이딩 된 메서드가 실행됨
  • 다형성으로 인터페이스를 구현한 객체를 실행 시점에 유연하게 변경할 수 있음
  • 클래스 상속 관계도 다형성, 오버라이딩이 적용 가능(다만 클래스는 다중 상속안되므로 인터페이스로)

다형성의 본질

  • 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있다.
    - 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

스프링과 객체 지향

  • 객체 지향에서 다형성이 가장 중요하다!
  • 스프링은 다형성을 극대화해서 이용할 수 있게 도와준다.
  • 스프링에서 제어의 역전(Ioc), 의존관계 주입(DI)는 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원한다.

다형성과 SOLID 법칙을 합쳐야 스프링에 대해서 제대로 설명할수 있다!

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

이 부분은 면접에도 자주 나오니 기억해두자.

SOLID

😀 SRP(단일 책임 원칙)

한 클래스는 하나의 책임만 가져야 한다. (여기서 책임은 범위의 기준이 모호함)

  • 중요한 기준은 변경이다! 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것이다.
    e.g. UI 변경, 객체의 생성과 사용을 분리

😀 OCP(개방-폐쇄 원칙)

이 원칙이 가장 중요하다.
소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.

  • 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현한다.
    → 인터페이스를 구현한 새로운 클래스를 만드는 것은 변경이 아니다

문제점

public class MemberService {
	//아래의 두 개중 필요한 것을 선택해서 사용할 수 있게 된다.
	MemberRepository memberRepository = new MemoryMemberRepository();
    
    MemberRepository memberRepository = new JdbcMemberRepository();
}

클라이언트는 역할만 보고 있으면 구현체가 변경되더라도 상관이 없다는 것이다. 변경이 없다는 것을 코드의 변경이 없다는 것으로 이해하면 조금 더 편하다. 그런데 여기서 보면, MemberRepository라는 역할을 가지지만 실제 구현 객체는 클라이언트가 코드를 변경해서 사용하고 있는 것을 알 수 있다.
다형성을 사용하고 있지만, OCP가 지켜지지 않는 것이다. 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다. ( 나중 강의에서 설명할 내용 )

이 문제점을 해결하려면 객체를 생성하고 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다. --> 스프링 컨테이너

😀 LSP(라스코프 치환 원칙)

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

- 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것이다.

😀 DIP(의존관계 역전 원칙)

이 원칙 역시 너무나도 중요
구현 클래스에 의존하지 말고 인터페이스에 의존해야 한다. (= 구현보다 역할에 의존해야 한다.)

예전에 봤던 예시를 보자. 운전자가 구현 클래스라 할 수 있는 K3에 의존을 하고 있었다고 해보자. K3만 알고, K3에 존재하는 기능들만 운전자는 알고 있는 것이다. 자동차가 테슬라 모델3로 변경되면 어떨까? 실제 세계에서는 기본적으로 운전하는 것은 가능하겠지만, K3만 알고 있다는 가정으로는 테슬라의 기능은 사용할 수 없게 된다고 보면 된다.

public class MemberService {
	//아래의 두 개중 필요한 것을 선택해서 사용할 수 있게 된다.
	MemberRepository memberRepository = new MemoryMemberRepository();
    
    MemberRepository memberRepository = new JdbcMemberRepository();
}

이 코드의 경우도 MemeberRepository 라는 인터페이스에 의존을 하고 있지만, 실제로 구현 클래스도 동시에 의존하고 있다. 의존하고 있다는 것은 해당 코드를 알고 있다는 것이라고 보면 된다. --> 이해해야만 하는 부분!

이렇게 객체 지향 설계의 5가지 원칙을 지키기 위해서는 추가적으로 필요한 것들이 존재한다. 그것이 바로 다음부터 설명하게 되는 스프링인 것이다.

정리하자면, 객체 지향의 핵심은 다형성이다.

  • 다형성만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경해야하는 문제가 있다.
  • 즉, 다형성만으로는 OCP, DIP를 지킬 수 없다 --> 무언가가 더 필요.

스프링에서 왜 객체지향 이야기가 나오는가?
스프링은 다음 기술로 다형성 + OCP, DIP를 가능하게 지원한다.

  • DI : 의존관계, 의존성 주입
  • DI 컨테이너 제공
    --> 클라이언트 코드의 변경없이 기능 확장 가능해짐 !!
profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글