Windows ConfidentialWindows에서 할 수 있지만 하지 않는 것

Raymond Chen

Windows는 사실 사용 중인 DLL을 교체할 수 있습니다. 원본 이름을 바꾼 다음 새 파일을 그 자리에 복사하면 됩니다. 그러나 Windows에서는 이런 방식을 선호하지 않습니다. 왜일까요?

사용 중인 파일을 교체할 수는 있지만 시스템에는 여전히 교체되기 전 버전을 사용해야 하는 코드가 있을지도 모르기 때문입니다. 예를 들어 함께 동작하는 A.DLL과 B.DLL이라는 두 파일이 있다고 가정해 보겠습니다. 두 파일을 모두 업데이트하는 패치를 적용하는데, A.DLL이 사용 중입니다. 문제 없습니다. 두 파일 모두 바꾸면 됩니다. 결과적으로 A.DLL을 사용 중이었던 프로그램은 이전 버전을 계속 사용하게 되고 새 프로그램은 새 버전을 사용하게 됩니다. 그리고 모든 프로그램은 새 버전의 B.DLL을 받습니다.

이제 이전 A.DLL을 사용 중이었던 프로그램이 함수를 호출합니다. 이 프로그램은 당연히 이전 버전의 B.DLL을 기대하지만 이 기대와 달리 새 버전을 받게 됩니다. B.DLL에서 어떤 부분을 변경했는지에 따라 이 호출은 동작할 수도 있고 오류를 일으킬 수도 있습니다. 두 DLL은 각자 상대방의 버전이 자신과 동일하다고 가정합니다.

종속성이 없는 하나의 DLL을 업데이트하는 경우라도 이 DLL은 자기 자신의 이전 버전과 상호 운용해야 하기 때문에 잠재적인 문제는 여전히 있습니다.

사용 중인 ole32.dll을 교체한다고 가정해 보겠습니다. 새로 시작된 프로그램은 새로운 ole32.dll을 호출하고 끌어서 놓기 작업을 시작합니다. 사용자는 업데이트 전에 시작한 프로그램 중 하나에서 만든 창에서 개체를 끌어 옵니다. 이 경우 새 ole32.dll이 이전 ole32.dll에 메시지를 보내게 됩니다.

프로세스 사이에서 통신하는 코드를 작성하는 경우 여러분은 일반적으로 각 프로세스에서 동일한 버전의 코드가 실행된다고 생각합니다. 통신 채널에서 두 끝점은 통신 방식에 대해 상호 동의해야 하기 때문입니다. 예를 들면 "나는 너한테 '텍스트 요청'을 의미하는 메시지 5를 보낼텐데, 너는 나한테 '여기 요청한 텍스트가 있다'를 의미하는 메시지 12를 응답으로 보내야 해", 이런 식입니다. 양쪽이 실행하는 코드 버전이 다른 경우 통신 메커니즘도 다를 가능성이 있습니다. 미세한 차이라도 비호환성을 일으킬 수 있습니다.

어떤 구조에 필드를 추가했는데, 이 구조가 메시지 5의 일부로 사용되는 경우를 가정해 보겠습니다. 멋지군요. 이제 서로 호환되지 않는 두 개의 메시지 5 버전이 존재하게 됩니다. 하나는 이전 구조를 사용하고, 다른 하나는 새 구조를 사용합니다. 통신을 수행하는 양쪽이 구조에 동의하지 않을 경우 메시지 5는 동작하지 않습니다.

이전 버전과 새 버전을 나란히 실행하는 경우를 지원할 생각이라면 새 메시지, 예컨대 메시지 52를 만들고 새 버전의 DLL에서 메시지 5와 메시지 52를 모두 지원하도록 해야 합니다. 먼저 상대편에서 실행 중인 DLL 버전을 알아낸 다음 여기에 맞춰 적절한 메시지를 보내야 합니다.

구조 자체는 변경하지 않았더라도 구조에 있는 일부 필드의 의미는 바꾸었을 수 있습니다. 이 구조에 열거형이 있고 새 버전이 이 열거형에 새 값을 추가하는 경우 이전 버전과 새 버전 사이에 여전히 비호환성이 존재합니다.

물론 패치를 적용할 때마다 새 메시지를 정의하고, 충돌하는 두 버전의 DLL이 동시에 실행되는 시간 동안 이전 버전과 새 버전 사이의 상호 운용을 지원하기 위한 코드를 작성할 수 있습니다. 그러나 세 번째 패치가 나오면서 4가지의 메시지 집합이 만들어지게 되면(하나는 처음 버전을 위한 메시지, 이후 각 패치마다 하나씩 추가) 이 방법은 다루기 어렵게 됩니다.

패치를 순서대로 설치해야 한다는 요구 사항을 넣어도 할 일이 줄어들지는 않습니다. 원본 프로그램 실행을 계속 허용하는 한 이 프로그램과 계속 상호 운용해야 합니다.

그러다 보면 사람들은 패치가 너무 늦게 나온다면서 여러분을 조롱하는 기사를 씁니다.

요점은 사용 중인 파일을 교체한 후에 Windows를 다시 시작해야 한다는 것이 아니라, 다시 시작하지 않을 경우 발생하는 복잡성을 피하는 것이 좋다는 것입니다. 엔지니어링은 타협의 집합체입니다. 여러분이라면 권장되는 정상적인 구성조차 아닌 상황을 위해 여러분 자신의 이전 버전을 지원해야 하는 수고를 감수하시겠습니까?

Raymond Chen은 자신의 웹 사이트 The Old New Thing에서 Windows의 역사와 Win32 프로그래밍에 대해 다루고 있으며 동명의 저서에서도 이에 대해 다루었습니다. Chen의 안부 인사를 대신 전합니다.