회원가입

접근 제어자 - 설명

Beany 2024-09-17

접근 제어자


접근 제어자 이해 1

자바는 public, private 같은 접근 제어자(access modifier)를 제공한다. 접근 제어자를 사용하면 해당 클래스 외부에서 특정 필드나 메서드에 접근하는 것을 허용하거나 제한할 수 있다.

이런 접근 제어자가 왜 필요할까? 예제를 통해 접근 제어자가 필요한 이유를 알아보자.

 

우리는 스피커에 들어가는 소프트웨어를 개발하는 개발자다.
스피커의 음량은 절대로 100을 넘으면 안된다는 요구사항이 있다. (100을 넘어가면 스피커의 부품들이 고장난다.)

스피커 객체를 만들어보자.
스피커는 음량을 높이고, 내리고, 현재 음량을 확인할 수 있는 단순한 기능을 제공한다.
요구사항 대로 스피커의 음량은 100까지만 증가할 수 있다. 절대 100을 넘어가면 안된다.

package access;

public class Speaker {
    int volume;

    Speaker(int volume) {
        this.volume = volume;
    }

    void volumeUp() {
        if (volume >= 100) {
            System.out.println("음량을 증가할 수 없습니다. 최대 음량입니다.");
        } else {
            volume += 10;
            System.out.println("음량을 10 증가합니다.");
        }
    }

    void volumeDown() {
        volume -= 10;
        System.out.println("음량을 10 감소합니다.");
    }
    
    void showVolume() {
        System.out.println("현재 음량은 " + volume + "입니다.");
    }
}

생성자를 통해 초기 음량 값을 지정할 수 있다.
volumeUp() 메서드를 보자. 음량을 한번에 10씩 증가한다. 단 음량이 100을 넘게되면 더는 음량을 증가하지 않는다.

 

package access;

public class SpeakerMain {
    public static void main(String[] args) {
        Speaker speaker = new Speaker(90);
        speaker.showVolume();

        speaker.volumeUp();
        speaker.showVolume();

        speaker.volumeUp();
        speaker.showVolume();
    }
}
현재 음량은 90입니다.
음량을 10 증가합니다.
현재 음량은 100입니다.
음량을 증가할 수 없습니다. 최대 음량입니다.
현재 음량은 100입니다.

초기 음량 값을 90으로 지정했다. 그리고 음량을 높이는 메서드를 여러번 호출했다.
기대한 대로 음략은 100을 넘지 않았다. 프로젝트는 성공적으로 끝났다.

오랜 시간이 흘러서 업그레이드 된 다음 버전의 스피커를 출시하게 되었다. 이때는 새로운 개발자가 급하게 기존 코드를 이어받아서 개발을 하게 되었다.
참고로 새로운 개발자는 기존 요구사항을 잘 몰랐다. 코드를 실행해보니 이상하게 음량이 100이상 올라가지 않았다. 고리를 더 올리면 좋겠다고 생각한 개발자는 다양한 방면으로 고민했다.

Speaker 클래스를 보니 volume 필드를 직접 사용할 수 있었다. volume 필드의 값을 200으로 설정하고 이 코드를 실행하는 순간 스피커의 부품들에 과부하가 걸리면서 폭발했다.

 

SpeakerMain - 필드 직접 접근 코드 추가

package access;

public class SpeakerMain {
    public static void main(String[] args) {
        Speaker speaker = new Speaker(90);
        speaker.showVolume();

        speaker.volumeUp();
        speaker.showVolume();

        speaker.volumeUp();
        speaker.showVolume();

        // 필드에 직접 접근
        System.out.println("volume 필드 직접 접근 수정.");
        speaker.volume = 200;
        speaker.showVolume();
    }
}
현재 음량은 90입니다.
음량을 10 증가합니다.
현재 음량은 100입니다.
음량을 증가할 수 없습니다. 최대 음량입니다.
현재 음량은 100입니다.
volume 필드 직접 접근 수정.
현재 음량은 200입니다.

 

Speaker 객체를 사용하는 사용자는 Speaker 의 volume 필드와 메서드에 모두 접근할 수 있다.
앞서 volumeUp() 과 같은 메서드를 만들어서 음량이 100을 넘지 못하도록 기능을 개발했지만 소용이 없다. 왜나하면 Speaker 를 사용하는 입장에서는 volume 필드에 직접 접근해서 원하는 값을 설정할 수 있기 때문이다.

이런 문제를 근본적으로 해결하기 위해서는 volume 필드의 외부 접근을 막을 수 있는 방법이 필요하다.

 

 

접근 제어자 이해 2


이 문제를 근본적으로 해결하는 방법은 volume 필드를 Speaker 클래스 외부에서는 접근하지 못하게 막는 것이다.

Speaker - volume 접근 제어자를 private 으로 수정

public class Speaker {
    private int volume;
    ...
}

private 접근 제어자는 모든 외부 호출을 막는다. 따라서 private 이 붙은 경우 해당 클래스 내부에서만 호출할 수 있다.

 

 

접근 제어자 종류


자바는 4가지 종류의 접근 제어자를 제공한다.

접근 제어자 종류

  • private: 모든 외부 호출을 막는다.
  • default(package-private): 같은 패키지 안에서 호출은 허용한다.
  • protected: 같은 패키지 안에서 호출은 허용한다. 패키지가 달라도 상속 관계의 호출은 허용한다.
  • public:모든 외부 호출을 허용한다.

순서대로 private 이 가장 많이 차단하고, public 이 가장 많이 허용한다.

private -> default -> protected -> public

참고로 protected 는 상속 관계에서 자세히 설명할 예정이다.

 

default(package-private)

접근 제어자를 명시하지 않으면 같은 패키지 안에서 호출을 허용하는 default 접근 제어자가 적용된다.
default 라는 용어는 해당 접근 제어자가 기본값으로 사용되기 때문에 붙여진 이름이지만, 실제로는 package-private 이 더 정확한 표현이다.
왜냐하면 해당 접근 제어자는 사용하는 맴버는 동일한 패키지 내의 다른 클래스에서만 접근이 가능하기 때문이다. 참고로 두 용어를 함께 사용한다.

 

접근 제어자 사용 위치

접근 제어자는 필드와 메서드, 생성자에 사용된다.
추가로 클래스 레벨에도 일부 접근 제어자를 사용할 수 있다. 이 부분은 뒤에서 따로 설명한다.

 

접근 제어자 예시

package access;

public class Speaker {
    private int volume;  // 필드

    public Speaker(int volume) {  // 생성자
        this.volume = volume;
    }

    protected void volumeUp() {  // 메서드
        if (volume >= 100) {
            System.out.println("음량을 증가할 수 없습니다. 최대 음량입니다.");
        } else {
            volume += 10;
            System.out.println("음량을 10 증가합니다.");
        }
    }

    void volumeDown() {
        volume -= 10;
        System.out.println("음량을 10 감소합니다.");
    }

    void showVolume() {
        System.out.println("현재 음량은 " + volume + "입니다.");
    }
}

 

0 0
JAVA
이 공간은 개인 공부를 통해 얻은 정보를 체계적으로 정리하고 공유하는 곳입니다. 학습한 내용, 발견한 지식, 그리고 문제 해결 방법 등을 기록하여 나만의 학습 자료를 구축하고, 필요할 때 쉽게 참고할 수 있는 유용한 자원으로 활용할 수 있도록 합니다.
Yesterday: 456
Today: 234