MicrosoftVisual Studio for Yukon Version C# 언어로 여러 가지 개발 및 산업 언어의 다양한 기능을 통합 하려는 계획을 세우고 있습니다. 이 계획의 일부로 개발자의 생산성을 향상시켜 주는 실용적인 언어 구문으로 Generics, Iterator, Anonymous, Partial 등의 기능이 포함 되었습니다.

 

여기서 간단히 다룰 자료형은 Generics입니다. Generic을 우리말로 일반적, 포괄적이다 라고 번역할 수 있습니다. 우리는 앞에서 자료형은 값 형식(Value Type)과 참조 형식(Reference Type)으로 구분 되어지고, 값 형식(Value Type) Stack에 참조 형식(Reference Type) Heap에 저장된다고 배웠습니다. 그러나 이 두 가지 자료형을 모두 고려한 메소드를 만들고자 하면 System.Object 형으로 변환하여 저장하고, 다시 값 형식(Value Type)이나 참조 형식(Reference Type)으로 변환하여 사용해야 하는 불편함 및 많은 문제점을 야기 시켰습니다.

이를 대체하기 위해 미리 Type을 지정하지 않고 실제 자료형이 저장되는 시점에 자료형이 결정 되어지는 일반적인 자료형을 지원하기 위해 Generics 자료형이 추가된 것입니다.

 

1. Generics의 필요성 제시(System.Object 사용에 따른 문제 정의)

 

예를 들어 범용 Stack 데이터 구조를 개발한다고 가정해봅시다. Stack의 지원 메서드로는 Pop() Push() 메서드가 있습니다. 이를 사용하여 다양한 형식의 인스턴스를 저장할 수 있습니다. , Stack에 사용되는 내부 데이터 형식은 무정형 개체이며, stack 메서드는 개체와 상호 작용합니다.

 

.Net 기반 형식으로 기본 제공되는 개체 기반 stack을 사용하여 모든 형식의 항목을 보관할 수 있습니다. 그러나 개체 기반 솔루션에서 다음과 같은 문제점이 있습니다.

public class Stack

{

readonly int m_Size;

   int m_StackPointer = 0;

   object[] m_Items;

 

public Stack():this(100)

   {}

 

   public Stack(int size)

   {

      m_Size = size;

      m_Items = new object[m_Size];

   }

 

   public void Push(object item)

   {

if(m_StackPointer >= m_Size)

         throw new StackOverflowException();      

      m_Items[m_StackPointer] = item;

      m_StackPointer++;

}

 

   public object Pop()

   {

m_StackPointer--;

      if(m_StackPointer >= 0)

         return m_Items[m_StackPointer];

      else

      {

         m_StackPointer = 0;

         throw new InvalidOperationException("스택이 비워 있어 Pop할 자료가 없습니다.");

      }

}

}

 

Stack vstack = new Stack();

vstack.Push(1);

int number = (int) vstack.Pop();

 

Stack rstack = new Stack();

rstack.Push(new Customer());

Customer c = (Customer) rstack.Pop();

 

<문제점 제시>

1) 성능에 문제가 있습니다.

값 형식(Value Type)을 사용할 경우 값을 넣으려면(Push) 박싱(Boxing) 처리하고, 받아 내려면(Pop) 언박싱(UnBoxing) 처리를 해야 하는데 그 자체만으로도 성능이 크게 저하되며, 의 부담도 늘어 나므로 성능이 좋지 않습니다.

참조 형식(Reference Type)을 사용하는 경우에도 개체에서 상호 작용하고 있는 실제 형식으로 형 변환 해야 하고 형 변환에 따른 추가 작업이 필요하므로 성능이 여전히 저하됩니다.

Stack vstack = new Stack();

vstack.Push(1);

int number = (int) vstack.Pop();

 

2) 형식의 안전성에 문제가 있습니다.

컴파일러(Compiler)에서는 모든 내용을 Object 타입으로 형 변환 하거나, Object 타입에서 다른 타입으로 형 변환할 수 있으므로 컴파일(Compile)시 형식의 안전성이 떨어 집니다.

타입별로 안전한 스택을 만들어 박싱 및 형 변환에 따른 성능 저하 및 컴파일(Compile)시 잘못된 형 변환에 따른 형식의 안전성 문제를 해결할 수 있을 것입니다. 하지만, 이에 못지 않은 문제점이 발생 합니다.

Stack rstack = new Stack();

rstack.Push(new Customer());

Customer c = (Customer) rstack.Pop();

 

3) 작업 생산성이 낮아지는 상황이 발생합니다.

타입별 데이터 구조를 작성하는 작업은 더디고, 반복적이며 오류가 발생하기 쉽습니다. 데이터 구조에서 결함을 수정할 경우 동일한 데이터 구조를 타입별로 중복 항목이 있는 곳마다 결함을 해결해야 합니다. 또한 알 수 없거나 아직 정의되지 않은 미래의 형식이 사용될지도 모르므로 개체 기반 데이터 구조도 유지해야 합니다.

public class Stack

{

   int[] m_Items;

   public void Push(int item)

   {...}

   public int Pop()

   {...}

}

 

2. Generics의 정의

 

C# Generics는 새로운 주요 개발 방법으로서 적절하고 읽기 쉬운 구분을 사용하여 성능, 형식 안정성 및 품질을 향상 시키고, 반복적인 프로그래밍 작업을 줄이, 전체 프로그래밍 모델을 단순화 하는 새롭게 추가된 자료형입니다. IL(Intermediate Language) CLR(Common Language Runtime) 자체에서 기본적으로 지원하며, generic Class 코드를 컴파일하면 다른 모든 형식과 마찬 가지로 IL로 컴파일합니다. , IL에는 실제 특정 형식의 매개 변수나 자리 표시자만 들어 있습니다. 또한 Generic Class의 메타 데이터에는 Generic 정보만 들어 있습니다. 다음은 C# Generics에 대해 쉽게 표현하고 있습니다.

 



3. Generics
의 구현 (적용)

 

IL(Intermediate Language) CLR(Common Language Runtime)에서 generics를 기본적으로 지원하므로 CLS(Common Language Specification) 규약 및 CTS(Common Data System) 데이터 형식이 적용된 대부분의 CLR 호환 언어는 generic 형식을 활용할 수 있습니다. 다음은 앞에서 개체 기반 stack Generics를 적용하여 C#으로 구현해 보겠습니다.

 

public class Stack<T>

{

   readonly int m_Size;

   int m_StackPointer = 0;

   T[] m_Items;

 

   public Stack():this(100)

   {}

 

   public Stack(int size)

   {

      m_Size = size;

      m_Items = new T[m_Size];

   }

 

   public void Push(T item)

   {

      if(m_StackPointer >= m_Size)

         throw new StackOverflowException();

      m_Items[m_StackPointer] = item;

      m_StackPointer++;

   }

 

   public T Pop()

   {

      m_StackPointer--;

      if(m_StackPointer >= 0)

      {

         return m_Items[m_StackPointer];

      }

      else

      {

         m_StackPointer = 0;

         throw new InvalidOperationException("스택이 비워 있어 Pop할 자료가 없습니다.");

      }

   }

}

 

Stack<int> vstack = new Stack<int>();

vstack.Push(1);

int number = vstack.Pop();

 

Stack<Customer> rstack = new Stack<Customer>();

rstack.Push(new Customer());

Customer c = rstack.Pop();

 

Stack 클래스 선언 시 클래스명 뒤에 꺾쇠 괄호 안에 Generic 형식 매개 변수를 지정하여 Stack Generic 클래스 선언합니다.

public class Stack<T>

 

