가끔 우리 솔루션에서는 System.Runtime.Serialization.SerializationException이 발생한다. 문제가 발생한 상황이니까 예외가 던져지는 것은 당연하다. 하지만 문제는 실제 에러는 SerializationException이 아니라는 것이었다. 그리고 SerializationException은 다들 알다시피 객체가 Serialization/Deserialization하는 과정에서 나는 문제인데, 이 에러가 날만한 시나리오를 딱히 생각해낼 수는 없었다.
Stacktrace를 보니 이 예외는 솔루션 내부의 로깅 컴포넌트에서 던져지고 있었다. 로깅 컴포넌트는 에러나 문제가 발생했을 때 그 정보를 파일에 기록하는 역할을 하는 COM+ 서버 타입 컴포넌트였다. 문제가 생긴 함수는 다음과 같았다.
Public Function WriteException(ByVal userName as string, ByVal exception as System.Exception) as string
이 함수는 Exception객체를 받아서 그 예외 정보를 포맷한 뒤 파일에 쓰는 함수였다. 여기서 문제가 될만한 부분은 인자로
System.Exception 객체를 받는 부분뿐이었는데, 로깅 컴포넌트가 COM+ 서버 타입이기 때문에 Exception객체가 프로세스간 이동을 하기 때문이었다. 하지만 System.Exception 객체가 Serialization 과정에서 문제가 생긴다는 것은 사실 상상하기가 힘들었는데..
암튼 조사 끝에 이유를 알아내었다. 문제가 생긴 객체는 모두 System.Web.HttpException이었다. 그리고 이 System.Web.HttpException이 무슨 이유인지는 몰라도, .NET Framework 1.1에서는 Serializable로 마킹이 되어 있지 않다는 사실을 알게 되었다. 즉 Logging컴포넌트에서 HttpException을 인자로 받았는데, 이게 COM+ 서버 타입이라 프로세스 이동을 하려면 Serialization과정을 거치다가.. Serializable 마킹이 안 되어 있어서 Serialization작업을 못한 것이다. 그래서 SerializationException도 났던 것이고..
1.1의 경우
2.0의 경우
.NET Framework 2.0에서는 Serializable 어트리뷰트가 있지만, .NET Framework 1.1에서는 없는 것을 볼 수 있다. 왜 1.1에서 없는지는 속시원한 설명을 제대로 찾지 못했다. 현재로서는 버그가 아닐까 추측만 될 뿐이다. 그리고 2.0이상부터는 이런 문제가 없는 것 같다.
우리 솔루션은 로깅 컴포넌트의 COM+ 유형을 Server Type에서 Library Type 으로 바꾸어서 해결했다. Library Type이라면 프로세스가 다르지 않을테고 프로세스간 객체 이동도 없을 것이니, 이 문제를 신경쓰지 않아도 되는 것이다.
다른 곳에도 이 케이스처럼 Exception객체가 프로세스를 넘어가는 시나리오가 있다면, 이 문제를 조심해야 할 것이다.