Java

객체 지향 프로그래밍

공부처음하는사람 2024. 5. 8. 06:17

 

이번 섹션에선 절차 지향 프로그래밍과 객체 지향 프로그래밍을 비교해보고 객체 지향 프로그래밍에 대해 학습했다.

 

절차 지향 프로그래밍

절차지향 프로그래밍은 이름 그대로 절차를 지향한다. 이전에 다뤘던 예제들은 모두 절차지향 프로그래밍이다.

실행 순서를 중요하게 생각하는 방식으로 코드를 작성했기 때문이다. 즉 "어떻게"를 중심으로 프로그래밍 한다.

 

객체 지향 프로그래밍

객체지향 프로그래밍은 이름 그대로 객체를 지향한다. 객체를 중점으로 프로그래밍 하는 방법이다.

객체지향은 실제 세계의 사물이나 사건을 객체로 보고, 객체간의 상호작용을 중심으로 프로그래밍한다.

즉 "무엇을" 중심으로 프로그래밍 한다.

 

이 중 핵심은 객체 지향은 속성(변수)과 기능(메서드)가 객체 안에 포함되어 있다는 것이다. (캡슐화)

 

 

자바에서 data class라고 표현해도 될 지 모르겠지만.. data class를 사용했다고 해서 객체지향 프로그래밍이 되는것은 아니다.

음악 플레이어를 만드는 예제로 예시를 들어보겠다.

package oop1;

public class MusicPlayerData {
    int volume;
    boolean isOn;
}
package oop1;

public class MusicPlayerMain2 {
    public static void main(String[] args) {
        MusicPlayerData data = new MusicPlayerData();

        // 플레이어 켜기
        on(data);
        // 볼륨증가
        volumeUp(data);
        // 볼륨증가
        volumeUp(data);
        // 볼륨감소
        volumeDown(data);
        // 플레이어 상태
        playerStatus(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 playerStatus(MusicPlayerData data) {
        System.out.println("음악 플레이어 상태 확인");

        if (data.isOn) {
            System.out.println("음악 플레이어 On, 볼륨: " + data.volume);
        } else {
            System.out.println(" 음악 플레이어 OFF");
        }
    }
}

 

클래스를 도입해 중복되는 로직을 줄이고, 모듈화했으나 여기서 절차지향 프로그래밍의 한계가 보인다.

음악 플레이어의 데이터는 MusicPlayerData 클래스에 있는데, 데이터를 사용하는 메서드는 MusicPlayerMain3에 있다.

이렇게 된다면 추후에 데이터가 변경되었을 땐 Main3에 있는 메서드까지 이중으로 수정이 되어야한다는 단점이 생긴다.

 

이러한 문제는 객체지향 프로그래밍을 하면 유지보수 할 포인트가 줄어들게 된다.

 

package oop1;

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 playerStatus() {
        System.out.println("음악 플레이어 상태 확인");

        if (isOn) {
            System.out.println("음악 플레이어 On, 볼륨: " + volume);
        } else {
            System.out.println(" 음악 플레이어 OFF");
        }
    }
}
package oop1;

public class MusicPlayerMain4 {
    public static void main(String[] args) {
        MusicPlayer player = new MusicPlayer();

        // 음악 플레이어 켜기
        player.on();
        // 볼륨증가
        player.volumeUp();
        // 볼륨증가
        player.volumeUp();
        // 볼륨감소
        player.volumeDown();
        // 플레이어 상태
        player.playerStatus();
        // 플레이어 종료
        player.off();
    }
}

 

MusicPlayer 클래스에 속성과 기능을 모두 정의했다. 이제 유지보수가 훨씬 쉬워졌고 음악 플레이어를 만들 때 이전보다

이해하기 쉬운 코드를 작성할 수 있게 되었다.

 

MusicPlayer 클래스처럼 속성과 기능을 하나로 묶어서 필요한 기능을 메서드를 통해 외부에 제공하는 것을 캡슐화라고 한다.

 


 

이전에 객체지향을 잘 이해하지 못한 상태에서 개발을 했을 땐, 그냥 강의에서 보여준 예제코드를 따라치며 외우는 방식으로 코딩을 했었다.

나도 모르게 쓰고 있던 내용들이 하나씩 이해가 가기 시작한다.

서비스단의 코드를 간결하게 작성하기 위해 Entity에 메서드를 작성하고 메서드를 호출했었던 것 등등..

 

코틀린으로 개발을 배웠을 땐 dto에 변수만 정의해두고 사용했었는데, dto에 메서드를 정의했어야 했나 싶다.

companion object를 사용해서 매개변수에 엔티티 클래스를 매개변수로 받아 객체 필드를 사용해 메서드를 작성할 수 있다고 한다.

companion object {
    fun toResponse(post: Post): PostResponse {
        // 메서드 내용
    }
}

 

그럼 여태 entity에 메서드를 정의했던 이유가 무엇이었을까...  캡슐화에 대한 개념을 몰라서 그랬을지도 모르겠다.

짧은시간에 너무 깊은개념을 공부했던 것 같다. 

 

'Java' 카테고리의 다른 글

접근 제어자  (0) 2024.05.28
생성자  (0) 2024.05.15
기본형과 참조형  (0) 2024.05.07
클래스 - 배열  (1) 2024.05.07
클래스, 객체, 인스턴스  (0) 2024.05.07