본문 바로가기

IT 살이/04. 기술 - 프로그래밍

개발 프레임워크 만들기 대장정 16 - Unity 컨테이너 확장예제 I부

이제 Unity 컨테이너를 확장하는 방법을 예제를 통해서 알아보자. 이 포스트에서는 어떻게 strategy를 작성하고 어떻게 객체 생성 과정에 끼워넣을 수 있는지를 알아본다. 그러면서 컨테이너 익스텐션에 대해서도 알아본다.

그러나 필자도 생업이 있는지라 예제를 구상하고 구현할 시간이 없다. 대신에 필자도 공부를 할 겸 훌륭하신 분들이 미리 만들어놓은 예제를 분석하는 수준에서 대신하려 한다. 물론 포스트를 그대로 번역만 하지는 않을 것이다. 필자가 필요한 대로 재구성해서 설명하겠다.

이것이 저작권 또는 지적 재산권 뭐 그런거 침해로 봐야 하는지는 모르겠다. 해외 아티클을 번역해주는 블로그도 많은데....만약 그 아티클을 내 생각대로 재해석해서 설명하면 그것은 법적으로 문제가 있나? 문제가 있을 수 있겠다. 원작자가 실컷 해결책을 만들어 놨는데, 뒤에 오는 넘이 그것을 잘 설명하겠다고 다른 사람에게 다르게 설명하면, 콜럼버스의 달걀이라고 원작자가 기분나쁠 수도 있지 않을까나. 에이 몰것다. 이 넘은 외국 넘이니까 나한테 소송걸일은 없겠지.

포스트의 제목은 Unity with AppDomains로 되어 있다. 이 예제는 strategy도 만들어서 strategy 체인에 끼워넣는 간단한 예와 그리고 Unity 컨테이너 익스텐션을 만드는 방법도 보여주고 있다. 각 stage별 strategy 객체들은 하나의 리스트로 묶여 있는 구조로 되어 있다. 이것을 strategy 체인이라 한다. 앞의 그림을 보라. 체인처럼 보이지 않나? 아님 말고. 그리고 여기서 말하는 "Unity 컨테이너 익스텐션"이라 함은 이전까지 말했던 "Unity 컨테이너 확장하기"라는 말과는 구분된다. 이전까지 필자가 "Unity 컨테이너 확장"이라고 한 것은 기존의 프레임워크를 커스터마이징할 수 있는 모든 방법을 다 포함하는 일반적인 표현이었다. 상속도 포함되고 플러그인 방식의 확장등 모든 확장을 의미한다. 

이 예제에서 말할 "Unity 컨테이너 익스텐션"이라는 표현에서 "익스텐션"을 우리말로 번역하면 "Unity 컨테이너 확장"이 되어 앞에서 말했던 일반적인 용어와 구분하기 쉽지 않다. 그래서 구분을 위해서 발음 그대로를 유지했다.

사실 이 예제를 분석하면서 "Unity 컨테이너 익스텐션"이 뭔지를 짐작할 수 있었다. 처음에 "익스텐션"이란 말만 듣고서는 상속에 의한 확장을 상상했다. Java 에서는 상속을 extend로 표현하고 있다. 그리고 필자도 평소 상속이라는 말 대신에 확장이라는 말을 자주 사용하곤 했다. 아마 그런 습관때문이었나 보다. 그런데 예제를 보고 나서 필자가 오해를 했다는 것을 알 수 있었다.
물론 기존의 기본 컨테이너 기능을 유지하면서 상속을 통해서 새로운 컨테이너를 만드는 확장도 가능할 것이다. 그러나 "Unity 컨테이너 익스텐션"에서 말하는 것은 차라리 플러그인 방식의 확장이라고 보는 것이 옳을 것이다.  새로운 객체를 컨테이너에 로딩시키고 그것의 기능을 컨테이너에서 사용하는 것이다. 예를 들어 익스텐션 객체를 컨테이너에 만들어 두고 그 익스텐션을 통해서 ObjectBuilder에 strategy를 하나 더 끼워넣는 작업을 할 수 있다. 이곳에서 설명하는 예제가 그렇다. 이렇게 하려면 익스텐션 객체도 필요하지만 새로운 strategy 객체도 필요하다. "Untiy 컨테이너 익스텐션"이라고 하면 주로 이런 의미로 사용되는 듯 하다. 그러나 새로운 익스텐션을 stratey 설치외에도 다른 목적으로 사용해도 될 것이다. 안된다는 법이 있겠는가. 아니면 말고.

우선 예제를 위한 사전 지식을 알아보자.

■ 사전 지식

어플리케이션이 실행되는 동안에 특정 어셈블리의 내용이 변경되면 애플리케이션이 종료되지 않고서도 즉시 즉시 바로 바로 그 변경된 내용을 반영하는 애플리케이션이 있다면 유용하게 쓰일 곳이 많지 않을까? 음...막상 생각해보려 하니 웹 서버 외에 딱히 떠오르는 용도는 없다-_-;;

