728x90
스프링 핵심 원리 - 기본편 강의를 듣다가 객체 지향에 대한 이야기가 나와서 좀 더 자세히 알아보았다.
객체 지향 프로그래밍
- 객체 지향 프로그래밍 이전의 프로그래밍 패러다임 : 컴퓨터가 중심!
- 컴퓨터가 사고하는대로 프로그래밍을 하는 것
- 객체지향 프로그래밍 : 인간 중심적 프로그래밍 패러다임
- 즉, 현실 세계를 프로그래밍으로 옮겨와 프로그래밍하는 것
- 현실 세계의 사물들을 객체로 보고, 개발하고자 하는 애플리케이션에 객체로부터 필요한 특징들을 뽑아와 프로그래밍 하는 것 = 추상화
객체 지향 프로그래밍의 장점
- 코드 재사용이 용이함
- 타인이 만든 클래스를 가져와서 이용할 수 있고, 상속을 통해 확장해서 사용할 수 있음
- 자주 사용되는 로직을 라이브러리로 만들어두면 계속해서 사용할 수 있으며 그 신뢰성을 확보 할 수 있음
- 버그 발생이 줄어듦
- 라이브러리를 각종 예외상황에 맞게 잘 만들어두면 개발자가 사소한 실수를 하더라도 그 에러를 컴파일 단계에서 잡아낼 수 있으므로 버그 발생이 줄어듦
- 생산성이 높아짐
- 내부적으로 어떻게 동작하는지 몰라도 개발자는 라이브러리가 제공하는 기능들을 사용할 수 있음
- 디버깅과 유지보수에 용이함
- 객체 단위로 코드가 나눠져 작성되기 때문
- 절차지향 프로그래밍에서는 코드를 수정해야 할 때 일일이 찾아 수정해야하는 반면, 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 멤버 변수 혹은 메서드로 있기 때문에 해당 부분만 수정하면 됨
- 요구사항을 보다 명확하게 파악할 수 있음
- 데이터 모델링을 할 때 객체와 매핑하는 것이 수월하기 때문에 요구사항을 보다 명확하게 파악하여 프로그래밍 할 수 있음
- 대형 프로젝트에 적합함
- 클래스 단위로 모듈화 시켜서 개발할 수 있으므로, 대형 프로젝트처럼 여러 명 혹은 여러 회사에서 개발이 필요할 시 업무 분담 쉬움
객체 지향 프로그래밍의 단점
- 처리 속도가 상대적으로 느림
- 객체 간의 정보 교환이 모두 메시지 교환을 통해 일어나므로 실행 시스템에 많은 overhead 가 발생하게 됨
- 하지만 이는 하드웨어의 발전으로 많은 부분 보완되었음
- 객체가 많으면 용량이 커질 수 있음
- 설계 시 많은 시간과 노력 필요함
- 객체가 상태를 가짐 : 변수가 존재하기때문에 버그를 발생시킴
- 객체 지향 프로그래밍의 치명적인 단점은 함수형 프로그래밍 패러다임의 등장 배경을 통해서 알 수 있음
- 변수가 존재하고 이 변수를 통해 객체가 예측할 수 없는 상태를 갖게 되어, 애플리케이션 내부에서 버그를 발생시킨다는 것
- 이러한 이유로 함수형 패러다임이 주목받고 있음
함수형 패러다임
데이터를 함수로 연결하는 것을 중심으로 사고하고 프로그래밍을 하는 것
자료처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임을 의미함
객체 지향의 특징
- 추상화 : 실생활에서 객체를 추상화하여 클래스로 구현
- 캡슐화 : 외부의 접근을 막아 데이터 변경을 제한, 함수 호출을 통해 데이터 변경 (기능)
- 상속 : 클래스나 인터페이스를 상속받아 추가, 변경하여 사용 가능
- 다형성 : 하나의 객체가 여러가지 타입을 가질 수 있는 것, 프로그램을 유연하고 변경이 용이하게 만들 수 있음 (주로 대규모 소프트에어 개발에 많이 사용)
객체 지향 프로그래밍에 있어 가장 중요한 것은 다형성!
다형성
- 역할 + 구현
- ex) 자동차와 운전자가 있을 때, 운전자는 어떤 자동차든 운전할 수 있음
- 자동차 = 역할
- K3, 테슬라, 모닝... = 구현
- ex) 뮤지컬에서 같은 배역에 여러 배우를 쓸 수 있음
- 로미오 = 역할
- 류승룡, 원빈, 강동원... = 구현
- ex) 자동차와 운전자가 있을 때, 운전자는 어떤 자동차든 운전할 수 있음
- 역할과 구현으로 구분 → 단순 + 유연
- 클라이언트는 역할만 알아도 사용 가능
- 역할만 유지하면 서버를 수정해도 영향을 받지 않음
자바 다형성
- 객체 지향의 핵심
- 역할 = 인터페이스
- 구현 = 인터페이스 구현 클래스 or 객체
- 객체 설계 시 역할과 구현의 명확한 분리 필요
- 인터페이스 먼저 설계 후 구현
좋은 객체 지향 5가지 원칙 : SOLID
1. SRP (Single Reponsibility Principle)
- 단일 책임 원칙
- 한 클래스는 하나의 책임만 가짐
- 하나의 책임이라는 기준이 모호함
- 규모의 차이
- 문맥의 차이
- 하나의 책임이라는 기준이 모호함
- 기준 : 변경이 불러오는 파급 효과
- 변경 시 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것
2. OCP (Open/Closed Principle)
- 개방-폐쇄 원칙
- 확장에는 열려 있고 변경에는 닫혀 있음
- 확장을 하려면 기존 코드를 변경해야 하는데? (DIP 참조)
- 다형성을 활용해서 인터페이스를 새로운 클래스로 새로운 기능 구현
- 그래도 수정은 필요하므로 연관 관계를 맺어주는 조립, 설정자가 필요함
- 확장을 하려면 기존 코드를 변경해야 하는데? (DIP 참조)
3. LSP (Liscov Substitution Principle)
- 리스코프 치환의 법칙
- 컴파일의 성공여부를 떠나서 인터페이스의 규약은 하위 클래스들은 무조건 지켜야 함
- 컴파일 가능 여부 < 신뢰성 = 프로그램의 정확성
- 엑셀 = 앞으로 가는 기능 → 뒤로 가면 안 됨
4. ISP (Interface Segregation Principle)
- 인터페이스 분리 원치
- 범용적으로 사용되는 하나의 인터페이스보다 특정 역할에 맞는 다수의 인터페이스가 더 나음
- ex) 자동차 인터페이스와 클라이언트를 운전, 정비로 나누기
- 자동차 인터페이스 → 자동차 운전 인터페이스, 자동차 정비 인터페이스
- 클라이언트 → 운전자 클라이언트, 정비사 클라이언트
- 인터페이스가 명확해지고 대체 가능성도 높아짐
- ex) 자동차 인터페이스와 클라이언트를 운전, 정비로 나누기
5. DIP (Dependency Inversion Principle)
- 의존 관계 역전 원칙
- 추상화에 의존O, 구체화에 의존X
- 구현 클래스보다 인터페이스에 의존
- 역할에 의존하기 → 클라이언트가 인터페이스에 의존해야 구현을 유연하게 할 수 있음
- OCP에서 기존 코드를 변경했던 것은 서비스가 인터페이스를 의존하지만 동시에 구현 클래스도 의존하기 때문임
따라서 다형성만으로는 OCP, DIP를 지키면서 프로그래밍할 수 없음 → 스프링의 DI Container로 해당 문제 해결 가능
(사실 모든 설계에 인터페이스를 구현하는 것이 가장 이상적이지만 별도의 비용이 들어가므로... 추후에 refactoring을 통해 인터페이스를 도입해주는 것도 방법임)
'Spring > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
[Spring] 5. 싱글톤 컨테이너 (2) | 2024.01.04 |
---|---|
[Spring] 4. 스프링 컨테이너와 스프링 빈 (2) | 2024.01.04 |
[Spring] 3. 객체 지향 원리 적용 (2) | 2024.01.04 |
[Spring] 2. 예제 만들기 (1) | 2024.01.04 |