Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

스프링

스프링은 자바의 객체 지향이라는 특성을 극대화하는 프레임워크이다.


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

  1. SRP(Single Responsibility Principle) - 단일 책임 원칙
    한 클래스는 하나의 책임만 가져야 한다.
  2. OCP(Open/Closed Principle) - 개방-폐쇄 원칙
    새로운 기능을 추가할 때, 기존 코드를 변경하지 않아야 한다.
  3. LSP(Liskov Substitution Principle) - 리스코프 치환 원칙
    자식 클래스는 부모 클래스의 역할을 대체할 수 있어야 한다.
  4. ISP(Interface Segregation Principle) - 인터페이스 분리 원칙
    특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
    (클라이언트는 딱 필요한 기능만 하는 인터페이스를 의존하는 것이 좋다)
  5. DIP(Dependency Inversion Principle) - 의존관계 역전 원칙
    구현 클래스가 아닌, 인터페이스나 추상 클래스에 의존해야 한다.

여기서 스프링 없이 자바로만 객체 지향 설계를 하면,
OCP, DIP를 지키기 어렵다.

다형성을 통해 3가지 원칙(SRP, LSP, ISP)을 지킬 수 있지만,
OCP, DIP를 지키기 어렵다.

클라이언트는 인터페이스 변수를 생성해도
구현체를 직접 생성해야 한다.

직접 구현 객체를 생성했기 때문에 DIP를 위반했고,
구현 객체를 변경하려면 클라이언트 코드도 변경해야 하기 때문에,
OCP도 위반했다.


스프링과 객체 지향

스프링은 DI 컨테이너로 객체를 생성하고, 의존 관계를 주입한다.
-> OCP, DIP를 가능하게 한다.
-> SOLID 원칙을 지킬 수 있게 한다.

클라이언트는 코드의 변경 없이 기능 확장이 가능하다.
(스프링이 알아서 구현 객체를 변경해준다)

IoC(Inversion of Control) - 제어의 역전

프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것

클라이언트가 필요한 객체를 직접 생성하지 않고 외부에서 주입받아 사용한다.

클라이언트가 직접 구현 객체를 제어하지 않고, 외부에서 제어한다.
(스프링 컨테이너가 객체를 생성하고 관리한다)

DI(Dependency Injection) - 의존관계 주입

클라이언트가 직접 의존 객체를 생성하고 관리하는 것이 아니라 외부에서 주입받아 사용하는 것

(스프링에서) 스프링 컨테이너를 통해 의존 객체를 주입받아 사용하는 것
이때 스프링 컨테이너를 DI 컨테이너라고도 부른다.


아래 내용은 객체 지향 프로그래밍에 대해 정리한 내용이다.


객체 지향 프로그래밍(Object-Oriented Programming)

객체 지향 프로그래밍은 데이터를 객체로 표현하고,
그 객체들이 상호작용하며 프로그램을 구성하는 방법이다.
(각각의 객체들이 메시지를 주고 받을 수 있다)

이로 인해 코드의 재사용성, 유지보수성, 확장성이 높아진다.

객체 지향 특징

다형성 말고 캡슐화, 상속, 추상화도 있지만,
여기서는 가장 중요한 다형성에 대해 다룬다.

캡슐화: 객체의 상태와 행위를 하나로 묶고, 외부에서 접근을 제한하는 것
(보안을 높일 수 있고, 클라이언트는 객체의 내부 구조를 알 필요가 없다)

상속: 부모 클래스의 특성을 자식 클래스가 물려받는 것
(코드의 중복을 줄일 수 있고, 유지보수성이 높아진다)

추상화: 객체의 공통된 특성을 추출하는 것
(객체의 공통된 특성을 추출해 인터페이스로 만들어 다형성을 활용할 수 있다)

다형성(Polymorphism)

하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미
(하나의 인터페이스를 여러 가지 구현으로 사용할 수 있는 것)

다형성이 객체 지향의 핵심이다.

운전자가 자동차를 운전하려고 한다.
운전자는 자동차의 시동을 걸고, 기어를 변경하고, 방향을 전환한다.
운전자는 자동차의 기능을 사용한다.

위 기능은 여러 자동차에서 동일하게 제공되는 기능이다.
운전자는 자동차의 기능을 사용할 때, 자동차의 종류에 상관없이 동일한 방식으로 사용한다.

