'XML'에 해당되는 글 2건

  1. 2013.05.24 Umc Core IoC 통합 컨테이너 #1
  2. 2007.08.30 XDocument 클래스와 LINQ

객체지향 프로그래밍 이야기

IoC(Inversion of Contol)[1], 우리말로는 ‘역전제어’라고 한다. 객체지향 프로그래밍의 기본은 만들어진 객체를 잘 쓰는 것 부터 시작한다. 이 경우 개체(Object)를 인스턴스화(Instance)하기 위해 개체(Object)를 직접 참조해야 한다.

개체(Object)는 class 로 선언되는 빌딩의 명세서(설계도?)와 같고, 인스턴스(Instance)는 만들어진 빌딩(Building-건물)을 의미한다. 전자를 개체(Object)라고 부르며, 후자를 객체(Object) 또는 인스턴스라고 부른다.

명세서를 찍어내는 방법은 매우 간단하다. Building b = new Building() 이것이 객체지향에서 개체를 인스턴스화 하는 코드가 되겠다. 그런데 현실에서의 건물은 매우 다양하다. 아파트도 있고, 오피스텔도 있고, 고층빌딩도 있다. 어떤 건물은 지하 주차장이 완비되어 있고, 어떤 건물은 주차장이 옥상에 있다. 물론 없는 건물도 있다. 어떤 건물은 건물 전체가 주차장이다.

하나의 객체로 건물의 모든 기능을 담기란 힘들다. 방, 화장실, 출입문, 엘리베이터 등 각각 작은 객체들을 기능 단위로 쪼개야 나중에 다른 건물을 지을 때도 재사용성이 높아진다. 여러개로 쪼개진 기능을 한대 묶어 복합적으로 배치하면(Complex + Composition) 오피스텔이 되기도 하고, 원룸텔이 될 수 있다. 이 얼마나 아름다운 객체지향의 세계인가.

그런데 어느 엘리베이터 업체가 가장 최신의 기능을 넣기 위해 독자 표준으로 만들었다. 이 엘리베이터는 총 중량도 검사해서 작동 여부가 결정되고, 중량이 넘어서면 목적지 까지 중간에 서지도 않는 똑똑한 지성도 갖추었다. 환풍 설비도 갖추고, 향기도 나고, 내부 벽은 고급스러운 스테인레스로 쫙 깔았다.

공포 영화에나 나올 법한 허름한 구닥다리 병원의 삐그덕 거리는 엘리베이터와는 차원이 다르다. 이 병원 건물은 환상적인 저 엘리베이터 업체의 객체를 샀다. 젠장, 안맞는다. 크기도 국제 표준의 규격과 다르고, 외벽과 연결되는 환풍 설비는 꽉 끼어 찌그러질 판이다. 마치 38인치 바지를 입는 사람이 30인치 바지를 억지로 입으려는 것과 같다.

인터페이스 지향적인 프로그래밍 이야기

이 엘리베이터 업체는 최첨단 기술이 도입되는 건설사의 수주를 받아 개발한 엘리베이터인데, 건설사와 계약이 끝나니 손가락만 빨게 생겼다. 독자 표준의 엘리베이터를 국제 표준에 맞게 다시 만들었고 이제야 다시 매출이 조금씩 오르기 시작했다.

국제 표준 규격에 맞게 정해진 규약을 지켜서 만들었다. (말도 안되는 ISOxxxxElevatorOutputV1 이라는 인터페이스가 규약이라고 치자)

public interface IStarbucksElevator
{  
    ISOxxxxElevatorOutputV1 Open();  
    ISOxxxxElevatorOutputV1 Close();

    ISOxxxxElevatorOutputV1 Up();  
    ISOxxxxElevatorOutputV1 Down();
}  

세상이 변하고 살기 좋아지면서 새로운 기술도 쏟아진다. 국제 표준 기구는 엘리베이터에 범죄 예방을 위해 CCTV 규격을 V2 에 포함시켰고, V3 버전에는 어린이들도 쉽게 버튼을 누를 수 있도록 버튼의 위치와 비상벨의 위치가 매우 낮아졌다.

이 엘리베이터 업체는 모든 최신 규격을 지키기 힘들다. 기술력 확보를 위해 인재도 뽑아야 하고, 최신 표준 규격에 맞는 부품을 수입도 해야하고, 아직 모든 준비는 되지 않았지만, 국제 표쥰은 지킬 수 있다. 이렇게 말이다.

public interface IStarbucksElevator
{  
    ISOxxxxElevatorOutputV1 Open();  
    ISOxxxxElevatorOutputV3 Close();

    ISOxxxxElevatorOutputV1 Up();  
    ISOxxxxElevatorOutputV2 Down();
}  

그리고 국제 표준 인터페이스는 하위 호환을 지켜야 하므로 이렇게 생겨먹었다.

public interface ISOxxxxElevatorOutputV1
{  
    // ... 생략 ...
}  

public interface ISOxxxxElevatorOutputV2 : ISOxxxxElevatorOutputV1
{  
    // ... 생략 ...
}  

