본문 바로가기

기타/객체지향 토막글

캡슐화와 정보은닉 - 수필 객체지향

캡슐화란 용어는 용어의 뜻을 이해하는것도 두루뭉실하지만 그 쓰임새도 애매모호하다. 나는 몇년 경력이 되어서도 캡슐화란, 객체의 속성을 private로 만들어 이것을 get/set 메소드로 호출하는 방법으로만 이해했다. 그런데 저 객체지향 캡슐화 이론과는 다르게 실제 프로그래밍에서는 객체의 속성을 public으로 만들어 직접 호출하는것과의 차이점을 느끼지 못했다. 오히려 private로 선언하면 클라이언트에서 저 속성을 가져올때 get/set을 쓰느라 코드 보기가 더 지저분해서 좋게 생각하지 않았다.

[삽화]

캡슐화는 객체지향 개발의 중요한 장점중에 하나이지만, 나는 상속과 구성 폴리모피즘의 장점은  이해하면서 유독 캡슐화의 장점을 이해하지 못했다. 캡슐화의 정의와 캡슐화가 왜 좋은지 따로 공부해야 했다.

캡슐화의 정의는 관련있는 여러 정보들을 어떤 틀안에 담는 것이다. 여기서 어떤 틀안에 담는다는 것은 외부에 필요없는 정보들을 노출시키지 않고 숨기는 것이다. 여기서 정보를 노출하지 않고 숨기는 것은 정보은닉의 정의와 같다. 이렇게 캡슐화와 정보은닉을 하는 이유는 캡슐화를 통해 객체 안의 데이터가 다른 객체에게 잘못 조작되는 것을 막기 위해서이다. 데이터를 직접 접근할수 없기 때문에 캡슐화된 속성에 대해 ‘그 속성을 가진 객체’가 별도로 조작해야 하는 경우, 그 속성이 보호되는 효과가 있다. 마치 친구에게 자신의 웹하드를 공개해주었는데 읽기 권한만 주고 쓰기 권한은 제한하여 자신의 파일을 보호하려는 경우와 같다.  

캡슐화를 통해 데이터가 다른 객체에게 잘못 조작되는 것을 막을 수 있다. 그래서 데이터의 주인 객체가 따로 계산하거나 확인한 값이 보존되는 효과가 있다. 이 점이 캡슐화의 장점을 이해하는데 중요한 단서이다.

public class MountainClimbingBoots {  // 등산화 클래스
    private int durability = 60;      // 내구성
    private boolean isGoreTex = true; // 고어텍스 유무

    public int getDurability() {      // 내구성 속성 get접근 메소드
        if(isGoreTex) {               // 고어텍스 기능이 맞으면
            return durability + 30;   // 내구성에다가 30을 더해서 리턴한다.
        }
        return durability;
    }
}
[캡슐화된 등산화 클래스]

등산화 객체는 내구성이란 속성이 있다. 내구성이란 속성은 기본적으로 60으로 지정되어 있다. 그리고 ‘클라이언트 객체’가 get메소드로 내구성 속성을 가지고 올때 내구성 데이터를 조작하는 로직이 포함되어 있다. 위의 예제처럼 만약 고어텍스 기능이 있다면 내구성에 +30을 더해 90을 리턴하는 로직이 추가되어있다. 그런데 만약 내구성 속성이 public으로 오픈되어 있어서 클라이언트가 직접 속성 값을 가지고 오는 경우가 생긴다면 본래 등산화 객체 설계자가 의도했던 설계를 망가뜨리는 참사가 발생한다.

더 나아가 ‘클라이언트 객체’가 객체 구성요소의 쓰임새를 잘 모른채 직접 속성 값을 조작하는 경우가 생긴다면, 직접 조작한 ‘클라이언트 객체’ 뿐만 아니라 다른 ‘클라이언트 객체’까지 조작된 속성값을 써야 되기 때문에 피해가 확대되는 더 큰 참사도 발생될 수 있다. 마치 ‘산에서 떨어트린 담뱃재가 산불이 되는 경우’와 같다.