기존에 사용하고 있는 자동차를 다른 자동차로 변경해도 운전자는 동일한 방식으로 자동차를 운전할 수 있다.

여기서 위 기능들은 자동차의 역할(책임)이다.
자동차의 역할은 여러 자동차에서 공통으로 사용할 수 있다.
운전자는 자동차의 종류에 관계없이 동일한 방식으로 자동차를 운전할 수 있다.

자바에서의 다형성

역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스

객체를 설계할 때 역할과 구현을 명확하게 분리
(객체 설계 시 역할(인터페이스)을 먼저 설계하고, 그 역할을 수행하는 구현 클래스를 만든다)

오버라이딩(Overriding)

부모 클래스의 메서드를 자식 클래스에서 재정의하는 것
(부모 클래스의 메서드를 자식 클래스에서 재정의하면, 부모 클래스의 메서드 대신 자식 클래스의 메서드가 호출된다)

다른 객체는 현재 객체가 무엇인지 알 필요가 없다.
(다형성을 활용하면 클라이언트는 인터페이스만 알면 된다)

다형성의 본질

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


객체 지향의 장단점

장점

  1. 유연하고 변경이 용이하다.
  2. 확장 가능한 설계
  3. 클라이언트에 영향을 주지 않고 기능을 변경할 수 있다.

하지만 인터페이스가 변경되면 구현체와 클라이언트 모두에 영향을 준다.
-> 인터페이스를 안정적으로 설계해야 한다.

단점

과도한 설계로 인해 개발 기간이 길어질 수 있다.


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

설계와 구현을 분리해야 한다.

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

  1. 클라이언트는 대상의 역할(인터페이스)만 알면 된다.
  2. 클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
  3. 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.
  4. 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.

따라서 클라이언트는 인터페이스만 알면 된다.
(구현 객체를 변경해도 클라이언트 코드를 변경할 필요가 없다)

SRP(Single Responsibility Principle) - 단일 책임 원칙

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

그런데 하나의 책인은 모호하다.

중요한 기준은 변경이다.
(변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것)

OCP(Open/Closed Principle) - 개방-폐쇄 원칙

확장에는 열려 있고, 변경에는 닫혀 있어야 한다.
새로운 기능을 추가할 때, 기존 코드를 변경하지 않아야 한다.

다형성을 활용하면 쉽게 구현할 수 있다.
(인터페이스를 구현한 새로운 클래스를 만들어 기존 코드를 수정하지 않고 새로운 기능을 추가할 수 있다)

그리고 새로운 구현 객체를 사용하기 위해 클라이언트 코드를 변경하지 않아도 된다.
(클라이언트는 인터페이스만 알면 된다)

이때 스프링의 DI를 사용하면 기존 코드를 전혀 손대지 않고 설정만으로 구현 클래스를 변경할 수 있다.

LSP(Liskov Substitution Principle) - 리스코프 치환 원칙

상위 타입의 객체를 하위 타입의 객체로 치환해도 프로그램의 의미는 변하지 않아야 한다.

인터페이스를 구현 한 객체는 인터페이스 규약을 지켜야 한다.
(새로운 자동차 객체는 액셀을 밟으면 자동차가 앞으로 움직여야 한다)

ISP(Interface Segregation Principle) - 인터페이스 분리 원칙

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

클라이언트는 딱 필요한 기능만 하는 인터페이스를 의존하는 것이 좋다.
-> 불필요한 의존성을 줄인다.

인터페이스를 분리하면
각각의 인터페이스가 명확해지고, 대체 가능성이 높아진다.

DIP(Dependency Inversion Principle) - 의존관계 역전 원칙

구현 클래스에 의존하지 말고, 인터페이스나 추상 클래스에 의존해야 한다.

특정 자동차 객체가 아닌 자동차 인터페이스에 의존해야 한다.


다형성만 가지고는 OCP, DIP를 지킬 수 없다.
이를 위해 스프링 컨테이너와 DI를 사용한다.

객체 지향 설계와 스프링

스프링은 DI 컨테이너로 객체를 생성하고, 의존 관계를 주입한다.
이를 통해 다형성 + OCP, DIP를 가능하게 한다.

클라이언트 코드의 변경 없이 기능 확장이 가능하다.