전역적인 상태
전역 변수(global variables)나 싱글톤 패턴(singleton pattern)을 두고 어떤 사람은 악이라고도 하고, 어떤 사람은 필요악이라고도 한다. 어쨌든간 나는 저러한 구체적인 것에 대해 좋으니 나쁘니 하는 것은 사실은 별 생각이 없다는 증거라고 생각한다.
나는 전역적인 상태(global state)가 문제라고 보는데, 방점을 찍을 부분은 “전역”보다는 “상태”이다. 반대로 상태를 가지는 것이 아니라면 전역적이어도 아무런 문제가 없다는 뜻이다. 기본적으로 전역적인 것은 아무데서나 참조 가능하다는 이야기다. 그런 식이면 클래스 이름이나 함수 이름도 결국은 전역적인 것이 된다. 그러나 아무도 전역 상수(global constants)에 대해 뭐라고 떠들지는 않는다. 결국 실행 시간에 바뀌는 것이 아무데서나 간섭받으면 프로그램이 꼬이기 십상이라는 말이다. 바뀌지 않으면 문제가 되지 않는다.
값 객체(value object)라고도 하고 상태 없는 객체(stateless object)라고도 하고 변형되지 않는 객체(immutable object)라고도 하지만, 이름이야 어쨌든 객체는 변경되지 않도록 디자인되는 게 좋다고 생각한다. 모든 연산은 가능하면 자기 자신을 수정하는 대신, 새로운 객체를 반환하는 편이 낫다. 성능의 문제가 있지만, 이런 부분은 컴파일러 등의 언어 구현이 잘 해내야 할 몫이라고 생각하는 편이다.
나는 비슷한 관점에서 Ruby의 열린 클래스(open class) 정책이 안 좋은 면도 많이 포함한다고 생각한다. 물론 Python 등의 언어도 클래스가 런타임에 수정 가능한 객체이긴 하지만, Ruby 공동체는 실행 시간에 클래스를 수정하는 짓을 장려하는 문화를 갖고 있다는 점이 큰 차이다. 게다가 Ruby 언어는 그것을 깔끔하게 해낼 수 있도록 문법이 설계되어 있다.
전역적인 상태의 또 다른 문제는 여러 상태가 존재해야할 필요성이 생기면 바로 문제가 생기는 디자인이라는 점이다. 예를 들어 간단한 웹 서버를 내장한 애플리케이션이 있다고 치자. 원래는 80 포트에 하나의 웹 서버만 있으면 됐지만, 둘 이상의 포트에 연결되어 여러 웹 서버를 돌릴 필요가 생기게 되는 식의 상황은 생각보다 적지 않다. (웹 서버 대신 예를 들 다른 것들도 많을 것이다.) 처음에 전역적인 웹 서버를 가지고 있었다면, 여러 웹 서버 인스턴스를 생성할 수 있도록 고치는 작업은 꽤 성가신 일이 될 것이다. 게다가 어떤 객체가 전역성을 띄게 디자인되었다는 것은 그 객체가 다중화될 여지가 없다는 확신이 있어야 가능하기 때문에, 그러한 확신 아래 코드 곳곳에서 신나게 전역 객체와 직접적으로 참조를 하고 있을 가능성이 높다.
서상현 씨가 프레임워크와 라이브러리의 차이에 대한 훌륭한 아포리즘을 적으신 적이 있는데,
내가 부르면 라이브러리고, 내가 불리면 프레임워크다. 같은 값이면 라이브러리가 프레임워크보다 낫다.
프레임워크 역시 그 자신이 전역적인 상태를 가진다는 점에서 같은 문제를 공유한다. 여러 프레임워크 인스턴스를 가질 수는 없다. 만약 그게 가능하다면 라이브러리라고 불러야 한다. “같은 값이면 라이브러리가 프레임워크보다 낫다”는 이야기는 정말 지당한 말이다.
물론 여기서도 문제가 되는 것은 그 객체가 상태를 가질 때 뿐이다. 상태를 가지지 않는다면 굳이 다중화할 필요가 없다. 결국 라이브러리는 상태를 갖지 않거나 전역적이지 않고(둘 중 하나라도 만족하면 라이브러리다), 프레임워크는 전역적인 상태를 갖는다고 표현할 수도 있다.1
결국 정말 문제가 되는 것은 전역성이 아니라 상태를 가지고 있는지 여부이다. 전역성은 상태를 가지고 있는 객체의 문제를 특히 두드러지게 하는 요소일 뿐이다.
-
쓰고 보니 동어반복. ↩

October 20th, 2009 at 3:48 AM
엽우의 생각…
Stateless, Fortran, Haskell…