만약 ‘캡슐화’를 지킨다면,
1. 속성은 private로 선언한다.
2. get메소드를 만들어 get메소드로만 속성을 가져올수 있게 한다.
3. set 메소드로 데이터를 제한적으로 조작하게 허용하거나, 아예 set메소드를 제거하여 외부로부터 속성값의 조작을 금지한다.
이렇게 하여 자신 객체의 설계 사상을 잘 모르는 다른 클라이언트 객체들의 ‘무자비한’ 조작으로부터 자신의 속성와 설계 사상을 안전하게 보호한다. 이제 내가 get/set메소드를 이용한 캡슐화 규칙을 지키기보다 속성을 조작하길 좋아했던 습관이 어떻게 잘못 되었는지 이해할 수 있었다.

[삽화]
 
객체지향에서 캡슐화란 뜻은 다른 관점 에서도 사용한다. 객체지향 설계관점에서도 사용한다. 예를들면 ‘변하는 기능을 분리해서 따로 캡슐화하라~’ 는 객체지향 원칙을 쓰곤 한다.

캡슐화의 정의는 관련있는 여러 정보들을 어떤 틀안에 담는 것이다. 그럼 객체의 기능중에 일부를 그 객체로부터 분리하여 다른 ‘객체 패밀리’로 새롭게 구성하는 것도 캡슐화이다. 객체의 일부 기능을 다른 ‘객체 패밀리’의 새로운 틀로 담았으니 이것도 캡슐화다. 이렇게 객체의 기능을 별도의 ‘객체 패밀리’ 틀로 분리하여 담으면, 유연성과 확장성이 좋아진다.

[삽화]

정보은닉이란 개념은 캡슐화 개념과 거의 비슷하되, 정보은닉 규칙을 준수하기 위해 캡슐화가 쓰이고 있다. 캡슐화를 지키면 정보은닉 규칙을 준수할 수 있다. 정보은닉은 외부에 필요없는 정보들을 노출시키지 않고 숨기는 것이다.

예를 들어 우리가 비행기 객체를 인식할 때 비행기를 구성하는 엔진, 전자제어장치 등의 복잡한 부품은 모른다. 다만 비행기로 ‘이동’ 할 뿐이다. 사용자 입장에서는 ‘복잡한 속성’보다는 ‘중요 기능’만 알면 된다. 보통 세상이 이러므로 객체지향 개발에서도 ‘복잡한 부품’은 외부에 노출하지 않고, 객체 외부에서 인식하기 편리한 ‘중요 정보’만을 외부로 노출시켜야 한다.

이런 정보은닉을 잘 지원하는 객체지향 요소가 인터페이스이다. 인터페이스의 기능 명세를 설계하고 그 기능 명세의 구현은 하위 클래스에 맞긴다. 클라이언트는 인터페이스에만 의존되어 있다. 그러면 클라이언트는 인터페이스에 명시된 ‘기능의 용도’만 알기 때문에 정보은닉을 지킬 수 있다. 이 설명에서도 ‘객체지향 보물지도’ 그림이 떠올라야 한다. ‘객체지향 보물지도’의 그림과 동일한 설명이다.

이렇게 캡슐화와 정보은닉을 잘 활용하면,
1. 정밀한 제어가 필요한 속성이 다른 객체의 조작에 의해 훼손되는 경우를 막을 수 있다.
2. 객체끼리 정말 필요한 정보들만 의존한다.
3. 변하는 기능은 캡슐화를 통해 별도의 틀로 구성하여 기능의 수정과 확장 요구에 유연하게 대처할 수 있다.
4. 그 결과 객체간의 응집도가 높고 결합도가 낮아져 유연성과 확장성이 높아질 것이다.

[삽화]


덧) 아직 고쳐쓰기가 덜 되었습니다. 예를 들면 도입부는 그럴듯하게 쓰다가 실제 설명부분에서는 풀어쓰는 부분이 덜 되었습니다. 어려운 용어의 풀어쓰기가 안되었습니다. 기타 삽화가 부족함을 이해해 주시길 바라며, 향후 책에 쓰일 원천 자료이기 때문에 펌은 불허, 링크 환영 합니다. 조언 부탁드립니다. ^ ^;