반응형
OOP
1. 객체지향 프로그래밍은 무엇인가?
- 객체 지향 프로그래밍은 어떤 속성과 동작을 가진 객체를 만들고, 객체들을 조립하여 하나의 프로그램을(상호작용을 하는) 만드는 방법을 객체지향 프로그래밍이라 한다.
2. 객체 프로그래밍의 장,단점 설명
- 장점
- 코드 재사용이 용이하다.
- 남이 만든 클래스를 가져와서 이용할 수 있고 상속을 통해 확장할 수 도 있다.
- 유지보수가 쉽다.
- 절차 지향 프로그래밍에서는 코드를 수정해야할 때 일일이 찾아 수정해야 하는 반면 객체 지향 프로그래밍은 수정해야 할 부분이 클래스 내부의 멤버 변수혹은 메서드로 있기 때문에 해당 부분만 수정하면 됨
- 프로그램을 유연하고 변경 용이하게 만든다.
- 코드 재사용이 용이하다.
- 단점
- 처리속도가 상대적으로 느림
- 객체가 많으면 용량이 커질 수 있음
- 설계시 시간과 노력이 필요
3. 객체지향의 특징
- 추상화
- 캡슐화
- 상속
- 다형성 (핵심)
4. 클래스와 인스턴스(객체)는 무엇인지 설명해주세요
- 클래스는 객체를 정의하는 설계도를 말한다.
- 객체는 클래스에서 정의한 것을 토대로 실제 메모리상에 할당 된 것으로 실제 프로그램에서 사용하는 데이터이다.
5. 추상화란?
- 객체들의 공통적인 속성과 기능을 뽑아내는 작업, 즉 우리가 구현하는 객체들이 가진 공통적인 데이터와 기능을 묶어 이름을 붙이는 것을 말한다.
6. 캡슐화란?
- 연관있는 속성과 기능을 클래스로 묶는 작업을 말한다.
- 캡슐화는 은닉성을 통해 클래스에 담는 중요한 데이터나 기능을 외부에서 접근하지 못하게 할 수 있다.
- 자바 언어는 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지를 결정하기 위해 접근 제한자를 사용한다.
7. 상속이란?
- 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것이다.
- 상속 받은 것을 자식클래스에서 다시 재정의 해서 사용하는 다형성과도 이어져있다.
8. 다형성이란?
- 객체를 설계할 때 역할과 구현을 명확히 분리
- 같은 역할이라도 구현된 것에 따라 그 결과가 다르게 발현되는 것을 말한다.
- 오버라이딩 (인터페이스, 상속)
- 오버로딩
- 자바 언어의 다형성을 활용
- 역할 = 인터페이스
- 구현 = 인터페이스를 구현한 객체
- 객체를 설계할 때 역할과 구현을 명확히 분리
- 객체 셜계시 역할(인터페이스)을 먼저 부여하고, 그 역할을 수행하는 구현 객체 만들기
- 다형성의 본질
- 다형성으로 인터페이스를 구현한 객체를 실행 시점에 유연하게 변경할 수 있다.
9. 좋은 객체지향 프로그래밍이란 무엇인가?
- 모든 설계에 역할과 구현을 분리하여 언제든지 유연하게 변경할 수 있도록 만드는 것이 좋은 객체 지향 설계이다.
- 키보드, 마우스 갈아 끼우듯이, 컴퓨터 부품 갈아 끼우듯이
- 역할과 구현을 분리하면?
- 유연하고 변경이 용이
- 확장 가능한 설계
- 클라이언트에 영향을 주지 않고 변경가능
- 인터페이스를 안정적으로 잘 설계하는 것이 중요
- 인터페이스 자체가 바뀌면 모든 것이 변한다.
10. SOLID란?
[ 좋은 객체 지향 설계를 하기 위한 5가지 원칙을 말한다]
- SRP : 단일 책임 원칙 (Single Responsibility Principle)
- OCP : 개방-폐쇄 원칙 (Open-Closed Principle)
- LSP : 리스코프 치환 원칙 (Liskov Subsitution Principle)
- ISP : 인터페이스 분리 원칙 (Interface Segregation Principle)
- DIP : 의존관계 역전 원칙 (Dependency Inversion Principle)
(1) 단일 책임 원칙 (SRP : Single Responsibility Principle)
- 한 클래스는 하나의 책임만 가져야 한다.
- 하나의 책임이라는 것은 모호하다.
- 클 수 있고, 작을 수 있다.
- 문맥과 상황에 따라 다르다.
- 중요한 기준은 변경이다. 변경이 있을 때 파급 효과(하나의 지점만 고치면)가 적으면 단일 책임 원칙을 잘 따른 것
- 예) UI 변경, 객체의 생성과 사용을 분리
(2) 개방-폐쇄 원칙 (OCP : Open-Closed Principle)
- 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
- 다형성을 활용해보자.
- 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현
[ 문제점 ]
기존 코드
public class MemberService {
private MemberRepository memberRepository = new MemoryMemberRepository();
}
변경 코드
public class MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JdbcMemberRepository();
}
- MemberService 클라이언트가 구현 클래스를 직접 선택하고 있다.
- MemberRepository memberRepository = new MemoryMemberRepository(); // 기존 코드
- MemberRepository memberRepository = new JdbcMemberRepository(); // 변경 코드
- 구현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.
- 분명 다형성을 사용했지만 OCP 원칙을 지킬 수 없다.
- 해결 : 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자가 필요하다. -> DI, IoC
(3) 리스코프 치환 원칙 (LSP : Liskov Substitution Principle)
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다.
- 단순히 컴파일에 성공하는 것을 넘어서는 이야기
- 예) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능, 뒤로 가게 구현하면 LSP 위반, 느리게 가더라도 앞으로 가야함
(4) 인터페이스 분리 원칙 (ISP : Interface Segregation Principle)
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
- 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리
- 사용자 클라이언트 -> 운전자 클라이언트, 정비사 클라이언트로 분리
- 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않음
- 인터페이스가 명확해지고, 대체 가능성이 높아진다.
(5) 의존관계 역전 원칙 (DIP : Dependency Inversion Principle) (의존하다: 알고있다, 바라본다)
- 프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나다.
- 쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻
- 앞에서 이야기한 역할(Role)에 의존하게 해야 한다는 것과 같다. 객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다! 구현체에 의존하게 되면 변경이 아주 어려워진다.
- OCP에서 설명한 MemberService는 인터페이스에 의존하지만, 구현 클래스도 동시에 의존한다.
- MemberService 클라이언트가 구현 클래스를 직접 선택
- MemberRepository memberRepository = new MemoryMemberRepository();
- DIP 위반
[ 정리 ]
- 객체 지향의 핵심은 다형성
- 하지만 다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.
- 다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경된다.
- 다형성 만으로는 OCP, DIP를 지킬 수 없다.
- 스프링은 다음 기술로 다형성 + OCP, DIP를 가능하게 지원
- DI(Dependency Injection): 의존관계, 의존성 주입
- DI 컨테이너 제공
- 결과 : 클라이언트 코드의 변경 없이 기능 확장 -> 쉽게 부품을 교체하듯이 개발
- 스프링은 다음 기술로 다형성 + OCP, DIP를 가능하게 지원
- 모든 설계에 역할과 구현을 분리하자.
- 애플리케이션 설계도 공연을 설계 하듯이 배역만 만들어두고, 배우는 언제든지 유연하게 변경할 수 있도록 만드는 것이 좋은 객체 지향 설계다.
- '이상적으로는' 모든 설계에 인터페이스를 부여하자.
- [ 실무고민 ]
- 하지만 인터페이스를 도입하면 추상화라는 비용이 발생한다.
- 기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하고, 향후 꼭 필요할 때 리팩터링해서 인터페이스를 도입하는 것도 방법이다.
참조
- 인프런 스프링 핵심 원리 - 기본편 (김영한)
- https://jeong-pro.tistory.com/
- https://blog.metafor.kr/
'프로그래밍 > 스프링 자바' 카테고리의 다른 글
[Java] JVM, 자바 메모리, GC (0) | 2021.07.03 |
---|---|
[Spring] 스프링 개념 정리 (0) | 2021.06.30 |
JUnit5 정리 (0) | 2021.06.28 |
TDD , 단위 테스트, 리팩토링 (0) | 2021.06.28 |
[Spring] Spring MVC 이동 구조 (feat. jsp) (0) | 2021.04.20 |