본문 바로가기
Java_language

자바 접근제어자(Access Modifier)

by 헬로제이콥 2025. 12. 1.

자바에서 정말 중요한 접근제어자(Access Modifier)는 내가 만든 코드(변수나 함수)를 다른 코드에서 얼마나 쉽게 볼 수 있고 사용할 수 있는지 정해주는 '비밀번호'나 '울타리' 같은 거예요.  


🔑 접근제어자는 '공개 범위'를 정하는 규칙이에요!자바에는 크게 네 가지 규칙이 있어요.\

1. public (공개! 📢)

  • 의미: 누구나 볼 수 있고, 누구나 사용할 수 있어요.
  • 비유: 학교 운동장에 있는 미끄럼틀 같아요. 학교 안의 모든 학생(다른 코드)은 물론, 학교 밖의 사람(다른 프로그램)도 와서 탈 수 있죠. 완전히 공개되어 있어요!

2. protected (가족끼리만! 🏡)

  • 의미:  내 가족(상속받은 클래스), 그리고 같은 동네(같은 패키지) 사람들만 볼 수 있어요.
  • 비유: 우리 집 마당에 있는 강아지 같아요. 나(강아지 클래스)는 당연히 볼 수 있고, 우리 가족(나를 상속받은 클래스)도 볼 수 있고, 같은 동네에 사는 이웃(같은 패키지)도 강아지를 볼 수 있어요. 하지만 다른 동네 사람은 못 보죠.

3. (아무것도 안 씀) 기본/Default (같은 동네만! 🏘️)

  • 의미: 아무것도 안 쓰면, 같은 동네(같은 패키지) 사람들만 볼 수 있어요.
  • 비유: 우리 집 현관 비밀번호 같아요. 나(클래스)는 당연히 알고, 같은 동네(같은 패키지) 이웃들끼리는 비밀번호를 공유해서 들어갈 수 있지만, 가족이라도 이 동네를 벗어나 살면 못 들어와요.

4. private (나만 볼 거야! 🔒)

  • 의미: 오직 나만(내가 만든 이 클래스 안에서만) 볼 수 있어요. 다른 곳에서는 절대 볼 수 없어요.
  • 비유: 내 방 책상 서랍 속 비밀 일기장 같아요. 나(클래스)만이 내용을 볼 수 있고, 심지어 가족이나 이웃이라도 볼 수 없답니다. 가장 강력한 비밀이에요!

 


왜 이런 규칙이 필요할까요?

만약 모든 것이 public처럼 다 공개되어 있다면, 누구든지 내가 만든 중요한 물건이나 정보를 함부로 만지거나 바꿀 수 있어서 복잡하고 위험해질 수 있겠죠?

접근제어자는 우리가 만든 프로그램이 질서 있고 안전하게 돌아가도록 도와주는 아주 중요한 약속이에요! 이렇게 비밀의 정도를 정해 놓아야 서로에게 피해를 주지 않고 멋진 프로그램을 만들 수 있답니다.

 

 

1. public (공개! 📢) 예제

개념: public으로 선언된 요소는 어디에서든 접근할 수 있습니다. 마치 학교 운동장의 미끄럼틀처럼 누구나 이용할 수 있는 것이죠.

pack1/Car.java

java

package pack1; // pack1 패키지에 Car 클래스를 선언합니다.

public class Car {
    // public 필드는 어디서든 접근 가능합니다.
    public String model = "테슬라 모델 3";

    // public 메서드도 어디서든 호출 가능합니다.
    public void startEngine() {
        System.out.println(model + "의 시동이 걸렸습니다! 🚗");
    }
}

pack2/CarExam.java

java

package pack2; // pack2 패키지에 CarExam 클래스를 선언합니다.

import pack1.Car; // 다른 패키지에 있는 Car 클래스를 사용하기 위해 import 합니다.

public class CarExam {
    public static void main(String[] args) {
        // Car 객체를 생성합니다.
        Car myCar = new Car();

        // public 필드에 직접 접근하여 값을 출력합니다. (어디서든 접근 가능)
        System.out.println("내 차의 모델은: " + myCar.model); // 출력: 내 차의 모델은: 테슬라 모델 3

        // public 메서드를 호출합니다. (어디서든 호출 가능)
        myCar.startEngine(); // 출력: 테슬라 모델 3의 시동이 걸렸습니다! 🚗
    }
}

실행 결과: CarExam.java를 컴파일하고 실행하면, Car 클래스의 public 필드와 메서드에 pack2 패키지에 있는 CarExam에서 아무 문제 없이 접근하는 것을 볼 수 있습니다.

 
내 차의 모델은: 테슬라 모델 3
테슬라 모델 3의 시동이 걸렸습니다! 🚗

2. protected (가족끼리만! 🏡) 예제