Object 간에 데이터 변환하는 대신 Generic 클래스의 Instance는 해당 Instance가 만들어진 데이터 형식을 받아 들이며, 해당 형식의 데이터를 변환 없이 저장합니다. Generic 형식 매개 변수 T는 지정된 실제 형식이 사용될 때까지 자리 표시자 역할을 합니다. T는 내부 항목 배열의 요소 형식(T[] m_Items;)으로, Push 메서드에 대한 매개 변수 형식(public void Push(T item))으로, Pop 메서드에 대한 반환 형식(public T Pop())으로 사용됩니다.

 

Generic Class Instance 생성시 꺾쇠 괄호 표기법을 사용하여 기본 정수 형식을 매개 변수로 지정하여 Stack Class에서 정수 형식을 사용하도록 합니다.

Stack<int> vstack = new Stack<int>();

vstack.Push(1);

int number = vstack.Pop();

 

Customer Class(Reference Type)를 매개 변수로 지정하여 Stack Class에서 Customer Class 형식을 사용하도록 합니다.

Stack<Customer> rstack = new Stack<Customer>();

rstack.Push(new Customer());

Customer c = rstack.Pop();

 

Generic 형식 매개 변수는 형식의 기본값을 반환하는 default라는 속성을 지원합니다.

Stack Pop() 메서드를 다음과 같이 수정하여 Exception으로 처리하지 않고 default 값을 Return하도록 합니다(참조 형식(Reference Type)의 기본값은 null이고, 정수 또는 열거 및 구조체와 같은 값 형식(Value Type)일 경우 기본값은 0입니다).

public T Pop()

{

      m_StackPointer--;

      if(m_StackPointer >= 0)

      {

         return m_Items[m_StackPointer];

      }

      else

      {

         m_StackPointer = 0;

         return T.default;

         //throw new InvalidOperationException("스택이 비워 있어 Pop할 자료가 없습니다.");

      }

}

 

위와 같이 클래스에서 Generics을 사용했듯이 구조체에서도 Generics을 사용할 수 있습니다. 예제를 통해 유용한 Generic point 구조체를 만들어 봅시다.

 

001 using System;

002 using System.Collections.Generic;

003 using System.Text;

004

005 namespace DataGenericsType

006 {

007  public struct Point<T>

008  {

009    public T X;

010    public T Y;

011  }

012

013  class Program

014  {

015    static void Main(string[] args)

016    {

017         // 일반정수좌표

018         Point<int> intPoint;

019         intPoint.X = 1;

020         intPoint.Y = 2;

021         Console.WriteLine("정수형 Point 좌표: X({0}), Y좌표({1})", intPoint.X, intPoint.Y);

022         Console.WriteLine("");

023

024          // 부동소수점 정밀도가 필요한 차트좌표

025          Point<double> doublePoint;

026          doublePoint.X = 1.2;

027          doublePoint.Y = 3.4;

028          Console.WriteLine("부동 소수점 Point 좌표: X({0}), Y좌표({1})", doublePoint.X, doublePoint.Y);

029          Console.WriteLine("");

030    }

031  }

032 }

 

[Generics형 변수 실행결과]



 

4. C# Generics와 다른 언어에서 지원되는 Generics의 차이점

 

C++ Template (Generics 지원)

 

C++에서는 Template라는 형태로 Generics를 제공해 왔습니다. 패턴적인 측면에서는 C# Generics와 크게 다르지 않으나, 결정적인 차이가 있다면 C#에서는 CLR이 지원한다는 것입니다. 일종의 매크로(템플릿에 제공된 각 형식 매개 변수에 대한 특수화된 형식을 생성)일 뿐인 C++ Template과는 달리 Generics Runtime시에 JIT 컴파일러에 의해 적절히 해석되고 Native Code로 컴파일된다는 것입니다.
C++
와 같은 후기 바인딩 방식에서는 단지 클래스 또는 인터페이스의 상속을 통한 바인딩이었기에 Logic의 확장이 어려웠고, 형식의 안정성에서의 문제점도 꼼꼼히 따져야만 했습니다. 적어도 전달되는 클래스는 같은 클래스에서 상속을 받거나 같은 인터페이스를 구현해야 했습니다. 물론, C
OM IUnknown 같이 자기기술자[Self-Descriptor]를 가진 클래스/인터페이스를 만들면 해결할 수 있겠지만 그 노력은 만만치 않습니다. C# Generics를 적용하면 LogicLogic에 의해 다뤄지는 객체를 명확하게 구분할 수 있습니다.

 

결국 Domain/Business Logic을 구현이라는 점에서는 크게 다를 바가 없지만 그 유연성에 있어서는 상당히 선택의 폭이 넓어졌다고 할 수 있다.

 

JAVA Generics (Parametric polymorphism)

Java Generics Pizza라는 프로젝트로부터 시작되었으며, 이후 GJ라고 이름이 붙여졌고, JSR로 바뀐 것입니다. Sun Java Virtual Machine을 수정할 필요가 없는 구현을 선택했습니다. 따라서 Sun은 수정되지 않은 가상 시스템에서 generics를 구현함으로 해서 많은 단점들을 가지게 되었습니다.

 

Java Generics는 어떤 실행 능률도 높여 주지 못합니다. Java Compiler List<Integer>라는 Parameterized Type을 만들면 Integer Object로 모두 변환하고 필요한 곳에 (Integer) 형 변환을 실행합니다. 이는 수정되지 Java Virtual Machine이 값 형식(Value Type)에 대해 Generics를 지원하지 못하기 때문입니다. 따라서 Java Generics에서는 실행 효율성을 얻을 수 없습니다.

 

Java Generics erasure of the type parameter(매개변수 타입의 말소)라는 것에 의존하기 때문에 Runtime시에 List<Integer> List라는 클래스와 동일한 클래스로 표현됩니다. 이것은 어떤 클래스가 List<Integer>인지 List<String>인지 Runtime시에는 알 수 없다는 것입니다. 이는 Runtime시에 Generics 형식의 Instance에 대한 형식 매개 변수를 확인할 수 방법이 없으며 다른 리플렉션(Reflection) 사용이 엄격하게 제한된다는 의미입니다.

Posted by Sting!
,
ASP.NET 마스터하기 #3 - ASP.NET의 아키텍처

필자의 잡담~

잡담이 없어서... ^^; 안재우님의 블로그는 http://blog.naver.com/saltynut 입니다

지난 시간에 우리는 ASP.NET의 설치에 대해서 알아봤습니다. 여러분들 중에는 이미 이전에 ASP.NET을 설치해두신 분들도 계실 것이고, 행여나 제 글을 읽고 무작정 설치하신 분들도 계실 겁니다.

자, 그럼 일단 우리가 생각해봐야 질문은...

"ASP.NET이 대체 뭘까요?"

"내가 ASP.NET을 설치한 이유는 뭘까요? 어디다 써 먹으려고 설치하셨습니까?"

어떤 개발자들은 자신이 설치하는 녀석이 뭔지도 모르고 일단 설치부터 하고 보는 사람들이 많습니다. 왜? 남들이 다 하니깐. 좋은 거라고 하니깐. 새로 나온 거라고 하니깐.

ASP.NET 아키텍처 가르쳐 준다면서 왜 이런 질문을 하냐구요? 성격이랑 정체도 모르면서 얘가 왜 이런 아키텍처로 만들어 졌는지를 이해할 수 있겠습니까?

ASP.NET을 한 줄로 정의하자면, ‘.NET 프레임워크를 기반으로 한 웹 애플리케이션 개발 모델, 프레임워크, 관련 기술을 총칭해서 부르는 것’이라고 하겠습니다. MSDN의 정의로는 ‘엔터프라이즈 수준의 웹 응용프로그램을 최소한의 코딩으로 구축하는데 필요한 서비스를 포함하는 통합 웹 개발 모델’이라고 합니다.

이 정의는 간단한 내용이지만, 상당히 중요한 사항을 담고 있습니다.

