.NET Core 부터는 System.Drawing.Image를 못 쓰지만 WPF라서 쓰고 있습니다.
오늘 일하다가 System.Drawing.Image의 MemoryStream에 관하여 이슈가 있었습니다.
제가 Cloud에 올라간 Image를 URI를 통해 byte[] 로 받아서 MemoryStream을 using으로 열어 System.Drawing.Image으로 변환한 다음, ViewModel의 ObservableCollection<System.Drawing.Image>에 Add 했습니다. using으로 열었었기 때문에 당연히 method가 종료되고 MemoryStream은 닫혔을 것입니다.
이후 ViewModel의 ObservableCollection를 ListView에 Binding할 때 WPF는 System.Drawing.Image를 System.Windows.Media.ImageSource로 변환해서 Binding 해야하기 때문에 Converter를 사용해야 했습니다. 이 때 value로 들어온 System.Drawing.Image를 다시 MemoryStream을 열어 Image.Save(MemoryStream, ImageFormat.Jpeg) 를 했더니 A generic error occurred in GDI+. 예외가 발생하면서 Save가 되지 않았는데요. 구글링해서 찾아보니 Image가 살아있는동안 Stream을 닫지 마세요 라는 글만 계속해서 검색이 되었습니다. 분명 Converter 안의 로직은 stream이 닫혀지지 않은 채로 Image를 Save했었는데 알고보니 이전에 이 Image에 대하여 MemoryStream을 이미 한 번 열고 닫았기 때문 에 오류가 발생했던 것이 었습니다.
아마도 이건 제가 Stream을 잘 이해하지 못했기 때문에 발생한 것 같습니다. 그냥 단순하게 byte[]나 string이나 image 등등의 객체들을 중간에서 다리 역할을 해주는 가상계층이라고만 생각했었는데 제가 모르는 뭔가가 있었나봅니다.
통상 Stream이라는 것은 한 번쓰고나면 using으로 제깍제깍 처리해버렸는데 Image에 대하여서는 Image가 살아있는 동안은 Stream을 제거하지 않고 Image가 필요없어 졌을 때 Dispose를 실행하면 같이 연결되어 있는 Stream도 함께 제거 된다고 합니다.
이 경우만 본다면, MemoryStream은 일종의 특정 Image에 대한 static처럼 유일한 객체처럼 될 수 있는데요. (stream이 static이 아니라 static처럼 유일하다는 맥락) 이걸 전역으로 편하게 관리할 수 있는 방법이 있을까요? 메서드에서 using으로 사용하지 않더라도 stream을 사용하고 나면 리턴 후 함수에서 사용된 stream은 관리되지 않는 가비지 가 될 것이기 때문입니다.
장문의 글이 되었지만, 혹시 노하우가 있으신 분이 계실까요?