public interface ISOxxxxElevatorOutputV3 : ISOxxxxElevatorOutputV2
{  
    // ... 생략 ...
}  

국제 표준을 지키기 때문에 명확하게 인터페이싱이 가능하지만, 이 업체의 내부 구현 코드는 점점 엄망이 되어 간다. 내부적으로 지나치게 코드의 버전이 많아지고, 또 갈리게 된다.

이 업체는 표준 규격에 맞게 제작된 엘리베이터의 종류가 여럿 있다. 소형, 중형, 대형 건물마다 필요한 엘리베이터 버전들이 많다.

이제는 엘리베이터 내부 개발자들은 객체를 생성하는 것이 점점 무서워질 정도다. 가끔 헷갈리기도 하는데, 소형 엘리베이터의 코드에서 return new ISOxxxV1LargeBuildingInternalV2_5 이렇게 대형 건물용 엘리베이터 객체를 반환했다간 아작이 난다.

인터페이스 기반의 프로그래밍은 분명한 장점이 많다. 특히 인터페이스 기반으로 다른 객체를 쓸 때 편하다. 내부적인 코드의 개선이 필요하거나 인터페이스에 살짝 변화가 온다던가, 분석이 필요한 경우 인터페이스 기반으로 구현된 코드를 보면 난독증이 올 지경이다. 특히, 인터페이스나 객체들을 이용하여 다형성을 가지는 개체들은 디버깅 기능이 떨어지는 개발툴(IDE)에서는 거의 시간과 씨름하는 노가다와 같다.

국내의 엘리베이터 적용에 관한 법이 바뀌었다. CCTV 기능이 있는 국제 표준 버전 2(ISOxxxxElevatorOutputV2) 기능이 없으면 대형 건물에 엘리베이터를 설치할 수 없다. 또 구현해서 바꿔야 한다. return eturn new ISOxxxV1LargeBuildingInternalV2_5_RequiredCCTV

객체의 생성과 파괴는 간접적 컨테이너(Container)에 의해

그렇다. 객체를 직접 생성하려고 하면 강하게 응집력이 생긴다. 그래서 인터페이스를 활용하여 응집력을 낮추었다. 근데 매우 복잡한 객체지향적인 코드에서는 인터페이스 기반은 너무 힘들다. 인터페이스가 변하지 않음을 보장하고 인터페이스의 상속의 스택이 없거나 매우 짧다면 쉽지만, 스택이 깊어지면 당연히 더 어려워질 수 밖에 없다. 디버깅 경험을 떠올려 보라. 메서드 안의 메서드(Inner Method), 또 그 안에서 또 다른 메서드 호출이 깊어지면 복잡해질 수 밖에 없다.

그래서 IoC(Inversion of Control-역전 제어)는 직접 개체를 핸들링 하던 것을 간접 참조를 통해 제어 방향을 완전히 반대로 바꾸는 방법이다.

기존의 객체를 직접 핸들링 하던 방식과 인터페이스 기반의 방식을 표현하면 아래와 같이 표현할 수 있겠다.


아래의 그림은 각각의 장점과 단점을 기술한 표이다.

IoC(Inversion of Control)에 대해 필자와 같은 돌팔이가 아닌 ‘집단 지성’의 명쾌하고 깔끔한 정의는 링크를 통해 확인하기 바란다.


Umc Core IoC 통합 컨테이너의 탄생 배경

Umc Core IoC는 여러 개의 서로 다른 프레임워크의 인터페이스와 스키마, 그리고 Dependency & Injection, AOP Weaving 의 인터페이스를 모두 통합한 프레임워크이다.

오픈 소스의 시대이다. 객체를 다루는 트랜드도 바뀌어 이 전에 아티클의 내용인 다이나믹 프록시(Dynamic Proxy) 와 AOP(Aspect Oriented Programming) 등과 같은 기법들을 사용한다.


아래 현재 버전의 오픈 소스가 참조하는 IoC 컨테이너 오픈 소스는 2011년 당시와 다를 수 있음.


문제는 오픈 소스들마다 사용하는 다이나믹 프록시 오픈 소스, IoC 컨테이너 오픈 소스가 제각기 다르다는 문제에서 출발하게 된다. NHibernate, iBatis.NET(현 myBatis.NET)Castle Windsor 프레임워크의 다이나믹 프록시 및 IoC 컨테이너를 사용하고, Enterprise LibraryUnity Application Block 프레임워크를 사용한다.

만약, Enterprise Library를 기반으로 ORM 프레임워크로 NHibernate 조합으로 사용한다고 치자. 내부적으로 객체를 생성하는 곳이 두 군데가 된다. 이 객체의 생명 주기를 관리하는 곳도 두 곳이 된다. 다이나믹 프록시(Dynamic Proxy) 개체가 생성된다면 똑 같은 개체가 두 군데에서 생성하므로 괜한 메모리 공간만 차지하게 된다.

아래의 그림은 2011년 당시 수집한 자료를 기반으로 작성이 되었다.



