프로그래밍 언어/Java

[Java] 23. 접근 제어자

WooZzing 2025. 4. 15. 14:44

 

 

 

 

접근 제어자란?

클래스, 변수, 메서드 등에 누가 접근할 수 있는지를 정해주는 키워드입니다.

 

말 그대로 "이건 누가 볼 수 있고, 누가 못 보게 막을지"를 정하는 키워드입니다.
➡ 캡슐화(정보 은닉)를 구현하는 핵심 도구입니다.

 

 

✅ 캡슐화에 관한 자세한 내용은 아래 글을 참고해주세요

캡슐화

 

[Java] 10. 캡슐화란?

캡슐화란?객체의 속성(데이터)과 메서드(동작)를 하나로 묶고, 외부에서 직접 접근하지 못하도록 감추는 것을 말합니다. 즉, 데이터를 보호하고, 의도하지 않은 결과가 일어나지 않게, 통

development-world.tistory.com

 

 

 

접근 제어자의 종류

자바에는 총 4가지 접근 제어자가 있습니다.

접근 제어자 같은 클래스 같은 패키지 자식 클래스 전체 접근 (외부)
private
(default)
protected
public

 

 

 

private

✅ 가장 강력한 보호 수준!

 

private은 자바에서 가장 제한적인 접근 제어자입니다.
오직 해당 클래스 내부에서만 사용할 수 있습니다.
외부 클래스, 다른 클래스, 심지어 자식 클래스에서도 직접 접근은 절대 불가❌입니다.

 

📌 주로 클 클래스의 내부 데이터를 외부에서 함부로 바꾸지 못하게 보호하는 역할을 합니다.
➡ 캡슐화의 핵심

객체 지향 프로그래밍에서는 "데이터를 직접 건드리지 말고, 메서드를 통해 접근해라"는 원칙이 있습니다.
이 원칙을 지키기 위해서 private을 자주 사용합니다.

 

사용 환경

  • 비밀번호처럼 외부에서 건드리면 안 되는 민감한 정보에 사용
  • 외부에서는 getPassword()와 같은 메서드로만 접근하도록 만듬

 

예시

* PrivateExp 클래스

public class PrivateExp {
    private String name = "홍길동";

    public void printName() {
        System.out.println(name);  // ⭕ 클래스 내부에서는 접근 가능
    }
}

* 실행 클래스

public class PrivateMain {
    public static void main(String[] args) {
        PrivateExp p = new PrivateExp();
        // System.out.println(p.name);  // ❌ private이라서 접근 불가
    }
}

👉 위에서 p.name을 직접 호출하면 컴파일 에러가 납니다.
대신, printName() 메서드를 통해 간접적으로 접근하는 건 가능합니다.

 

 

 

(default)

제어자를 안 쓰면 default!

 

자바에서는 접근 제어자를 아예 안 쓰면, 자동으로 default 접근 제어자가 적용됩니다.
default는 별도로 키워드를 쓰지 않고, 그냥 아무것도 안 썼을 때 적용되는 접근 범위입니다.

아무 접근 제어자도 안 쓰면 default 입니다.
같은 패키지 내에서만 접근 가능, 외부나 상속 관계라도 패키지가 다르면 접근 불가합니다.

 

👉 default 접근 제어자는 같은 패키지끼리만 볼 수 있습니다.
패키지가 다르면 클래스 자체도 보이지 않습니다!

 

사용 환경

  • 패키지 내에서만 쓰는 도움 메서드
  • 라이브러리 내부에서 모듈 간 공유하고 싶지만, 외부에서는 숨기고 싶을 때 사용

 

예시

💡 패키지 구조

📦 chapter21
	└── defaultExp1
		└── Tiger.java
	└── defaultExp2
		└── Zoo.java

* Tiger 클래스 (defaultExp1 패키지)

package chapter21.defaultExp1;

// public 클래스 → 어디서든 보임
public class Tiger {

    // default 변수
    String name = "호랑이";

    // default 메서드
    void roar() {
        System.out.println("어흥!");
    }
}

* Zoo 클래스 (defaultExp2 패키지)

package chapter21.defaultExp2;

import chapter21.defaultExp1.Tiger;

