Post

[JAVA] 객체지향 프로그래밍

[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 클래스를 보면 마치 하나의 캡슐에 쌓여있는 것 같다 이렇게 속성과 기능을 하나로 묶어 필요한 기능을 메서드를 통해 외부에 제공하는걸 ‘캡슐화’ 라고 한다.


출처: 김영한의 실전 자바 - 기본편

This post is licensed under CC BY 4.0 by the author.

Trending Tags