자바 고급(JAVA)

객체지향 프로그래밍의 4가지 핵심 개념 - 캡슐화(Encapsulation)

beginner-development 2026. 5. 12. 22:40

1. 캡슐화란?

  • 특정 객체 안에 관련된 속성과 기능을 하나의 단위로 묶고, 외부로부터 데이터를 보호하는 객체지향 프로그래밍(OOP)의 핵심 개념이다. 객체가 제공하는 메서드를 통해서만 데이터에 접근하게 함으로써, 데이터 보호불필요한 외부 노출 방지라는 두 가지 목적을 달성한다.
  • 특징
    1. 외부에서 객체의 속성을 직접 접근하지 못하도록 제한한다.
    2. 데이터의 유효성을 검증할 수 있는 메서드를 통해 접근 가능하게 한다.
    3. 객체 간 결합도를 낮추어 유지보수성을 향상시킨다.

1 - 1. 캡슐화가 필요한 이유

1. 필드에 직접 접근할 때의 문제점
- 유효하지 않은 데이터 입력을 막을 수 없다.
- 클래스 내부 필드가 변경되면 사용하는 모든 코드에 영향을 미친다.

2. 캡슐화의 장점

장점 설명
데이터 보호 외부에서 필드 직접 접근 제한. setter에서 유효성 검사 가능
구조 은닉 내부 구조 변경 시 외부 영향 최소화(API 유지)
유지보수 용이 구조가 바뀌어도 메서드만 유지하면 외부 코드 수정 필요 없음
결합도 감소 객체간 관계가 느슨해지고, 테스트 및 재사용성이 향상됨

2. 접근 제어자(Access Modifier)

2 - 1. 제어자(Modifier)란?

  • 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드이다. 제어자는 접근 제어자와 기타 제어자 두 가지로 구분된다. 접근 제어자는 하나만 적용 가능하지만, 기타 제어자는 복수로 조합하여 사용할 수 있다.

1. 접근 제어자 : public, protected, (default), private

2. 기타 제어자 : static, final, abstract, native, synchronized 등

2 - 2. 접근 제어자란?

  • 클래스 또는 멤버(필드, 메서드 등)의 접근 범위를 제한하는 키워드이다. 주로 캡슐화의 수단으로 사용되어, 데이터 은닉보안성 강화를 가능하게 한다.
접근 제어자 접근 허용 범위
private 같은 클래스 내부에서만 접근 가능
default 같은 패키지 내에서 접근 가능
protected 같은 패키지 + 다른 패키지의 자식 클래스에서 접근 가능
public 모든 곳에서 접근 가능
  • 접근 수준 정리 : public > protected > default > private

접근 제어자 별 접근 수준

2 - 3. 접근 제어자 주의사항

  • 좋은 객체지향 설계는 필요한 정보만 최소한으로 외부에 공개하는 것이다. 접근 제어자를 적절히 사용하면 유지보수성, 보안성, 유연성을 높일 수 있다. 접근 제어자는 단 한 번만 사용이 가능하다. 기타 제어자는 static, final, abstract 키워드가 주로 사용되기 때문에 이 세 가지를 중심으로 학습을 먼저 진행하자.

3. Getter와 Setter 메서드

3 - 1. Getter와 Setter란?

  • 객체지향 프로그래밍에서 캡슐화를 구현하는 대표적인 방법 중 하나는 클래스의 필드를 private으로 선언하고, 외부에서는 public 메서드를 통해 간접적으로 접근하게 만드는 것이다. 이 때 사용되는 메서드가 바로 getter와 setter메서드이다.
  • getter는 필드 값을 읽는 메서드, setter는 필드 값을 설정하는 메서드이다.

- 왜 필요할까?

  1. 데이터 보호 : 외부 클래스에서 객체의 필드 값을 마음대로 수정하지 못하게 막는다.
  2. 데이터 유효성 검증 : setter 내부에 조건문을 추가하여 잘못된 값을 차단할 수 있다.
  3. 내부 구현 변경의 유연성 확보 : 필드이름이나 자료형이 변경되어도 getter/setter만 유지되면 외부 코드에 영향을 주지 않는다.

Getter/Setter를 정리하자면,

  1. getter/setter는 캡슐화 구현의 핵심 수단이다.
  2. 필드 접근을 제어함으로써 데이터 보호와 무결성을 높일 수 있다.
  3. setter에는 검증 로직을 넣을 수 있어 잘못된 데이터 입력을 방지한다.
  4. 설계 시 필요한 필드에만 getter/setter를 제공하는 것이 좋다.
  5. 읽기 전용, 쓰기 전용 설계도 가능하다.(getter만 제공/setter만 제공)

4. 패키지(Package)

4 - 1. 패키지란?

  • 비슷한 목적을 가진 클래스와 인터페이스들을 묶어 관리하는 단위이다. 파일 시스템에서 폴더로 파일을 정리하는 것과 같은 개념으로, 자바 클래스들을 계층적으로 조직화하고 충돌을 방지하는 데 중요한 역할을 한다.
  1. 클래스와 인터페이스들을 논리적으로 그룹화한 디렉토리 구조
  2. 대규모 프로젝트에서 클래스 이름 중돌을 방지
  3. 접근 제어자와 결합하여 접근 범위를 제어할 수 있는 기준

4 - 2. 패키지 선언

- 자바 소스 파일의 첫 번째 줄에 package 키워드를 사용하여 패키지를 선언한다. 패키지를

  선언하지 않으면 이름 없는 기본 패키지에 속하게 된다.

  • 패키지는 실제 디렉토리 경로와 일치해야 한다.
  • .은 하위 디렉토리를 의미하며, 계층 구조를 나타낸다.