public class Zoo {
    public static void main(String[] args) {
        Tiger t = new Tiger();           // ⭕ Tiger 클래스는 public이므로 생성 가능
        // System.out.println(t.name);   // ❌ default 변수는 접근 불가
        // t.roar();                     // ❌ default 메서드도 접근 불가
    }
}
  • Tiger 클래스는 public이라 다른 패키지에서도 import 가능합니다.
  • name 변수와 roar() 메서드는 default라서 다른 패키지에서는 접근 불가합니다.

✅ 클래스가 public이더라도, 내부 멤버가 default면 다른 패키지에서 접근 불가!

 

 

 

protected

✅ 접근 범위가 중간쯤 되는 제어자!

 

private보단 넓고, public보단 좁습니다.

✅ 같은 패키지 안에서는 누구든 접근 가능
✅ 패키지가 달라도 자식 클래스라면 접근 가능
❌ 단, 패키지도 다르고 상속 관계도 없으면 접근 불가!

 

사용 환경

👉 패키지 바깥에 있는 자식 클래스가 부모의 필드나 메서드에 접근할 수 있게 해주는 데 쓰입니다.

  • 자식 클래스에서 공통적으로 상속받아 사용하거나, 오버라이딩 해야 하는 기능
  • 외부에서는 사용 못하지만, 상속받은 쪽에서는 접근 가능하게 열어두고 싶을 때

 

예시

* Parent 클래스 (protectedExp1패키지)

package chapter21.protectedExp1;

public class Parent {
    protected String name = "부모님";

    protected void hello() {
        System.out.println("안녕, 나는 부모야!");
    }
}

* Child 클래스 (protectedExp2 패키지)

package chapter21.protectedExp2;

import chapter21.protectedExp1.Parent;

public class Child extends Parent {
    public void introduce() {
        System.out.println("내 부모는: " + name);  // ⭕ protected 접근 가능
        hello();  // ⭕ 메서드도 호출 가능
    }
}

👉 Parent는 다른 패키지지만, Child가 상속받았기 때문에 접근 가능!

 

상속받지 않은 클래스는?

package chapter21.protectedExp2;

import chapter21.family.Parent;

public class Stranger {
    public void show() {
        Parent p = new Parent();
        // System.out.println(p.name);  // ❌ 에러 발생
        // p.hello();                   // ❌ 에러 발생
    }
}

❌ protected 멤버는 상속받은 클래스가 아니면 외부에서 접근할 수 없습니다!

 

 

 

public

✅ 어디서든 접근 가능!

자바에서 가장 넓은 접근 범위를 갖는 접근 제어자입니다.
"어디서든 접근 가능" 하다는 의미입니다.
  • 같은 클래스 ✅
  • 같은 패키지 ✅
  • 다른 패키지 ✅
  • 상속 여부 관계없이 ✅

모든 위치에서 자유롭게 접근할 수 있습니다!

 

사용 환경

  • 많은 곳에서 공통으로 사용해야 하는 클래스나 메서드
  • 다른 패키지, 다른 프로젝트에서 접근해야 하는 공개 API
  • 라이브러리나 프레임워크에서 외부에 제공하는 기능

💡 즉, 누구나 쓸 수 있어야 하는 기능이라면 public이 필요합니다.

 

예시

* Person 클래스 (publicExp1 패키지)

package chapter21.publicExp1;

public class Person {

    public String name = "홍길동";  // 누구나 접근 가능한 변수

    public void introduce() {     // 외부에서도 호출 가능한 메서드
        System.out.println("안녕하세요, 제 이름은 " + name + "입니다.");
    }
}

* 실행 클래스 (publicExp2 패키지)

package chapter21.publicExp2;

import chapter21.publicExp1.Person;

public class PublicMain {
    public static void main(String[] args) {
        Person p = new Person();          // ✅ 클래스 접근 가능
        System.out.println(p.name);       // ✅ 변수 접근 가능
        p.introduce();                    // ✅ 메서드 호출 가능
    }
}
  • public class → 다른 패키지에서도 이 클래스를 import해서 사용할 수 있음
  • public 필드/메서드 → 외부에서 직접 호출 가능

패키지가 다르더라도 모든 접근이 OK!
바로 이게 public의 특징입니다.

 

 

주의사항

클래스가 public이어야 다른 클래스에서 import 가능합니다.

 

  • public이 없는 클래스는 다른 패키지에서 보이지 않음
  • 클래스 자체를 공개하려면 반드시 public으로 선언

 

 

 

 

읽어주셔서 감사합니다 😊

 


소스 코드 바로가기