[JAVA] 객체지향 프로그래밍
프로그래밍은 크게 두 가지로 나뉘는데 그 두가지를 절차지향 프로그래밍과 객체지향 프로그래밍 이라 한다.
절차지향 프로그래밍(Procedural Programming)
- 이름 그대로 순서대로 시작하는 일련의 과정을 중심으로 프로그래밍 하는 방식
- 데이터보단 절차(로직)을 중심으로 생각
- 프로그램을 순차적이고 단계적인 절차라 생각함.
- 코드 재사용/유지보수 어려움
- 시작→처리→결과 순서(절차)를 중요시함
- ex) C언어
👉“순서대로 실행되는 일련의 과정(절차)을 중심으로 코드를 작성하는 방식”
객체지향 프로그래밍(OOP: Object-Oriented Programming)
- 이름 그대로 객체를 지향 객체로 모든걸 생각함
- 현실세계의 사물처럼 객체 단위로 프로그래밍
- 캡슐화, 다형성, 상속, 추상화, 메시지 전달과 같은 특징이 있음
- 코드 재사용, 유지보수, 확장성이 뛰어남
- 순서보단, 어떻게 처리할지
- ex) Java, Phython
👉”현실 세계처럼 객체를 중심으로 프로그램을 구성하는 방식” 객체는 속성과 기능만 존재
ex) 자동차라는 객체
속성: 색깔, 차종, 크기 기능: 엑셀, 브레이크, 문 열기 닫기
컴퓨터
속성: cpu, 램, 그래픽카드, 메인보드 기능: 킨다, 끈다
객체지향과 절차지향의 차이
- 서로 반대되는 개념이 아니라 프로그래밍을 하는 방법
- 절차지향은 데이터와 해당 데이터에 대한 처리방식이 분리되어 있음
- 객체지향은 데이터와 해당 데이터에 대한 처리방식(메서드)가 하나의 객체 안에 포함
절차지향 프로그래밍 실습
절차지향으로 음악플레이어를 만들어보자
요구사항
- 온/오프 기능
- 볼륨 업/다운
- 상태확인
1
2
3
4
public class MusicPlayerData {
int volume = 0;
boolean isOn = false;
}
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class MusicPlayerMain2 {
public static void main(String[] args) {
MusicPlayerData data = new MusicPlayerData();
//음악 플레이어 켜기
on(data);
//볼륨 증가
volumeUp(data);
//볼륨 증가
volumeUp(data);
//볼륨 감소
volumeDown(data);
//음악 플레이어 상태
showStatus(data);
//음악 플레이어 끄기
off(data);
}
static void on(MusicPlayerData data) {
data.isOn = true;
System.out.println("음악 플레이어를 시작합니다");
}
static void off(MusicPlayerData data) {
data.isOn = false;
System.out.println("음악 플레이어를 종료");
}
static void volumeUp(MusicPlayerData data) {
data.volume++;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
static void volumeDown(MusicPlayerData data) {
data.volume--;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
static void showStatus(MusicPlayerData data) {
System.out.println("음악 플레이어 상태 확인");
if (data.isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + data.volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
}
- 클래스는 단지 데이터를 담기 위한 그릇(DTO, VO) 처럼 사용
- 그 데이터를 이용한 처리는 서비스 계층의 함수나 메서드가 담당
- 즉, 데이터와 기능이 분리되어 있는 구조
음악 플레이어의 기능들을 메서드를 사용해 분리했다. 그로인해 모듈화 되었다
모듈화의 장점
- 중복 제거: 같은 로직이 필요하면 해당 메서드를 가져와 쓰기만 하면 된다.
- 변경 영향 범위: 기능 수정이 필요할 때 메서드 내부만 수정하면 된다.
- 가독성: 메서드 이름을 통해 기능을 유추할 수 있고 코드를 좀 더 쉽게 이해할 수 있다.
👉레고를 조립하듯 필요한 레고들만 가져와 사용하면 된다. 즉 필요한 기능이 있는 메서드만 호출해 음악플레이어 프로그램을 만들 수 있다.
절차지향 프로그래밍의 한계
1
2
3
static void on(MusicPlayerData data) {
data.isOn = true;
}
데이터와 기능 분리
on() 함수는 MusicPlayerData에 직접 접근해 데이터를 바꾸고 있음.
MusicPlayerData는 데이터를 담는 그릇역할만 진짜 행동들은 main이나 다른함수에서 하고있음
👉 데이터와 행동이 따로노니까 유지보수나 확장이 힘듦;;;
스파게티 코드
기능이 많아질 수록 사용하는 함수가 많아지고, main에서부터 순서(절차적)를 정확이 지켜야 안터지고 돌아감 누가 언제 뭘 바꿨는지 파악하기 힘들고 하나 고치면 여기저기 다 영향받음 → 유지보수 지옥 → 스파게티 코드
재사용 어려움
volumeUp(data)
같은 함수는 오직 MusicPlayerData
만 쓰도록 설계
다른 프로그램에서 사용할 수 없어 따로 수정해 줘야함;;
재사용과 확장성 ⬇️
👉 절차지향은 프로그램이 단순할 땐 괜찮지만,
기능이 많아질수록 유지보수, 확장성, 재사용성에서 한계가 드러남.
객체지향 프로그래밍 실습
데이터와 기능을 하나로 묶어 음악플레이어라는 개념을 하나의 클래스에 담아보자 즉 음악플레이어라는 객체를 지향해보자
속성: volum, isOn
기능: on, off, volumeUp, volumeDown, showStatus
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
31
32
33
public class MusicPlayer {
int volume;
boolean isOn;
void on() {
isOn = true;
System.out.println("음악 플레이어를 시작합니다");
}
void off() {
isOn = false;
System.out.println("음악 플레이어를 종료");
}
void volumeUp() {
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
}
void volumeDown() {
volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
}
void showStatus() {
System.out.println("음악 플레이어 상태 확인");
if (isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
}
- 클래스는 데이터(멤버 변수)와 그 데이터를 다루는 기능(메서드)를 하나의 단위로 묶는 것
- 각 객체는 자기 자신이 책임지고 처리해야 할 로직을 가짐
- 예:
User
라는 클래스가 있다면, 사용자 정보(이름, 나이)와 그 사용자에 대한 동작(로그인, 수정 등)을 같은 클래스 안에서 처리하게 되는 구조.
클래스에 필요한 속성/기능을 모두 정의했다. 이렇게 하면 음악플레이어가 필요한 곳에서 이 클래스만 있으면 언제든 호출해 음악 플레이어를 사용할 수 있다.
👉음악 플레이어를 프로그래밍 하는데 필요한 모든 속성과 기능이 한 클래스에 포함
이제 호출해 사용해 보자.
1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
MusicPlayer player = new MusicPlayer();
player.on();
player.volumeUp();
player.volumeUp();
player.volumeDown();
player.showStatus();
player.off();
}
MusicPlayer 객체를 생성하고 필요한 메서드만 호출하면 된다. 이걸 다른 사람이 사용하는 입장에서는 MusicPlayer 내부에서 어떻게 돌아가는지 몰라도 필요한 기능을 호출해 사용하면 된다.
캡슐화
MusicPlayer 클래스를 보면 마치 하나의 캡슐에 쌓여있는 것 같다 이렇게 속성과 기능을 하나로 묶어 필요한 기능을 메서드를 통해 외부에 제공하는걸 ‘캡슐화’ 라고 한다.
출처: 김영한의 실전 자바 - 기본편