-
[Spring] Spring의 핵심과 객체 지향 프로그래밍Back-end/Spring 2022. 3. 2. 13:18
안녕하세요 이번 포스팅은 좋은 객체 지향 프로그래밍과 스프링의 핵심에 대해서 알아보겠습니다.
스프링의 진짜 핵심!!
스프링은 자바 언어 기반의 프레임워크입니다.
그렇다면 자바 언어의 가장 큰 특징은 무엇일까요? 바로 객체 지향 언어라는 것입니다.
그리고 스프링은 객체 지향 언어가 가진 강력한 특징을 살려내는 프레임워크라고 할 수 있고 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크입니다.
좋은 객체 지향 프로그래밍
객체 지향의 특징은 다음과 같습니다.
- 추상화
- 캡슐화
- 상속
- 다형성
이번 포스팅은 다형성에 대해서 알아보겠습니다!
우선 객체 지향 프로그래밍의 사전적 정의는 다음과 같습니다.
• 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. (협력)
• 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.
여기서 유연하고 변경이 용이하다는 것은 무엇일까요?
바로 컴포넌트를 레고 블록 조립하듯이 유연하게 변경할 수 있도록 블록을 꼈다가 뺏다가를 할 수 있다는 것입니다.
예를 들어서 저희가 컴퓨터를 사용하면서 키보드와 마우스를 갈아 끼워도 컴퓨터에는 아무런 영향이 없고 키보드는 키보드의 역할만 하고 컴퓨터는 컴퓨터의 역할만 할 수 있습니다.
다형성(Polymorphism)
좋은 객체 지향 프로그래밍의 핵심 중 한 가지는 다형성인데 말 그대로 다양한 형태를 가질 수 있다는 것입니다.
실세계와 객체 지향을 정확히 1:1로 매칭 하는 것은 불가능 하지만 실세계의 어떤 사물로 이해하기에는 좋습니다.
그전에! 실세계를 한번 역할과 구현으로 구분해서 바라보도록 하겠습니다.
위의 사진에서 역할은 자동차의 역할이며, 자동차의 역할을 구현하는 것들은 하위의 K3, 아반떼, 테슬라 모델 3가 있습니다. 다형성의 관점에서 보면 자동차의 역할은 운전자가 운전을 한다는 단 한 가지만 존재합니다. 하지만 그런 역할을 구현할 수 있는 구현체는 위의 자동차 모델들 뿐만 아니라 여러 가지 자동차들이 있겠죠?
여기서 중요한 것은 운전자는 자동차 운전 면허증만 있으면 운전을 할 수 있는 것이지 K3를 운전하는 법, 아반떼를 운전하는 법을 아는 것이 아닙니다. 즉 운전자(Client)는 역할(Interface)에 의존해야지 구현체(class)에 의존해서는 안됩니다.
운전자는 자동차가 k3인지 아반떼인지 테슬라 모델 3인지는 관심이 없고 오직 자동차의 역할만 바라봅니다.
또한 자동차 모델이 바뀌어도 운전자가 운전을 할 수 있는 능력에는 전혀 변함이 없다! 이런 것들이 바로 핵심입니다.
공연 무대를 빗대어 볼 때도 마찬가지 입 니니다. 로미오의 역할과 줄리엣 역할이 있다고 가정을 하면 그 역할을 구현할 수 있는 배우들은 굉장히 많습니다. 각 역할은 배역에 맞게 대본이 주어져있고 배우들을 그 대본으로 보고 연습을 해서 공연을 하는 것이죠
여기서도 공연 캐릭터의 역할만 주어 진다면 배우 들은 언제든지 교체가 가능해야 하고 공연 팀은 오직 로미오 역할, 줄리엣 역할에만 의존해야 합니다. 즉, 대본이 주어진 다면 누구나 그 역할을 구현할 수 있어야 합니다.
만약 공연 팀이 대본 없이 장동건에게 의존했다가 그 배우가 개인적인 사정으로 공연을 할 수없거나 다른 배우로 교체를 해야 된다고 하면 큰 문제가 발생하겠죠?
다시 한번 여기서 중요한 것은 역할과 구현을 분리한다입니다. 역할과 구현을 구분하면 다음과 같은 장점이 있습니다.
• 역할과 구현으로 구분하면 세상이 단순해지고, 유연 해지며 변경도 편리해진다.
• 장점
• 클라이언트는 대상의 역할(인터페이스)만 알면 된다.
• 클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
• 클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.
• 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
객체를 설계할 때는 역할과 구현을 명확히 분리하고, 인터페이스를 먼저 부여하고, 그 역할을 수행하는 구현 객체를 만들어야 합니다.
MVC패턴을 활용해서 웹 개발을 할 때 Service 인터페이스를 먼저 만들고 인터페이스를 구현하는 ServiceImpl 구현체를 만드는 것이 같은 맥락입니다.
클라이언트와 서버라 하면은 HTTP Request를 보내는 것이 클라이언트고 그 Request 객체를 받아서 요구에 맞게 비즈니스 로직으로 처리한 후 HTTP Response 객체로 돌려보내는 것이 서버라고 합니다.
또한, 만약 Controller에서 Service에 있는 메서드를 호출해서 사용했다면 Controller는 클라이언트, Service는 서버라고 표현하기도 합니다.
자바 언어의 다형성
자바의 오버 라이딩을 한번 떠올려 봅시다.
위의 그림에서 클라이언트는 MemberService이고 서버는 MemberRepository Interface입니다.
그리고 인터페이스를 구현하는 클래스는 2개가 있습니다(MemoryMemberRepository, JdbcMemberRepository).
MemoryMemberRepository는 DB에 저장하지 않고 객체 상태로 Heap에 저장하는 클래스이며,
JdbcMemberRepository DB에 저장하는 클래스입니다.
MemberService에서 MemoryMemberRepository를 사용하려면 다음과 같이 할 수 있습니다.
클라이언트(MemberService)는 MemberRepository(역할)에 의존하고 있는 것처럼 보이기 때문에 괜찮은 코드인 것 같지만, 뒤가 문제입니다.
만약 MemoryMemberRepository를 사용하다가 JdbcMemberRepository로 사용하려면 어떻게 해야 할까요?
이렇게 기존의 코드를 변경해야 합니다. 인터페이스를 구현하는 구현체를 변경함으로 인해서 클라이언트의 코드가 변경된다면 객체 지향 프로그래밍 SOLID 원칙 중 하나인 개방 폐쇄 원칙을 위반하는 것이며 좋은 코드가 아닙니다.
즉, 클라이언트를 변경하지 않고 서버의 구현 기능을 유연하게 변경할 수 있어야 합니다.
또한, 인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있어야 합니다.
그렇다면 이것을 어떻게 해결할 수 있을까요? 역할과 구현을 분리하는데 한계가 존재하는데 이것을 해결하도록 도와주는 것이 스프링 프레임워크입니다.
스프링은 다형성을 극대화해서 이용할 수 있게 도와주고, 제어의 역전(IoC), 의존관계 주입(DI)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원합니다.
다음 포스팅에서는 좋은 객체 지향 설계의 5가지 원칙(SOLID)을 알아보고 위의 코드가 어떠한 원칙을 위반했는지 알아보겠습니다.
'Back-end > Spring' 카테고리의 다른 글
[Spring]IoC, DI, 컨테이너 그리고 AppConfig 스프링으로 변환하기, 스프링 빈 조회하기 (0) 2022.03.04 [Spring] DI 컨테이너를 예제 만들기 ( 2 ) (0) 2022.03.04 [Spring] DI 컨테이너 예제 만들기 ( 1 ), JUnit 사용하기 (0) 2022.03.03 [Spring] 좋은 객체 지향 설계의 5가지 원칙(SOLID) (0) 2022.03.02 [Spring] Spring의 역사에 대해서 알아보자 (1) 2022.03.02