개념: protected로 선언된 요소는 같은 패키지 내에서는 모두 접근 가능하며, 다른 패키지에 있어도 해당 클래스를 상속받은(자식 클래스) 경우에만 접근할 수 있습니다.

pack1/Car.java

java

package pack1; // pack1 패키지

public class Car {
    // protected 필드는 같은 패키지 또는 상속받은 자식 클래스에서 접근 가능합니다.
    protected String color = "빨간색";

    // protected 메서드도 같은 패키지 또는 상속받은 자식 클래스에서 호출 가능합니다.
    protected void accelerate() {
        System.out.println(color + " 차가 속도를 냅니다. 💨");
    }
}

pack2/SportsCar.java (Car를 상속받은 자식 클래스)

java

package pack2; // pack2 패키지

import pack1.Car; // Car 클래스를 상속받기 위해 import 합니다.

// SportsCar는 Car의 자식 클래스입니다.
public class SportsCar extends Car {
    public void turboBoost() {
        // 상속받은 SportsCar는 부모 Car의 protected 필드와 메서드에 접근할 수 있습니다.
        System.out.println(color + " 스포츠카가 터보 부스트를 사용합니다! 🚀");
        accelerate(); // 부모의 protected 메서드 호출
    }
}

pack2/CarExam.java

java

package pack2; // pack2 패키지

import pack1.Car; // Car 클래스를 사용하기 위해 import 합니다.

public class CarExam {
    public static void main(String[] args) {
        // 1. SportsCar (자식 클래스)를 통해 protected 멤버 접근
        SportsCar mySportsCar = new SportsCar();
        mySportsCar.turboBoost();
        // 출력: 빨간색 스포츠카가 터보 부스트를 사용합니다! 🚀
        // 출력: 빨간색 차가 속도를 냅니다. 💨

        System.out.println("---");

        // 2. Car (부모 클래스) 객체를 직접 생성하여 protected 멤버에 접근 시도 (다른 패키지)
        Car normalCar = new Car();
        // 아래 두 줄은 컴파일 에러가 발생합니다!
        // 왜냐하면 pack2의 CarExam은 pack1의 Car와 다른 패키지에 있고,
        // CarExam은 Car를 상속받은 자식 클래스가 아니기 때문입니다.
        // System.out.println(normalCar.color); // 에러 발생!
        // normalCar.accelerate(); // 에러 발생!

        System.out.println("일반 Car 객체에서는 protected 멤버에 직접 접근할 수 없습니다. (컴파일 에러 예상)");
    }
}

실행 결과: pack2/CarExam.java를 컴파일하면 normalCar.color와 normalCar.accelerate() 부분에서 컴파일 에러가 발생합니다. SportsCar를 통한 접근은 정상적으로 이루어집니다.

 
빨간색 스포츠카가 터보 부스트를 사용합니다! 🚀
빨간색 차가 속도를 냅니다. 💨
---
일반 Car 객체에서는 protected 멤버에 직접 접근할 수 없습니다. (컴파일 에러 예상)

(실제 컴파일 시 에러가 발생하여 System.out.println문만 출력되고 프로그램이 완료되지 않습니다. 주석 처리된 부분을 풀어보면 에러를 확인할 수 있습니다.)


3. (아무것도 안 씀) default (같은 동네만! 🏘️) 예제

개념: 접근제어자를 명시하지 않으면 default (또는 package-private) 접근 권한을 가집니다. 같은 패키지 내에서만 접근할 수 있고, 다른 패키지에서는 접근할 수 없습니다.

pack1/Car.java

java

package pack1; // pack1 패키지

class Car { // 클래스 자체에도 default 접근제어자를 적용할 수 있습니다. (다른 패키지에서 이 클래스 자체를 사용할 수 없음)
    // default (접근제어자 명시 안 함) 필드는 같은 패키지 내에서만 접근 가능합니다.
    String brand = "현대";

    // default (접근제어자 명시 안 함) 메서드도 같은 패키지 내에서만 호출 가능합니다.
    void honk() {
        System.out.println(brand + " 차가 빵! 빵! 하고 경적을 울립니다. 📢");
    }
}

pack1/CarExam.java (같은 패키지)

java

package pack1; // pack1 패키지

public class CarExam {
    public static void main(String[] args) {
        // 같은 pack1 패키지에 있는 Car 객체를 생성합니다.
        Car myCar = new Car();

        // 같은 패키지이므로 default 필드에 접근하여 값을 출력할 수 있습니다.
        System.out.println("내 차의 브랜드는: " + myCar.brand); // 출력: 내 차의 브랜드는: 현대

        // 같은 패키지이므로 default 메서드를 호출할 수 있습니다.
        myCar.honk(); // 출력: 현대 차가 빵! 빵! 하고 경적을 울립니다. 📢
    }
}

pack2/OtherPackageCarExam.java (다른 패키지)

java

package pack2; // pack2 패키지

// import pack1.Car; // Car 클래스 자체가 default 이므로 다른 패키지에서 import 자체가 안 됩니다. (컴파일 에러)

