AccessModifiers

📌 접근 제어자 & 메서드 통한 데이터 제어: 핵심 요약 정리

1. 접근 제어자를 사용하는 이유

  • 데이터 무결성 보장: 클래스 외부에서 필드(예: age, volume)에 직접 접근 가능하면 잘못된 값이 들어갈 수 있음.

  • 유효성 검사 가능: 필드를 private으로 두고 메서드(setAge(), volumeUp() 등)를 통해 값을 변경하게 하면, 그 안에서 유효성 검사를 수행할 수 있어 안전한 값 변경이 보장됨.

  • 유지보수성 향상: 전체 코드 곳곳에서 직접 필드를 변경하면 로직 수정 시 모든 부분을 찾아 고쳐야 하지만, 메서드를 통해 변경하면 해당 메서드만 수정하면 됨.

  • 코드 일관성 유지: 필드를 직접 수정하는 대신, 동일한 메서드를 사용해 값이 변경되므로 개발자마다 다른 방식으로 로직이 분산되는 것을 막을 수 있음.

  • 객체 내부 보호(정보 은닉): private 필드를 외부에서 임의로 수정할 수 없게 하여, 객체가 스스로 상태를 관리하도록 강제(객체 지향 원칙 준수).

2. 접근 제어자 이해

  • 자바에서는 private, default, protected, public 네 가지 접근 제어자를 제공하여 클래스·필드·메서드의 접근 범위를 조절함.

  • 접근 범위는 private → default → protected → public 순으로 점점 넓어짐.

3. 접근 제어자 종류

접근 제어자
접근 가능 범위

private

같은 클래스 내부에서만 접근 가능

default

같은 패키지 내에서만 접근 가능

protected

같은 패키지 + 자식 클래스에서 접근 가능

public

모든 패키지, 모든 클래스에서 접근 가능

  1. private

    • 가장 제한적인 접근 제어자. 클래스 내부에서만 필드/메서드 호출 가능.

    • 필드를 private으로 설정하면 외부에서 직접 값을 수정할 수 없고, 메서드를 통해서만 값 변경 가능.

  2. default (package-private)

    • 접근 제어자를 명시하지 않으면 기본 적용.

    • 동일 패키지에 속한 클래스에서만 접근 가능.

  3. protected

    • 동일 패키지 + 상속 관계의 자식 클래스에서만 접근 가능.

    • 주로 상속을 다룰 때 사용.

  4. public

    • 어디서든 접근 가능.

    • 클래스, 필드, 메서드를 공개하고 싶을 때 사용.

4. 필드·메서드에서의 접근 제어자 사용

아래 예시는 필드와 메서드에서 접근 제어자를 설정하는 예시:

public class Person {
    private String name;    // 외부에서 직접 접근 불가
    int age;                // default 접근, 같은 패키지 내에서만 사용 가능

    public Person(String name, int age) {  // public 생성자
        this.name = name;
        this.age = age;
    }

    public void sayHello() {  // public 메서드, 외부에서 호출 가능
        System.out.println("Hello, I'm " + name + ", age " + age);
    }

    private void secretMethod() { // private 메서드, 내부에서만 사용
        System.out.println("비밀 메서드 실행");
    }
}
  1. 필드(변수)

    • 보통 private → 외부에서 함부로 값을 바꾸지 못하도록 하여 데이터 보호.

  2. 메서드

    • 외부에서 호출해야 하는 공개 기능public.

    • 내부에서만 사용하는 도우미 메서드private으로 숨겨 캡슐화.

    • 같은 패키지에서만 공유해야 하는 경우 default 사용.

  3. 클래스 레벨 접근 제어자

    • public 클래스: 어디서든 인스턴스 생성 가능.

    • default 클래스: 같은 패키지 내에서만 사용 가능. (파일명·클래스명 일치 규칙은 public 클래스에만 적용)

5. 메서드를 통한 데이터 제어의 이점

아래 예시는 유효성 검사를 통해 잘못된 금액이 들어가지 않도록 하는 코드입니다:

public class BankAccount {
    private int balance;

    public void deposit(int amount) {
        if (amount < 0) { // 유효성 검사
            System.out.println("유효하지 않은 금액입니다.");
            return;
        }
        balance += amount;
    }

