객체 지향 프로그래밍
객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 객체들의 모임으로 파악하고자 하는 것이다.
- 각 객체는 메시지를 주고 받고 데이터를 처리할 수 있다.
- 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.
클래스와 객체의 관계
객체 지향의 특성을 알아보기 전, 객체 지향에서 말하는 객체와 클래스에 대해 먼저 정의해보자.
대학교 때 전공 강의나 서적에서는 다음과 같이 말한다.
- 클래스와 객체의 관계는 ‘붕어빵틀과 붕어빵의 관계’다!
- 붕어빵틀로 붕어빵을 찍어내듯이, 클래스로 객체를 만들어 낸다.
그런데, 결론부터 말하자면 위 정의는 옳지 않다.
클래스는 붕어빵틀이 아니다.
자바에서 객체를 생성하는 코드는 다음과 같다.
클래스 객채명 = new 클래스();
만약, 클래스와 객체가 붕어빵틀과 붕어빵이라면 다음과 같이 쓸 수 있다.
붕어빵틀 붕어빵 = new 붕어빵틀();
사람의 언어로 위 코드를 해석하자면 “붕어빵틀을 새로 만들어서 붕어빵이 되었다.”라고 할 수 있겠다.
붕어빵틀을 만들었는데 어떻게 붕어빵틀이 붕어빵이 될 수 있는가? 그러므로, 위 정의는 잊어버리도록 하자.
클래스와 객체의 관계는 무엇인가?
간략하게 정리하자면,
- 클래스는 분류(Class)에 대한 개념이고, 객체는 실체(사물, Object)이다.
- 클래스는 사람, 펭귄 등의 ‘개념’이다.
- 객체는 홍길동, 뽀로로 등의 세상에 존재하는 유일무의한 사물, 즉 ‘실체’이다.
정리하자면
- 객체는 속성과 기능을 가진 유일무이한 사물이다.
- 클래스는 같은 특성을 지닌 여러 객체를 총칭하는 집합의 개념이다.
- 클래스를 이용해 만든 객체를 인스턴스라고 한다.
객체 지향의 4대 특성
객체 지향은 다음과 같은 특성을 가지고 있다.
- 추상화 (Abstraction)
- 캡슐화 (Encapsulation)
- 정보 은닉 (information hiding)
- 상속 (Inheritance)
- 다형성 (Polymorphism)
추상화 (Abstraction)
요약
추상화란 구체적인 것을 분해해서 관심 영역(애플리케이션 경계)에 있는 특성만 가지고 재조합하는 것이다.
= 모델링
- 객체 지향에서, 추상화의 결과는 클래스다.
- 클래스 설계를 위해서는 애플리케이션 경계부터 정해야 한다.
- 추상화의 개념을 넓게 본다면, 아래 내용들도 포함한다.
- 상속을 통한 추상화와 구체화
- 인터페이스를 통한 추상화
- 다형성을 통한 추상화
추상화란
추상의 사전적 정의는 다음과 같다.
여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용
즉, 추상화는 구체적인 것을 분해해서 관심 있는 특성만 가지고 재조합하는 것이다.
예를 들어, 실제 사람들을 관찰해서 공통된 특성을 뽑아 다음과 같은 클래스를 추출할 수 있다.

애플리케이션 경계: 컨텍스트(Context)
위에서 든 사람을 다시 보자. 사람의 속성과 기능(행위)는 정해져 있지 않다. 즉, 뽑아내려면 얼마든지 뽑아내고 늘릴 수가 있다.
이때 사용되는 개념이 애플리케이션 경계(Application Boundary)이다.
- 컨텍스트라고도 부르며, 다음과 같은 질문을 던져 경계를 알아낼 수 있다.
내가 만들고자 하는 애플리케이션은 어디에서 사용될 것인가?
예를 들어, 사람이라는 건 은행이냐, 병원이냐에 따라 필요한 속성과 행위가 다음과 같이 정해진다.

캡슐화 (Encapsulation)
요약
캡슐화는 정보 은닉(information hiding)으로, 자바에서는 대표적으로 접근 제어자를 이용한다.
객체의 속성과 기능을 캡슐처럼 묶어, 외부로부터 데이터(속성)를 보호한다.
접근 제어자
이건 자바의 신을 공부하면서 정리했던 내용이니, 여기선 간략하게 짚고 가자.
- public
- protected
- 상속/같은 패키지 내의 클래스에서 접근 가능
- aaa.jar와 bbb.jar에 같은 이름의 패키지가 있다면, aaa.jar의 패키지 내의 객체가 bbb.jar의 패키지 내 객체가 가진 protected 멤버에 접근할 수 있다.
- [default]
- 아무것도 적지 않았을 경우
- 같은 패키지 내의 클래스에서 접근 가능
- private
상속 (Inheritance)
요약
상속은 상위 클래스의 특성을 하위 클래스에서 상속(재사용)하고, 거기에 더해 필요한 특성을 추가(확장)해서 사용할 수 있다는 의미이다.
상속은 분류도다
상속하면 나오는 예제는 바로 다음과 같은 계층도이다.
- 부모 - 자식 관계
- 부모 클래스와 자식 클래스

하지만, 상속은 계층도가 아닌 분류도로 이해하는 것이 맞다.
- 상위 클래스와 서브 클래스
- 슈퍼 클래스와 서브 클래스
- 상위 분류와 하위 분류