첫째, ASP.NET은 .NET 프레임워크를 기반으로 한다는 점입니다. 따라서 .NET에서 제공하는 클래스 라이브러리를 사용할 수 있으며, 프로그래밍 언어로는 .NET이 제공하는 모든 언어를 사용할 수 있고, .NET 프레임워크 기반의 애플리케이션에 적용되는 모든 요소들이 ASP.NET에도 적용된다는 것입니다. 그 얘기는 .NET에 대해서 잘 알지 못하면서 ASP.NET을 잘 안다는 것은 불가능하다는 의미도 됩니다.

둘째, ASP.NET은 웹 애플리케이션을 만들기 위한 것이라는 점입니다. 따라서 일반적인 웹 애플리케이션의 특성을 그대로 가지며, 웹 애플리케이션이 수행 가능한 범위 내에서만 능력을 발휘할 수 있다는 점입니다.

셋째, ASP.NET은 ‘엔터프라이즈 수준’의 애플리케이션을 맞추는데 가장 큰 초점을 맞추고 있다는 점입니다. 따라서 간단한 애플리케이션 등을 만드는데는 최적의 개발 모델이 아닐 수도 있다는 점을 염두에 두어야 하며, 엔터프라이즈 애플리케이션을 개발할 때 고려해야 할 사항들에 대해서도 알 필요가 있다는 점입니다.

이 세가지가 별거 아닌 거 같지만, 이후에 ASP.NET을 이해하면서 이 3가지 사항을 잘 염두에 두고 있느냐 아니냐에 따라서 많은 차이가 나게 됩니다.

절대 변하지 않는 진리, 웹의 동작방식

