최근 백엔드 공부를 시작하면서 인프런 김영한 강사님의 스프링 핵심원리 강의를 듣기 시작했다. 그에 대한 내용을 정리해보려고 한다.
✅ Spring
spring은 자바 기반의 오픈소스 프레임워크이다. 백엔드 공부를 시작하면서 자바 언어를 선택했으면 Spring과 SpringBoot는 공부해야 한다는 말을 정말 많이 들었는데, 이걸 왜 공부해야할까 ?
✅ 스프링의 핵심
자바 언어의 가장 큰 특징은 객체지향언어 라는 점이다. 그래서 우리는 객체지향언어의 장점을 최대한 살려 프로그래밍을 해야하는데, 이때 객체지향언어의 특징을 잘 살려주는 프레임워크가 스프링이다!
스프링은 좋은 객체지향 애플리케이션을 개발할 수 있도록 도와주는 프레임워크이다.
그럼 여기서 좋은 객체 지향 프로그램은 무엇일까 ?
✅ 좋은 객체 지향 프로그래밍
자바를 공부하면, 객체 지향의 특징에 대해 공부하게 된다. 객체지향언어의 특징은 크게 4가지가 있다.
- 추상화
- 캡슐화
- 상속
- 다형성
여기서 가장 눈여겨볼 특징은 다형성이라고 할 수 있을 것이다. 다형성에 대해 설명하기 전에, 일단 모든 특징을 간략하게 정리하려고 한다.
추상화
추상화는 객체의 공통적인 속성과 기능을 추출하여 정의하는 것이다. 예를들면 자동차와 오토바이를 구현할 때, 이동수단이라는 공통점과 전진과 후진을 할 수 있다는 공통점이 있으므로, 이 공통점을 이동수단이라는 상위클래스에 구현할 수 있다.
추상화를 구현하는 문법적 요소에는 인터페이스와 추상클래스가 있다. 인터페이스를 사용할 때에는 implements를 사용하면 된다.
상속
상속은 상위 개체의 속성이 하위 개체로 물려져서, 하위 객체가 상위 객체의 속성을 모두 갖는 관계를 말한다.
즉 자식클래스는 부모 클래스의 속성을 물려받고 기능을 확장할 수 있다. 상속을 사용할 때에는 extends를 사용하면 된다.
상속 특징 덕분에, 클래스들 간 공유하는 속성과 기능들을 반복적으로 정의할 필요 없이 딱 한 번만 정의해두고 간편하게 재사용할 수 있어 반복적인 코드를 최소화하고 공유하는 속성과 기능에 간편하게 접근하여 사용할 수 있게 된다.
상위 클래스의 기능과 속성들을 그대로 사용할 수도 있지만, 각각의 클래스에 맞게 오버라이딩(method overriding)을 사용하여 내용을 재정의할 수도 있다!
캡슐화
캡슐화는 객체를 캡슐로 싸서 내부를 볼 수 없게 하는 것이다. 서로 연관있는 데이터와 기능을 한 곳에 모아 관리한다. 캡슐화를 하는 이유는 크게 두가지이다.
- 데이터 보호 : 외부로부터 클래스에 정의된 속성과 기능 보호
- 데이터 은닉 : 내부의 동작을 감추고 외부에는 필요한 부분만 노출
메소드나 클래스앞에 붙이는 접근 제어자인 public, default, protected, private를 이용해 캡슐화를 실현할 수 있다.
다형성
다형성은 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질을 의미한다. 즉, 어떤 객체의 속성이나 기능이 맥락에 따라 다른 역할을 수행할 수 있는 특성을 의미한다. 예시로는 메소드 오버라이딩과 오버로딩이 있다.
다형성을 실현시키기 위해서는 역할과 구현을 분리해야한다. 예를 들어 운전자가 자동차를 운전한다고 할 때, 자동차의 종류마다 역할이 다르면 안 될 것이다. 아반떼의 운전자가 소나타를 운전할 때 큰 불편을 겪지 않는 것처럼!
이럴 수 있는 이유는 역할과 구현으로 나누어졌기 때문이다.
이렇게 역할과 구현으로 구분하면 단순하고 유연해져서 변경이 편리해진다. 이렇게 구분하면 여러 장점이 생긴다.
- 클라이언트는 대상의 역할 즉 인터페이스만 알면 된다. (내부구조는 몰라도 된다)
- 클라이언트는 내부 구조가 변경되어도 영향을 받지 않는다
여기서 역할은 인터페이스, 구현은 인터페이스를 구현한 클래스이다. 우리는 다형성의 본질을 이용해 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.
이렇게 스프링을 사용하면 다형성을 극대화할 수 있어 재사용과 코드 줄이기에 용이하다는 장점이 있다.
✅ 좋은 객체 지향 설계의 5가지 원칙 (SOLID)
좋은 객제지향설계를 위한 5가지 원칙이 있다.
- SRP : 단일 책임 원칙 (Single Responsibility Principle)
- OCP : 개방 폐쇄 원칙 (Open Closed Principle)
- LSP : 리스코프 치환 원칙 (Liskov Substitution Principle)
- ISP : 인터페이스분리 원칙 (Interface Segregation Principle)
- DIP : 의존관계 역전 원칙 (Dependency Inversion Principle)
하나씩 알아보자
SRP 단일 책임 원칙
한 클래스는 하나의 책임만 가져야 한다는 원칙이다. 변경이 있을 때 파급효과가 적으면 단일 책임 원칙을 잘 따른 것이라고 할 수 있다.
OCP 개방 폐쇄 원칙
소프트웨어 요소는 확장에는 열러있으나, 변경에는 닫혀 있어야 한다는 원칙이다. 다형성을 활용하여 역할과 구현의 분리를 해주면 된다.
public class MemberService {
private MemberRepository memberRepository = new MemoryMemberRepository();
}
public class MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JdbcMemberRepository();
}
그런데, 구현 객체를 변경하려면 위 코드처럼 클라이언트 코드를 변경해야한다. 다형성을 사용했으나 OCP원칙을 지킬 수 없는 경우이다. 이때는 객체를 생성하고 연관관계를 맺어주는 별도의 설정자가 필요하다. (Configuration이라는 개념을 추후에 배웠다)
LSP 리스코프 치환 원칙
프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다.
ISP 인터페이스 분리 원칙
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 한 개보다 낫다는 원칙으로, 인터페이스가 명확해지고 대체 가능성이 높아진다.
DIP 의존관계 역전 원칙
프로그래머는 추상화에 의존해야하고, 구체화에 의존하면 안 된다는 원칙이다. 스프링의 의존성 주입은 이 원칙을 따르는 방법 중 하나이다. 즉, 구현 클래스에 의존하지 말고 인터페이스에 의존하라는 의미이다.
프로그래머가 구현체에 의존하게 되면 변경이 아주 어려워지기 때문에 인터페이스에 의존해야 한다. 그래야 유연해짐
그런데 OCP에서 작성한 코드를 보면, MemberService는 인터페이스와 구현 클래스에 동시에 의존한다. MemberService 클라이언트가 구현 클래스를 직접 선택하는 것을 볼 수 있다. 이는 DIP 위반이다.
이렇게 다형성 만으로는 OCP와 DIP를 동시에 지키는 것이 불가능하다. 그래서 스프링의 기술이 필요하다!
✅ 스프링 프레임워크의 특징
스프링의 기술 중 DI는 다형성 + OCP, DIP를 가능하게지원한다.
DI(Dependency Injection)
DI란 개발자가 Spring 프레임워크에 의존성을 주입하는 것이다. 의존성을 주입하면 객체 간 결합이 느슨해져 코드의 재사용성이 증가하고, 단위 테스트가 용이해진다.
IoC(Invesion of Control)
IoC란 컨트롤의 제어권이 개발자가 아닌 프레임워크에 있는 것을 의미한다. Bean같은 코드를 개발자가 직접 작성하지 않고 프레임워크가 대신 수행한다.
기존에는 객체 생성, 의존관계 설정 등을 개발자가 했으나 이를 프레임워크가 대신 해준다고 이해하면 된다.
✅ 정리
정리하자면 다음과 같다.
- 모든 설계에 역할과 구현을 분리하기
- 모든 설계에 인터페이스 부여하기
- 인터페이스 도입시 추상화라는 비용이 발생하기 때문에 기능확장가능성이 있는 경우에 인터페이스를 구현하자
'백엔드 > 스프링' 카테고리의 다른 글
[Spring] 5. 빈 생명주기 콜백- 스프링 핵심원리 기본편 (1) | 2024.02.09 |
---|---|
[Spring] 4. 자동으로 의존관계 주입하기 - 스프링 핵심원리 기본편 (2) | 2024.02.07 |
[Spring] 3. 싱글톤 컨테이너 - 스프링 핵심원리 기본편 (1) | 2024.02.05 |
[Spring] 2. 스프링으로 전환하기 (스프링 빈, 스프링 컨테이너) - 스프링 핵심원리 기본편 (1) | 2024.02.05 |
[Spring] 1. 순수 자바로 설계하기 - 스프링 핵심원리 기본편 (1) | 2024.01.29 |