    public int getBalance() {
        return balance;
    }
}
  1. 잘못된 값 입력 방지 → 유효성 검사

    • private 필드를 직접 수정하지 못하게 하고, 메서드 안에서 음수·최대값 초과 등 검사를 수행해 오류를 방지.

  2. 유지보수성·확장성 증가

    • 로직이 바뀔 때 메서드 내부만 수정하면 되므로, 외부 코드 수정을 최소화할 수 있음.

  3. 코드 일관성

    • 특정 필드를 변경하는 모든 곳이 동일한 메서드를 사용하므로, 로직이 일관되고 추적이 쉬움.

  4. 객체 보호(정보 은닉)

    • 객체 내부 필드가 임의로 바뀌지 않도록 막고, 객체 스스로 상태를 관리.

  5. 객체 지향 원칙 준수

    • 객체가 자신의 상태와 행동을 책임지므로, 자율성과 일관성을 유지할 수 있음.

6. 캡슐화

캡슐화(Encapsulation)는 데이터와 그 데이터를 처리하는 메서드를 하나로 묶고, 외부에서의 직접 접근을 제한하는 객체 지향 프로그래밍의 핵심 개념이다.

  • **데이터(필드)**를 가능한 숨기고(private), **객체가 제공하는 기능(메서드)**을 통해서만 접근하도록 유도.

  • 굳이 알 필요가 없는 내부 기능(메서드)은 private으로 감추고, **외부에서 꼭 필요한 기능만 public**으로 노출.

  • 접근 제어자는 캡슐화를 안전하게 완성하기 위한 핵심 장치:

    1. 데이터를 숨겨라

      • 외부가 내부 로직을 무시하고 직접 필드에 접근하면, 100 넘으면 안 되는 음량을 200으로 바꾼다든지 하는 문제가 발생.

      • 자동차, 음악 플레이어 예시처럼, 우리는 내부 전원부나 볼륨 데이터 자체를 직접 건드리지 않고 버튼(메서드)만 사용하는 것이 바람직.

    2. 기능을 숨겨라

      • 외부가 사용할 필요가 없는 내부 엔진 로직, 세부 처리 과정을 모두 공개하면 복잡도만 증가.

      • **꼭 필요한 기능만 public**으로 제공하고, 나머지는 private으로 감춰 사용자가 더 쉽게 사용할 수 있도록 함.

간단 코드 예시

public class Speaker {
    private int volume; // 1. 데이터 숨김

    public Speaker(int volume) {
        this.volume = volume <= 100 ? volume : 100;
    }

    public void volumeUp() { // 2. 꼭 필요한 기능만 공개
        if (volume < 100) {
            volume += 10;
        }
    }

    private void internalDiagnostics() { // 2. 기능 숨김
        System.out.println("내부 엔진 점검 중...");
    }
}
  • volumeprivate으로 설정.

  • 외부에서 음량을 조절할 때는 오직 volumeUp()(or volumeDown()) 같은 메서드를 통해서만 가능.

  • internalDiagnostics()처럼 내부에서만 필요한 기능은 private으로 감춰두어 사용자가 볼 필요가 없음.

7. 정리

  1. 접근 제어자를 활용하면 필드 값을 보호하고, 잘못된 값 입력이나 임의 변경을 방지할 수 있음.

  2. **클래스의 필드는 private**으로, 외부에서 필요한 기능만 public 메서드를 통해 제공하는 것이 권장됨.

  3. 메서드를 통한 데이터 변경으로 유효성 검사와 로직 추가가 용이해져 유지보수성이 높아짐.

  4. 캡슐화를 통해 데이터와 기능을 하나로 묶어 객체의 일관성을 유지하고, 안전하게 보호할 수 있음.

  5. 캡슐화 구현의 핵심은 데이터와 내부 로직은 숨기고, 꼭 필요한 기능만 공개하며, 접근 제어자가 이를 가능케 함.

결론:

필드를 직접 수정하지 않고 메서드를 통해 조작함으로써, 데이터 무결성과 안전성을 높이고 객체 지향의 캡슐화 원칙을 충실히 구현할 수 있다.

Last updated