[OOP] 캡슐화(Encapsulation)에 대해서

calm0_0·2023년 8월 30일
0

OOP

목록 보기
3/6

캡슐화란?


캡슐화(Encapsulation)는 대상을 분리하여 어떤 틀 안에 숨기고 보호한다는 의미이다.

캡슐화는 관련 있는 여러 정보들을 어떤 틀 안에 담아 외부에 필요 없는 정보들을 노출시키지 않고 숨긴다(정보은닉). 캡슐화와 정보은닉을 하는 이유는 캡슐화를 통해 객체 안의 데이터를 다른 객체가 잘못 조작하는 것을 막기 위해서이다.

객체지향에서의 캡슐화의 역할에는 다음과 같은 것들이 있다.

  • 속성을 숨기고 보호하는 역할
  • 변하는 기능을 분리하여 어떤 틀 안에 숨기고 보호하는 역할
  • 정보 은닉, 집합과 분해로 불필요한 정보를 감추고 필요한 정보만 추상화하여 제공하는 역할

속성의 캡슐화


캡슐화를 통해 다른 객체가 속성에 직접 접근하여 잘못 조작하는 것을 막을 수 있다. 이로 인해 속성의 주인 객체가 의도를 가지고 조작한 값이 그대로 보존되는 효과가 있다.

private int durablility = 60;  // 내구성
private boolean isHighArmor = true;  // 초강력 장갑 탑재 유무

public int getDurability() {  // 내구성 속성 get 접근 메서드
	if (isHighArmor) {  // 초강력 장갑 탑재 기능이 맞으면
    	return durablility + 40;  // 내구성에 40을 더해 리턴한다.
    }
    return durablility;
}

위의 코드는 비행기 클래스인데 비행기 클래스에는 내구성(durablility) 속성이 기본값으로 60이 지정되어 있다. 그리고 클라이언트 객체가 getter 메서드로 내구성 속성을 가져올 때, 내구성 속성을 조작하는 getDurability() 메서드가 있다. 이 메서드에는 만약 초강력 장갑 탐재 기능(isHighArmor)이 있다면 내구성에 40을 더해 리턴하는 로직이 들어있다.

여기에는 비행기 클래스에서 내구성 속성(durablility)과 초강력 장갑 탑재 기능(isHighArmor) 여부와 연동해야 하는 의도를 가지고 있다.

그런데 내구성 속성이 public으로 오픈되어 있다면, 비행기 클래스의 설계 의도를 모르는 다른 클라이언트 클래스가 직접 값을 조작하는 문제가 발생할 수 있다. 이러한 문제를 예방하기 위해 캡슐화를 사용한다.

캡슐화를 지키기 위한 원칙에는 다음과 같은 것들이 있다.

  1. 속성은 private로 선언한다.
  2. getter 를 만들어 getter 로만 속성을 가져올 수 있게 한다.
  3. setter 를 만들어 데이터를 제한적으로 조작하게 허용하거나 setter 를 제거하여 외부로부터 속성값의 조작을 금지한다.

기능의 캡슐화


'변하는 기능을 분리해서 따로 캡슐화하라'

캡슐화는 관련 있는 여러 정보들을 어떤 틀 안에 담는 것이다. 그렇다면 객체의 기능 중 일부를 그 객체로부터 분리하여 다른 클래스 그룹으로 새롭게 구성하는 것 역시 캡슐화이다.

객체의 기능을 별도의 클래스 그룹으로 분리해 담으면 프로그램의 유연성과 확장성이 좋아진다. 비슷한 기능을 하나의 객체에 모두 구현하려고 한다면 하나의 클래스에 로직이 섞여 객체가 지저분해진다. 그래서 유지보수 할 때나 기능을 확장할 때 수정이 어렵다.

하지만 분리 가능한 기능을 별도의 클래스 그룹으로 캡슐화하면, 하나의 클래스에 필요한 최소한의 기능만 갈끔하게 구현하고, 모듈화한 다른 기능은 원하는 기능만 선택해서 사용할 수 있다.


정보의 캡슐화, 집합과 분해


정보은닉과 같은 말이다. 캡슐화를 지키면 정보은닉 규칙도 함께 지킬 수 있다. 정보은닉이란 외부에 필요 없는 정보들을 노출하지 않고 숨기는 것을 말한다.

예를 들어, 우리가 비행기 객체를 인식할 때 비행기를 구성하는 엔진, 제어장치 등 복잡한 부품은 모른다. 다만 비행기를 타고 어딘가를 향해 이동할 뿐이다. 사용자 입장에서는 복잡한 속성보다는 우리에게 필요한 기능만 알고 있으면 된다. 객체지향 개발에서도 복잡한 속성과 기능은 외부에 노출하지 않고 외부에서 인식하기 편리한 중요 정보만 외부에 노출해야 한다.

정보은닉을 잘 지원하는 객체지향 요소에는 인터페이스가 있다. 인터페이스를 통해 기능 명세를 설계하고 이에 대한 구현은 하위 클래스에 맡긴다. 클라이언트 클래스는 인터페이스에만 의존되어 있다. 따라서 클라이언트 클래스는 인터페이스에 명시된 기능의 용도만 알기 때문에 정보의 캡슐화를 지킬 수 있다.

집합과 분해를 통해 불필요한 정보를 감추고 필요한 정보만 추상화하여 제공해야 한다.

이를 잘 보여주는 것이 '패키지' 개념이다. 패키지는 서로 관련성이 높은 클래스를 어떤 기준을 가지고 통합한다. 예를 들어,

java.util : 각종 자료구조 클래스를 모은 패키지
java.math : 각종 수학 클래스를 모은 패키지

이런 식으로 패키지화한다. 이렇게 하면, 개발자는 자신이 필요한 클래스를 쉽게 찾을 수 있다. 집합과 분해에서 집합은 내부에 포함된 요소를 감춰 시스템의 구조를 추상화한다. 사용자 입장에서 많이 생각하지 않아도 될 내부의 요소를 감추는 것이다.



Reference
한 번 읽으면 두 번 깨닫는 객체지향 프로그래밍

profile
공부한 내용들을 정리하는 블로그

0개의 댓글