1. 개요
객체지향의 캡슐화를 검색해보면 흔히 다음과 같이 설명합니다.
- 캡슐화란, 서로 연관 있는 속성과 기능을 하나의 캡슐로 묶고 외부에서 불필요하게 접근하지 못하도록 감추는 것을 말합니다.
- 이를 통해 객체의 내부 구현을 숨기고, 외부에는 꼭 필요한 동작만을 노출시켜 안전하고 단순하게 사용할 수 있게 합니다.
- 자바에서는 private, protected 같은 접근 제어자와 getter/setter 메서드를 통해 캡슐화를 구현하는 경우가 많습니다.
하지만 이를 보았을 때 왜 캡슐화를 해야하는지 와닿지 않고, 객체 지향이란 무엇인가 암기만 하는데 쓰였습니다.
그래서 이번에는 제가 실습을 통해 직접 느낀 캡슐화의 필요성을 중심으로 정리해보겠습니다.
2. 왜 캡슐화를 해야 하는가?
캡슐화의 필요성은 다음과 같이 정리할 수 있습니다.
- 내부 데이터를 보호한다 (잘못된 사용 방지, 무결성 유지)
- 복잡한 내부 구현을 감춘다 (사용자는 단순한 인터페이스만 사용)
- 변경에 유연해진다 (내부 구조를 바꿔도 외부 코드는 그대로 둘 수 있음)
아래는 실습에서 캡슐화를 충분히 고려하지 않고 작성한 코드입니다.
public static void main(String[] args) {
// 전자제품 데이터 저장
List<Product> electronicProducts = new ArrayList<>();
electronicProducts.add(new Product("Galaxy S25", 1200000, "최신 안드로이드 스마트폰", 30));
electronicProducts.add(new Product("iPhone 16", 1350000, "Apple의 최신 스마트폰", 25));
Category electronics = new Category(electronicProducts, "전자제품");
// 전자제품 목록 출력
CommerceSystem commerceSystem = new CommerceSystem(electronics);
commerceSystem.start();
}
이 코드는 두 가지 문제점이 있습니다.
1. 내부 구현이 노출되어 있다.
여기서 살펴볼 부분은 CommerceSystem이 Category 객체를 직접 전달받고 있다는 점입니다.
사용자는 어떤 객체를 넘겨줘야 하는지도 알고 있어야 하죠. 즉, 내부 구현을 사용자에게 노출시키고 있는 셈입니다.
2. 변경에 취약하다
만약 CommerceSystem이 Category가 아닌 다른 방식의 데이터 구조를 사용하도록 변경되면, main 메서드처럼 외부에서 CommerceSystem을 사용하는 모든 코드를 수정해야 합니다. 카테고리가 추가된다고 생각해보면 매번 CommerceSystem 생성자의 인자를 수정해야 합니다. 즉, 내부 구현의 변경이 외부에 영향을 미칩니다.
이제 캡슐화를 적용하면 다음과 같이 수정할 수 있습니다.
public static void main(String[] args) {
// 전자제품 목록 출력
CommerceSystem commerceSystem = new CommerceSystem();
commerceSystem.start();
}
public class CommerceSystem {
private List<Category> categories = new ArrayList<>();
public void start() {
// 전자제품 데이터 저장
List<Product> electronicProducts = new ArrayList<>();
electronicProducts.add(new Product("Galaxy S25", 1200000, "최신 안드로이드 스마트폰", 30));
Category electronics = new Category(electronicProducts, "전자제품");
// 카테고리 정보 저장
this.addCategory(electronics);
}
public void addCategory(Category category) {
categories.add(category);
}
}
캡슐화가 적용된 이 코드는 앞선 문제점들을 해결합니다.
내부 구현 숨김
main 메서드는 CommerceSystem의 start() 메서드만 호출하면 됩니다. 내부에서 Category 객체가 어떻게 생성되고 관리되는지 알 필요가 없습니다. 복잡한 내부 구현이 CommerceSystem 클래스 내부에 감춰져 있습니다.
변경에 유연
CommerceSystem 내부에서 카테고리를 관리하는 방식이 변경되더라도, main 메서드와 같이 외부에 노출된 start() 메서드와 addCategory() 메서드의 시그니처가 유지된다면 외부 코드는 전혀 수정할 필요가 없습니다.
3. 정리
캡슐화에 대해 이론으로만 알았을 때는 사실 잘 와닿지 않았습니다. 그런데 이번에 직접 코딩해보면서 그 중요성을 제대로 깨달았습니다.
복잡한 내부 구현을 감추고, 사용하는 쪽에서는 그저 단순한 인터페이스만 쓰면 되게끔 하는 것.
코드를 수정하거나 확장할 때 훨씬 편하다는 것을 확실히 느낄 수 있었습니다.
앞으로는 코드를 짜기 전에 설계 단계부터 객체지향적인 사고를 더 깊이 고민해봐야겠습니다.
'트러블슈팅' 카테고리의 다른 글
| [JPA] JPA 테이블 생성 (0) | 2025.12.05 |
|---|---|
| 트러블 슈팅/ 데이터 무결성 (0) | 2025.11.18 |
| 트러블 슈팅/ 퍼블릭 IP로 서버 접속하기 (0) | 2025.11.13 |
| 트러블 슈팅/ 의존성 설정 (0) | 2025.10.27 |
| 트러블슈팅/ 절차적 코드를 객체 지향으로 리팩토링하기 (0) | 2025.09.26 |