Home [실전 자바 기본편] 접근 제어자
Post
Cancel

[실전 자바 기본편] 접근 제어자

접근 제어자

  • 김영한님의 실전 자바 강의 중 접근 제어자 챕터를 학습하며 private, public, protected, default의 차이와 활용법, 그리고 캡슐화를 통한 데이터 보호와 객체 지향 설계 원칙을 정리함



왜 접근 제어자가 필요한가

데이터 보호의 필요성

  • 객체의 필드에 직접 접근을 허용하면 검증 로직을 우회할 수 있음
  • 데이터 무결성을 보장하려면 클래스가 정의한 규칙을 따르도록 강제해야 함



private으로 데이터 보호하기

AirConditioner 예제

  • 에어컨 온도를 관리하는 클래스
  • 온도는 최저 18도 이상, 최대 30도 이하로 설정 가능해야 함

문제 상황

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package climate;

public class AirConditioner {
    int temperature; // 온도 저장 (18~30도)

    // 생성자: 초기 온도 설정
    AirConditioner(int temperature) {
        this.temperature = temperature;
    }

    // 온도 상승 (최대 30도)
    void increaseTemp() {
        if (temperature >= 30) {
            System.out.println("온도 상승 불가: 최대 30도입니다.");
        } else {
            temperature += 1;
            System.out.println("온도 1도 상승");
        }
    }

    // 온도 하강 (최저 18도)
    void decreaseTemp() {
        if (temperature <= 18) {
            System.out.println("온도 하강 불가: 최저 18도입니다.");
        } else {
            temperature -= 1;
            System.out.println("온도 1도 하강");
        }
    }

    // 현재 온도 출력
    void showTemperature() {
        System.out.println("현재 온도: " + temperature + "도");
    }
}
1
2
3
4
5
6
7
8
9
10
11
package climate;

public class AirConditionerMain {
    public static void main(String[] args) {
        AirConditioner aircon = new AirConditioner(28);

        // 필드에 직접 접근하여 검증 로직 우회
        aircon.temperature = 50; // 온도 범위를 벗어난 값 설정 가능
        aircon.showTemperature(); // 현재 온도: 50도
    }
}
  • temperature 필드에 직접 접근하여 50도로 변경 가능
  • increaseTemp() 메서드의 검증 로직을 우회
  • 데이터 무결성이 깨짐

private으로 해결

1
2
3
4
5
package climate;

public class AirConditioner {
    private int temperature; // private으로 외부 접근 차단
}
  • private 키워드를 사용하면 해당 클래스 내부에서만 접근 가능
  • 외부에서 aircon.temperature = 50 시도 시 컴파일 오류 발생
1
temperature has private access in climate.AirConditioner

private 키워드의 효과

  • 필드를 private으로 선언하면 클래스 외부에서 직접 접근 차단
  • 온도 변경이 필요하면 반드시 increaseTemp(), decreaseTemp() 메서드 사용
  • 메서드 내부의 검증 로직을 우회할 수 없음
  • 18~30도 범위를 벗어나는 값 설정 불가
  • 데이터 무결성 보장



접근 제어자의 종류

4가지 접근 제어자

  • private
    • 모든 외부 호출을 막음
    • 같은 클래스 내부에서만 접근 가능
  • default (package-private)
    • 같은 패키지 안에서만 호출 허용
    • 접근 제어자를 명시하지 않으면 default 적용
  • protected
    • 같은 패키지 안에서 호출 허용
    • 패키지가 달라도 상속 관계의 호출 허용
  • public
    • 모든 외부 호출 허용

접근 제어자 범위

1
private -> default -> protected -> public
  • 왼쪽에서 오른쪽으로 갈수록 접근 범위가 넓어짐

접근 제어자 사용 위치

1
2
3
4
5
6
7
8
9
public class AirConditioner {
    private int temperature;        // 필드

    public AirConditioner(int temp) {}  // 생성자

    public void increaseTemp() {}   // 메서드
    public void decreaseTemp() {}
    public void showTemperature() {}
}
  • 필드와 메서드에 모든 접근 제어자 사용 가능
  • 클래스 레벨에서는 public, default만 사용 가능
  • public 클래스는 반드시 파일명과 이름이 같아야 함



접근 제어자 비교

DataContainer 예제

1
2
3
4
5
6
7
package security.level1;

public class DataContainer {
    public int openValue;      // 어디서나 접근
    int packageValue;          // 같은 패키지만
    private int hiddenValue;   // 클래스 내부만
}

접근 테스트 결과

위치 public default private
같은 클래스 O O O
같은 패키지 O O X
다른 패키지 O X X

같은 패키지에서 접근

1
2
3
4
5
6
7
8
9
10
11
package security.level1;

public class SamePackageTest {
    public static void main(String[] args) {
        DataContainer container = new DataContainer();

        container.openValue = 1;      // public 접근 가능
        container.packageValue = 2;   // default 접근 가능
        // container.hiddenValue = 3; // private 컴파일 오류
    }
}
  • 같은 패키지(security.level1)에서는 public, default 접근 가능
  • private은 접근 불가

다른 패키지에서 접근

1
2
3
4
5
6
7
8
9
10
11
12
13
package security.level2;

import security.level1.DataContainer;

