오늘 드디어 C++의 mutable 키워드를 살짝 이해한 것 같아서 적는다.

C++ 개발자 경력을 쌓은지 이제 3년째.

C++의 mutable 키워드를 처음 알게된 것은 입사 후 팀장님과 effective C++책을 공부할 때였다.

그 전까지는 mutable 키워드가 있는지도 몰랐다.

effective C++ 책의 초반부의 2장 3장 4장에는 const에 대한 소개와 객체지향설계에서의 const의 효용이 주를 잇는다.

이 부분을 한 문장으로 요약하면

const를 일단 붙이고보자!

이다. 그리고 이 장을 공부하면서 팀장님이 강조하셨던 부분은 const_cast를 쓰지마라였다.

역시나 이때는 const_cast도 뭐하는 녀석인지 하나도 몰랐다.

const_cast는 한 마디로 const 키워드가 붙어 상수화된 변수 또는 개체의 상수성을 제거하는 것이다.

이걸 쓰면 안되는 이유는 const의 목적과 위배되기 때문이다.

const를 붙이는 이유는 보통 개발자가 고려하지 않은 외부 참조에 의한 값 변경을 방지하기 위해서이다.

그런데 const_cast를 통해서 이렇게 const 상수성을 무시하고 값 변경을 하다보면 보이지 않는 버그가 자라난다.

이건 지난 2년 반 동안 무척 많이 겪었다. (side-effect가 장난아니다.)

그럼에도 const_cast에 손이 가는 이유는 마감은 임박하는데 const로 인해서 계속된 컴파일 오류가 발생하면 그냥 const를 무시하고 const_cast를 써서 쉽게 가고 싶은 욕구가 든다.

하지만 이런 방식은 결국 기술적 채무로 다가온다.

처음 선배들이 한 const에 대한 고심끝에 설계한 클래스 또는 구조를 내가 망치는 셈이다. 조심하자.

그리고 컴파일에서 오류를 걸러주는 것은 무척이나 행복한 일이다.

런타임에서 서비스 후 문제가 발생하는 것은 끔찍하다. 차라리 손쉽게 해결할 수 있는 컴파일 오류가 좋다.

이런 const를 책에서는 이렇게 표현한다.

'팔방미인'이라고.

그만큼 객체지향설계에서 const 키워드가 가진 힘은 대단하다고 한다.

이 책에 영향받아 나도 const에 무척 좋은 인상을 가졌고 잘 쓰고싶은데 ... 사실 잘 안된다.

아무튼 이번 주제는 const가 아닌 mutable이므로 mutable에 대해 쓰자면 처음 mutable에 대해 이해가 어려웠던 것은 책에서 나오는 다음과 같은 말 때문이었다.

'mutable키워드는 비정적 데이터 멤버를 비트수준 상수성의 족쇄에서 풀어 주는 아름다운 오색약수같은 키워드입니다.'

지금 다시봐도 이게 뭔 말인지 다 이해는 안간다.

비트수준 상수성이라니. (책에서 비트수준의 상수성에 대해 소개한다. effective C++ 64 page, 2번째 줄) 

지금도 이럴진데 객체지향 개념도 거의없던 신입 시절의 내가 이를 이해하는 것은 솔직히 어려웠다.

그래서 더 mutable에 대해서 기피하게되었고 혹시나 코드 안에 mutable이 있으면 그 이미지로 인해서 코드가 확 어렵게 다가왔다.

그런데 오늘 드디어 mutable이 마음에 다가왔다.

그 시작은 바로 상수 객체에 대한 이슈로 인해서다.

mutable은 상수 객체안에 해당 키워드가 작성된 멤버에 한해서 상수 객체임에도 해당 멤버는 변경될 수 있음을 컴파일러에게 알리는 키워드다.

내가 본 클래스는 클립보드의 데이터를 구현한 객체인데 (클립보드는 우리가 메모장에서 ctrl+c 한 내용을 포털에서도 crtrl+v로 붙여넣기 할 수 있게 해주는 운영체제 내부의 복사 개체를 저장해두는 보드를 일컫는 개념이다. 꼭 메모장<->포털이 아니더라도 각각의 독립적인 프로그램이나 App들이 하나의 복사한 객체를 공유할 수 있게 하는 기술.)

클립보드 데이터는 복사한 순간부터 다른 외부 조건에 의해 내부 정보가 변하면 안되므로 모든 클래스의 멤버 및 함수가 const가 붙어있는 상수 객체로 설계되었다.

이 클래스의 작성 시점은 2009년이었다.

이 때만해도 이 클립보드 상수 객체는 완전한 설계였을텐데, 지금 2019년에 클립보드 관련된 새로운 기능이 추가되면서 이 상수성을 해결해야했다.

이 완전 상수화된 클립보드 데이터 클래스는 base class로서 존재했고 현재는 약 8개의 클래스가 상속받아서 각자의 필요한 부분이 작성되도록 코드가 짜여져있었는데 나는 이 8개의 클래스 중 약 3개의 클래스에 새로운 기능을 추가해야 했다.

이 새로운 기능은 클립보드 데이터 클래스로 하여금 유저가 선택한 정보를 가지도록 구현되어야 했다.

이 유저가 선택한 정보는 App 실행중에도 언제든지 변할 수 있어야 했으므로 상수 객체와는 어울리지 않았다.

초기 설계를 지키기 위해서는 이 유저 선택에 따라 변하는 값을 외부에 저장하도록 하고 구조를 변경해야 했지만

그렇게되면 또 코드 응집성이 떨어져서 나중에 문제가 될 것 같기도하고 또한 이 클래스의 코드는 정리된지 오래 지나서 잠깐 사이에 구조 변경을 할 수 있지 않았다. (당장 내일까지 해결해야 하는 문제였다.)

그 때 mutable 키워드를 사용한 선배의 코드가 보였다.

컴파일 오류도 해결하고

관리하기 어렵게 외부에 데이터를 둘 필요도 없고

const의 기본적인 존재 이유인 개발자가 의도하지 않은 멤버 변수의 변경이 아닌 개발자가 의도한 멤버 변수의 변경으로

만들어 주는 mutable 키워드가 갑자기 이뻐보였다.

물론 아무리 개발자의 의도라고해도 남발하면 const_cast처럼 어느덧 객체의 상수성을 깨트릴 확률이 크겠지만

알고 적절히 주석을 달고 조화롭게 사용한다면 저자가 왜 오색약수라고 표현했는지 알 것 같은 쓰임이었다.

물론 책에 따르면 무조건적인 상수성을 지향하는 비트수준 상수성 (물리적 상수성)

몇몇 비트는 변경을 허용한다는 논리적 상수성 (지금같은 mutable 키워드)

두 상수성 사용에 대한 논쟁은 많이 있다고 한다.

이 부분은 C++ 거장들의 철학 논쟁과도 같으니 아직 새내기인 나로서는 mutable을 잘 사용해봤다는 것에 의의를 두자.

끝.

+ Recent posts