4 - 3. 패키지의 장점

  1. 관련 클래스와 인터페이스를 논리적으로 묶어 유지보수성을 향상시킨다.
  2. 클래스 이름의 중복을 방지할 수 있다.
  3. 접근 제어자(public, protected, default, private)의 적용 범위를 설정하는 기준이 된다.

패키지를 정리하자면,

  1. 패키지는 자바 클래스 및 인터페이스를 논리적으로 그룹화하는 디렉토리 단위이다.
  2. 소스 파일 상단에 package 키워드를 사용해 선언한다.
  3. 클래스 이름의 충돌을 방지하고 접근 제어자와 연계해 설계를 명확하게 할 수 있다.
  4. import 문을 사용하면 다른 패키지의 클래스를 간결하게 불러올 수 있다.
  5. 실무에서는 팀과 모듈 단위로 패키지를 나누어 관리하는 것이 일반적이다.

5. 불변 객체(Immutable Object)

5 - 1. 불변 객체란?

  • 객체가 생성된 이후 그 상태가 절대 변하지 않는 객체를 의미한다. 내부 필드의 값이 한 번 초기화되면 이후에는 변경될 수 없다.
  • 자바에서 대표적인 불변 객체로는 String, Integer, LocalDate 등이 있다.

5 - 2. 불변 객체가 중요한 이유

  1. 스레드 안전성
    • 여러 스레드에서 동시에 접근해도 상태 변경이 없기 때문에 별도의 동기화 처리가 필요 없다.(**특히 중요!!!**)
  2. 객체 상태 예측 가능성 증가
    • 외부에서 객체 상태를 변경할 수 없으므로, 버그 발생 가능성을 줄이고 안정적인 코드 작성이 가능하다.
  3. 설계 단순화
    • 상태를 고려한 방어적 코드가 필요 없으므로, 설계와 유지보수가 단순해진다.
  4. 값 객체에 적합
    • 좌표(Point), 통화(Money), 이름(Name) 등 값으로서 의미를 가지는 객체에 적합하다.

5 - 3. 불변 객체 설계 원칙

설계 원칙 설명
final 클래스 선언 상속을 막아 클래스 구조 고정
모든 필드를 private final로 선언 외부 접근 및 값 변경을 방지
생성자를 통해서만 초기화 이후 값 변경 불가 보장
setter 메서드 제거 값 변경 경로를 아예 차단
가변 객체 포함 시 복사 사용 깊은 복사를 통해 불변성 유지

불변 객체에 대해 정리하자면,

  1. 불변 객체는 상태 변경이 불가능한 객체로, 캡슐화된 안정성을 제공한다.
  2. 스레드 안정성, 예측 가능성, 유지보수성을 크게 향상시킨다.
  3. 설계 시에는 final, private, 방어적 복사 등 다양한 요소를 조합해 불변성을 유지해야 한다.
  4. DTO, 값 객체 등에서 적극적으로 활용되며, 자바에서도 다양한 표준 라이브러리가 불변 객체를 제공한다.

6. Java Bean 규약

6 - 1. Java Bean이란?

  • 일정한 규칙을 따르는 자바 클래스로, 주로 데이터를 저장하고 전달하는 용도(DTO, VO 등)로 사용된다. 프레임워크나 라이브러리에서 자동으로 객체를 생성하거나 바인딩할 수 있도록 표준화된 구조를 따르는 것이 특징이다.

6 - 2. Java Bean 작성 규칙

  1. 기본 생성자 필수
    • 명시적으로 매개변수가 없는 생성자를 제공해야 한다.
  2. 모든 필드는 private으로 선언
    • 외부에서 직접 접근하지 못하도록 캡슐화한다.
  3. Getter/Setter 메서드 제공
    • 각 필드에 대응하는 getx(), setx() 형식의 메서드를 public으로 제공한다.
  4. 직렬화 가능 (선택사항)
    • implements Serializable을 통해 객체 직렬화를 지원할 수 있다.
  5. 패키지에 속해야 함
    • Java Bean은 기본 패키지에 둘 수 없으며, 반드시 명시적인 패키지 안에 있어야 한다.

 

6 - 3. Java Bean의 특징과 목적

  1. 표준화된 구조
    • 프레임워크(Spring, JSP 등)에서 객체 자동 생성, 데이터 바인딩에 활용된다.
  2. 높은 호환성
    • setter/getter를 통해 다양한 도구 및 라이브러리와 통합이 용이하다.
  3. 유지보수 용이
    • 명확한 규칙으로 코드 구조를 빠르게 파악하고 유지보수하기 쉽다.
  4. 캡슐화 중심
    • 내부 상태 보호와 외부 데이터 전달을 분리하여 관리한다.

 

6 - 4. 불변 객체와 Java Bean 비교

항목 불변 객체 Java Bean
필드 변경 가능 불가능(final) 가능(setter 제공)
생성자 모든 값 초기화 필수 기본 생성자 필수
setter 제공 제공하지 않음 반드시 제공
용도 스레드 안정성, 상태 고정 도구와의 연동, 데이터 전달

 

  - Java Bean은 DTO/VO 형태로 프레임워크와의 연결, 외부 데이터 입력 등을 쉽게 처리할

    수 있게 해주는 표준 구조이다. 하지만 상태 변경이 일어나지 않아야 할 경우에는 Java Bean

    보다는 불변 객체 설계가 더욱 적합할 수 있다.