2025-08-09 09:39
Tags:
객체 지향 프로그래밍(OOP) 핸드북
1. 만들어진 이유: 소프트웨어 위기의 해결사
1960년대, 컴퓨터 하드웨어는 눈부시게 발전했지만 소프트웨어 개발 속도는 이를 따라가지 못했음. 프로그램의 규모가 커지고 복잡해지면서 기존의 절차 지향 프로그래밍(Procedural Programming) 방식은 한계에 부딪힘. 코드가 길어질수록 스파게티처럼 얽히고설켜 유지보수가 어려워지는 ‘소프트웨어 위기’ 가 찾아옴.
이를 해결하기 위해 등장한 것이 바로 객체 지향 프로그래밍(OOP). 복잡한 문제를 잘게 나누어 독립적인 ‘객체(Object)’ 단위로 만들고, 이 객체들을 조립하여 전체 프로그램을 완성하는 방식. 이는 마치 레고 블록으로 원하는 모양을 만드는 것과 같음. 각 블록(객체)은 고유한 기능과 데이터를 가지고 있으며, 다른 블록과 상호작용하며 더 큰 구조를 형성.
이러한 접근 방식은 코드의 재사용성을 높이고, 유지보수를 용이하게 하며, 대규모 프로젝트를 여러 개발자가 협업하여 개발하기 쉽게 만들어 소프트웨어 위기를 극복하는 열쇠가 됨.
2. 핵심 개념: OOP를 지탱하는 네 개의 기둥
OOP는 네 가지 핵심 개념(캡슐화, 상속, 다형성, 추상화)을 바탕으로 구성.
가. 캡슐화 (Encapsulation)
-
정의: 데이터(속성)와 그 데이터를 처리하는 함수(메서드)를 하나로 묶어 객체로 만드는 것.
-
목적: 객체 내부의 복잡한 구현 내용은 숨기고, 외부에는 필요한 기능만 노출하여 **정보 은닉(Information Hiding)**을 실현. 이를 통해 객체의 무결성을 보장하고, 외부의 부적절한 접근으로부터 데이터를 보호.
-
비유: 알약. 캡슐 안에 약 성분이 들어있어 외부로부터 보호받는 것처럼, 객체는 캡슐화를 통해 내부 데이터를 안전하게 보호. 사용자는 알약의 내부 성분을 몰라도 정해진 방법(메서드)으로 복용하여 효과를 볼 수 있음.
나. 상속 (Inheritance)
-
정의: 부모 클래스(Superclass)의 속성과 메서드를 자식 클래스(Subclass)가 물려받는 것.
-
목적: 코드의 재사용성을 극대화. 이미 만들어진 클래스의 기능을 그대로 사용하면서, 자식 클래스에서는 새로운 기능을 추가하거나 기존 기능을 변경(오버라이딩)할 수 있음.
-
비유: ‘포유류’라는 부모 클래스는 ‘걷다’, ‘먹다’와 같은 공통적인 특징을 가짐. ‘사람’과 ‘고양이’라는 자식 클래스는 이러한 포유류의 특징을 그대로 물려받으면서, ‘사람’은 ‘말하다’라는 고유한 기능을, ‘고양이’는 ‘야옹하다’라는 고유한 기능을 추가로 가질 수 있음.
다. 다형성 (Polymorphism)
-
정의: ‘여러(Poly) 가지 형태(Morph)‘라는 뜻으로, 동일한 이름의 메서드가 객체에 따라 다른 방식으로 동작하는 것.
-
목적: 코드의 유연성과 확장성을 높임. 객체의 구체적인 타입에 의존하지 않고, 공통된 인터페이스를 통해 다양한 객체를 동일한 방식으로 처리할 수 있게 함.
-
비유: ‘소리를 내다’라는 동일한 명령에 대해, ‘개’ 객체는 ‘멍멍’ 짖고, ‘고양이’ 객체는 ‘야옹’하며, ‘소’ 객체는 ‘음메’하고 우는 것과 같음. 명령은 하나지만, 실제 행동은 각 객체의 특성에 따라 달라짐.
라. 추상화 (Abstraction)
-
정의: 객체의 공통적인 속성과 기능(메서드)을 추출하여 **추상 클래스(Abstract Class)**나 **인터페이스(Interface)**로 정의하는 것.
-
목적: 불필요한 세부 정보는 숨기고, 핵심적인 기능에만 집중하게 하여 시스템의 복잡성을 낮춤. 클래스 간의 **느슨한 결합(Loose Coupling)**을 유도하여 유연한 설계를 가능하게 함.
-
비유: 자동차 운전. 운전자는 가속 페달, 브레이크, 핸들 등 인터페이스를 통해 자동차를 조작. 엔진의 복잡한 내부 동작 원리(구현)를 몰라도 운전하는 데는 아무런 문제가 없음. 추상화는 이처럼 복잡한 내부를 감추고 사용자에게 필요한 핵심 기능만 보여주는 것.
3. 구조: 클래스와 객체의 관계
OOP의 기본 설계도는 **클래스(Class)**이며, 이 설계도를 바탕으로 만들어진 실체가 바로 객체(Object).
-
클래스 (Class): 객체를 만들기 위한 ‘설계도’ 또는 ‘틀’. 객체가 가질 데이터(속성)와 기능(메서드)을 정의. 예를 들어, ‘자동차’ 클래스는 ‘색상’, ‘속도’라는 속성과 ‘전진하다’, ‘정지하다’라는 메서드를 정의할 수 있음.
-
객체 (Object): 클래스로부터 생성된 ‘실체’. 클래스에 정의된 속성과 메서드를 실제로 메모리에 할당받아 사용. ‘파란색 소나타’, ‘빨간색 페라리’ 등은 모두 ‘자동차’ 클래스로부터 생성된 개별적인 객체. 이들을 **인스턴스(Instance)**라고도 부름.
// 자동차 설계도 (Class)
class Car {
// 속성 (Attribute)
String color;
int speed;
// 메서드 (Method)
void goForward() {
System.out.println("자동차가 전진합니다.");
}
void stop() {
System.out.println("자동차가 멈춥니다.");
}
}
// 설계도를 바탕으로 실제 자동차 만들기 (Object/Instance)
public class Main {
public static void main(String[] args) {
Car myCar = new Car(); // Car 클래스의 인스턴스(객체) 생성
myCar.color = "blue"; // 객체의 속성 값 할당
myCar.speed = 60;
myCar.goForward(); // 객체의 메서드 호출
}
}
4. 사용법: 실제 프로그래밍에 적용하기
OOP는 Java, C++, Python, C# 등 현대적인 프로그래밍 언어 대부분에서 지원.
-
문제 분석 및 객체 도출: 해결하려는 문제에서 핵심적인 역할을 하는 명사들을 찾아 객체로 정의. (예: 은행 시스템 → 고객, 계좌, 은행원)
-
클래스 설계: 각 객체가 가져야 할 공통된 속성과 기능을 정의하여 클래스로 설계.
-
관계 설정: 클래스 간의 관계(상속, 포함 등)를 설정하여 시스템의 전체 구조를 만듦.
-
구현: 설계된 클래스를 코드로 작성하고, 객체를 생성하여 상호작용하도록 프로그래밍.
5. 심화 내용: SOLID 원칙
객체 지향 설계를 더 견고하고 유연하게 만들기 위한 5가지 원칙.
-
단일 책임 원칙 (SRP): 클래스는 단 하나의 책임만 가져야 함.
-
개방-폐쇄 원칙 (OCP): 확장에 대해서는 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 함.
-
리스코프 치환 원칙 (LSP): 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 함.
-
인터페이스 분리 원칙 (ISP): 사용하지 않는 인터페이스에 의존해서는 안 됨.
-
의존관계 역전 원칙 (DIP): 구체적인 것에 의존하지 말고, 추상적인 것에 의존해야 함.
이 원칙들을 따르면 변화에 유연하고 유지보수가 쉬운 소프트웨어를 만들 수 있음.
객체 지향 프로그래밍에 대해 더 궁금한 부분이 있으신가요? 예를 들어, SOLID 원칙 각각에 대한 더 자세한 설명이나 특정 언어에서의 OOP 구현 예시가 필요하신가요?