Spring .NET을 소개합니다.

사용자 삽입 이미지

 

 

 

 

 

자바를 하시는 분들은 다들 아실만한 스프링 프레임워크가 있습니다.  C#을 하다 보니깐 스프링 프레임워크의 DI(Dependency Injection)이나 AOP(Aspect Oriented Programming)가 그리워 지더군요.

그래서 찾아보니 C#에서 Spring .NET이라는 프레임워크가 존재 하더군요. 확실히 자바로 만들어진 스프링에 비하면 좀 어설픈 느낌이 있지만 그래도 정말 멋지게 구현되었습니다.

그래서 한번 간단하게 정리해 보겠습니다. Spring .NET은 [이곳] 에서 다운 받으실 수 있습니다. 혹은 소스포지의 주소는 [이곳]입니다.

Spring .NET이란?

  • 객체의 라이프사이클을 관리하기 위해 의존성 주입(Dependency Injection)을 사용하는 경량(Lightweight) 컨테이너
  • 엔터프라이즈급 .NET 어플리케이션 개발을 위한 어플리케이션 프레임워크

Core

Spring .NET Framework의 Core에는 IoC(Inversion of Control) Container와 Base Functionality가 포함되어있습니다. 간단한 예제로 다음과 같은 의존성 부패(Dependency Rot) 문제가 있는 소스가 있습니다.

Public class Human
{
    public Money money;
    public Human() { this.money = GET_MONEY_OBJECT(); }
}

Public class Container
{
    public Human Born()
    {
        return new Human();
    }
}

위의 예제에서는 Human은 Money 인스턴스를 생성하는 방법에 종속됩니다. 다른 말로 Money객체의 생성 여부가 Human에게 달려있다는 것이죠. Container 클래스 제작자는 Money가 Human안에서 생성되는지도 혹은 어떤식으로 사용되는지도 모를 수 있습니다. 그렇다면 DI(Dependency Injection)을 통한 제어 역전(IOC Container)을 사용하는 예제를 보여드리겠습니다.

Public class Human
{
    protected Money money;
    public Money pMoney { set { this.money = value; }} 
}

Public class IoCContainer
{
    public Human Born()
    {
        Human human = new Human();
        Money money = new Money();
        human.pMoney = money;
        return human;
    }
}

정확하게 Money 인스턴스는 Born 메서드에서 생성되어 Human에 Set 됩니다. 이로서 Spring에서 말하는 느슨한 결합이 구현됩니다. 다음에서 이를 실제 적용한 예제를 만들어 보도록 합시다.

using System;
using System.Collections.Generic;
using System.Text;

Namespace HelloApp
{
    class Hello
    {
        public string sayHello(string name)
        {
            return “안녕하세요? “ + name + “씨!”;
        }
    }
}
<?xml version=“1.0” encoding=“utf-8” ?>
<configuration>
    <spring>
        <objects xmlns=“http://www.springframework.net”>
            <object id=“MyHello” type=“HelloApp.Hello”/>
        </objects>
    </spring>
</configuration>
using System;
using System.Collections.Generic;
using system.Text;
using Spring.Context;
using Spring.Context.Support;

Namespace HelloApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IapplicationContext ctx = ContextRegistry.GetContext();
            Hello hello = (Hello) ctx.GetObject(“MyHello”);
            string name = “홍길동”;
            string result = hello.sayHello(name);
            Console.WriteLine(result);
        }
    }
}

결과

사용자 삽입 이미지보시면 코드의 형태는 다를지 몰라도 자바의 그것과 매우 똑같습니다. XML에 객체들을 등록하고 컨텍스트에서 GetObject를 통해 존재하는 객체(Bean)을 가져오게 됩니다.

AOP

관점지향프로그래밍(Aspect Oriented Programming)이라는 것은 처음 접했을때는 매우 이해하기 난해한 개념이었습니다. 물론 지금도 제가 완벽히 이해하고 있는지도 모를 실정이지만, Spring에 적용시켜 보면 무언이구나 하는 생각이 들긴 하는군요.

