1. 들어가며
필자는 객체 지향 프로그래밍이란 객체라는 개념을 숙지하고 객체들을 몇몇 특징과 SOLID원칙에 맞게 프로그래밍하는 것이라고 생각한다. 그렇기에 들어가기에 앞서 객체라는 것을 간략히 설명하겠다.
2. 객체란?
객체는 상태와 행위로 나눠볼 수 있다.
- 객체
- 객체는 포괄적인 개념을 지칭한다. The Thing, Object.
- 예시로 자동차라는 개념을 떠올릴 때 연상할 수 있는 모든 것들을 의미한다.
- 상태
- 해당 객체의 속성을 지칭한다.
- 자동차가 어떤 외형인지, 어떤 상태인지, 어떤 속성을 가지고 있는지 등을 나타낸다.
- 코드 상에서는 필드로 표현된다.
- 몇몇 속성은 행위로 인해 결정되는 경우도 있다. 대표적인 예시는 속도, 움직임이 없는 객체는 속도라는 상태가 필요 없다.
- 행위
- 해당 객체의 기능을 지칭한다.
- 자동차가 가지고 있는 기능들을 의미한다.
- 코드 상에서는 메서드로 표현된다.
3. 객체 지향 프로그래밍
객체 지향 프로그래밍은 앞서 언급한 것처럼 객체를 다음과 같은 특징과 SOLID원칙에 맞게 프로그래밍하는 것이다.
1) 특징
- 추상화
- 객체에서 공통된 상태와 행위를 추출하는 것.
- 보통 인터페이스로 추출.
- 캡슐화
- 변수(상태)와 함수(행위)를 하나로 묶는 것.
- 하나의 인터페이스 혹은 하나의 클래스에 작성하는 것.
- 상속
- 클래스의 경우 상속, 인터페이스의 경우 구현이라고 표현.
- 상위 클래스의 상태와 행위를 하위 클래스에게 확장하는 것.
- 자동차라는 추상적인 개념을 BMW, 산타페, 프라이드 등 구현체를 통해서 실현, 구현하는 것.
- 다형성
- 하나의 변수명, 함수명이 상황에 따라 다른 의미로 해석될 수 있는 것.
- 코드를 상위 클래스로 작성하면 하위 클래스를 모두 포용할 수 있다.
- 필자가 프라이드를 소유하건, 산타페를 소유하건, BMW를 소유하건 모두 자동차를 소유하고 있다고 표현할 수 있다. 즉 필자가 자동차를 소유하고 있다면, 그 자동차가 프라이드, 산타페, BMW 중 어느 것이든 상관없다.
2) SOLID 원칙
각 원칙의 초성을 따서 SOLID 원칙이라고 한다.
- SRP 단일 책임 원칙
- 하나의 클래스는 하나의 책임만 가져야 한다.
- 책임은 보통 변경을 기준으로 분리.
- 변경이 있을 때 수정해야 할 코드가 적다면 단일 책임 원칙을 잘 지킨 것.
- OCP 개방 폐쇄 원칙
- 확장에는 열려 있으나 변경에는 닫혀있어야 한다.
- 다형성을 적극적으로 활용.
- 객체의 역할과 구현의 분리가 선행되어야 함.
- 객체를 생성하고 연관관계를 맺어주는 별도의 설정자(DI 컨테이너, IoC 컨테이너)가 필요.
- LSP 리스코프 치환 원칙
- 하위 클래스는 상속받은 상위 클래스의 규약을 다 지켜야 한다.
- 즉 인터페이스를 구현체는 인터페이스를 모두 원래 의도대로 작성해야 함.
- 자동차 인터페이스를 구현한 산타페에서 기어 D를 뒤로 가게 구현하면 LSP원칙 위반, 기어 D는 앞으로 가야 함.
- ISP 인터페이스 분리 원칙
- 특정 클라이언트를 위한 여러 개의 인터페이스가 하나의 범용 인터페이스보다 더 명확하고 대체 가능성이 높고 좋다.
- SRP원칙과 연계하여 자동차 기능 중 운전에 관한 기능은 운전 인터페이스, 정비에 관한 기능은 정비 인터페이스로 분리.
- DIP 의존 관계 원칙
- 구체화(BMW)에 의존하지 말고 추상화(자동차)에 의존.
- OCP와 마찬가지로 객체를 생성하고 연관관계를 맺어주는 별도의 설정자(DI 컨테이너, IoC 컨테이너)가 필요.
3) 예시
(1) 전제 조건
- 클라이언트(필자)
- 1종 보통 운전면허(자동차 운전 가능 + 스틱 + 오토)
- 2종 소형 운전면허(자동차 운전 가능 + 오토)
- 서버(자동차)
- 프라이드(자동차 + 스틱)
- 산타페(자동차 + 오토)
- BMW(자동차 + 오토)
- KTX(기차)
(2) 상황
- A는 1종 보통 운전면허를 가지고 있다. 그렇기에 프라이드, 산타페, BMW 모두 운전 가능하다. 세 차량은 모두 자동차이며, 1종 보통은 스틱과 오토를 모두 다룰 줄 알기 때문이다.
- B는 2종 소형 운전면허를 가지고 있다. 그렇기에 산타페와 BMW는 운전 가능하지만, 프라이드는 운전할 수 없다. 세 차량은 모두 자동차이지만, 산타페와 BMW와는 다르게 프라이드는 스틱이기 때문이다.
- A와 B는 KTX를 운전할 수 없다. KTX는 자동차가 아니다. KTX를 운전하기 위해서는 철도차량 운전면허라는 속성을 클라이언트가 가지고 있어야 한다.
이렇듯 운전면허는 자동차를 다루는 객체 지향 프로그래밍이다.
4. 마치며
좋은 객체 지향 프로그래밍의 조건은 다음과 같다. 그 중 이 부분들이 가장 중요하다고 생각한다.
- 수많은 객체 클라이언트와 객체 서버는 협력 관계.
- 역할과 구현을 명확하게 분리.
- 상속과 다형성을 적극 활용.
- 역할을 먼저 부여하고 역할을 수행하는 구현 객체 만들기.
- 클라이언트를 변경하지 않고 서버의 기능 변경 가능.
- DI, IoC와 함께해야 객체 지향 프로그래밍이 완성.
차분히 멀리 가자.