내가 관여했던 기술적으로 잘못된 결정들 SW

여태까지 내가 직/간접적으로 영향을 끼칠 수 있었던 위치에서 바람직하지 않은 결정에 관여하거나, 기존의 결정을 바꾸는 데 노력을 덜 기울였던 기억들이 있습니다. 물론 그 당시에 나름대로 이유가 있어서 했던 결정 들인데 지금 와서 보면 아쉽네요.
해당 과제를 수행하고 있을 때에는 언급하기 힘들지만 이제는 다른 일을 하고 있으니 정리 해 봅니다. 아래 내용들은 여러 이유로 현재에는 적용되지 않습니다.

Tizen의 app ID

Tizen은 지금은 deprecate 되어서 삭제되었지만 당시 bada의 legacy API와 합쳐지면서 bada의 유산을 이어 받은 부분이 있고, 그 중에서 app ID의 format이 있습니다. bada에서의 app ID는 지금 와서 보면 OAuth2의 ID와 secret 같은 체계로 app ID와 app Secret이 있었고, app ID는 서버에서 발급 받는 10자의 random number였었습니다.
이 자체가 큰 문제는 아니었습니다만 경쟁 플랫폼인 iOS나 Android가 모두 개발자 친화적인 FQDN을 사용하는 데에 비해서 그 자체로도 허들입니다. 물론 몇 년 전에 가장 먼저 빠진 게 이 부분으로 알고 있는데, 변경하는 요구사항을 잘 수용하지 못했습니다.

App ID를 몇 가지 다른 용도로 사용하던 것도 있고 해서 기존의 방안을 고수했던 것인데, 한 가지 이름을 너무 여러 곳에 사용했던 것 자체가 문제이고 추후의 플랫폼의 운신에 제약을 주게 되었습니다.

PIMPL idiom

C++이 Java나 스크립트 언어에 비해서 호환성을 유지하는 게 쉽지는 않습니다. bada에서 앱 호환성 때문에 고생했던 경험으로 Tizen 초기에 도입했던 게 PIMPL idiom 입니다.
PIMPL idiom은 쉽게 말하면 class의 호환성을 유지하는 것이 힘드니, 외부 class에서는 member variable을 두지 않고, 내부 객체에 대한 pointer만을 유지합니다. 의도는 좋긴 한데 코드를 보는 입장에서 절대로 아름답지 않은 구조이고 코드를 읽는 쪽에서는 쓸데 없이 2배의 객체를 만드는 문제로 항상 공격하게 됩니다.

지금 와서는 확실히 global하게 모든 코드에 PIMPL을 강제하는 것은 절대로 바람직한 구조는 아니고, 꼭 필요한 곧에서만 선택적으로 적용했어야 합니다. 예전에 고려하지 않았던 중요한 Software 원칙 중 하나가 짧은 코드가 유지보수에도 더 좋고 성능 적으로 더 좋다 입니다. 물론 더 아름답기도 합니다. 지금 와서 다시 구현하라면 Java style의 interface를 적용하는 게 더 정답이라고 생각합니다. 예를 들어 PIMPL을 이용한 class 구현은 다음과 같습니다.
class AppManager {
public:
static AppManager& getInstance();
const String& getAppName() const;
private:
AppManager();
private:
class AppManagerImpl* pImpl;
};
AppManager& AppManager::getInstance() {
static AppManager appManager;
return &appManager;
}
const String& AppManager::getAppName() const {
return pImpl->getAppName();
}

class AppManagerImpl {
...
}
지금 구현하라면 다음과 같이 구현하겠습니다.
class AppManager {
public:
virtual ~AppManager() {}
virtual const String& getAppName() const = 0;
static AppManager& getInstance();
};
AppManager& AppManager::getInstance() {
static AppManagerImpl impl;
return &impl;
}

class AppManagerImpl : AppManager {
...
}
const String& AppManagerImpl ::getAppName() const {
return ...;
}
Java의 interface를 흉내냈고, 위의 AppManager class는 내부 변수를 가지지 않습니다. 물론 둘 다 class를 2번 구현해야 한다는 점은 동일하지만 위의 쪽의 구현은 모든 method가 내부 구현으로 위임을 해야 하는데, 아래 구현은 public class에서는 interface만 제공하고 위임을 할 필요가 없습니다. 상황에 따라 구현 class가 public으로 제공되고 여러 구현체를 제공 할 수도 있습니다.


위의 두 가지 모두, 그 당시의 결정은 요구사항에 맞게 나왔지만 시간이 지난 후에 변경되는 요구사항을 따르지 못해서라고 생각합니다. 두 번째의 경우 호환성이 중요하다고만 생각했지 그에 못지 않게 중요한 성능이나 코드 유지보수 같은 다른 요구사항들을 희생시켰습니다.