하나의 응용 프로그램의 레이어(Layer) 안에서 두 개의 컨테이너와 프록시 객체가 생성되는 것도 문제지만, 두 개의 프레임워크가 제공하는 인터페이스도 판이하게 다르다는 것은 코딩 스타일에 문제가 된다. 당연히 응용 프로그램 차원에서는 더 큰 문제로 보아야 된다.

아래의 그림에선 두 개의 IoC 프레임워크가 전혀 다른 XML 스키마와 인터페이스를 제공하는 것을 알 수 있다.



Umc Core IoC 프레임워크의 소스 코드는 https://github.com/powerumc/UmcCore/tree/master/Src/Base%20Frameworks/Src/Core/IoC 에서 먼저 확인할 수 있다.

To be continue #2…


  1. In software engineering, inversion of control (IoC) is a programming technique, expressed here in terms of object-oriented programming, in which object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.  ↩

    http://en.wikipedia.org/wiki/Inversion_of_control


'Umc Projects > Umc.Core' 카테고리의 다른 글

Umc Core IoC 통합 컨테이너 #1  (0) 2013.05.24
Umc.Core 프레임워크 다이나믹 프록시(Dynamic Proxy) #1  (0) 2013.05.23
Umc.Core 미공개 Preview  (6) 2008.05.14
Umc.Core 란?  (0) 2007.12.01
Posted by 땡초 POWERUMC

댓글을 달아 주세요

XDocument 클래스와 LINQ

.NET/C# 2007. 8. 30. 00:22 |
XDocument 클래스
 
Framework 3.0 에 들어서면서 새로이 등장한 클래스이다.
그 이전 Framework 1.1, 2.0 에서 XML 작성을 해보았다면, 그 노가다와 다름없는 코딩을
해보았을 것이다.
 
XmlDocument 또는 XmlTextWriter, XmlTextReader 클래스 사용하여 편리하게 XML 작업을 했다.
XmlDocument 는 DOM 과 같은 형태로 작업이 가능하며, 빠른 탐색이 장점이다.
XmlTextWriter 와 XmlTextReader 는 Inline 작업이 가능하며, 간결한 사용법이 장점이었다.
 
기존 XmlTextWriter 로 XML 만드는 일반적인으로 작업하는 예
 
하지만, 오늘 XDocument 클래스를 알게된다면, 위 두 클래스를 쳐다도 안보게 될 상황이 생길 것 같다^^
 
 
XDocument 시작하기
 
기존 DOM 과 같은 형태로 객체를 생성하여 XML 을 만드는 방법이다.
 
// XElement 의 객체를 생성하는 방법
XDocument xdoc = new XDocument();
xdoc.Add(new XComment("XML TEST"));
XElement xele1 = new XElement("ROOT");
xele1.Add(new XElement("Child1", "1"));
xele1.Add(new XElement("Child2", "2"));
xdoc.Add(xele1);
Console.WriteLine(xdoc.ToString());
[코드1] 객체를 생성하여 XML 만들기
 
 
위와 같은 방법은 Element 에 가공이 필요할 때(attribute 추가) 사용하면 될 것 같다.
만약, 그러한 작업이 필요 없다면 더욱 간결하게 코딩 할 수 있다.
 
// params 로 선언된 XDocument 에 연속적으로 XElement 를 코딩.
xdoc = new XDocument(
        new XComment("XML TEST"),
        new XElement("ROOT",
               new XElement("Child1", "1"),
               new XElement("Child2", "2")));
        // 위의 결과와 동일
Console.WriteLine(xdoc.ToString());
[코드2] XDocument 의 params 인자로 연속적인 작업
 
XDocument 의 두번째 생성자는 params 키워드로 object 로 선언된 불특정 다수의 인자값을
받을 수 있다.
 
 
그렇기 때문에 위의 [코드2] 와 같은 연속적인 인자를 받는 코딩이 가능하다.
 
 
 
LINQ 를 이용한 Element 추출
 
위의 샘플과 같은 XML 데이터가 있을 경우, 이것을 추출하기 위해 탐색작업을 해야한다.
Framework 3.0 의 LINQ 는 간결하다 못해, 강력한 기능의 데이터 탐색 작업을 할 수 있다.
 
var result = from r1 in xdoc.Element("ROOT").Elements()
                where r1.Name == "Child1"
                select r1;
                      
foreach (var r in result)
{
        Console.WriteLine(r.Name);
}
[코드3] LINQ 를 이용한 XML 탐색 작업
 
 
XML Element Name 이 Child1 인 것을 탐색하는 구문이다.
기존 SQL 쿼리와 다른 것은 select 가 맨 마지막에 위치한다는 것이다.
 
데이터베이스의 SQL 구문과 C# 의 객체지향을 어느정도 이해한다면
그리 어렵지 않게 LINQ 쿼리를 만들어 낼 수 있을 것이다.
Posted by 땡초 POWERUMC
TAG c#, C# 3.0, XML

댓글을 달아 주세요