잠시 예제를 좀 더 이해하기 쉽도록 하기 위해서 예제에서 기본적으로 사용하고 있는 개념에 대해서 살펴보겠다. AppDomain이나 섀도우 복사에 대해서 알고 있는 사람들은 이 부분은 스킵해도 된다.

▶ ASP.NET 애플리케이션의 AppDomain

웹서버는 가상 디렉토리별로 하나씩의 AppDomain을 생성한다. AppDomain을 모르겠다면 이전 포스트를 참조한다. 동일한 서버에 두개의 ASP.NET 애플리케이션을 생성하는 경우를 생각해보자. 어떤 일이 일어나나?  특별한 설정을 하지 않는한 하나의 ASP.NET 작업 프로세스가 두 개의 애프리케이션을 호스팅한다. 이 프로세스 이름은 XP 또는 Win 2000에서는 aspnet_wp.exe이고 ASPNET 계정으로 실행된다. Win2k3에서는 w3wp.exe가 작업 프로세스가 되고 기본적으로 계정은 NETWORK SERVICE가 된다.

하나의 객체는 하나의 AppDomain에서만 살아간다. 각각의 ASP.NET 애플리케이션은 자신만의 전역 변수 객체를 가지고 있다. Cache, Application 그리고 Session 객체들은 다른 애플리케이션과 공유되지 않는다. 비록 같은 프로세스내에서 존재하더라도 isolation의 단위는 AppDomain이다.

▶ 섀도우 복사 및 재시작

그리고 예제를 이해하기 위해서는 섀도우 복사라는 것도 알고 있어야 한다. 이 내용도 앞의 포스트를 참조하면 설명되어 있다. 필자도 몰랐다. -_-;; 어셈블리가 일단 하나의 AppDomain으로 로딩되면, 그 AppDomain에서 그 어셈블리를 제거할 방법은 없다. 프로세스에서 AppDomain을 내리고(unloading) 나서 다시 새로운 AppDomain을 생성해야 새로운 버전의 어셈블리를 사용할 수 있게 된다.  근데 문제는 현재 프로세스에서 사용되고 있는 어셈블리는 파일 시스템상에서 덮어쓸 수가 없게 된다. 흔히 말하는 프로세스가 잡고(lock) 있는 상태가 되는 것이다.

AppDomain의 섀도우 복사 기능을 이용하면 파일 시스템상에서의 파일에 락을 걸지 않을 수 있다.  ASP.NET 애플리케이션용 AppDomain은 필요한 dll들을 우선 bin폴더에서 임시 디렉토리로 복사한다. 그런 다음 락을 걸고 나서 메모리로 로딩한다. 따라서 애플리케이션이 실행되고 있는 동안에도 bin 폴더로 파일들을 복사할 수 있는 것이다. 이런 복사를 섀도우 복사라 한다.

섀도우 복사는 AppDomain에서 지원하는 기능이다. 즉 AppDomain을 생성할때 섀도우 복사와 관련된 속성 즉 어느 곳에 있는 파일을 섀도우 복사할 것인가, 그리고 복사를 어디로 할 것인가만 설정하면 어셈블리를 로딩할때 자동으로 섀도우 복사를 하게 된다. 여기서 bin 폴더로 새로운 파일이 덮어씌여졌다는 것을 자동인식하는 기능은 AppDomain의 기능이 아니다. bin 폴더의 변경을 감지하고 기존의 AppDomain을 내리고 새로운 것을 올리는 작업은 ASP.NET 런타임이 하는 일이다.

■ 예제 제한

이 예제에서는 bin 폴더의 파일이 변경되는 것을 감지할 수 있는 기능은 구현하지 않고 있다. 예제에서는 웹 서버나 자동 감지 기능을 구현하려는 것이 아니라  Unity 컨테이너를 확장하는 방법을 보이려는 것이다. 파일 변경 자동 감지에 관심있는 사람은 FileSystemWatcher 클래스 같은 것을 사용해보길 바란다. 여기서는 파일 변경 감지가 이뤄졌다고 보고 해당 AppDomain을 코드상에서 수동으로 내렸다가 다시 올리고 있다. 만약 파일 변경 감지를 할 수 있는 프로그램을 만들어서 AppDomain을 수동으로 내렸다 올렸다 하는 부분을 대신한다면 좀 더 멋있는 예제가 될 것이다.

이번 포스트는 너무 길어질 것 같다. 그림도 그려야 제대로 설명할 수 있을 것 같고. 본격적인 예제 설명은 다음 포스트로 미뤄야겠다. 예제가 너무 궁금한 사람은 앞에서도 소개한 페이지를 보라.

오늘도 빨리 자야 내일 아침 수영할 수 있다. 다른 사람들, 계속 왕복하고 있는 동안 필자는 졸려서 걸어가는게 태반이다. 물속에서 눈 감고 걸어다니는 사람을 상상해봐라. 좀비같지 않나?