public class DifferentPackageTest {
    public static void main(String[] args) {
        DataContainer container = new DataContainer();

        container.openValue = 1;       // public 접근 가능
        // container.packageValue = 2; // default 컴파일 오류
        // container.hiddenValue = 3;  // private 컴파일 오류
    }
}
  • 다른 패키지(security.level2)에서는 public만 접근 가능
  • default, private은 접근 불가



캡슐화

캡슐화의 개념과 장점

  • 데이터와 해당 데이터를 처리하는 메서드를 하나로 묶어서 외부 접근을 제한하는 것
  • 객체의 내부 구현을 숨기고 필요한 기능만 외부에 제공

데이터 보호

  • 외부에서 임의로 데이터를 변경하지 못하도록 막음
  • 데이터 무결성 유지

내부 구현 은닉

  • 내부 구현을 변경해도 외부 코드에 영향을 주지 않음
  • 유지보수성 향상

사용 편의성

  • 복잡한 내부 로직을 숨기고 간단한 인터페이스만 제공
  • 사용자는 세부 구현을 몰라도 사용 가능

Wallet 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package payment;

public class Wallet {
    private int amount; // 잔액을 외부에서 직접 수정 불가

    public Wallet() {
        amount = 0;
    }

    // 충전 시 유효성 검증
    public void charge(int value) {
        if (isValidValue(value)) {
            amount += value;
        } else {
            System.out.println("올바르지 않은 금액");
        }
    }

    // 사용 시 유효성 및 잔액 검증
    public void spend(int value) {
        if (isValidValue(value) && amount - value >= 0) {
            amount -= value;
        } else {
            System.out.println("금액 오류 또는 잔액 부족");
        }
    }

    // 잔액 확인
    public int checkAmount() {
        return amount;
    }

    // 내부에서만 사용하는 검증 로직
    private boolean isValidValue(int value) {
        return value > 0;
    }
}

private 멤버

  • amount 필드: 외부에서 직접 접근 불가, 메서드를 통해서만 접근
  • isValidValue() 메서드: 내부에서만 사용하는 검증 로직, 외부 노출 불필요

public 메서드

  • charge(): 충전
  • spend(): 사용
  • checkAmount(): 잔액 확인

캡슐화의 효과

  • Wallet은 3개의 public 메서드만 외부에 제공
  • 내부 검증 로직(isValidValue)은 외부에서 알 필요 없음
  • 내부 구현을 변경해도 외부 코드는 영향받지 않음
  • 예를 들어 최대 충전 금액 제한을 추가하려면 charge() 메서드만 수정하면 됨



접근 제어자 사용 원칙

기본 원칙

  • 데이터는 private으로 선언
  • 기능은 필요한 경우에만 public으로 공개
  • 내부에서만 사용하는 기능은 private으로 선언
  • 불필요한 공개는 최소화

접근 제어자 선택 가이드

멤버 권장 접근 제어자 이유 예시
필드 private 데이터 보호 private int amount;
생성자 public 객체 생성 허용 public Wallet() {}
메서드 (공개) public 외부에서 사용 public void charge() {}
메서드 (내부) private 구현 은닉 private boolean isValid()



연습 문제

  1. 접근 제어자가 필요한 가장 주된 이유는 무엇일까요?

    a. 데이터를 외부에서 마음대로 변경하는 것을 막기 위해

    • 데이터가 외부에서 무분별하게 수정되는 것을 막아 데이터 무결성을 지키기 위함
    • 내부 로직을 따르도록 강제할 수 있음
  2. 자바에서 가장 엄격하게 접근을 제한하는 접근 제어자는 무엇인가요?

    a. private

    • private는 선언된 클래스 내부에서만 접근을 허용해서 가장 엄격함
    • 외부에서는 접근할 수 없음
  3. 어떤 필드를 private으로 선언했을 때, 이 필드에 외부 클래스에서 직접 접근하려 하면 어떻게 될까요?

    a. 컴파일 단계에서 오류가 발생하여 실행되지 않는다.

    • private 멤버는 외부에서 직접 접근할 수 없다는 규칙 때문에 컴파일러가 이를 막음
    • 따라서 프로그램이 실행되지 않음
  4. 자바에서 클래스 자체에 적용할 수 있는 접근 제어자는 무엇인가요?

    a. public과 default

    • 클래스에는 public과 default 접근 제어자만 사용 가능
    • private나 protected는 클래스 레벨에 사용할 수 없음
  5. 객체 지향 프로그래밍에서 ‘캡슐화’의 가장 중요한 목표는 무엇인가요?

    a. 데이터를 숨기고 필요한 기능만 외부에 노출하는 것

    • 캡슐화는 데이터를 외부에서 직접 접근하지 못하게 숨기고, 데이터를 다루는 기능만 공개하는 것이 핵심
    • 데이터 보호가 주 목적ㄴ



요약 정리

접근 제어자 범위

  • private < default < protected < public

캡슐화 3원칙

  • 데이터는 private으로 보호
  • 필요한 기능만 public으로 제공
  • 내부 구현은 숨김

기본 설계 규칙

대상 권장 방식
필드 private
생성자 public
공개 메서드 public
내부 메서드 private
클래스 public 또는 default



Reference

Contents

Kotlin 프로퍼티와 접근 제어자

[주니어 백엔드 개발자가 반드시 알아야 할 실무 지식] 6장 동시성, 데이터가 꼬이기 전에 잡아야한다