public class OtherPackageCarExam {
    public static void main(String[] args) {
        // 다른 패키지에 있는 Car 클래스는 default 접근제어자이므로 접근할 수 없습니다.
        // 아래 줄은 컴파일 에러가 발생합니다!
        // Car otherCar = new Car(); // 에러 발생!

        System.out.println("다른 패키지에서는 default 접근제어자를 가진 Car 클래스에 접근할 수 없습니다. (컴파일 에러 예상)");
    }
}

실행 결과: pack1/CarExam.java는 정상적으로 컴파일 및 실행됩니다. pack2/OtherPackageCarExam.java를 컴파일하려고 하면 Car 클래스를 찾을 수 없다는 컴파일 에러가 발생합니다.

 
<pack1/CarExam.java 실행 결과>
내 차의 브랜드는: 현대
현대 차가 빵! 빵! 하고 경적을 울립니다. 📢

<pack2/OtherPackageCarExam.java 컴파일 시도 시 에러 메시지>
error: Car is not public in pack1; cannot be accessed from outside package

4. private (나만 볼 거야! 🔒) 예제

개념: private으로 선언된 요소는 오직 해당 클래스 내부에서만 접근할 수 있습니다. 외부에서는 그 누구도 접근할 수 없습니다. 마치 개인 일기장처럼 말이죠.

pack1/Car.java

java

package pack1; // pack1 패키지

public class Car {
    // private 필드는 오직 이 Car 클래스 내부에서만 접근 가능합니다.
    private int speed = 0; // 현재 속도

    // private 메서드도 오직 이 Car 클래스 내부에서만 호출 가능합니다.
    private void checkSpeedLimit() {
        if (speed > 100) {
            System.out.println("속도 위반! 천천히 운전하세요! 🚨");
        } else {
            System.out.println("안전 속도 유지 중입니다. 😊");
        }
    }

    // private 필드에 접근하기 위한 public 메서드 (getter)
    public int getSpeed() {
        return speed;
    }

    // private 필드를 변경하기 위한 public 메서드 (setter)
    public void setSpeed(int newSpeed) {
        if (newSpeed >= 0) { // 속도는 음수가 될 수 없습니다.
            this.speed = newSpeed;
            System.out.println("현재 속도는 " + this.speed + "km/h 입니다.");
            checkSpeedLimit(); // private 메서드는 같은 클래스 내에서 호출 가능합니다.
        } else {
            System.out.println("속도는 음수가 될 수 없습니다.");
        }
    }
}

pack1/CarExam.java

java

package pack1; // pack1 패키지

public class CarExam {
    public static void main(String[] args) {
        Car myCar = new Car();

        // private 필드에는 직접 접근할 수 없습니다. (컴파일 에러 발생!)
        // System.out.println(myCar.speed); // 에러 발생!
        // myCar.checkSpeedLimit(); // 에러 발생!

        System.out.println("private 필드와 메서드에는 직접 접근할 수 없습니다. (컴파일 에러 예상)");

        // private 필드에 접근하기 위해서는 public 메서드 (getter/setter)를 사용해야 합니다.
        myCar.setSpeed(60); // setter를 통해 속도를 60으로 설정합니다.
        // 출력: 현재 속도는 60km/h 입니다.
        // 출력: 안전 속도 유지 중입니다. 😊

        myCar.setSpeed(120); // setter를 통해 속도를 120으로 설정합니다.
        // 출력: 현재 속도는 120km/h 입니다.
        // 출력: 속도 위반! 천천히 운전하세요! 🚨

        System.out.println("현재 차의 속도: " + myCar.getSpeed() + "km/h"); // getter를 통해 속도를 가져옵니다.
        // 출력: 현재 차의 속도: 120km/h
    }
}

실행 결과: myCar.speed와 myCar.checkSpeedLimit() 부분을 주석 처리하지 않으면 컴파일 에러가 발생합니다. 주석 처리된 상태로 CarExam.java를 컴파일하고 실행하면 아래와 같은 결과를 볼 수 있습니다.

 
private 필드와 메서드에는 직접 접근할 수 없습니다. (컴파일 에러 예상)
현재 속도는 60km/h 입니다.
안전 속도 유지 중입니다. 😊
현재 속도는 120km/h 입니다.
속도 위반! 천천히 운전하세요! 🚨
현재 차의 속도: 120km/h

이렇게 public, protected, default, private 접근제어자가 실제 코드에서 어떻게 동작하는지 살펴보았습니다. 

'Java_language' 카테고리의 다른 글

캡슐화 (private)  (0) 2025.12.01
자바의 static과 this에 대해서  (0) 2025.12.01
BankAccount 클래스  (0) 2025.11.27
클래스를 활용한 학생 정보 출력 프로그램  (0) 2025.11.26
클래스 만들기 연습문제  (0) 2025.11.26