2025-08-09 13:00
Tags:
캡슐화(Encapsulation) 핸드북
1. 만들어진 이유: 복잡성과의 싸움
캡슐화의 탄생 배경을 이해하기 위해, 캡슐 커피 머신을 떠올려 볼 수 있음.
우리가 커피를 마시기 위해 필요한 것은 ‘커피 캡슐을 넣고, 버튼을 누르는 것’ 뿐. 캡슐 내부의 원두 분쇄 상태, 물의 온도나 압력 같은 복잡한 내부 동작 원리를 알 필요가 없음. 만약 이 모든 과정을 사용자가 직접 제어해야 한다면, 커피를 내리는 과정은 매우 복잡하고 실수할 가능성도 커질 것.
소프트웨어 개발도 마찬가지. 초기의 프로그래밍 방식에서는 데이터와 그 데이터를 처리하는 함수(기능)가 분리되어 있었음. 이는 프로그램의 규모가 커질수록 다음과 같은 문제를 야기함.
-
의도치 않은 데이터 변경: 프로그램의 어떤 부분에서든 데이터에 직접 접근하여 수정할 수 있었기 때문에, 데이터가 예상치 못하게 변경되어 오류를 추적하기 어려웠음. 이를 ‘스파게티 코드’ 문제라고도 함.
-
높은 결합도: 데이터 구조가 변경되면, 그 데이터를 사용하는 모든 함수를 찾아 일일이 수정해야 했음. 이는 유지보수를 매우 어렵게 만드는 요인.
캡슐화는 이러한 문제를 해결하기 위해 등장. 관련된 데이터와 그 데이터를 처리하는 함수들을 하나의 ‘캡슐’ 또는 ‘객체(Object)‘로 묶어버린 것. 이를 통해 객체 내부는 안전하게 보호하고, 외부에는 미리 정해진, 안전한 방법으로만 상호작용하도록 만든 것.
2. 구조: 캡슐의 구성 요소
캡슐화는 크게 세 가지 요소로 구성됨.
-
데이터 필드 (Data Fields): 객체의 상태를 나타내는 변수들. 캡슐 안에 담긴 내용물에 해당하며, 외부로부터의 직접적인 접근을 막기 위해 보통 **
private
**으로 선언. -
메서드 (Methods): 데이터 필드를 조작하고 사용하는 함수들. 캡슐의 외부 ‘버튼’에 해당하며, 외부에서 호출할 수 있도록 **
public
**으로 선언. -
접근 제어자 (Access Modifiers): 캡슐의 벽과 같은 역할. 데이터와 메서드에 대한 외부의 접근 수준을 제어함.
-
public
: 어디서든 접근 가능. 객체의 공식적인 인터페이스. -
private
: 해당 클래스 내부에서만 접근 가능. 완벽하게 숨겨진 내부 로직. -
protected
: 해당 클래스와 상속받은 하위 클래스에서 접근 가능.
-
이 구조 덕분에, 객체 사용자는 public
메서드라는 공식적인 통로로만 객체와 소통할 수 있으며, private
데이터의 복잡한 내부 구조나 처리 방식은 전혀 신경 쓸 필요가 없음.
3. 사용법: 실제 코드 예시
‘사람’을 나타내는 Person
클래스를 통해 캡슐화가 어떻게 적용되는지 살펴보겠음.
public class Person {
// 1. 데이터 필드를 private으로 선언하여 외부 접근을 차단
private String name;
private int age;
// 생성자
public Person(String name, int age) {
this.name = name;
// 나이는 유효성 검사를 거쳐 설정
setAge(age);
}
// 2. public 'Getter' 메서드를 통해 데이터에 안전하게 접근 (읽기)
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
// 3. public 'Setter' 메서드를 통해 데이터를 안전하게 수정 (쓰기)
public void setAge(int age) {
if (age > 0) { // 나이는 0보다 커야 한다는 '규칙' 적용
this.age = age;
} else {
System.out.println("유효하지 않은 나이입니다.");
}
}
}
사용 예시:
public class Main {
public static void main(String[] args) {
Person person = new Person("홍길동", 25);
// 직접 접근 시도 -> 컴파일 에러 발생!
// person.age = -10; // The field Person.age is not visible
// Setter를 통한 안전한 수정
person.setAge(30); // 정상적으로 수정됨
System.out.println("수정된 나이: " + person.getAge()); // 출력: 30
person.setAge(-5); // "유효하지 않은 나이입니다." 메시지 출력
System.out.println("잘못된 값 입력 후 나이: " + person.getAge()); // 출력: 30 (이전 값 유지)
}
}
위 코드에서 age
는 private
이므로 직접 person.age = -10
과 같이 수정할 수 없음. 반드시 setAge()
라는 공개된 메서드를 통해야만 함. 이 메서드 안에는 ‘나이는 0보다 커야 한다’는 비즈니스 로직이 포함되어 있어, 데이터가 항상 유효한 상태로 유지되도록 보장함. 이것이 캡슐화의 핵심적인 역할.
4. 심화: 정보 은닉과의 관계
캡슐화(Encapsulation)와 **정보 은닉(Information Hiding)**은 종종 혼용되지만 미묘한 차이가 있음.
-
캡슐화: 데이터와 메서드를 하나로 묶는 기술 또는 메커니즘 그 자체.
-
정보 은닉: 캡슐화를 통해 달성하고자 하는 목표 또는 원칙. 즉, 객체의 내부 구현을 외부에 숨겨 모듈의 독립성을 높이는 개념.
쉽게 말해, 정보 은닉이라는 목표를 달성하기 위해 캡슐화라는 기술을 사용하는 것. 캡슐화를 했더라도 모든 멤버를 public
으로 선언한다면, 정보 은닉의 이점은 전혀 얻을 수 없음.
5. 핵심 이점 요약
캡슐화를 통해 얻을 수 있는 이점은 명확함.
-
모듈성 (Modularity): 각 객체가 독립적인 모듈처럼 작동하여 개발과 관리가 용이함.
-
유지보수성 (Maintainability): 객체의 내부 구현을 변경해도,
public
인터페이스만 그대로 유지된다면 다른 코드에 영향을 주지 않음. -
재사용성 (Reusability): 잘 만들어진 객체는 다른 프로젝트에서도 쉽게 가져다 쓸 수 있음.
-
보안성 (Security): 데이터가 의도치 않게 변경되는 것을 막아 프로그램의 안정성을 높임.
결론적으로 캡슐화는 복잡한 시스템을 단순하고, 안정적이며, 유연하게 만드는 객체 지향 프로그래밍의 근간이 되는 강력한 도구.