| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 배치
- lv1
- Spring
- 스프링
- 로드밸런서
- java
- 템플릿 메서드 패턴
- 코드카타
- 자바
- redis
- 추상클래스
- Spring Batch
- DB
- 트러블슈팅
- 계산기
- 김영한
- 프록시 패턴
- 스프링 배치
- 스케줄러
- 토스
- spring boot
- 성능 개선
- 디자인 패턴
- 빌더 패턴
- Effective Java
- GoF 23
- 프로그래머스
- Til
- 백엔드
- 이펙티브 자바
- Today
- Total
김코딩
객체지향 본문
자바 공부를 하다보면 객체 지향 프로그래밍에 대한 이야기를 많이 들어볼 것 입니다. 이번 글에서는 제가 객체지향에 대해 공부하며 느낀 점과 함께, 객체지향이란 무엇인지 제 시각으로 풀어보려 합니다.
객체 지향 프로그래밍에 대한 나의 생각...
제가 처음 객체지향 프로그래밍을 배웠을 때는, "그냥 레고처럼 객체를 조립해서 기능을 만드는 거 아닌가?" 라고만 생각했습니다.
이번에 객체지향의 기본 개념부터 실습까지 공부하면서 조금씩 이 개념이 왜 중요한지, 어떻게 적용해야 하는지 감이 잡히기 시작했습니다.
그래서 이 글에서는 객체지향의 개념을 제 나름대로 정리하고, 실습하면서 느낀 점을 공유해보려 합니다. 그리고 언젠가는 누군가에게 "객체지향이란 이런 거야!" 라고 자신 있게 설명할 수 있는 개발자가 되고 싶습니다.
절차지향 프로그래밍이란?
객체지향에 대해서 설명한다면서 왜 갑자기 절차지향이 나오냐? 라고 생각하실 수 있으실텐데. 객체지향을 이해하기 전에 먼저 '절차지향 프로그래밍'에 대해 이해하고 들어가는게 "아! 이래서 객체지향 프로그래밍을 사용하는구나!" 라고 생각하실 수 있으실 것입니다. 절차지향은 프로그램을 순차적인 '절차(로직의 흐름)'에 따라 작성하는 방식입니다.
쉽게 말해, "위에서 아래로 순서대로 실행되는 코드"를 기반으로 모든 걸 구성하는 방식입니다. 간단한 코드로 예시를 보여드리자면
요구 사항:
- 음악 플레이어를 켜고 끌 수 있어야 한다.
- 음악 프레이어의 볼륨을 증가, 감소할 수 있어야 한다.
- 음악 플레이어의 상태를 확인할 수 있어야 한다.
public class MusicPlayerMain1 {
public static void main(String[] args) {
int volume = 0;
boolean isOn = false;
//음악 플레이어 켜기
isOn = true;
System.out.println("음악 플레이어를 시작합니다.");
//볼륨 증가
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
//볼륨 증가
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
//볼륨 감소
volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
//음악 플레이어 상태
System.out.println("음악 플레이어 상태 확인");
if (isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
//음악 플레이어 끄기
isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
}
이런 방식은 단순한 문제를 풀기에는 매우 직관적이고 빠릅니다.
하지만 코드가 커지고 복잡해지면,
- 동일한 코드가 여러 곳에 반복되고
- 데이터를 다루는 로직과 데이터 자체가 섞이면서
- 유지보수와 확장에 큰 어려움이 생기게 됩니다.
그래서 이러한 문제를 해결하기 위해 등장한 것이 바로 객체지향 프로그래밍입니다.
객체 지향 프로그래밍이란?
객체 지향 프로그래밍 (Object-Oriented Programming, OOP)은 프로그래밍에서 필요한 데이터를 추상화 시켜 상태와 행위를 가진 객체로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.
“각자의 역할을 가진 객체들이 팀처럼 협력해서 동작하는 구조를 만드는 것”
그러면 이제 객체지향에 대한 정의를 알아보았으니 이런 고민이 생길 것 입니다. "그래서 객체는 무엇이고, 각자 어떤 역할을 하는데?"
객체(Object)란?
객체는 상태(데이터)와 행동(기능)을 함께 가지는 프로그래밍 세계의 실체입니다.
현실 세계로 치면, 사람, 자동차, 강아지, 컴퓨터처럼 이름과 행동이 있는 것들을 객체로 볼 수 있습니다.
객체지향 프로그래밍의 4가지 특징
- 캡슐화 (Encapsulation) : 객체는 상태와 행동을 하나로 묶고, 외부에는 꼭 필요한 기능만 제공합니다.
- 데이터(필드)와 그 데이터를 다루는 행위(메서드)를 하나로 묶는 것
- 외부에 불필요한 내부 구현을 숨기고, 필요한 기능만 노출
- 예: private, getter, setter, public method
- 상속 (Inheritance) : 부모 클래스의 특징을 자식 클래스가 물려받을 수 있습니다. 코드 재사용과 확장에 매우 유용합니다.
- 기존 클래스의 속성과 기능을 새로운 클래스가 물려받는 것
- 코드 재사용, 계층 구조 설계에 유리함
- 예: extends, 부모-자식 클래스
- 다형성 (Polymorphism) : 같은 이름의 메서드라도 상황에 따라 다르게 동작할 수 있습니다.
- 같은 메서드 이름이 상황에 따라 다르게 동작할 수 있음
- 오버라이딩/오버로딩, 부모 타입으로 자식 객체를 참조 가능
- 예: speak()를 오버라이드하는 Cat, Dog 클래스
- 추상화 (Abstraction) : 객체의 복잡한 내부는 감추고, 꼭 필요한 부분만 인터페이스로 드러냅니다.
- 공통적인 성질만 뽑아낸 '설계도'를 만드는 것
- 복잡한 내부는 숨기고 중요한 것만 드러냄
- 예: abstract class, interface
절차지향 코드 vs 객체지향 코드
지금까지 객체지향의 개념과 특징에 대해서 간단히 살펴보았는데 그러면 코드로는 어떻게 작성하는지 이전에 절차지향 프로그램 코드에서 객체지향 코드로 바꿔보겠습니다.
public class MusicPlayerData {
private int volume = 0;
private boolean isOn = false;
public void showPlayerStatus() {
//음악 플레이어 상태
System.out.println("음악 플레이어 상태 확인");
if (isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
public void playerOff() {
//음악 플레이어 끄기
isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
public void playerOn() {
isOn = true;
System.out.println("음악 플레이어를 시작합니다.");
}
public void volumeDown() {
volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
}
public void volumeUp() {
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
}
}
public class MusicPlayerMain3 {
public static void main(String[] args) {
MusicPlayerData data = new MusicPlayerData();
//음악 플레이어 켜기
data.playerOn();
//볼륨 증가
data.volumeUp();
//볼륨 증가
data.volumeUp();
//볼륨 감소
data.volumeDown();
data.showPlayerStatus();
data.playerOff();
}
}
절차지향 방식 VS 객체지향 방식
| 항목 | 절차지향 방식 | 객체지향 방식 |
| 상태 저장 | main() 안에서 직접 변수 사용 | MusicPlayer 객체 내부에 상태 저장 |
| 로직 처리 | 하나의 메서드 안에 모든 로직 나열 | 객체의 메서드로 동작을 분리 |
| 재사용성 | 거의 없음 | 객체만 생성하면 여러 곳에서 사용 가능 |
| 유지보수 | 볼륨/상태 관련 변경 시 모든 코드 수정 | MusicPlayer 클래스만 수정하면 됨 |
마무리
오늘은 절차지향 방식에서 객체지향 방식으로 변경하는 간단한 예제를 통해
객체지향 프로그래밍이 왜 필요한지, 어떤 구조로 동작하는지를 살펴보았습니다.
처음에는 단순히 "코드를 보기 좋게 정리하는 방식" 정도로 생각했지만, 직접 클래스를 만들고 객체로 나누다 보니
유지보수가 쉬워지고, 코드가 읽기 쉬워지고, 역할이 명확해지는 경험을 할 수 있었습니다.
이번 글이 객체지향 개념이 막막했던 분들에게 "아, 이런 느낌이구나!" 하는 실마리를 제공할 수 있었길 바랍니다.
앞으로 더 복잡한 프로그램을 만들면서 객체 간의 협력, 상속 구조 설계, 다형성 활용 같은 부분도 자연스럽게 익혀가고 싶습니다.