사용자 삽입 이미지기존의 OOP는 객체간 위와 같은 느낌으로 얽혀 있습니다. 각종 include혹은 import를 사용하여 조립한다는 개념으로 서로 연결되죠. 이는 컴파일 순서에서 서로 얽히게 되며 강한 결합을 통해 서로 강하게 묶여있습니다. 그렇기 때문에 객체들의 추가/제거/교체/수정 등을 할 시에 많은 것을 고려해야 합니다. 위의 그림에서는 오른쪽 녹색 유틸리티 객체들의 내용이 수정, 추가되었거나 기능이 변경되었다면 그것을 사용하는 모든 왼쪽의 파란 메인 객체들의 소스또한 수정될지도 모릅니다.
사용자 삽입 이미지하지만 위의 그림의 느낌은 어떤가요? 유틸리티 객체들은 메인 객체의 배경이 되며 얼마든지 수정/교체가 가능합니다. 하지만 그때에 메인 객체들의 소스는 수정되지 않습니다.  이것이 관점지향프로그래밍의 개념입니다. 예제를 통해 어떻게 구현하는 것인지 알아보도록 하겠습니다.

using System;
using System.Collections.Generic;
using System.Text;
using AopAlliance.Intercept;

namespace HelloAop
{
    class ConsoleLoggingAroundAdvice : IMethodInterceptor {
        public object Invoke(IMethodInvocation invocation) {
            Console.WriteLine("수행전...");
            object retVal = invocation.Proceed();
            Console.WriteLine("수행후...");
            return retVal;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace HelloAop
{
    class ServiceCommand : ICommand
    {
        public object Execute(object arg)
        {
            Console.WriteLine("\n명령 수행 : {0}", arg);
            return null;
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Text;
using Spring.Aop.Framework;

namespace HelloAop
{
    class Program
    {
        static void Main(string[] args) {
            ProxyFactory factory = 
                new ProxyFactory(new ServiceCommand());
            factory.AddAdvice(new ConsoleLoggingAroundAdvice());
            ICommand command = (ICommand)factory.GetProxy();
            command.Execute("이것은 인자입니다.");
        }
    }
}

ProxyFactory를 이용하여 ServiceCommand를 프록시로 선언합니다. 그후에는 AddAdvice를 이용하여 미리 만들어둔 어드바디스를 추가합니다. 이후에 프록시를 생성하여 명령을 실행하면 “수행전… → 명령수행 : 이것은 인자입니다 → 수행후“가 출력됩니다.

입력되는 인자나 반환된 결과값을 검사하거나 다른 루틴을 얼마든지 추가할 수 있습니다.  위의 과정을 통해 실제로 ServiceCommand 객체의 소스에는 손대지 않고 기능을 추가, 변경 할 수 있게 되었습니다.

사용자 삽입 이미지

위의 그림과 같이 실제로는 별개의 객체들을 프록시로 한데 묶은 다음에 프록시가 메서드 실행 요청을 대리 수령하고 어드바이스를 참고하여 실체 명령을 수행하게 됩니다.

Spring .NET을 도입할 시 얻을 수 있는 장점

  • 중급 이상의 프로젝트 수행 시 각각의 프로그래머 간 개발 스타일이 통일 될 수 있다.
  • 신입 개발자의 교육과정을 줄이고 Spring .NET을 할 줄 아는 개발자를 뽑아 바로 실무에 투입할 수 있다.
  • 각각의 모듈/컴포넌트별로 종속성이 제거 되므로 업그레이드, 추가, 제거가 용이하다.

[WOC] 내가 참여하고 싶은 프로젝트 Coord+Lucene을 이용한 분산 색인/검색 시스템

NC소프트 산하 항상 새로운 웹서비스를 만드는 오픈마루 스튜디오에서 매년 하는 Winter of Code라는 행사가 있다.

항상 참여하고 싶지만 하는 시작해 놓은 일이 많아 참여하기엔 무리가 있어왔다. 아니나 다를까 올해도 지금 내 앞가림 하기도 힘든 상태라 참여하기엔 무리가 있어 보인다.

성격상 미친듯이 못할꺼 같으면 참여 자체가 남들에게 피해를 주는 것이라 생각되기에… 내년에는 꼭 참여해서 좋은 결과 내보도록 해야겠다!!

이번에 새롭게 추가된 프로젝트를 보니 학생을 위한 여러가지 프로젝트들이 많이 나왔다는 것을 알 수 있었다.

학교에서 쉽게 접할 수 없는 그런 내용 들이니 매우 유익하리라 생각한다. 근데 나의 눈길을 끄는 엄청난 프로젝트가 있었으니 그 이름하여.

오픈소스 Coord와 Lucene을 이용한 대용량 데이터를 위한 고성능 분산 색인/검색 시스템 개발-김우현

라고 한다. 김우현 님은 NHN에서 분산 시스템을 개발/운영 하시는 분이신거 같다.

언제 기회가 되면 꼭 찾아뵙고 인사를 드리고 싶다. 사실 예전부터 관심이 있던 분야라 혼자 루씬을 돌려보고 하긴 했었는데 보통 Lucene + Hadoop을 이야기를 많이 하는데 NHN에서 독자적으로 사용하는 Coord라니 무엇인지 관심도 가고 궁금하기도 하였다.

프로젝트의 내용은 다음과 같다.
사용자 삽입 이미지

분산 색인 시스템 및 검색 시스템을 개발하는 것도 모잘라 랭킹 알고리즘과 같은 실전에 쓰일법한 내용까지 다룬다고 한다.

괜히 나까지 긴장되는 순간이다. 저런것을 공짜로 배울 수 있다니 이 얼마나 아름다운 기회일까..

제약 및 요구사항에 특이한점이 있다. C++을 떡 주무르듯 다루는 학생?

C++을 떡주무르듯이 다룬다는건 어떤것을 말하는 것일까? 개발은 그래도 자신 있는 편이지만 C++로 떡을 주물러야 한다니~!

옵션으로 자바를 요구하는것을 보니, 아마도 Coord를 이용한 시스템은 C언어 기반으로 구축하고 그걸 끌어다 쓰는 응용 어플리케이션단은 JAVA(JSP)로 만들것인 모양이다.

이쯤 되면 이것을 한번쯤 실행해 보는 것이 예의이리라. 소스코드는 [이곳]에서 다운 받는다.

현재 0.1.2 소스버젼을 다운 받았다. 서버에 coord 폴더를 만들고 소스의 압축을 풀어놨다고 가정하고 시작해 보겠다.

gsoap을 설치해야 하는데 위키에 보면 최신 버젼을 다운받아 설치하는 과정이 나와있는데 실제로 압축을 풀어보니 이미 소스가 존재해 있었다. 바로 컴파일만 하자
[code]# cd xlib/gsoap/
# ./configure –prefix=`pwd`
# make
# make install[/code]

이렇게 되면 현재 디렉토리에 바로 설치가 되게 된다. 다음은 coord 설치를 진행하자.

etc/profile.mk 파일을 열어 WN항목을 coord 소스 압축을 풀어놓은 절대 경로로 넣어주자.
[code]# vi etc/profile.mk[/code]

설정을 하자. 대충 봐서 잘은 모르겠지만 컴파일에 필요한 각종 링크를 생성하는것 같다.
[code]# cd sbin/
# ./config.sh[/code]

이제 컴파일을 하자. libmagic이 필요하다고 한다. 컴파일이 잘 되는거 보니 있는 모양이다..-_-a
[code]# cd src/
# make[/code]

conf 디렉토리 안에 coord.conf, master.conf, worker.conf 세가지 설정 파일이 있다. 신경 쓰지 말고 실행해 보기로 했다.
[code]# ./bin/coord -c ./conf/master.conf
===================================================
coord v.1 : coord cluster master


# available services
cube.service.discovery
===================================================[/code]

마스터모드로 실행되었다. cube.service.discovery서비스가 사용가능하다는 것도 알았다.

혹여나 실행이 안된다면 LD_LIBRARY_PATH를 정해주자.
[code]# export LD_LIBRARY_PATH=<coord/lib경로>[/code]

example 안에 각종 예제가 들어있는데 실제로 보니 컴파일이 안되어있었다.

Makefile을 열어 include 항목의 경로를 수정해 주니 컴파일 되긴 한다. 개발자님 목적은 이게 아닐텐데…
[code]include ../etc/profile.mk[/code]
[code]# make
g++ -c client_server_test.cpp -I/home/eye/coord/include
g++ -o client_server_test client_server_test.o -L/home/eye/coord/lib -lcoord -lwooh -lpthread -lmagic -lz -ldl
g++ -c master_worker_test.cpp -I/home/eye/coord/include
g++ -o master_worker_test master_worker_test.o -L/home/eye/coord/lib -lcoord -lwooh -lpthread -lmagic -lz -ldl
g++ -c scatter_gather_test.cpp -I/home/eye/coord/include
g++ -o scatter_gather_test scatter_gather_test.o -L/home/eye/coord/lib -lcoord -lwooh -lpthread -lmagic -lz -ldl[/code]

컴파일은 되었지만 실제로는 실행이 되지 않았다. 그냥 쭉 컴파일 해서 실행하면 예제들은 왠지 실행될꺼 같았는데 그건 아닌 모양이다.

오늘은 일단 여기서 마치고 좀더 공부해본 뒤에 다음 포스팅에서 예제를 실행하는데 도전해 보도록 하겠다.

이런 매력적인 프로젝트를 잘 모르는 학생들에게 이끌어주시며 진행해 주실 김우현님께 미리 감사 드립니다.