두 번째 항목, ASP.NET이 웹 애플리케이션이라는 것은 ASP.NET이 웹이라는 한계를 벗어나지는 못한다는 것은 이미 강조된 사실입니다. 마찬가지로 웹의 동작방식은 적어도 당분간은 절대 변하지 않을 특성들을 다음과 같이 가지고 있습니다.

  • Request(요청) & Response(응답)의 구조를 취한다.
  • 기본적으로 전송 시에 HTTP 프로토콜을 사용한다.
        HTTP 프로토콜은 기본적으로 상태를 가지지 않는다(Stateless).
  • Request를 보내고, Response를 처리하는 웹 클라이언트가 있어야 한다.
  • Request를 처리하고, Response를 보내는 웹 서버가 있어야 한다.
  • 기본적으로 Request에는 Get 방식과 Post 방식이 존재한다.
  • 기본적으로 Response의 최종 형태는 정적 HTML이다.

    위의 내용을 포함해서 보다 순차적으로 이 내용을 도식화하면 다음과 같습니다.

    뻔한 내용입니다만, 위 그림 내에 지금까지의 웹 기술들이 발전해오면서 이루고자 했던 목표들이 다 존재합니다. 예를 몇 가지 들어볼까요? 대용량 바이너리 데이터를 전송하기 위해 HTTP 업로드 컴포넌트가 나왔고 HTTP 이어받기 기능이 등장합니다. 주고 받는 프로토콜의 전송 수준에서의 보안(Transport Level Security)을 위해 SSL(Secured Socket Layer)가 등장합니다. 최대한 많은 요청을, 가장 빨리 처리하기 위해 웹 서버 기술이 발전합니다. 요청에 따라 동적으로 응답을 생성해 내기 위해 웹 서버 애플리케이션 기술(CGI, ISAPI, ASP, ASP.NET, PHP 등)이 나왔습니다. 정적 컨텐츠인 HTML에 동적인 측면과 상호작용성(Interactivity), 재사용성을 부여하기 위해 DHTML, JavaScript, CSS, ActiveX, 애플릿 등이 나오게 됩니다. 효율적으로 요청을 처리하고, 응답 속도를 보다 빠르게 하고, 응답 결과를 렌더링 해서 보여주기 위해 브라우저 기술이 발전합니다. 전세계는 저 그림 속의 내용을 보다 효율적으로 개선하기 위해 그 오랜 시간을 투자한 셈입니다.

    그럼 위 그림에서 ASP.NET에 해당하는 부분은 어디일까요? (이거에 대한 답이 아직도 안 떠오르신다면 별로 이 글을 성의 있게 읽지 않으셨거나, 관심이 없으시거나, 빨리 이 길을 접고 리니지 게임머니 작업장을 차리시는게 개인과 사회를 위한 도움이 되실지도…)

    위 그림처럼 웹 서버 단의 영역입니다. 다시 한번 정리하자면 요청을 받아서 응답을 만들어내는 역할을 하는 부분입니다. 이미 잘 아실 역사적인 얘기를 간단히 해보자면, 초기의 웹 서버는 HTML(*.htm, *.html), 그림파일(.gif, .jpg)와 같은 정적 컨텐츠에 대한 요청을 받아서 이를 그대로 전달할 뿐이었습니다. 초기의 웹은 FTP나 Gopher와 같이 뭔가 ‘통신’을 한다는 의미보다는 단순히 ‘전송’을 한다는 의미가 강했습니다. 웹이 진화되면서 정적 컨텐츠가 아닌 동적 컨텐츠를 전달할 방법이 없을까를 궁리하게 되었고, 동적 요청을 위한 매개변수를 어떻게 전달할 것인가와 이를 받아서 어떻게 처리해야 하는가라는 문제가 대두되게 됩니다.

    매개변수의 전달은 웹 프로그래밍을 해봤으면 들어봤음직한 Get 방식과 Post 방식이 존재합니다. Get 방식은 URL 뒤에 ? 이후에 키-값 쌍으로 이루어진 Query String을 붙여서 매개변수를 전달하는 방법입니다. 이에 비해 Post 방식은

    태그를 사용하며, 키-값 쌍을 HTTP 헤더 내에 집어넣어서 전달하는 방법입니다.

    정적 컨텐츠에 대한 요청과 동적 컨텐츠에 대한 요청을 구분하기 위해 편의상 동적 컨텐츠를 구분하기 위한 확장자를 사용하게 됩니다. 즉, .html이나 .htm 대신에 .cgi, .asp, .php, .jsp, .aspx 등을 사용하게 된 것입니다. 이렇게 동적 컨텐츠로 구분되는 확장자로 요청이 들어올 경우, 웹 서버는 이를 가로채서 동적 컨텐츠 처리 모듈에 던져주게 됩니다.

    동적 컨텐츠를 처리하는 모듈, 즉 웹 애플리케이션은 최초에는 CGI 형태가 사용되었지만, 시간이 흐름에 따라 ISAPI 방식과 Script 기반 방식 등으로 진화되어 나갔습니다. 현재 우리가 사용하고 있는 대부분의 방식은 Script 기반 방식으로 보면 되겠습니다. ASP.NET 역시 여기에 속한다고 보면 되겠습니다. (사실 이런 얘기들은 옛날 ASP 책들을 보면 서두에 자세하게 잘 설명되어 있습니다.)

    그런데, CGI -> ISAPI -> Script 기반 방식 등으로 변경되어 온 이유는 무엇일까요?

    우선 첫째는 복잡한 것에서 간단한 것으로의 이동입니다. 간혹 예외도 있긴 하지만, 모든 IT 기술은 복잡한 것이 간단해질 때 성공하는 경우가 많습니다. 물론 복잡도의 감소와 해당 기술 보유자의 월급은 반비례합니다만.. ^^ CGI 시절까지만 해도 일단 C나 C++를 알아야 하는 것은 기본이었습니다. 이 당시 유명했던 게시판 중에 CrazyBoard가 있었던 걸로 기억하는데 게시판 소스의 양도 엄청난데다 분석하려면 상당한 시간을 투자해야 했습니다. 현재 우리가 쓰고 있는 ASP 게시판 소스는 그 시절과는 비교할 수 없을 정도로 분량도 적은데다 이해하기 쉽습니다. 게시판 소스만 있으면 초등학생도 직접 게시판을 올릴 수 있을 정도이니까요.

    둘째로 보다 적은 리소스를 소모하면서 보다 많은 요청에 대응해야 한다는 목적을 달성하기 위한 것입니다. 해묵은 얘기입니다만, CGI 시절에는 요청당 하나씩의 프로세스가 만들어져서 사용자 수가 적을 때는 괜찮지만 사용자 수가 늘어날 경우 엄청난 리소스 소모와 함께 성능이 떨어지기 시작했습니다. ISAPI 방식은 이를 보완하여, 요청 수와 관계없이 프로세스는 하나만 만들고, 처리모듈은 DLL 형태로 만드는 것이라고 생각하면 이해가 쉬울 겁니다. ASP의 예를 들면, asp.dll이 .asp 확장자에 대해 처리하는 ISAPI 모듈입니다.

    ASP.NET 역시 이러한 ISAPI 방식을 동일하게 사용합니다만 기존 ASP에서 발생되는 문제점을 해결하기 위해서 아키텍처가 변경되었습니다. 앗, 감이 오셨습니까? 지금까지의 글은 이번 글의 핵심내용을 유도하기 위한 설명이고, 우리가 알아봐야 할 건 대체 기존 ASP 아키텍처에서 어떤 문제가 있었고, ASP.NET의 아키텍처는 이를 극복하기 위해 어떤 형태를 취하고 있는 가입니다.

    ASP의 아키텍처와 문제점

    사실 ASP의 아키텍처에 대해 자세히 알고 싶다면 이 글이 아니라 다른 ASP 글이나 서적을 참고하십시오. 저는 어디까지나 간단하게 설명을 하도록 하겠습니다.

    ASP는 기본적으로 IIS 웹 서버 상에서 사용될 목적으로 만들어졌습니다. ASP가 처음 등장한 건 훨씬 이전이긴 하지만, 널리 사용된 것이 NT 4.0의 옵션팩에 탑재된 IIS 4.0부터 이니깐 이 때를 기준으로 설명을 하도록 하겠습니다.

    IIS 4.0 시절, ASP가 구동되는 기본 아키텍처는 다음과 같은 In-Process 모델입니다.

    inetinfo.exe는 System 계정으로 구동되는 IIS의 메인 프로세스입니다. 이 프로세스는 .asp 확장자에 대한 요청이 올 때 asp.dll을 자신의 프로세스 내에 로딩해서 요청을 처리하게 됩니다.

    In-Process 모델의 문제는 asp.dll 내에서 문제가 발생해서 asp.dll이 죽어버린 경우, 메인 프로세스인 inetinfo.exe마저 죽어버린다는 겁니다. 쉽게 말해서 무한루프를 도는 .asp 페이지가 있는 경우, 그 페이지 하나 때문에 웹 서버 전체가 먹통이 되어 버린다는 겁니다.

    Windows 2000과 Windows XP의 IIS 5.x에서는 이를 방지하기 위해 COM+ 서비스와 IIS를 결합하여 다음과 같은 옵션을 가지게 됩니다.

    IIS를 다뤄본 분이시라면 한번쯤은 본 적이 있을 겁니다만, 구체적으로 이게 뭐하는 건지 모르시는 분들도 많더군요. 우선 ‘낮음(IIS 프로세스)’은 IIS 4.0의 In Process 모드와 동일한 것입니다. 따라서 성능은 가장 좋지만, 안정성은 가장 떨어집니다.

    보통(풀링됨)과 높음(격리됨)은 웹 애플리케이션을 inetinfo.exe 내에서 구동하는게 아니라 별도의 프로세스(dllhost.exe)에서 구동하는 Out-of-Process 모델입니다. 둘 다 기본 개념은 유사하지만 약간의 차이점이 있는데, 먼저 ‘보통(풀링됨)’으로 지정된 웹 애플리케이션들은 하나의 dllhost.exe 내에서 풀링되어 동작하게 됩니다.

    쉽게 설명하면 inetinfo.exe가 아닌 별도의 dllhost.exe 안에서 In Process 모드처럼 동작한다고 보면 됩니다. 풀링된 애플리케이션들은 모두 단일한 dllhost.exe 내에서 동작됩니다.

    이와 관련하여 구성요소 서비스에서는 Out-of-Process Pooled Applications라는 COM+ 애플리케이션을 찾아볼 수 있습니다.

    풀링은 성능(리소스)과 안정성이라는 양쪽을 나름대로 절충한 것이라 볼 수 있습니다. 일단 inetinfo.exe와 dllhost.exe라는 두 개의 프로세스로 분리함으로써 안정성은 어느 정도 확보됩니다만, 역시 풀링되어 있는 애플리케이션이 죽었을 경우에는 같은 dllhost.exe 내의 다른 애플리케이션도 같이 죽는다는 단점이 있습니다.

    높음(격리됨)은 각 웹 애플리케이션을 별도의 dllhost.exe에서 동작시키는 방법입니다.

    완전히 격리를 시키는 것이기 때문에 안정성 측면에서는 가장 우수하겠지만, inetinfo.exe 입장에서는 n개의 dllhost.exe와 Out-Of-Process 통신을 해야 하며, n개의 dllhost.exe가 돌게 되므로 사용되는 리소스가 더 많아져서 성능이 다소 떨어지게 됩니다.

    IIS 5.x에서는 이러한 형태로 ASP 애플리케이션에 대해 나름대로의 안정성을 확보했습니다만, 역시 여기서도 제기되는 단점들은 존재합니다. dllhost.exe는 한번 구동되면 명시적으로 종료를 시켜주기 전까지는 계속해서 구동하게 됩니다. 물론 잘 동작한다면 상관이 없지만, 문제(데드락 상황과 같은)가 발생했을 때는 반드시 수동으로 재시작을 해줘야 한다는 단점이 존재합니다. 즉, 자신이 죽는다고 해서 웹 서버 전체나 다른 웹 애플리케이션에 영향을 미치는 건 해결했지만, 자기 자신이 죽었을 때 처리할 수 있는 방법이 모호하다는 것입니다. 또한 버그 등으로 인해 리소스의 누수가 발생하는 경우 애플리케이션을 재시작함으로써 리소스의 클린업을 할 수 있는데(시스템을 재부팅하는 걸 생각해보세요), 이러한 과정(통상 Recycling이라고 합니다)을 지원하지 않는다는 것입니다. 또한 dllhost.exe는 웹 애플리케이션만을 위한 전용이 아닌 COM+ 서버 활성화 모드(Out-of-Process)에서 사용되는 범용 호스팅 프로세스입니다. 그렇기 때문에 웹 애플리케이션을 위한 구성 정보를 설정해서 동작 특성을 변경하는 것을 지원하지 않는다는 것입니다.

    IIS에서 COM+ 애플리케이션을 구동할 때도 동일한 문제가 발생했습니다. 예전에는 VB 6.0이나 ATL로 비즈니스 로직 컴포넌트를 만들어서 COM+에 올려 구동하곤 했는데, COM+가 라이브러리 활성화(In Process)일 때는 컴포넌트가 죽을 경우 호스팅 프로세스인 IIS가 죽게 되므로, IIS 안정성을 위해 서버 활성화(Out-Of-Process)로 돌리는 경우가 많았습니다.

    웹 서버가 죽는다는 것이 얼마나 큰 문제인지는 다들 알고 계실 겁니다. 당연히 죽게 되면 서비스를 못하게 되니깐 문제가 되죠. 죽은 웹 서버를 살리려면 재시작을 하면 되는데, 재시작을 해도 해결이 되지 않는 문제도 역시 존재합니다. 대표적인 것으로 ASP 시절에는 상태 정보, 즉 세션을 IIS 프로세스 내에서 In Process 모드로 관리합니다. 즉 IIS를 재시작하게 되면 세션 정보가 날아가 버린다는 것입니다.

    IIS가 죽을 때 상태 정보가 손실되는 것도 문제지만, 웹 팜(Web Farm) 환경처럼 웹 서버를 여러 대 두고 로드밸런싱하는 경우 역시 문제가 됩니다. 이 경우 서버 간의 상태 정보를 어떻게 공유해야 할지 방법이 막연해집니다. 결국은 L4를 Dedicated 모드(Per Session)로 설정해서 세션을 고정시켜버리거나 상태 정보를 DB와 같은 제3의 저장소로 돌려서 우회해야 합니다. 전자는 로드밸런싱의 취지를 저하시키게 될테고, 후자는 이를 지원하기 위한 코드를 직접 다 작성해야 한다는 단점이 있습니다.

    ASP.NET의 아키텍처와 개선사항

    지금까지 진정한 이번 글의 주제를 위해 기나긴 여정을 왔습니다. 지금까지 언급된 문제점들을 극복하기 위해 ASP.NET은 다음과 같은 구조를 가지고 있습니다.

    지난 번 ASP.NET의 설치 시에 aspnet_isapi.dll이라는 ISAPI 처리기가 등록되는 것을 봤을 겁니다. 이 놈은 .aspx와 같이 ASP.NET 관련 확장자를 가로채서 실제로 처리하는 작업자 프로세스(Worker Process)인 aspnet_wp.exe에게 전달합니다.

    aspnet_wp.exe는 내부에 요청의 전후에 개입하기 위한 HttpModule과 개별 요청을 처리하기 위한 HttpHandler로 구성됩니다. HttpModule이나 HttpHandler는 기본으로 제공되는 것 외에 사용자가 정의해서 확장하는 것이 가능합니다. aspnet_wp.exe 내에서 실제로 일어나는 일들은 다음 번에 좀 더 자세하게 알아 보도록 하겠습니다. 일단 여기서는 aspnet_wp.exe가 실제 요청을 처리해서 응답을 만들어내는 녀석이라고만 생각해 둡시다.

    일단 여기까지만 봤을 때, ASP.NET은 별도의 전용 프로세스인 aspnet_wp.exe에서 구동되므로 자신이 죽더라도 inetinfo.exe에는 영향을 미치지 않습니다. 따라서 이전 dllhost.exe에서 구동될 때처럼 안정성 측면에서는 확보가 된 셈이죠. aspnet_isapi.dll은 실행 중인 aspnet_wp.exe가 없을 때는 바로 이 프로세스를 다시 실행하며, 구성정보에 따라서 aspnet_wp.exe의 동작을 제어할 수도 있습니다. 이전 글에서 machine.config의 내용을 보면 이를 제어하기 위한 내용들이 존재합니다. 예를 들어 timeout을 지정해서 일정시간 동안 요청이 없으면 종료시켜버릴 수도 있고, 일정시간 이상 데드락이 걸렸을 때는 재시작하는 기능도 존재합니다. 다양한 구성정보에 따라서 동작 특성을 제어하는 것 역시 가능해졌다는 의미입니다.

    위 그림의 우측에 보면 aspnet_state.exe라는 프로세스가 있습니다. ASP.NET 역시 기본적으로는 세션을 In Process 모드로 관리하지만, 설정에 따라서 그림과 같이 세션을 별도의 프로세스(aspnet_state.exe)에서 관리할 수 있습니다. 따라서 aspnet_wp.exe가 죽는다고 하더라도 세션 정보 자체는 여전히 살아있게 되는 거죠. 상태 정보 관리에 대한 자세한 내용 역시 다음에 다루도록 하겠습니다.

    이리하여 대략 ASP.NET의 아키텍처가 왜, 무엇을 개선하기 위해 어떻게 구성되었는지에 대해 다뤄보았습니다. 사실 몇 가지 빠진 부분도 있긴 한데 여기에서 설명해야 할지 다음 글에서 설명해야 할지 약간 애매한데다, 너무 글이 길어지는 것 같아서 다음으로 넘기도록 하겠습니다.


  • authored by Lancers (안재우)


    Posted by Sting!
    ,
     

    Interface 좀만 더 생각해보자.

     

     

    개인적인 사견에 조금 과장을 곁들인다면 Interface가 OOP언어에서 가장 핵심적인 내용이 아닐까한다.

    Interface의 이해정도에 따라 초급/중급 개발자로 나누어도 될듯하다.

     

    특히나 J2EE쪽에서는 Interface를 알고있던 모르던 간에 필수적으로 사용되고 있다.

    (당연히 알고 있을거라 생각합니다. 아 왠지 무시하는듯한 말투..그런 뜻 아닌거 아시죠..^^?)

    J2EE기술중에 Interface를 쓰지않고 돌아가는것이 있을까?(본인의 얕은 지식으로는 없다고 생각합니다.)

     

    /*

    아이러니 하게도 필자는 C++ 프로젝트만 하고있는데도 설명은 자바로 하고 있네요..

    뭔가 잘못된듯..솔직히 자바 잘 모릅니다..-.-;

    Interface의 설명하는데 있어 역시 자바만한게 없다는 생각입니다.

    Interface에 대해 논하기 가장 쉽습니다.(극히 개인적인 생각)

    C++ 던 Java던 OOP언어에서 Interface의 이론은 대동소이합니다. 언어적으로 표현만 좀 다를뿐

    */

     

    여기서 생각해 볼 것은 왜 껍데기 뿐인 Interface를 강조하는가!

    필자가 공부할때(학교다닐때..아!! 벌써 약 10년전...-_-;), 당시엔 Java에서 Interface를 그리 중요하게 생각지 않았다.

    물론 이러한 생각은 필자가 Interface를 제대로 이해하지 못했기 때문이었다.

     

    "이런 껍데기를 왜 쓰는거지."

    "왜 이런걸 써서 코드만 난잡하게..하는 거지.."

    그러한 생각들로 인해..그리 중요하게 생각지 않고 넘어갔다.

    그때는 단지 "음 언어적인 제약(반드시 구현해라)을 주기위해 그런것인 갑다"하고 넘어가곤했다.

    (여러분은 어떤가요...? 저는 그랬습니다..^^)

     

     

    Interface가 나온것은 여러 이유가 있겠지만...

    여기서는 한가지 단면만을 토로하고자한다.

     

    과거 C/S 기반에서는 클라이언트가 지금의 서버의 모든 기능을 가지고 있었다.

    서버쪽은 단지 DB(주로...파워빌더가 그랬죠..? 아직도 많이 씁니다. 주로 사내용으로 사원관리, 급여관리 등등).

    클라이언트가 직접 DB를 접속하였다.

     

     

    이에 대한 문제점이 적지 않았는데..

    일단 클라이언트가 모든 기능을 가지고 있는데서 문제가 있다라고 볼 수 있다.

     

    1. DB의 접속 계정을 가지고 있다.

      => 보안에 취약.(이거 머 맘만 먹으면..-.-)

    2. 모든 비지니스 로직을 가지고 있다.

      => 클라이언트의 비대화

      => 업데이트 비용이 많이 든다.

      => 비지니스 로직이 포함되어 있으므로 정책 변경에 유연하지 않다.

     

    특히나 보안이나 정책 변경은 머리가 쥐가날 정도로 머리를 아프게 했다.

     

    /*

    정책 변경으로 인해 배포된 모든 클라이언트를 업데이트 해주자면..만만한 작업이 아니었습니다..

    게다가 업데이트된 클라이언트, 아직 업데이트되지 않는 클라이언트를 모두 수용하자면..

    생각만해도...머리가 지끈...

    게다가 C/S가 유행하던 당시는 지금의 랜 환경과는 다르죠!!

    */

     

    이러한 이유들로 인해

    후에 나온 개념이 3-tier(지금은 환경이 다양해서 n-tier라는 말도 나오는데)라는것인데..

    이 개념과 더불어 Thin Client라는 용어가 한때 유행하였다.

    지금은 3-tier가 너무 당연스러운 것이라서 Thin Client용어는 근자에는 잘 쓰이지 않는 용어가 되어버린듯 하다.

    하지만 Thin Client는 늘 강조해도 지나치지 않는 용어라 생각한다.

    물론 프로젝트 성격에 따라 다르긴하겠지만(오해없으시길)..

     

    3-tier의 목적은

    서버쪽 정책(비지니스 로직)이 변경된다하여도 클라이언트는 정책에 영향(업데이트없이)받지않고 종전과 동일하게 사용가능하다.

    서버쪽 변경으로 인한 클라이언트 변경(업데이트)이 없는 이유는 다름 아닌 Interface만 가지고 있고 구현은 서버단이 책임지고 있기때문이다.

     

    예를 들어

    웹서버에서 웹 어플리케이션의 내용(비지니스 로직)이 변경되었다고 웹브라우저를 업데이트하지 않는것과 같은 것이다.

     

    현재에는 어플리케이션의 설계 패러다임이 바뀌었다.

    어플리케이션 웹화 되면서 자연스레 저러한 패러다임이 있는지 조차 느낄 수 없을 정도로 당연한듯 설계되지만...

    (웹프로젝트는 기본적으로 3-tier입니다. 일반 응용프로그램은 얘기가 다릅니다. 고려되어야겠지요..)

    어찌되었던 저러한 C/S 방법론 각광받던 시기가 있었고, 그리 오래전 얘기는 아니다.

     

    이렇듯 Interface의 개념(3-tier의 개념) 필요하게되는 시점에 오기에 이르렀는데..

    클라이언트는 Interface만, 서버(혹은 미들웨어라고도 부르는)는 비지니스 로직을..(*중요 별표)

    담당(?)하게 된 것이다.

     

    /*

    네트웍 환경을 예로 들었지만..작게는 로컬 환경에서도 마찬가지입니다.

    윈도우 어플리케이션 제작시.

    UI에서 모든 기능을 구현해 놓으면 나중에 버그 잡으려고 할때..

    UI 코드와 비지니스 로직과 겹쳐서 무진 애먹습니다.

    처음엔 누구나 격는 진통이라 생각합니다..^^

     

    다른쪽 코드 수정으로 인해 이쪽 코드가 영향받지 않도록...하라...

    "느슨한 결합" 많이 들어 보셨죠..^^?

    */

     

    RMI(Romote Method Invocation, 원격 메소드 호출)에서는

    클라이언트에게 Interface 즉 껍데기만 줘서 어떠한 서비스가 있는지 알려주어(일전에 말하였던 공개)..

    서버의 비지니스 로직을 호출하게 되어있다.

     

    굳이 RMI 뿐만 아니라 분산객체라 불리는 것들이 이러한 방법으로 interface를 사용하게되는데...

    Interface의 프로토타입이 변경되지 않는한 클라이언트가 변경되어야할 일은 없다.

    그러므로 서버의 로직 변경에 클라이언트는 영향받지 않게된 것이다.

     

    그렇다면 Interface가 변경이 되어 버린다면 어떻게 될까?

    이전 글에서 Interface는 약속이라 하였다.

    서버에서 이 약속을 깨버리면..

    음..

    Interface가 변경되었다는것은 '클라이언트 변경이 불가피하다'라는것이다.

     

    그래서 한번 배포된 Interface는 함부로 변경(수정, 삭제, 확장을 포함해서)이 되어선 안된다는것이다.

    일대 혼란(업데이트 이슈)이 발생..

    (첫 배포가 그래서 중요합니다.)

     

    MS쪽에서는 Interface 변경해야할때..

    최초에 배포된 Interface는 변경하지 않고 확장만한다.

     

    예를 들어

     

    IXMLDOMDocument

    IXMLDOMDocument2(IXMLDOMDocument을 상속하여 좀더 확장된 버전)

     

    이런식으로 Interface를 넘버링으로 구별하여 변경하고 있다.

    관심 분야가 아니라도 간혹 이러한 네이밍 룰을 보았을것으로 생각한다.

     

    이는 종전에 배포된(IXMLDOMDocument) Interface는 이미 배포되었으니 그냥 쓰고 ..

    새로 App작성시 혹은 업데이트시 IXMLDOMDocument2를 사용하라는 MS의 의도이다.

     

    물론 최초에 IXMLDOMDocument2가 지원하는것을 고려해서 Interface를 작성하는것이 최선안이 되겠지만..

    모든것을 예측하기에는 인간은 너무나 부족하다.

     

     

    결국 이 글의 하고자하는 말은

    Interface는 상호간 약속이므로 함부로 변경되어선 안된다는것

    (이 한줄까지 오기위한 서론이 너무 길었습니다.^^)

     

    이는 Interface를 설계시 고려해야할 기본 덕목이라 할 수 있다.

     

     

    여기서 말하고자하는것은

    Interface 자체가 중요한게 아니라..

    Interface를 사용하는 의미가 중요하다라는것..

     

    이러한 컨셉으로 클라이언트를 더욱 가볍게 하는 것은

    Interface를 사용하는 또 하나의 보이지 않는 역할이라고도 할 수 있다.

     

    /*

    에필로그

     

    Interface 이야기는 여기까지하고자 합니다..

    성원을 보내주신 분들이 계셔서 탄력받아 계획에도 없던 글을 하나 더 올렸습니다.

     

    적고 보니 요즘에는 너무 당연하고 철지난 얘기라..

    좀 그렇습니다..^^;

     

    여기서 더 나가면 세부적인 기술 강좌로 가야할것 같습니다...그래서 여기까지만...^^

     

    부담없이 가볍게 읽어 내려갔으면하는 것이 바램입니다만, 그랬는지요..^^?

     

    저는 한때 작가의 길을 걷고자 했던적이 있었습니다. 고등학교때 문학이 너무 좋아서..

    나름 문학 소년이었답니다.(이글 작문한걸 보면 안 믿어지실테지만..-_-;;)

    그러나 다행히도 그당시에 재능이 없다는걸 빨리 깨닫고 포기를 했더랬습니다.

     

    그때 꿈을 접지 않았다면 지금 굶어 죽었을것 같습니다...-.-;;

    지금 생각해도 다행이라 생각합니다..-.-

    우스게 소리였습니다...ㅎ..

     

    수고하셨습니다.

     

    워낙 문장력이 없다보니 탈고해주신 분이 있습니다.

    special thanx. 꼼

    */





    출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=70&MAEULNO=4&no=130&page=3
    Posted by Sting!
    ,

    너무나 많은 곳에 쓰이는 단어 인터페이스(Interface)..

     

    UI(User Interface), 프로그래밍 언어에서 부르는 Interface, API, CGI 등..

     

    우리는 가끔 여러 사람 혹은 다른 회사와 공동 프로젝트 진행시

    "인터페이스를 맞추자"

    "인터페이스를 열어 달라"

    "인터페이스 만들어 주세요"

    "이렇게 하기로 인터페이스 정해 놓게 왜 인터페이스대로 하지 않습니까?"

     

    이말을 두루뭉술하게 여러곳에 적용해서 아주 빈번히 사용하고 있다.

     

    용어를 설명하는데 있어서 일반 사전적인 의미와 컴퓨터 사전적인 의미는 많이 다르다.

    주로 컴퓨터의 용어가 더 많은 의미를 내포하고 있는데..

     

     

    여러 방면에서 사용하고 있는 말이지만..

    프로그래밍 언어에서의 인터페이스의 역할에 대해 그리고

    이말을 사용하고 있는 공통적인 의미는 '약속'라는 뜻이 아닐까.?

    라는데서 이글을 써내려 가려고한다.

     

     

    프로그래밍 언어에서 Interface는 무엇으로 사용하는가..

     

    Interface

    하면 떠오르는 것들.

    폴리모피즘, 상속, 오버라이드, 동적 바인딩

    (저는 이런것들이 떠오르네요^^)

     

    본인은 C++을 주력 언어로 사용하고 있지만..

    java로 Interface라는 것으로 풀어 보려고한다.

     

    개인적으로는 java가 더 후대 언어라서 인지 C++ 보다는 좀더 언어가 명확하다라고 해야할까? 좀더 과학적이랄까.

    (java의 문법자체는 C에서 나온것에 이라는것에는 이견이 없습니다. 따라서 C 문법의 단점 또한 계승하고 있지요..-.-)

     

    암튼 java를 해본지 너무 오래 되긴했지만(달갑진 않지만 지금도 언어 자체가 진화하고 있더군요..), java로 부터 나름대로 느낌점은 그렇다.

     

    (뭐가 더 우수한 언어이고, 뭐가 좋은지에 대한 논쟁은 이 글에서 논하고자 하는 쟁점은 아니므로 있는 그대로만 받아들여 주시기 바랍니다.)

     

    일단 문법적으로 Interface를 파악해 볼까!

     

    java에서 Interface라는 키워드를 적었을때 문법적인 제약이 발생한다.

     

    1. prototype만 기술

    2. 자체 객체생성(instance) 할 수 없음.

    3. 반드시 sub class에서 구현.

    4. 그리고 접근자는 public !!

     

    1~3번 은 문법적인 제약 조건이지만..

    4번은 Interface를 사용하는것에 대한 아주 큰 의미를 내포하고 있다.

    혹은 Interface를 사용하는 의미의 전부라고도 할 수 있다.

    4번으로 인해 1~3이 왜 저러한 제약 조건이 붙은것인지에 대한 이유가 되기도 한다.

     

    java쪽 기술에서 보면 J2EE라는 기술이 있고, API에서는 javax로 따로 분류하고 있는데..

     

    Database관련하여 JDBC라는것이 있다.

    Interface를 설명하는데 아주 좋은 예라 할 수 있다.

     

     

    ODBC도 동일하지만 JDBC만을 예로 들자면

     

    JDBC를 이용하여 개발시 우선 3가지 요소가 존재한다.

     

    1. SUN :  Interface 만 제공

    2. DB 벤더 : Interface 구현

    3. 개발자 : Interface 활용

     

    우선 SUN사에는 sql을 이용할 수 있는 interface만 만든다(정확히 표현하자면 '명세한다', '공개한다').

    DB 벤더는 SUN서 공개한 Interface를 보고 구현을 한다(이것이 드라이버가 되겠지요).

    개발자는 드라이버에서 구현된 Interface를 호출해서 쿼리를 던진다.

     

     

    그럼 가정을 해보자.

    SUN에서 Interface를 제공하지 않았다면 어떻게 될까.

    A라는 DB 벤더는 독자적인 인터페이스를 만들어서 함수를 제공할것이다.

    B라는 DB 벤더 또한 독자적인 인터페이스를 만들어서 함수를 제공할것이다.

    C 벤더 또한 마찬가지로 독자적인 구현...

    (아...우울해지겠죠...그쵸..?)

     

    예를 들어 각 회사에서 쿼리를 실행하는 함수 다음과 같이 정의 했다.

    A: runExec(string str)

    B: RunQuery(String str)

    C: ExcuteQuery(String str)

     

    이와 같이 각 벤더가 정의 했다면 개발자는 각 벤더의 API문서를 봐야 할것이다.

    왜 냐하면 Interface가 모두 다르기 때문에..

    (이런것들을 native driver라 부르지요..)

     

    좀더 들어가서 개발자는 위 세가지 DB를 모두 지원하는 어플리케이션을 만든다고 가정한다면..

    if문의 분기 처리로 호출할것인지.. 이때부터 난잡해지는 코드에 고민에 빠지게 된다.

     

    하지만 JDBC를 이용하면 SUN에서 Interface를 공개(혹은 제약) 했기때문에...

    각 DB 벤더는 그 Interface 명으로 Interface를 자사의 DB에 맞게 각기 구현해야만한다.

    따라서 개발자는 각 벤더가 어떻게 구현했는지 알 필요가 없다.

     

     

    개발자는 각 DB 벤더가 어떻게 구현했는지는 몰라도 "나는 이 Interface만 호출하면 원하는 결과를 얻을 수 있다"라는 것을 알고있다.

    각 벤더의 API문서를 볼 필요도 없고(아주 가끔은 필요할 수 도..) 개발자는 SUN에서 제공한 Interface에대한 명세만 보면 되니까.

     

    'SUN에서 Interface라는 제약을 뒀기 때문에 각 벤더가 자사의 DB에 맞게 구현됐다'라고 보장을 받을 수 있기 때문이다.

    언어의 문법상 Interface는 상속하여 반듯이 구현해야 하기 때문에 각 DB 벤더는 알아서 구현했을 것이다.

     

    그럼 여기서 초반부에 Interface는 '약속'이다라고 무작정 정의해버린 문장에 부합된다고 볼 수 있지 않을까.

     

    여기서 Interface를 다른 말로 바꾸어 보면..

     

    Interface는

    약속이다.

    공개이다.

    명세이다.

    규약이다.

    프로토콜이다.

     

    모두 맞는 말이 아닐까..

     

    위에서 나열한 1~4에 대한 내용이 4이기 때문에 1~3이 그렇게 될 수 밖에 없다는것에 대한 이유가 된다고 볼 수 있다.

     

     

     

    아주 간단하게 정리해보자

     

    Interface는 어떻게 구현됐는지는 모르지만, Interface만 호출하면 원하는것을 얻을 수 있다.

    그러므로 인터페이스 공개(public)가 아닌것이 의미가 있을까!!

    ("공개가 아닌 인터페이스는 의미가 없다"라고 정의 해도 되겠지요?)

     

    Interface를 활용한기술이 또 무엇이 있을까?

    RMI

    CORBA

    COM

    EJB

    ...

    ...

     

    위 기술중 한가지는 반듯이 써봤을것을 믿어 의심치 않는다.

     

    COM을 사용하면서 우리는 COM에서 제공한 Interface만 보고 작성한다.

    어떻게 작성되어 있는지 우리는 알지 못하지만, Interface를 호출하면 된다는것 만큼은 알고있기 때문에..

    왜냐하면 그렇게 약속했으니까, 규약했으니까, 공개했으니까.



    출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=70&MAEULNO=4&no=128&page=3

    Posted by Sting!
    ,

    XML 그 편함

    XML 2008. 12. 26. 17:35

    프로젝트 진행시 XML을 많이 쓰나요..?

    저는 대부분의 프로젝트에서 XML을 활용하고 있습니다.

     

    제가 XML을 처음 접한것은...1999년도에 학교 친구들과 코엑스 IT전시회가서 입니다.

    교수님이 코엑스 갔다오면 결석한 수업 그것으로 인정해 주겠다 해서..-_-;;

     

    전시회에서 윈도우, 웹 어플리케이션으로 XML에 있는 데이터를 찾고, 갱신하는것 보여 주었습니다.

     

    그때 당시에는 별로 감흥이 오지 않았었죠.

     

    그러다 졸업 후 한국 SUN으로 부터 XML관련 강의를 들을 수 있는 기회가 있었는데.

    크게 깨달음은 없었으나 XML의 전반적인 기초 지식을 배우게 되었지요..

     

    본격적으로 하게 된것은 아마도 처음 들으시는 분들도 있겠지만 MPEG21 프로젝트 참여에서 부터였습니다.

     

    이 MPEG21은 아마도 현재까지도 표준화를 진행하고 있을것 같네요..

    MPEG21은...컨텐츠를 XML로 정의(생성)하고 있습니다.

    이때부터 본격적으로 XML을 하게되었는데..

     

    그 이후 부터는 엥간한 데이타 처리나 데이타 전송은 XML로 전달하고 있습니다.

    그 편함에 빠진것이지요..

     

    XML을 사용하기 이전에는 데이타 영속성을 처리를 위해

    보통은 file data, ini, 레지트리등을 사용하였습니다.

    (물론 DB를 사용해도 되겠지요.. 전 주로 기업용 보다는 일반 사용자용 app를 주로 작성하였답니다.)

     

     

    file data(대부분 처음 시작은 이것으로 시작하죠..)로 데이타 영속성 처리하기 위해서는

    app(어플리케이션)이 읽을 수 있도록 프로그래머가 데이타 포멧을 정의 해야하는데..

    대강 이런식으로..

     

    A;Hankyun;pnca@test.com;10

    B;Hankyun2;pnca2@test.com;20

     

    각 데이타를 분리해 내기위해 ';'으로 분리하고,

    각 레코드을 분리하기위해서는

    파일을 한줄씩 라인단위로 읽을것인지,

    버퍼로 모두 읽어 들여 라인 피드로 각 라인을 구분할 것인지 살짝 고민에 빠진다.

     

    위와 같은 정도 수준의 간단한 데이타 구조라면 그냥 할만하다..-.-;

     

    하지만 다음의 이미지 처럼 데이타가 상위 종속을 가진 트리구조(hierarchy 구조) 라면..?

     

    그렇다면 레지스트리?

    레지스트리는 데이타를 트리구조로 가지고 있으므로 위와 같은 상속 구조의 데이타를 표현해 낼 수 있다.

    가능은 하다...하지만 레지스트리가 미로가 될것이다..

    부사수가 "레지스트리로 가능한데 이걸로 하시죠"라는 주장에...사수를 설득하기란 쉽지 않을겁니다...-.-;

     

    이건 딴얘기인데..

    더 큰 문제는 윈95 부터 현재 2000을 거쳐 비스타까지 레지스트리를 쓰면서 문제가 없었나요..?

    윈도우 버전에 따른 레지스트리 접근 및 구조가 조금 바꼈습니다.(조금이지만 개발자에게 와 닿는 파장은 적지 않았습니다.)

     

    9x에서 잘 돌아가던것이 2000에 가서는 제대로 돌지 않는것이 태반(너무 비약했나..-.-)이었습니다.

    뿐만 아니라 x64 OS가 릴리즈 됨에 따라 생각할 것이 많아 지죠(레지스트리를 x86, x64따로 관리 합니다.).

    그리고 레지스트리에 대한 접근 권한도 문제가 심심치 않게 발생하기도 하죠..

     

    win 2000이후의 OS부터는 레지스트리 이슈는 정말 다행스럽게도 많이 줄었으나, 과거 9x -> 2000으로 변경되는 격동기가 있었습니다.

    더군다나 이 와중에 NT4 이슈도 정말 만만치 않았습니다...-.-;

    이 격동기에 오죽했으면 "나 앞으로 OS 하나 더 나오기 전에 이바닥 뜬다"라는 말도 했던 기억있습니다...-.-;;

    물론 저의 실력이 미천하여 문제가 많았을 수 도....-.-;;

     

     

    아..다 귀찮다...

    그동안 험난한 길을 걸어온 김군은 이제 데이타 처리는 전부 XML로..라고 자신에게 조용히(누가 들어줄리 만무하기에) 선언을 합니다.~( '')

     

    다시 본론으로... 

    XML은 기본적으로 MS에서 파서를 제공해줍니다.

    IE 5.0 이상인 PC에서는 파서가 들어있었던것으로 기억합니다..

    그래서 현재의 대부분의 PC에서는 XML을 사용하는데 별 문제가 되지 않습니다.

     

    그리고 MSXML, tinyXML, 기타 여러 XML 파서들이 존재합니다.(저는 한 서너개 써본듯)

     

    저는 MS에서 제공하는 MSXML파서를 좀더 구현해서 편하게 래핑한 클래스를 사용합니다.

    물론 처음에는 쉽지 않습니다..COM의 낯선 코드들, 더 힘들게 하는건 MSDN이 JS기준의 샘플로 되어 있어서...-.-;

    하지만 한번만 제대로 만들어 두면 두고 두고 써먹을 수 있습니다.

    전 5년 동안 써먹고 있습니다...뿌듯..-.-y

     

     

    제가 XML을 데이타로 사용하는 가장 큰 이유는..

    직접 파싱할 필요도 파싱하기 위한 포멧을 생각할 필요도 없습니다.

    데이타 구조(좀 있어보이는듯 한  용어로는' 메타데이타')만 생각하면 됩니다.

     

    주소만 주면 파서가 데이터를 찾아 오니까요..

    XPath를 이용하여 아이템이 몇개 존재하는지, 엘리먼트 및 속성의 값 뽑아오기,

    엘리먼트 및 속성을 추가, 수정, 삭제 등 아주 쉽게 데이트를 조작할 수 있지요.

     

    하여,

    소켓으로 데이타 전송시에도 간단한 데이타의 경우 바이트에 담아서 보내는데...

    복잡한 데이타의 경우 XML로 데이타를 구성하여 바이트에 담아서 전송하는 프로젝트를 종종 보았습니다.(당연?)

     

    그리고 규모가 큰 서버들의 경우에는 대부분 환경 정보들을 XML을 데이타로 사용하고 있습니다..

     

    예를들면,

    아파치 서버가 처음에는 일반 텍스트로 환경정보를 관리하다가 현재(?)는 XML로 환경 설정값을 데이타로 사용하고 있지요...

    웹로직도 그렇습니다.

    위 두 경우로 일반화할 순 없지만...사실입니다.

     

    이렇듯 복잡한 데이터 구조를 가지고 있는 경우

    XML 구조로 데이터를 가지고 있다면 데이타를 파싱해내기 무지 쉽기 때문이죠..

     

    그 편함에 한번 빠져 보시죠...^^

    대부분의 개발자 분들은 XML을 알고 계십니다..다만 활용은...음...

    XML자체는 어떠한 기술보다 쉬우며, 적은 시간의 투자로 많은것을 얻을 수 있는것이 XML이라 생각합니다.

     

     

    물론 세상엔 쉬운게 없습니다.

    더 깊이 들여다 보면,

    지금은 너무 복잡하여 사용하고 있지 않지만 DTD라는 것도 있고

    XML  Schema

    XSL or 스타일 시트

    등 XML과 연관된 것들이 있습니다.

     

    하지만 영속성을 위한 데이타용으로써는 XML자체만으로도 충분하다 생각합니다.

     

     

    그리고 XML의 사용 용도는 아주 다양한데..

    이를 기초로 해야할것이 녹녹치 않을 정도로 용어나 기술들의 응용 분야가 많습니다.

    SOAP, EJB, SmallTalk...등등

    엔터프라이즈 환경에서 XML은 아주 다양한 용도로 사용되고 있습니다.

    관심이 있다면 관련 강좌를 한번쯤 찾아서 읽어 보시는것도 좋을 것 같네요...^^

     

    네...

    아주 다양한 곳에 사용되고 있지요...

    다양한 곳에 사용하고 있지만, XML을 사용하는 공통적인 목적은 하나입니다.

    그것은 데이타



    출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=70&MAEULNO=4&no=139&page=3

    Posted by Sting!
    ,