Search

Effective C++ 22: 데이터 멤버가 선언될 곳은 private 영역임을 명심하자

개요

Effective C++의 22번째 항목은 C++ 프로그래밍의 핵심 원칙 중 하나를 다룹니다: 데이터 멤버는 private 영역에 선언해야 한다는 것입니다. 이 원칙은 단순해 보이지만, 객체 지향 프로그래밍의 근간을 이루는 중요한 개념인 캡슐화와 직결됩니다. 많은 초보 개발자들이 편의성 때문에 데이터 멤버를 public으로 선언하곤 하는데, 이는 장기적으로 코드의 유지보수성과 확장성을 저해할 수 있습니다. 이 글에서는 왜 데이터 멤버를 private으로 선언해야 하는지, 그리고 이것이 실제 코드에서 어떤 영향을 미치는지 살펴보겠습니다.

본문

public 데이터 멤버의 문제점

public 데이터 멤버를 사용하면 얼핏 편리해 보일 수 있습니다. 직접 접근이 가능하니까요. 하지만 이는 여러 가지 문제를 초래합니다:
1.
문법적 일관성 부족: 객체의 일부 멤버는 직접 접근하고, 다른 멤버는 함수를 통해 접근한다면 사용자 입장에서 혼란스러울 수 있습니다.
2.
세밀한 접근 제어 불가: public 멤버는 누구나 읽고 쓸 수 있어, 데이터의 무결성을 보장하기 어렵습니다.
3.
캡슐화 위반: 내부 구현이 외부로 노출되어, 향후 변경이 어려워집니다.

private 데이터 멤버의 장점

반면, 데이터 멤버를 private으로 선언하면 다음과 같은 이점이 있습니다:
1.
캡슐화 강화: 내부 구현을 숨겨 외부 코드와의 결합도를 낮춥니다.
2.
불변속성 유지: 데이터 접근을 제어하여 클래스의 불변속성을 보장할 수 있습니다.
3.
유연한 구현: 내부 구현을 변경해도 외부 인터페이스는 그대로 유지할 수 있습니다.

코드 예시

다음은 private 데이터 멤버를 사용한 좋은 예시입니다:
class SpeedDataCollection { private: std::vector<int> speeds; // private 데이터 멤버 double averageSpeed; public: void addValue(int speed) { speeds.push_back(speed); updateAverage(); } double averageSoFar() const { return averageSpeed; } private: void updateAverage() { double sum = std::accumulate(speeds.begin(), speeds.end(), 0.0); averageSpeed = sum / speeds.size(); } };
C++
복사
이 예시에서 speedsaverageSpeed는 private 멤버로 선언되어 있습니다. 외부에서는 addValue()averageSoFar() 함수를 통해서만 데이터에 접근할 수 있습니다. 이렇게 하면 다음과 같은 이점이 있습니다:
1.
데이터의 일관성을 유지할 수 있습니다 (새 속도가 추가될 때마다 평균이 자동으로 업데이트됨).
2.
향후 내부 구현을 변경하더라도 (예: 평균 계산 방식 변경) 외부 인터페이스는 그대로 유지됩니다.
3.
speeds 벡터에 직접 접근할 수 없어, 데이터의 무결성이 보장됩니다.

protected 데이터 멤버의 주의점

protected 멤버도 public 멤버와 마찬가지로 캡슐화를 약화시킬 수 있습니다. 상속을 사용할 때 protected 멤버를 통해 데이터에 접근하는 것보다, protected 멤버 함수를 제공하는 것이 더 안전합니다.

개인적 견해

private 데이터 멤버의 중요성은 당연하게 여겨졌습니다. 그러나 이 항목에서 protected 멤버가 public과 크게 다르지 않다는 점은 새로운 통찰이었습니다. 막연히 private과 public의 중간쯤이라고 생각했던 protected가 사실은 캡슐화 측면에서 public과 유사한 문제를 안고 있다는 점을 깨달았습니다.
이는 상속 관계에서 더욱 분명해집니다. protected 멤버는 파생 클래스에서 직접 접근할 수 있어, 결국 public 멤버와 마찬가지로 내부 구현을 노출시키는 결과를 낳습니다. 이러한 이해는 클래스 설계 시 데이터 은닉과 인터페이스 설계에 더욱 신중을 기하게 만듭니다.

결론

데이터 멤버를 private으로 선언하는 것은 객체 지향 프로그래밍의 기본적이면서도 핵심적인 원칙입니다. 이는 단순해 보이지만, 코드의 유지보수성, 확장성, 그리고 전체적인 설계 품질에 지대한 영향을 미칩니다. 특히 protected 멤버의 한계를 인식하고 적절히 사용하는 것은 더 견고한 캡슐화를 달성하는 데 중요한 요소가 됩니다.