상속 관계에서 반드시 만족해야 하는 문장
하위 클래스는 상위 클래스다.
이 문장은 다음 글에서 설명할 객체 지향 설계 5원칙 중 LSP(리스코프 치환 원칙)을 나타내는 말이다.
중요하므로 꼭 알고 넘어가자.
상속은 is-a 관계가 아니다!
상속은 is a 관계를 만족해야 한다는 말이 있다.
그 말에 따르면, 다음 문장은 이렇게 해석된다.
// 하위 클래스는 하나의 상위 클래스이다.
하위 클래스 is a 상위 클래스
- 하위 클래스는 분류다.
- “하나의 상위 클래스”는 객체다.
- 따라서, 하위 클래스는 객체라는 결론이 내려진다. (옳지 않음!)
따라서, 상속 관계를 더 명확하게 표현하자면 다음과 같이 사용해야 한다.
상속은 is a kind of 관계이다.
- 하위 클래스 is a kind of 상위 클래스
자바의 다중 상속 문제
자바에서는 다중 상속을 지원하지 않는다.
이건 자바의 신에서 정리한 내용이 있으므로, 해당 링크로 대체하도록 한다.
10장. 자바는 상속이라는 것이 있어요 > 다이아몬드-문제
상속과 인터페이스
자바는 다중 상속을 포기하고 인터페이스를 도입했다. 인터페이스는 여러 개를 구현할 수 있다.
인터페이스 관계는 다음과 같이 표현할 수 있다.
인터페이스는 is able to 관계이다.
- 구현 클래스 is able to 인터페이스
- 인터페이스는 “무엇을 할 수 있는(is able to)” 표현 형태로 만드는 것이 좋다.
- Serializable 인터페이스: 직렬화할 수 있는
- Cloneable 인터페이스: 복제할 수 있는
- Comparable 인터페이스: 비교할 수 있는
- 인터페이스는 클래스가 “무엇을 할 수 있는” 기능을 구현하도록 강제한다.
- 상위 클래스는 물려줄 특성이 풍성할수록 좋고(LSP), 인터페이스는 구현을 강제할 메서드의 개수가 적을 수록 좋다(ISP).
다형성 (Polymorphism)
요약
💡 객체지향의 핵심이 바로 다형성이다.
- 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법
- 인터페이스를 구현한 객체를 실행 시점에 유연하게 변경할 수 있다.
- 이 본질을 이해하려면 협력이라는 객체 사이의 관계에서 시작해야 한다.
- 객체를 설계할 때 역할과 구현을 명확히 분리해서 설계한다.
다형성이란
세상을 역할과 그 역할을 직접 행하는 구현으로 나눈다면, 다음과 같이 말할 수 있다.
- 역할은 인터페이스
- 구현은 실제 그 인터페이스를 구현한 개체
예를 들어, 운전자라는 역할과 자동차라는 역할이 있다.
- 운전자는 자동차를 운전할 수 있다.
- 자동차 역할(인터페이스)은 K3, 아반떼, 테슬라 모델3 등과 같은 자동차들이 구현하고 있다.
- 자동차 역할(인터페이스)은 K3, 아반떼, 테슬라 모델3 등과 같은 자동차들이 구현하고 있다.
- 운전자는 자동차 인터페이스에 대해서만 알고 있다.
- 자동차의 내부 구조를 몰라도 된다.
- 다시 말해, 운전자는 자동차 역할에 대해서만 의존하고 있다.
- 운전자는 자동차가 K3에서 아반떼로 바뀌더라도 운전할 수 있다.
- 자동차의 구현체(K3, 아반떼 등)가 자동차 역할에 맞춰서 구현하고 있으면 구현체가 바뀌어도 운전자에게 영향을 주지 않는다.
즉, 구현이 바뀌어도 역할에 영향을 주지 않고 다른 대상(구현)으로 대체가 가능하다. 이것을 유연하고 변경이 용이하다고 말한다.
물론, 일반 상속 관계도 다형성이 가능하지만 인터페이스는 다중 상속이 가능하고 다중 구현도 가능하기 때문에, 보통 인터페이스가 좋다.
다형성을 공부할 때 오해하는 것
다형성을 단순히 “부모가 있고, 부모를 구현한 자식이 있다”고 생각하면 안된다.
- 먼저, 요청하는 것을 클라이언트, 응답하는 것을 서버라고 한다.
- 객체는 서로 요청하고 응답하면서 협력 관계를 가진다.
- 여기서 응답은 클라이언트가 요청한 행위를 하는 것으로, 반환값이 없어도 된다.
- 객체 클라이언트는 동시에 서버 클라이언트가 될 수 있다.
- 객체는 요청을 할 수도 있고, 응답을 할 수도 있다.
- 클라이언트를 변경하지 않고 서버의 구현 기능을 유연하게 변경할 수 있다는 게 다형성의 본질이다.
자바의 다형성 구현
자바 언어의 다형성은 오버라이딩과 오버로딩이라고 할 수 있다.
- 오버라이딩 (overriding)
- 메서드 재정의
- 상속 관계의 다형성에 오버라이딩이 적용된다.
- 오버로딩 (overloading)
- 메서드 중복 정의
- 오버로딩이 다형성인지 아닌지에 대해서는 이견이 있다.
Reference
참고 서적
📔 스프링 입문을 위한 자바 객체 지향의 원리와 이해
인프런 강의
스프링 핵심 원리 - 기본편 강의 - 인프런