출처 : http://blog.tobegin.net/39  / Writer by 정은성

 

 회차
[C# 4.0] New Features in C# : 01. C# Programing Trend
[C# 4.0] New Features in C# : 02. C# 4.0 Overview
[C# 4.0] New Features in C# : 03. Dynamically Typed Objects #1 : DLR
[C# 4.0] New Features in C# : 04. Dynamically Typed Objects #2 : Dynamic Lookup
[C# 4.0] New Features in C# : 05. Optional and Named Parameters
[C# 4.0] New Features in C# : 06. Com-specific interop features
[C# 4.0] New Features in C# : 07. Covariance and Contravariance


01| C# 프로그래밍 동향

어느듯 .NET Framework 4가 Visual Studio 2010과 함께 런칭한지 3개월이 흘렀습니다.

Visual Studio 2010 과 함께 .NET Framework 4, Silverlight 4, WPF, WCF 등 유관 기술들이 새로운 변화를 하고 있는데요.

그래서 오늘은 Microsoft에서 지향하는 프로그래밍 패러다임에 대해 아티클로 잠시 다루어보기로 하겠습니다.
.NET Framework 디자인팀은 오래전부터  " 미래에는 어떤형태의 프레임워크가 되어야할지? " 고민을 하였다고 합니다.
지속된 디자인팀의 노력으로 .NET Framework 4에서는 완전한 프로그래밍으로 거듭 나고 있습니다.



* 선언적 프로그래밍
 : 명령형 프로그래밍의 반대되는 개념으로 어떤 방법으로 해야 하는지를 나타내기보다 무엇과 같은지를 설명하는 경우를 말합니다. 그내용을 축약한다면 목표를 명시하고 알고리즘은 명시하지 않습니다.
즉, 찾고자하는 필요한 해의 특성을 설명하고 그해를 찾는데 사용하는 실제 알고리즘은 설명을 하지 않습니다.
대표적인 예로는 SQL과 같이 질의문의 선형 언어가 있습니다. 이미 C# 3.0에서 선언형 언어 이론을 기반한 LINQ와 간결하고 확장 가능한 구문 람다 문장과 같은 스타일이 적용 된것을 알수 있습니다.

* 동적 프로그래밍
 : 위키 사전에서는 다음과 같이 정의를 하고 있네요.
"어떤 알고리즘이 부분 문제 반복과 최적 기본 구조라는 특징을 가지고 있을 때, 이 알고리즘의 실행시간을 줄이는 방법이다."
이와 같은 이론을 바탕으로 C# 4.0 에서는 Dynamic 이라는 새 형식이 도입이 되었습니다. dynamic 형식은 정적 형식이지만 이형식의 개체는 정적 형식 검사에서 제외가 됩니다. 또한 dynamic 타입은 컴파일 타임에 모든 작업을 지원하는 것으로 가정되며 COM API, IronPython, IronRuby 와 같은 언어이 프로그램 내의 다른 위치인지 신경 쓰지 않아도 됩니다.
CLR 버전이 4.0으로 업그레이드 되면서 동적 언어 런타임(DLR)을 통해 동적인 언어를 지원 합니다.

* 동시 프로그래밍
: 동시 프로그래밍은 동시에 많은 연산을 하는 방법중 하나입니다. 최근 컴퓨터 이용에서 발열과 전력소모에 대한 관심이 높아지는것과 함께, 멀티 코어 프로세서를 핵심으로 컴퓨터 구조에서 강력한 패러다임으로 주목받고 있습니다.
.NET Framework 4에서는 병렬 컴퓨팅의 패러다임을 손쉽게 가져다 쓸수 있도록 제공을 하고 있으며 .NET 4의 병렬 프로그래밍은 Task Parallel Library(TPL)과 PLINQ (Parallel LINQ)으로 구분 됩니다.

- TPL : 데이터 중심으로 네트워크 통신 및 병렬 연산 등을 통하여 실행 순차적으로 배포 또는 인터리빙이 실행하여 단일 프로세스들을 집합 과정으로 기존의 전통적인 비동기 패턴과 TPL을 통합하는 시나리오를 제공합니다.

- PLINQ : LINQ는 안정적인 방식으로 데이터 소스를 쿼리하기 위한 모델였지만 데이터가 열거 되기전까지 지연이 되어 병렬적으로 실행이 필요 하게 되었습니다. PINQ의 병렬 처리로 레거시 코드를 사용할 때보다 향상된 성능을 제공합니다.

포스팅을 마치며...

이번 포스팅은 Microsoft에서 추구하는 프로그래밍 패러다임에 대해서 잠시 아티클로 만나 보았습니다.
의미적으로 잘못 전달해드리지 않을까 걱정되네요 ^^; 추가 피드백이 있으시면 의견 남겨주시면 감사합니다.

다음 포스팅 부터는 C#의 새로운 기능들에 대해 소개를 해드릴 예정입니다.
무더위 준비 잘하시고 항상 좋은 하루 보내세요
감사합니다.

정은성 드림
 
출처 : http://blog.tobegin.net/39  / Writer by 정은성
아... 슬프다... 한국 IBM DeveloperWorks가 철수하면서 다 날아갔다...

IBM 사이트에서 번역된 JQuery 강좌입니다.
간단하지만 보면 도움이 될거 같습니다.
 
jQuery로 작업하기, Part 1: 브라우저로 데스크톱 응용 옮기기
jQuery로 작업하기, Part 2: 내일 나올 웹 응용을 오늘 구현해보자
jQuery로 작업하기, 3부: jQuery와 Ajax로 RIA 만들기

 
jQuery로 작업하기, Part 1: 매개체로서의 JQuery: 플러그인을 사용하여 jQuery 함수를 작성하고 확장하기 
jQuery로 작업하기, Part 2: 매개체로서의 JQuery: UI 프로젝트 
jQuery로 작업하기, Part 3: 매개체로서의 JQuery: 고유한 플러그인 작성하기 
 
 
Ajax로 사이트 전면 개편, Part 1: Ajax와 jQuery로 기존 사이트 개선하기 
Ajax로 사이트 전면 개편, Part 2: jQuery, Ajax, 툴팁, 라이트박스로 기존 사이트 개선하기 
Ajax로 사이트 전면 개편, Part 3: jQuery, Ajax 탭, 회전식 슬라이드쇼로 기존 사이트 개선하기 
Ajax로 사이트 전면 개편, Part 4: 기존 사이트를 jQuery와 Ajax forms를 사용하여 개선하기 
 
JSONP를 사용한 도메인 간 통신, Part 1: JSONP와 jQuery의 결합으로 강력한 매시업 빠르게 만들기 
JSONP를 사용한 도메인 간 통신, Part 2: JSONP, jQuery 및 Yahoo! Query Language로 매시업 만들기 
 
Scala, Lift 및 jQuery를 사용하여 Comet 애플리케이션 빌드하기
 
매개체로서의 jQuery(1) 
매개체로서의 jQuery(2) 
 
고급 jQuery(1) 
고급 jQuery(2) 
 
jQuery로 Ajax 개발을 단순화 하기 



ASP.NET의 주요 명령어 정리 : 내장 개체

▶ Response개체 : 응답(서버(C#)에서 클라이언트(IE)로)
     .Write() : 페이지에 문자열 출력
     .Redirect() : 해당 페이지로 이동
     .Expires : 현재 페이지의 새로 고침 기능
          Response.Expires = -1; // 응답캐시 지우기
     .Buffer : 버퍼링 사용 설정
          Response.Buffer = true; // 버퍼링
     .Flush() : 현재 버퍼 내용 출력
     .Clear() : 현재 버퍼의 내용 비우기
     .End() : 현재 페이지 종료...
     .WriteFile() : 파일 출력
     .Cookies[] : 쿠키 저장
     
▶ Request개체
     .QueryString[] : 넘겨져 온 쿼리스트링값을 반환 : key/value쌍으로…
          Get방식 : URI(URL)에 ? 뒤에 키와 값으로 전달
     .Form[] : Post방식으로 넘겨져 온 값 반환
          Post방식 : HTTP 헤더에 데이터를 실어서 전송
     .Params[] : Get/Post 방식 중 아무거나 다 받음.
     Request[] : Params[] 컬렉션과 동일
     
     .UserHostAddress : IP주소
     .ServerVariables["REMOTE_HOST"] : IP주소
     .ServerVariables["REMOTE_ADDR"] : IP주소
     
     .Cookies[] : 저장된 쿠키 읽어오기.
     
▶ Server개체
     .MapPath(".") : 현재 파일과 같은 경로 값 반환 : .., /, \
     .Execute() : 다른 파일 포함(인클루드)후 제어권 돌아옴
     .Transfer() : 다른 파일 포함(인클루드)후 제어권 넘김 : Execute() + Response.End()
     .UrlPathEncode() : 넘겨져온 쿼리 스트링을 유니코드로 변환(한글 처리)
     .ScriptTimeout : 서버측에서 현재 ASPX페이지를 몇초간 처리할 건지 설정
          대용량 파일 업로드 페이지는 일시적으로 Server.ScriptTimeout을 증가
          
▶ Application개체
     - Application 전역 변수 선언(Public)
          Application["변수명"] = 값; // 딱 한개만 생성
     .Lock() : 애플리케이션 변수를 잠그는 메서드
     .UnLock() : 잠긴 애플리케이션 변수를 해제하는 메서드
     
▶ Session개체
     - Session 전역 변수 선언(Private)
          Session["변수명"] = 값; // 사용자 수 만큼 생성
     .Abandon() : 현재 세션 지우기
          예전에는 세션으로 로그인 처리시 로그아웃 할 때 사용
     .SessionID : 현재 세션의 고유번호 값 반환
          GUID와 비슷 : 한명이 접속하면 웹서버는 고유한 인증값을 부여
     .SessionTimeout : 세션 시간 기록 : 기본값 20분... 더 추가시키거나 줄일경우 사용...
     
▶ Page 개체
     .IsPostBack : 현재 페이지가 처음 로드했는지, 다시 게시(PostBack)되었는 지 확인
          처음로드 : Page.IsPostBack => false
          다시게시(PostBack) : Page.IsPostBack => true
     .RegisterClientScriptBlock() : 자바스크립트를 동적으로 웹 페이지에 추가
          Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "스크립트 구분 이름", "자바스크립트코드");
     .RegisterStartupScript() : 자바스크립트를 동적으로 웹 페이지에 추가
          Page.ClientScript.RegisterStartupScript(this.GetType(), "스크립트 구분 이름", "자바스크립트코드");
     
▶ System.Web.Security.FormsAuthentication 개체 : 인증 관련
     
     [1] .SetAuthCookie() : 인증 쿠키값 부여... 인증 처리
          .GetRedirectUrl() : 인증 받기 이전의 페이지 경로값 반환.
     [2] .RedirectFromLoginPage() : 인증 처리와 동시에 이전(인증 받기 전) 페이지로 이동
     [3] Page.User.Identity.Name : 인증된 사용자명, SetAuthCookie()에서 부여된 인증 쿠키값, Admin, RedPlus식
     [4] Page.User.Identity.IsAuthenticated : 인증(로그인처리)되었다면, true, 그렇지 않으면 false를 반환
     
▶ 상태관리
     서버에 저장 : 웹 애플리케이션 전체에서 살아있는 변수값 저장
          Application[] : 1개만
          Session[] : 여러개
          Cache[] : 1개만 빠른 메모리에 저장
     클라이언트에 저장
          ViewState[] : 웹 브라우저의 소스코드에 히든필드로 저장
          Response.Cookies[] : 웹 브라우저에 쿠키 저장
          Request.Cookies[] : 저장된 쿠키 읽어오기

▶ 캐싱
     <%@ OutputCache Duration="3600" VaryByParam="None" %>
          3600초 동안 현재 페이지를 캐싱(메모리에 처리 결과 담고 바로 출력)


Request URL: http://WebResource.axd?d=9n4PyABCLnJPx4xoU3nxwC4Kt15K3u-a245UfT6hW8JSf4r6suGuS1kEScfmyvro0&t=633739595980000000

로컬테스트 및 개발서버에서 정상적으로 되던것들이 리얼서버로 올라갔을때 위메세지 처럼 발생하는 에러를 가끔씩 보실 수 있습니다.

WebResource.axd 는 ASP.NET 2.0에서 기본적으로 제공하는 HttpHandler 로서 커스텀 컨트롤의 DLL 내에 embedded resource 로서 제공되는 .gif .js .htm 등을 반환하기 위해 추가된 기능입니다.
WebResource.axd 가 리소스가 포함된 DLL과 리소스의 ID를 query string에 포함시키고 이것을 암호화 하는데 디폴트 암호화 알고리즘이 (AES)Rijndael 알고리즘 입니다.

이 알고리즘은 ASP.NET의 기본설정은 암호화/복호화에 사용하는 키를 자동생성 합니다.
암호화 할 때 사용한 키와 복호화 할 때 키값이 다를경우 예외가 발생합니다.

예외가 발생될 경우

/WebResource.axd?d= .... 렌더링 할 때 사용한 (자동 생성된) 암호화 키와 실제 이 URL이 요청되었을 때의 (자동 생성된) 복호화 키가 다를경우 패딩예외가 발생하는 것입니다.

ASP.NET으로 구성된 웹 어플리케이션 서버가 L4 Switch에 의하여 Load Balancing 되는 경우..

- 웹 페이지 접속 시 ASP.NET 컨트롤에서 없던 오류날 경우

- 이미지가 액박 표시 되는 현상


이 경우 Fiddler를 통하여 페이지 요청 시 WebResource.axd 요청이 실패하는지 확인합니다.
해당 요청에서 문제가 있다면 서버의 이벤트 로그에는 다음과 같이 CryptographicException 오류가 발생하였는지 확인해보는 것이 좋습니다.


Event code: 3005
Event message: 처리되지 않은 예외가 발생했습니다.
Event time: 2010-07-26 오후 오후 1:05:45
Event time (UTC): 2010-07-26 오후 1:05:45
Event ID: 28188a45397841e499de7a4c38b4f4cd
Event sequence: 61
Event occurrence: 3
Event detail code: 0
 
Exception information:
    Exception type: CryptographicException
    Exception message: 패딩이 잘못되었으며 제거할 수 없습니다.
 
Request information:
    Request URL: http://WebResource.axd?d=9n4PyABCLnJPx4xoU3nxwC4Kt15K3u-a245UfT6hW8JSf4r6suGuS1kEScfmyvro0&t=633739595980000000
    Request path: /WebResource.axd

[패딩이 잘못되었으며 제거할 수 없습니다. (Padding is invalid and cannot be removed.)]


이 에러는 WebResource.axd 파일을 요청할 때 발생합니다.
이 파일은 ASP.NET의 컨트롤을 사용하는 경우 요청되는데요.
이 때 암호화 작업이 발생합니다. 암호화에 사용되는 Machine Key는 서버가 가지고 있습니다.
ASP.NET에서 Machine Key를 설정한적이 없다면 동적으로 생성되어 사용됩니다.

서버가 한대일 경우는 상관 없지만, 여러대 이면서 LoadBalancing을 하는 경우는 문제가 발생합니다. 요청마다 서버가 바뀌므로 암호화 키를 전달해준 서버가 아닌 서버가 암호화된 정보를 받는다면 해독할 수 없으므로, 위 처럼 오류가 발생하는 것이지요.


이는 모든 웹 어플리케이션 서버의 Machine Key를 동일하게 함으로 해결할 수 있습니다.
새로운 Machine Key 키 생성은 다음의 사이트에서 도움을 받으세요.

http://aspnetresources.com/tools/machineKey


생성된 Machine Key는 web.config에 다음의 형태로 삽입하면 됩니다.
 </system.web>
 <machineKey validationKey="D3373ECBFB7F1D94A57890DD8C676F5E925713E79BCF5A8A2692D408A5E9A1E06ED9FBF352B876D2B465EE70DDCF69CA2FD263711401ED6171ED5AC8F795E88A" decryptionKey="0B12BC1D697005FF915095556F3E528F261F5D08847AAB9881E409D525D1D5C6" validation="SHA1" decryption="Auto" />
 </system.web>

 

참고자료
-- machineKey 요소(ASP.NET 설정 스키마)
http://msdn.microsoft.com/ko-kr/library/w8h3skw9.aspx

 

 

출처 : http://inaekkuya.blog.me/70090690083


Visual SourceSafe over the Internet using HTTP

여러 명이 공동작업을 하는 데 프리랜서 그룹이라고 하자. 멋있는 말로 분산개발환경이라고 하면 되나? 이번에 나온 Visual SourceSafe(VSS, 소스세이프)는 인터넷을 통한 작업이 가능하게 지원을 한다. SSL을 이용하면 더 안전하겠지만 이 부분은 생략하기로 한다.
먼저 Visual SourceSafe를 설치하고 공유할 데이터 베이스를 지정한다. HTTP를 사용할 경우 로컬인 경우도 꼭 \\ComputerName\SharedFolderName 으로 지정을 해야한다.


새로 추가된 기능의 하나로 Multiple Checkouts를 지원한다.


보안에 대한 안내로 Everyone 그룹에 대한 권한이 있다면 제거하라는...



HTTP를 통한 소스세이프 사용을 위해 SSL을 사용할 것을 권한다. 현재는 테스트라 Yes를 눌러 무시했다.

IIS관리자에 해당 SourceSafe 가상 폴더가 생성되고 VssService.asmx 웹서비스가 구성된 것을 확인 할 수 있다.

ASP.NET 1.0을 동시에 쓰는 경우는 꼭 APP Pool을 ASP.NET 2.0으로 맞춰주길~


WebDAV가 허용되어 있는 것을 확인할 수 있다.

Visual Studio 2005의 Tools ? Option을 보면 아래와 같이 Internet을 통한 소스제어가 가능하게 선택을 할 수 있다.

설정을 변경하고 프로젝트를 오픈하면 그림과 같이 SourceSafe (Internet)항목이 보인다.

Address에는 http경로를 넣으면 된다. 예를 들면 http://aaa.bbb.com/ 그리고 Folder에는 \\ComputerName\SharedFolderName ....

출처 동석이의 블로그 | 허둥사마
원문 http://blog.naver.com/tit99hds/120018010240

개요

페이지의 실행주기가 언뜻 아무것도 아닌것처럼 보이나 어떠한 복잡한 로직이 페이지에 구현될때

실행주기때문에 머리가 엉킨 경험을 한번씩은 경험 해 보았을 것이라고 생각합니다.

페이지의 실행주기를 한번만 확실히 집고 넘어가면 앞으로 개발하는데 많은 장점이 있을 듯 합니다.



<%@ Page Language="C#" Debug=true %>
<Script Language="C#" Runat="Server">
string s = "데이타 바인드 하기";
private void Page_Init(Object o , EventArgs e)
{
 Response.Write("Page_Init 이벤트 발생!<p>");
}
private void Page_Load(Object o , EventArgs e)
{
 Response.Write("Page_Load 이벤트 발생!<p>");
}
private void Page_PreRender(Object o , EventArgs e)
{
 Response.Write("Page_PreRender 이벤트 발생!<p>");
}
private void Page_Unload(Object o , EventArgs e)
{
 //페이지가 메모리에서 언로드 될때 발생, 아직 해제(disposed)되지는 않는다
 //응답을 사용할수 없다(Respnose개체 사용 불가)
 //화면에 출력하는 코드를 사용할 수 없다
}
private void Page_Disposed(Object o , EventArgs e)
{
 //페이지 생명주기 마지막 단계
 //페이지가 메모리에서 해제됨
}
private void DoClick(Object o , EventArgs e)
{
 Response.Write("클릭 이벤트 발생!(포스트 백 일어남)<p>");
 //Page.DataBind();
}
</Script>
<form runat="server">
 <asp:Button Runat="Server" OnClick="DoClick" Text="클릭!" /><p> <%# s %>
</form>

위의 코드는 페이지 실행주기동안에 발생하는 대부분의 이벤트입니다.

1. 페이지가 처음 로딩될 경우 [ init -> load -> PostBack체크 -> preRender 순으로 발생 ]


2. 포스트 백(버턴클릭시)이 될 경우 [ init -> load -> PostBack체크 -> 버턴클릭이벤트 -> PreRenader 순으로 발생 ]

주의 할 것은 포스트백이 일어날때 Page_Load 이벤트는 다시 호출되며 컨트롤의 
이벤트보다 먼저 수행된다는 점입니다. 
실수를 해보지 않은 사람은 다 아는 내용이지 않는냐 하겠지만 한번씩 실수를 해본 사람은 
이미 알고 있고 또한 기본적이지만 중요한 개념입니다. 
그리고 Page_PreRender 이벤트는 컨트롤의 이벤트 뒤에 또는 처음로딩시 호출되기에 
나름대로 유용하게 쓰일 수 있는 이벤트이기도 하죠. 
 
3.

private void Page_DataBind(Object o , EventArgs e)
{
    Response.Write("Page_DataBind 이벤트 발생<p>");
}
Page의 또다른 이벤트인 DataBind 입니다. 
이 놈은 페이지에서 DataBind 가 호출될때 발생하는 이벤트 입니다. ( ex> Page.DataBind(); ) 
이 외에도 실행주기에 대한 내용은 많지만 제가 아는 내용은 대략 이정도군요^^ 
 


페이지 요구시 처리과정

  1. init : 페이지 초기화
  2. ViewState복구
  3. Load : 일반적으로 알고 있는 Page_Load()
  4. PostBack 이벤트 처리
  5. PreRender
  6. ViewState 저장
  7. Render
  8. UnLoad : 페이지 객체 소멸 직전에 발생하는 이벤트


서버 컨트롤의 실행주기

  1. 컨트롤 생성
  2. Init
  3. ViewState 복구
  4. PostBack 데이터 처리
  5. Load
  6. 데이터 변경 이벤트
  7. PastBack 이벤트
  8. PreRenser
  9. ViewState 저장
  10. Render
  11. UnLoad

1. 단순 스크립트 블록일때.(cs파일에서)

string Script="<script language=javascript>";
Script+="parent.location.href='http://kr.yahoo.com';";
Script+="</";
Script+="script>";
------------------------------------------------------------- 자바스크립트 소스부분 스트링으로 선언

this.RegisterClientScriptBlock("OnStart",Script);
------------------------------------------------------------- 자바스크립트 실행 메소드

2. 메소드 스크립트 블록일때
aspx파일에서 스크립트 블록
<script language=javascript>
function test()
{
......( 메소드 내용);
}
</script>

cs파일에서 자바스크립트 메소드 호줄
private void Button1_Click(object sender, System.EventArgs e)
{
string method="test();";

Button1.Attributes.Add("onclick",method);
ASP.NET의 Visual SourceSafe 사용에 관한 모든 것

Paul Sheriff, Michael Krasowski

PDSA, Inc.

2003년 12월

요약 : Microsoft Visual SourceSafe를 사용하여 ASP.NET 프로젝트를 관리하는 전체 프로세스를 안내합니다(17페이지/인쇄 페이지 기준).

적용 대상:

Microsoft ASP.NET

Microsoft Visual SourceSafe

목차

소스 코드 컨트롤을 사용해야 하는 이유 소스 코드 컨트롤을 사용해야 하는 이유
격리 모드와 비격리 모드 비교 격리 모드와 비격리 모드 비교
SourceSafe 데이터베이스 설정 SourceSafe 데이터베이스 설정
VSS에 ASP.NET 솔루션 추가 VSS에 ASP.NET 솔루션 추가
VSS로 파일 조작 VSS로 파일 조작
파일 기록 추적 파일 기록 추적
소프트웨어 버전에 레이블 사용 소프트웨어 버전에 레이블 사용
Visual Studio .NET에서 솔루션 가져오기 Visual Studio .NET에서 솔루션 가져오기
결론 결론

일부 개발자들은 소스 코드 컨트롤을 반드시 사용해야 하지만 매우 번거로운 것으로 생각합니다. 하지만 소스 코드 컨트롤은 소프트웨어 개발 프로세스를 지원하는 안전한 업무 관례입니다. 이 문서에서는 실제로 Microsoft Visual SourceSafe를 소스 코드 컨트롤 메커니즘으로 유용하게 사용하는 단계별 방법을 보여 줍니다. 새 SourceSafe 데이터베이스를 만드는 방법, 파일을 체크 인하고 체크 아웃하는 방법, 레이블을 사용하여 릴리스를 만드는 방법을 볼 수 있습니다.

소스 코드 컨트롤을 사용해야 하는 이유

단순하게 말하자면 VSS(Visual SourceSafe) 같은 SCM(Software Configuration Management) 제품은 프로젝트를 구성하는 문서의 중앙 라이브러리(데이터베이스)입니다. Visual SourceSafe에는 프로젝트 계획, 사양 설명서, 데이터베이스 개체, 소스 코드 등의 비트 스트림과 프로젝트의 기타 모든 항목을 저장할 수 있습니다. 최상의 방법은 소스 코드뿐만 아니라 모든 프로젝트 항목을 Visual SourceSafe 데이터베이스에 포함시키는 것입니다. 그러면 액세스 및 팀 구성원 간 공유가 용이해지며, 무엇보다도 버전 제어가 용이해집니다.

여느 라이브러리에서처럼 사용할 파일을 "체크 아웃"하는 기능이 필요합니다. 사용자는 파일을 체크 아웃한 후 편집할 수 있습니다. 일반적으로 한 번에 한 명의 사용자만 파일을 체크 아웃하여 편집할 수 있습니다. 언제나 한 명의 사용자만 파일을 체크 아웃할 수 있도록 하는 것이 가장 좋습니다. 간혹, 같은 파일을 여러 사용자가 체크 아웃할 수 있도록 할 것을 권장하는 Visual SourceSafe 사용 시나리오를 소개하는 백서도 있습니다. 이러한 백서에서는 나중에 모든 변경 사항을 함께 병합할 수 있도록 할 것을 권장합니다. 그러나 VSS에 기본 제공되는 도구를 사용하면 쉽게 병합할 수 있을 것 같지만 실제로는 여러 가지 단점이 있습니다. 항목을 다시 체크 인하는 데 시간이 더 오래 걸리고, 병합 프로세스에서 충돌을 수동으로 점검해야 할 경우가 발생할 수 있으며, 데이터베이스, Microsoft Word 문서 등의 이진 항목에는 대개 사용할 수 없습니다. 또한 업데이트된 항목과 업데이트한 사람 및 시간에 대한 정확한 기록을 반영하지 못하는 경우가 있습니다.

VSS에서는 라이브러리 관리자가 액세스 제어를 정의할 수 있습니다. 사용자에게는 액세스 ID 및 암호, 그리고 액세스 권한이 주어집니다. 액세스 권한은 읽기 또는 읽기/쓰기 기능처럼 단순할 수도 있고, 기능 권한과 같이 복잡할 수도 있습니다. 예를 들어 파일을 삭제하는 기능도 하나의 기능 권한입니다.

모든 개별 파일(소스 코드, 프로젝트 계획, 요구 사항 등)에 대해 각각의 파일 주기 동안 어떠한 변화가 있었는지 파악하는 것은 매우 중요합니다. VSS는 파일을 만든 시간과 만든 사람, 해당 파일에 대한 각 수정, 해당 파일에 대한 메모 또는 주석, 그리고 해당 문서의 주기를 추적하는 데 도움이 되는 기타 정보 등 모든 작업 기록을 보관합니다.

위에서 언급한 VSS의 기능과 그 외 여러 기능을 통해 잘 관리된 구조적인 방식으로 개발, 빌드 및 유지 관리 프로세스를 효율적으로 관리할 수 있습니다. 이 외에도, VSS를 사용하여 소프트웨어 개발의 생산성을 높일 수 있는 이유에는 여러 가지가 있습니다.

격리 모드와 비격리 모드 비교

팀 환경에서 웹 응용 프로그램을 개발할 경우 두 가지 모델 중에서 하나를 선택할 수 있습니다. 첫 번째 방식인 비격리 모델에서는 모든 개발자가 중앙 서버에서 모든 파일을 만들고 수정합니다. 비격리 개발 모델에서는 중앙 공유 컴퓨터에서 하나의 Microsoft IIS(Internet Information Services) 서버를 사용해야 하며, 응용 프로그램의 모든 파일이 해당 서버의 가상 디렉터리에 상주해야 합니다. 모든 개발자가 VSS에서 파일을 체크 아웃하며, 체크 아웃된 파일은 중앙 IIS 서버의 가상 디렉터리로 이동합니다.

두 번째 웹 개발 방식인 격리 모델에서는 각 개발자가 자신의 개발 컴퓨터에서 실행 중인 IIS 안에 가상 디렉터리를 만듭니다. 격리 방식에서는 각 개발자가 중앙 VSS 데이터베이스에서 로컬 컴퓨터로 파일을 가져오거나 체크 아웃합니다. 개발자는 로컬 컴퓨터에서 모든 내용을 편집, 디버그 및 테스트하고 모든 내용이 정상적으로 작동하면 파일을 중앙 위치로 다시 체크 인할 수 있습니다. 체크 인된 파일은 다른 개발자가 가져올 수 있습니다.

두 가지 개발 유형 모두 장단점이 있습니다. 각각의 장점과 단점을 살펴보겠습니다.

비격리 개발의 장점

  • 개발자의 로컬 컴퓨터에서 IIS를 실행하고 있지 않아도 됩니다.

  • 모든 소스 코드가 서로 다른 개발자의 컴퓨터에 흩어져 있는 것이 아니라 한 위치에 모여 있습니다. 소스 코드가 저장된 컴퓨터에 문제가 발생할 경우 변경 내용을 SourceSafe에 체크 인하지 않았으면 해당 변경 내용을 잃을 수도 있습니다.

비격리 개발의 단점

  • 다른 개발자의 작업에 의도하지 않은 영향을 미치기 쉽습니다.

  • 한 개발자가 디버깅을 위해 응용 프로그램을 실행하는 동안에는 프로세스가 잠기므로 다른 개발자들이 응용 프로그램을 디버그할 수 없습니다.

  • 여러 개발자가 같은 파일을 작업하는 경우에는 마지막에 체크 인한 파일이 최종 파일이 됩니다.

  • 소스 제어 기능이 제한되어 있습니다.

  • 한 개발자가 일부 코드를 수정하여 해당 코드가 작동하지 않을 경우 다른 모든 개발자가 더 이상 프로젝트의 해당 부분을 실행할 수 없게 됩니다.

격리 개발의 장점

  • 다른 개발자를 부주의하게 방해하지 않고 응용 프로그램을 개발 및 디버그할 수 있습니다.

  • 다른 개발자에게 영향을 미치지 않고 로컬에서 변경 내용을 테스트할 수 있습니다.

  • 소스 코드 컨트롤에 대한 지원이 뛰어납니다.

  • 개발자는 네트워크에 연결하지 않아도 프로젝트를 다른 컴퓨터로 이동하거나 가지고 다니면서 사용자를 표시할 수 있습니다.

격리 개발의 단점

  • 각 개발자가 자신의 로컬 컴퓨터에 IIS를 설정해야 웹 응용 프로그램을 개발할 수 있습니다.

  • VSS 라이브러리가 백업 프로세스에 포함되는 경우 각 개발자는 파일이 백업되도록 퇴근하기 전에 모든 파일을 다시 체크 인해야 합니다.

선택할 모델

격리 개발 모델을 사용할 것을 권장합니다. 물론 이를 위해서는 각 사용자의 컴퓨터에 IIS가 있어야 하므로 일부 조직에서는 제약이 따를 수 있습니다. 하지만 격리 모델은 가장 유연한 소스 코드 컨트롤을 위한 최상의 모델입니다.

격리 개발을 위한 Visual Studio .NET 설정

격리 모델을 사용할 수 있도록 Microsoft Visual Studio .NET에서 올바른 옵션을 설정했는지 확인하십시오. Visual Studio .NET에서 도구 | 옵션 탭으로 이동하고 Microsoft FrontPage Extensions 옵션이 아닌 파일공유를 클릭합니다. FrontPage Extensions 옵션은 모든 파일이 중앙 서버에 위치한 비격리 방식을 사용할 경우 선택하는 옵션입니다.

SourceSafe 데이터베이스 설정

지금까지는 Visual SourceSafe의 개요 및 사용 이점에 대해 알아보았습니다. 이제 Visual SourceSafe를 시작하는 방법을 살펴보겠습니다. 첫 번째 단계는 중앙 VSS 데이터베이스의 위치를 찾는 것입니다. 이 데이터베이스는 엄밀한 의미에서 데이터베이스라기 보다는 하드 드라이브의 폴더입니다. 이 폴더는 모든 개발자가 찾을 수 있는 네트워크 공유에 배치되어야 합니다. 개발자가 한 명뿐일 경우에는 개발자의 로컬 하드 드라이브에 배치할 수도 있습니다.

VSS 관리 도구를 아직 설치하지 않았으면 VSS CD에서 설치합니다. 사용자 지정 설치를 통해 이 옵션을 선택해야 합니다. CDD에서는 일반적으로 ACMBoot.exe를 실행하여 관리 도구를 설치합니다. 사용자 지정 설치 옵션에서 Administrative ProgramsCreate SourceSafe Database 옵션을 선택해야 합니다.

관리 프로그램을 설치한 후에는 시작 메뉴로 이동하여 프로그램 | Microsoft Visual SourceSafe | Visual SourceSafe 6.0 Admin을 클릭합니다. 새로 시작되는 인터페이스에서 Tools | Create Database...를 클릭합니다 . 그러면 그림 1과 같은 대화 상자가 표시됩니다. 이 새 SourceSafe 데이터베이스를 만들 위치를 "D:\MyVSSDB" 또는 \\SharedDrive\MyVSSDB와 같이 입력합니다.

vssstarttofinish_fig01.gif

그림 1. 모든 SourceSafe 파일에 사용할 공유 폴더의 위치를 지정합니다.

데이터베이스를 만들고 나면 그림 2와 같은 대화 상자가 표시됩니다. 이 대화 상자는 이 SourceSafe 데이터베이스를 만들 때 만들어지는 Admin 사용자에 관련 암호가 없다는 것을 나타내는 경고일 뿐입니다. Admin 사용자를 클릭하고 메뉴에서 Users | Change Password...를 클릭하여 Admin 사용자에 암호를 할당하십시오.

vssstarttofinish_fig02.gif

그림 2. Admin 사용자에 암호를 할당하여 관리 도구를 보안합니다.

데이터베이스를 만들고 나면 Visual SourceSafe Administrator 도구(그림 3)가 나타납니다. 이 도구에서는 한 번에 하나의 VSS 데이터베이스에만 연결할 수 있습니다. 이 데이터베이스에서 파일을 체크 아웃하고 체크 인할 수 있도록 할 모든 사용자를 이 데이터베이스 안에서 만들어야 합니다. 만드는 각 데이터베이스마다 해당 사용자를 추가해야 합니다. 이 기능은 설정된 사용자만 이 데이터베이스를 사용할 수 있도록 하므로 유용합니다. 그러나 모든 사용자에게 액세스를 허용할 VSS 데이터베이스가 여러 개 있는 경우 각 데이터베이스에서 각 사용자를 개별적으로 설정해야 합니다.

vssstarttofinish_fig03.gif

그림 3. Administrator 도구에서는 사용자를 만들고, 데이터베이스를 만들고, 데이터베이스를 잠그며, SourceSafe 대한 기타 시스템 관리 기능을 수행할 있습니다.

이제 이 데이터베이스에 자기 자신을 새 사용자로 추가해야 합니다. SourceSafe에서 도메인 로그온 ID(도메인 이름 제외)를 사용자 이름으로 사용하고 있는지 확인하십시오. SourceSafe는 아무런 메시지를 표시하지 않고 도메인 로그온 ID를 사용하여 로그온을 시도합니다. 이 VSS 데이터베이스에 암호를 할당한 경우에는 해당 암호가 도메인 암호와 일치하는지도 확인하십시오.

이 새 데이터베이스의 위치를 기억해야 합니다. 데이터베이스에 사용자를 도메인 이름과 함께 추가한 후에는 사용자가 VSS 클라이언트 유틸리티를 처음 설정할 때 데이터베이스를 찾을 수 있도록 모든 사용자에게 데이터베이스 위치를 알려야 합니다.

VSS에 ASP.NET 솔루션 추가

새로 만든 VSS 데이터베이스에 프로젝트 및 프로젝트 항목을 추가할 수 있습니다. 두 가지 방법을 통해 이 VSS 데이터베이스를 조작할 수 있습니다. 즉, "다른 프로젝트 항목"을 데이터베이스에 추가하는 데 유용한 VSS Explorer 도구를 사용하거나 Visual Studio .NET 내에서 VSS를 사용할 수 있습니다. 사실 VSS에 새 프로젝트를 추가하는 경우에는 Visual Studio .NET을 사용하여 추가하는 것이 좋습니다. Visual Studio .NET 인터페이스를 사용하면 .SLN 파일에 몇 가지 바인딩 정보가 추가되므로 개발자가 VSS에서 솔루션을 가져올 때 VSS에 자동으로 연결될 수 있습니다.

참고 이 문서의 예제에서는 ASP.NET (US) 사이트에서 다운로드할 수 있는 Microsoft ASP.NET Portal Starter Kit을 사용하여 파일을 체크 인하고 체크 아웃했습니다. 원하는 다른 프로젝트를 사용할 수도 있습니다.

ASP.NET Portal Starter Kit을 다운로드하여 설치했다고 가정하고 VSS에 이 솔루션을 추가하는 방법을 설명하겠습니다. Visual Studio .NET에서 솔루션을 열고 그림 4와 같이 메뉴에서 File | Source Control | Add Solution to Source Control...을 선택합니다.

vssstarttofinish_fig04.gif

그림 4. Visual Studio .NET 에서 기본 제공하는 메뉴를 사용하여 솔루션을 SourceSafe 추가합니다.

이 메뉴 항목을 선택한 후에는 그림 5와 같은 대화 상자가 표시될 것입니다. 격리 개발 모드를 사용하는 경우 이 대화 상자는 FrontPage Server Extensions 대신 일반 파일 URL을 사용하여 모든 파일을 참조한다는 의미일 뿐입니다. Don't' show this dialog box again (Always allow addition of Web projects using File Share access to source control) 확인란을 클릭하고 Continue를 클릭하십시오.

vssstarttofinish_fig05.gif

그림 5. FrontPage Server Extensions 에서 파일 공유 액세스 사용으로 전환

이제 VSS 데이터베이스를 설정할 때 만든 로그온 ID와 암호(그림 6 참고)를 입력할 차례입니다. 설정한 ID(예: JohnD)와 암호를 입력합니다. 그런 다음 Browse...를 클릭하여 VSS 데이터베이스를 만든 특정 폴더를 찾습니다. 작업을 마쳤으면 OK를 클릭합니다.

vssstarttofinish_fig06.gif

그림 6. VSS 로그온

데이터베이스에서 만들 프로젝트 이름을 입력하는 대화 상자가 나타납니다. 첫 번째 대화 상자인 "Add to SourceSafe Project"(그림 7)는 솔루션 파일이 있는 Visual Studio .NET 프로젝트를 나타냅니다. 그림의 "ASP.NET Portal Starter Kit (VBVS)"와 같이 이 프로젝트의 이름을 입력합니다.

vssstarttofinish_fig07.gif

그림 7. 본인이나 다른 개발자가 나중에 쉽게 찾을 있도록 프로젝트에 이름을 지정합니다.

솔루션에 있는 모든 개별 Visual Studio .NET 프로젝트를 입력하는 대화 상자가 나타납니다. 그림 8과 같이 VSS는 각 Visual Studio .NET 프로젝트 이름을 "Add to SourceSafe Project" 대화 상자의 입력란에 자동으로 추가합니다. 이 경우 두 번째로 입력되는 내용은 PortalVBVS입니다. "ASP.NET Portal Starter Kit (VBVS)" 폴더를 클릭하여 이 프로젝트를 이 솔루션 아래에 배치해야 합니다.

vssstarttofinish_fig08.gif

그림 8. 각각의 프로젝트를 VSS 개별적으로 추가합니다.

솔루션 파일이 프로젝트와 동일한 폴더에 있다는 경고 메시지가 표시됩니다. 의도적으로 같은 폴더에 배치한 것이므로 확인란을 클릭하여 계속 진행합니다. 그림 9와 같은 대화 상자가 나타날 수도 있고 나타나지 않을 수도 있습니다. 이 대화 상자가 나타나면 확인란을 선택하고 OK를 클릭합니다. 이 경우 다른 항목은 프로젝트 파일의 일부분이 아닌 폴더에 있기 때문에 나중에 VSS Explorer 도구를 통해 수동으로 추가해야 합니다. 폴더 안에 있지만 프로젝트 파일로 새로 지정된 문서 또는 .SQL 파일이 이러한 항목에 해당할 수도 있습니다.

vssstarttofinish_fig09.gif

그림 9. 프로젝트 파일에서 참조하지 않는 추가 파일이나 폴더가 있으면 VSS 에서 이를 사용자에게 알립니다 .

솔루션과 프로젝트를 SourceSafe 제어 아래에 배치하고 나면 Visual Studio .NET이 그림 10과 같이 특수 아이콘을 사용하여 파일이 잠겼는지 아니면 체크 인되었는지 표시합니다. 소스 코드 컨트롤 아래의 각 파일 옆에는 자물쇠 아이콘이 표시됩니다. 자신이 체크 아웃한 파일 옆에는 확인 표시가 나타나고, 다른 사용자가 체크 아웃한 파일에는 원형 아이콘이 나타납니다.

vssstarttofinish_fig10.gif

그림 10. Visual Studio .NET 소스 코드 컨트롤 아래에 파일의 상태를 표시합니다 .

VSS 데이터베이스 내의 전체 프로젝트를 보려면 운영 체제 메뉴에서 시작 | 모든프로그램| Microsoft Visual SourceSafe| Microsoft Visual SourceSafe 6.0을 선택하십시오. 다시 로그온해야 할 수도 있습니다. 로그온 이름과 암호를 입력하십시오. VSS Explorer(그림 11 참고)를 처음 실행하는 경우 데이터베이스를 만든 폴더를 탐색하여 VSS 데이터베이스도 찾아야 합니다.

vssstarttofinish_fig11.gif

그림 11. Visual SourceSafe Explorer 에서는 전체 프로젝트 소스 코드 컨트롤 아래에 배치된 모든 파일을 있습니다.

VSS로 파일 조작

프로젝트 파일을 VSS 데이터베이스에 배치하고 나면 프로젝트의 모든 파일이 디스크에서 읽기 전용으로 설정됩니다. 체크 아웃되지 않은 파일로 솔루션을 실행할 수도 있습니다. 그러나 Visual Studio .NET 내에서 파일을 작업하려면 체크 아웃해야 합니다. 현재의 작업과 비교하면 한 단계가 추가된 것이지만 대신 이전 버전으로 다시 돌아갈 수 있으며 다른 개발자가 수정 중인 파일을 사용자가 동시에 수정할 수 없도록 합니다.

파일 체크 아웃

파일 작업을 위해 체크 아웃해야 할 때는 Solution Explorer 창에서 해당 파일을 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 Check Out...을 클릭하기만 하면 됩니다. 예를 들어 Portal Starter Kit에서 Default.aspx 파일을 클릭하고 마우스 오른쪽 단추를 클릭한 다음 Check Out...을 클릭합니다. 그림 12와 같은 대화 상자가 나타납니다. Check Out 단추를 클릭하면 .ASPX 파일뿐만 아니라 .ASPX.resx 및 .ASPX.VB 파일도 체크 아웃됩니다. 이제 해당 파일을 작업할 수 있으며 다른 사용자에게 파일이 체크 아웃된 것으로 표시됩니다.

vssstarttofinish_fig12.gif

그림 12. Check Out 대화 상자에서는 프로젝트 파일을 하나 또는 여러 가져와서 하드 드라이브에 있는 상태로 설정할 있습니다 .

파일 체크 인

체크 아웃한 파일에서 원하는 내용을 모두 수정한 후에는 SourceSafe에 다시 체크 인해야 합니다. 파일을 체크 인할 경우 두 가지 사항을 염두에 두어야 합니다. 첫째, 프로젝트의 페이지 또는 클래스에서 변경한 내용이 컴파일되는지 확인해야 합니다. 그렇지 않으면 SourceSafe 데이터베이스에서 최신 변경 사항을 가져오는 다른 개발자의 프로젝트에서 오류가 발생하는 곤란한 상황이 발생합니다. 둘째, 매일 일과가 끝나면 파일을 모두 체크 인해야 합니다. 그러면 파일이 단지 하드 드라이브에 저장되는 것이 아니라 다른 위치에 백업됩니다. 따라서 하드 드라이브에 문제가 발생할 경우에도 변경한 내용을 모두 보존할 수 있습니다. 일과 후에도 소스 코드가 아직 컴파일되지 않은 경우에는 문제가 되는 코드에 주석을 달고 체크 인하면 됩니다.

최신 버전 가져오기

팀 환경에서 작업하는 경우 프로젝트 내에서 다른 파일을 수정하는 다른 개발자도 있습니다. 특정 시점에서는 VSS 데이터베이스에 있는 모든 최신 변경 사항을 프로젝트와 동기화할 수 있습니다. 그러기 위해서는 Visual Studio .NET Solution Explorer 창에서 프로젝트를 클릭하고 마우스 오른쪽 단추를 클릭한 다음 Get Latest Version (Recursive)를 클릭합니다. 그러면 VSS 데이터베이스로 이동하여 변경된 모든 파일을 검색하고 해당 파일을 프로젝트로 가져옵니다. 이제 로컬 컴퓨터에서 프로젝트를 실행하고 나면 다른 개발자가 변경한 내용을 모두 볼 수 있습니다.

파일 기록 추적

특정 시점에서 개발 팀은 "빌드", "버전" 또는 "릴리스"를 만들 수도 있습니다. VSS는 버전 번호를 사용하여 파일 및 프로젝트에 대한 모든 변경 사항을 추적합니다. 따라서 파일 또는 프로젝트의 모든 버전을 검색할 수 있습니다. VSS는 내부 버전 번호, 날짜 및 사용자 정의 레이블의 세 가지 항목을 기준으로 이전 버전을 추적합니다. 버전을 자체적으로 지정하는 경우에는 VSS에서 할당한 내부 버전 번호가 아니라 사용자 정의 레이블을 사용합니다.

버전 번호

VSS는 체크 인된 각 파일에 대해 내부 버전 번호를 유지합니다. 파일을 체크 아웃하고 변경한 다음 VSS에 다시 체크 인할 때마다 해당 파일 버전에 대한 새 번호가 만들어집니다. VSS에서 History 대화 상자를 사용하여 파일의 전체 기록을 볼 수 있습니다. History 대화 상자는 Visual Studio .NET 또는 VSS Explorer 도구를 통해 볼 수 있습니다.

Visual Studio .NET에서 기록을 볼 파일(예: default.aspx)을 클릭한 다음 Visual Studio .NET 메뉴 시스템에서 File | Source Code Control | History를 클릭합니다. 그러면 그림 13과 같은 대화 상자가 나타납니다. default.aspx 파일을 아직 변경하지 않은 경우에는 첫 번째 버전 이외의 다른 버전이 없습니다.

VSS Explorer 도구를 사용하는 경우 Explorer에서 특정 파일을 찾아서 마우스 오른쪽 단추로 클릭한 다음 Show History... 메뉴 항목을 클릭하여 동일한 대화 상자를 표시합니다.

vssstarttofinish_fig13.gif

그림 13. VSS Explorer 파일의 전체 기록이 표시됩니다.

참고 내부 VSS 버전 번호는 단순히 참조용이며 빌드 또는 버전 번호와 직접적인 관련이 없습니다. 빌드 또는 버전 번호에는 레이블(아래 참고)을 사용합니다.

소프트웨어 버전에 레이블 사용

SourceSafe에서 파일에 할당하는 내부 버전 번호를 사용하는 대신 소프트웨어 릴리스를 정의하는 자신만의 코드 집합용 "레이블"을 만들 수도 있습니다. 릴리스는 첫 번째 베타 버전, 제품의 첫 번째 버전, 증분 릴리스, 제품의 두 번째 또는 세 번째 릴리스일 수 있습니다.
각 파일에는 자체 내부 버전 번호가 지정되며, 파일 수정 빈도에 따라 이 번호는 전체 프로젝트에서 전혀 일치하지 않게 됩니다. 따라서 내부 버전 번호 대신 자신만의 레이블을 전체 프로젝트에 적용하여 이 레이블을 만든 특정 시점에서 체크 인된 모든 파일을 식별할 수 있습니다.

레이블(최대 31자)을 만들 때 "1.0," "2.01b," "Final Beta" 또는 "Approved for QA" 같은 텍스트를 사용할 수 있습니다. 레이블을 적용한 후에는 기록 대화 상자에서 이 레이블과 연결된 모든 파일을 검색할 수 있습니다. 개별 파일에 레이블을 할당할 수도 있지만 대개 프로젝트 수준에서 레이블을 적용합니다. 프로젝트에 설명 문자열이 있는 레이블을 할당하면 해당 프로젝트의 모든 파일과 하위 프로젝트가 그 레이블을 사용합니다.

개발 주기의 어느 시점에서나 프로젝트에 레이블을 할당할 수 있습니다. 예를 들어 제품의 각 "릴리스"마다 알파, 베타 또는 최종 생산 코드에 관계없이 해당 시점에서 모든 프로젝트 항목에 레이블을 할당할 수 있습니다. 개발을 진행하다 베타 1.0의 소스 코드가 필요할 경우 그냥 가져오면 됩니다. 원하면 원본 파일에 아무런 영향을 미치지 않고 레이블의 이름을 바꿀 수 있습니다.

레이블을 만들려면 VSS Explorer 도구에서 레이블을 할당할 Project 폴더를 클릭하십시오. 메뉴에서 File | Label...을 클릭하면 그림 14와 같은 대화 상자가 나타납니다. 설명이 포함된 레이블 이름과 이 레이블의 사용 용도를 알려 주는 주석을 입력하고 OK를 클릭하여 레이블을 이 프로젝트와 이 프로젝트 아래의 모든 파일 및 하위 폴더에 적용합니다.

그림 14. VSS Explorer 도구를 사용하여 레이블 만들기

VSS Explorer에서 프로젝트를 다시 선택하고 마우스 오른쪽 단추로 클릭한 다음 Show History... 메뉴 항목을 클릭하여 History 대화 상자를 표시하면 그림 15와 같이 레이블이 표시됩니다.

vssstarttofinish_fig15.gif

그림 15. VSS Explorer History 대화 상자에서 적용한 여러 가지 레이블을 있습니다.

기존 레이블에 파일 추가

버전에 레이블을 할당했는데 나중에 레이블이 할당된 버전에 포함되었어야 할 파일을 빠뜨린 것을 발견하는 경우도 있을 수 있습니다. 파일을 레이블의 일부분으로 추가하려면 파일을 프로젝트에 추가하기만 하면 됩니다. VSS Explorer에서 해당 파일을 클릭한 다음 File | Label...을 클릭하고 프로젝트에 할당한 것과 동일한 레이블을 할당합니다. 레이블을 기준으로 파일을 가져올 경우 레이블 이름이 동일하기 때문에 이 파일도 함께 가져옵니다. 레이블 이름을 정확히 입력했는지 확인하십시오.

레이블에 할당된 모든 파일 가져오기

특정 레이블이 할당된 파일을 모두 가져오려면 해당 파일에 대해 "가져오기(get)" 작업을 수행하면 됩니다. 즉, 특정 레이블 아래의 파일을 체크 아웃할 수는 없지만 가져올 수는 있습니다. 그러기 위해서는 VSS Explorer에서 내용을 가져올 프로젝트를 마우스 오른쪽 단추로 클릭하고 Show History...를 클릭합니다. Project History Options 대화 상자(그림 16 참고)가 나타나면 Labels Only 확인란을 선택하고 OK를 클릭합니다.

vssstarttofinish_fig16.gif

그림 16. 프로젝트의 레이블 가져오기

선택한 프로젝트에 할당한 모든 레이블이 표시됩니다. 가져올 레이블을 클릭한 다음 화면(그림 15 참고) 오른쪽에서 Get을 클릭합니다. 그러면 이 레이블이 있는 모든 파일이 이 프로젝트에 할당된 작업 디렉터리로 복사됩니다. 이미 언급한 대로 레이블이 할당된 릴리스에서는 파일을 체크 아웃할 수 없습니다. 따라서 릴리스된 파일 집합은 아무도 무단으로 변경할 수 없습니다.

Visual Studio .NET에서 솔루션 가져오기

사용자가 빌드 중인 응용 프로그램에 대해 프로젝트 책임자가 초기 솔루션을 만들면 다른 개발자가 이 솔루션을 가져와서 각자의 컴퓨터에 설정할 수 있도록 해야 합니다. 이때 각 개발자가 자신의 컴퓨터에 가상 디렉터리를 다시 만들고 모든 파일을 올바른 위치로 가져왔는지 확인하게 할 필요는 없습니다. 다행히도 VSS 및 Visual Studio .NET에서는 이를 자동으로 처리합니다.

VSS와 통합된 Visual Studio .NET은 하드 드라이브에 적절한 폴더를 자동으로 만들고, 새 가상 디렉터리를 만들며, VSS에서 새 폴더로 파일을 자동 복사합니다. 항상 VSS가 아닌 Visual Studio .NET을 통해 이 프로세스를 수행해야 합니다. 그렇지 않으면 IIS를 수동으로 구성하고 VSS 데이터베이스에 대한 참조를 직접 설정해야 합니다.

다음 단계를 수행하려면 다른 컴퓨터를 사용하거나 앞에서 만든 가상 디렉터리를 지워야 합니다. Visual Studio .NET의 새 인스턴스를 엽니다. File | Source Control | Open from Source Control...을 클릭하면 그림 17과 같은 대화 상자가 나타납니다. 창에서 PortalVBVS 프로젝트를 클릭합니다. Create a new project in the Folder 입력란에 다른 폴더 이름을 입력하고 OK를 클릭합니다.

vssstarttofinish_fig17.gif

그림 17. 폴더로 SourceSafe 프로젝트 가져오기

드라이브에 없는 폴더를 선택하면 폴더를 만들라는 메시지가 표시됩니다. 이 예제의 경우에는 폴더가 드라이버에 없어야 정상입니다. Yes All을 클릭하여 이 프로젝트에 필요한 모든 폴더를 만듭니다.

그림 18과 같이 이 프로젝트를 배치할 가상 디렉터리를 입력하는 대화 상자가 나타납니다.

vssstarttofinish_fig18.gif

그림 18. 프로젝트에 가상 디렉터리 할당

SourceSafe 내의 프로젝트 및 솔루션 레이아웃 방법에 따라 열려는 솔루션 파일을 입력해야 할 수도 있습니다. 그럴 경우 대화 상자에서 .SLN 파일을 선택합니다. Portal 솔루션에서는 .SLN 파일이 분리된 자체 폴더 안에 있으므로 SourceSafe에서 아무런 대화 상자도 표시되지 않습니다.

다음으로는 이 가상 디렉터리를 만들 IIS의 위치를 입력하는 대화 상자가 나타납니다. 웹 서버 이름과 가상 디렉터리 이름을 입력하고 OK를 클릭합니다.

vssstarttofinish_fig19.gif

그림 19. 서버에 프로젝트 할당

이제 Visual Studio .NET에서 이 프로젝트의 모든 파일을 가져오기 시작합니다. 이 문서의 예제에서는 D:\PortalVBVS를 사용했습니다. 즉, 솔루션이 이 폴더에 저장된다는 의미입니다. 이 프로젝트의 다른 모든 파일은 기본 웹 사이트가 가리키는 폴더에 배치됩니다. 일반적으로 이 폴더는 c:\inetpub\wwwroot입니다. 이로써 프로젝트가 다른 개발자의 컴퓨터에 설정되었으며 사용 준비가 끝났습니다. 사이트의 시작 페이지를 선택하고 F5를 누르기만 하면 응용 프로그램이 실행됩니다. 이제 파일을 체크 아웃하여 작업하고 다시 체크 인할 수 있습니다. 이 모든 작업이 Visual Studio .NET 내에서 가능합니다.

결론

모든 개발자는 일상적인 작업에서 Visual SourceSafe를 사용해야 하며, 모든 개발 관리자는 팀에서 Visual SourceSafe를 사용하도록 해야 합니다. 개발자가 한 명뿐일 경우에도 이 도구를 효율적으로 사용하면 소스 코드를 다른 컴퓨터에 백업하고 소스 코드의 이전 버전으로 돌아갈 수 있습니다. VSS를 만들고 사용하는 것은 간단하고 쉽습니다. 사용 방법을 조금만 배우면 됩니다. 소스 코드 컨트롤이 뛰어나면 개발 프로세스가 향상되고 소프트웨어 구성 관리의 다양한 이점을 모두 활용할 수 있습니다.

BIO

Paul D. Sheriff는 SDLC 문서 및 아키텍처 프레임워크를 비롯한 .NET 컨설팅, 제품 및 서비스를 제공하는 PDSA, Inc.의 사장입니다(http://www.pdsa.com/ (US) 을 참고하십시오). 또한 남부 캘리포니아의 Microsoft 지역 책임자입니다. .NET 저서로는 ASP.NET Developer's Jumpstart(Addison-Wesley: 영문)와 PDSA 웹 사이트에서 구할 수 있는 여러 eBook이 있습니다. 전자 메일 주소는 PSheriff@pdsa.com입니다.

Michael Krasowski는 PDSA, Inc의 개발부 부사장입니다. 이전에는 The Boeing Company, Long Beach Division에서 선임 IT 관리자 직책을 역임했습니다. IT 분야에서 27년이 넘는 경험을 보유하고 있으며 캘리포니아 대학의 Irvine 사회 교육 과정에서 .NET에 대해 강의하고 있습니다. 전자 메일 주소는 Michaelk@pdsa.com입니다

최종 수정일: 2004년 2월 19일


출처 : MSDN
URL : http://msdn.microsoft.com/ko-kr/library/ms972977.aspx


<<정규화(Normalization)>>

 

* 함수의 종속성(Functional Dependency)
- 데이터들이 어떤 기준값에 의해 종속되는 현상을 지칭

- 결정자(determinent) --> 종속자(dependent)

  ex> 주민등록번호 --> (이름, 출생지, 주소)

 

 

1. 제1 정규화
- 복수의 속성값을 갖는 속성의 분리
- 즉, 테이블 하나의 컬럼에는 여러 개의 데이터 값이 중복되어 나타나지 않아야 한다.

- 모든 엔티티 타입의 속성에는 하나의 속성 값만을 가지고 있어야 하며 반복되는 속성 값의 집단은 별도의 엔티티 타입으로 분리한다.

- 로우(Row) 단위로 1차 정규화가 안된 모델은 PK의 유일성이 확보되지 않으므로 인해 실전 프로젝트에서는 거의 찾아보기 힘들다.

- 반면 로우 단위로 중복된 내용을 컬럼 단이로 펼쳐 중복하는 경우가 아주 많이 발견되는데 추가 업무 발생시 모델을 변경해야 하는 치명적인 결함이 있다.

 

 

2. 제2 정규화
- 주식별자에 종속적이지 않은 속성 분리
- 주식별자를 구성하는 일부 속성에 종속적인 속성(부분 종속 속성)을 분리하는 것.
- 주식별자가 둘 이상의 컬럼으로 이루어져 있을때 모두에게 종속적이어야 한다.

- 반드시 자신의 테이블을 주식별자를 구성하는 속성이 복합 식별자일 경우에만 대상이 되고 단일 식별자일 경우에는 2차 정규화 대상이 아니다.

- 코드 유형의 엔티티 타입들이 2차 정규화가 되지 않고 하나의 엔티티 타입으로 표현되는 경우가 많다.

 

 

3. 제3 정규화
- 주식별자가 아닌 속성에 종속적인 속성 분리.
- 주식별자에 의해 종속적인 속성 중에서 다시 속성 간에 종속관계(이전 종속)가 발생되는 경우

- 결정자 역할을 하는 일반 속성이 존재하고, 결정자 역할 속성에 의존하는 의존자가 존재하는 엔티티 타입이 대상이다.

 

 

4. 보이스-코드 정규화(BCNF)
- 테이블에 존재하는 식별자가 여러개 존재할 경우 식별자가 중복되어 나타나는 현상을 제거

- 주식별자 속성 중에 주식별자의 유일성을 확보하는 최소한의 속성이 아닌 쓸데없이 추가된 속성을 분리하는 것.

 

 

5. 제 4정규화
- 특정 속성값에 따라 선택적인 속성의 분리

- 하나의 테이블에 두 개 이상의 독립적인 다가속성(multi-valued attribute)이 존재하는 경우에 다가종속(multi-valued dependency)이 발생되어 문제가 생긴다. 다가종속이란 하나의 속성 값에 두개 이상의 의미를 가지는 값을 가지는 것을 의미한다.

- 실제로 2정규화나 BCNF보다 더 많이 발생된다.

- 불필요한 관계때문에 새로운 값을 채울 경우에 값을 기본값(Default value)으로 지정해버리는 경우가 많이 있다. 참조무결성(FK)를 걸지 않는 경우에 가능한데 좋지 않은 경우이며 이와 같은 경우 데이터모델에 나타난 관계가 실제 데이터에서 불가피하게 단절되어 나타나므로 무결성 체크가 불가능해진다.







원래 정규화란 중복성을 최소화하고 정보의 일관성을 보장하기 위한 관계형 데이터 베이스에서 제일 중요한 개념인데요

제1정규화는  < repeating group 제거>


여러 값을 가진 컬럼이 존재할 수 없다. 즉 반복되는 그룹이 존재해서는 안 된다. 각 행과 열에는 하나의 값만이 올수 있다.
예를 들면

고객번호(P.K) 고객명 취미
1 노무현 영화
여행
2 이화숙 등산

이런 테이블이 있을수는 없고 이걸 수정한다면

고객번호(P.K) 고객명
1 노무현
2 이화숙

하고 또하나

고객번호(P.K) 일련번호(P.K) 취미
1 1 영화
1 2 여행
2 1 등산

이런식으로 두개로 분리해야 한다는거죠

제2정규화 < 부분종속 제거 >


모든키가 아닌 컬럼은 기본 키 전체에 의존적이여야 한다. 기본키의 일부분에 의존적이어서는 안 된다.

예를 들어

사번(p.k) 프로젝트번호(p.k) 부서 프로젝트역할 고과율
1 a 전산 팀장 A
1 b 전산 조원 C
1 c 전산 부팀장 B
2 c 경리 팀장 A
3 c 기획 팀장 A

이 테이블의 기본키는 사번과 프로젝트번혼데 부서 컬럼은 사번에만 의존적이다.
이것은 2정규화를 거치면

사번(p.k) 프로젝트번호(p.k) 프로젝트역할 고과율
1 a 팀장 A
1 b 조원 C
1 c 부팀장 B
2 c 팀장 A
3 c 팀장 A

요렇게 하고 부서 테이블을 다시 따로 때네서

사번 부서
1 전산
2 경리
3 기획

요렇게 해서 릴레이션을 걸면 됩니다.

그리고 3정규화 < 이행종속 제거 >


키가아닌 컬럼은, 다른 키가 아닌 컬럼에 의존적일어서는 안된다.
예를 들어

사번(p.k) 프로젝트번호(p.k) 프로젝트역할 고과율
1 a 팀장 A
1 b 조원 C
1 c 부팀장 B
2 c 팀장 A
3 c 팀장 A

요 테이블을 다시 보면 고과율은 프로젝트 역할에 의존적인걸 알수 있습니다.

이것을 또 3정규화 거치면

사번(p.k) 프로젝트번호(p.k) 프로젝트역할
1 a 팀장
1 b 조원
1 c 부팀장
2 c 팀장
3 c 팀장

프로젝트역할 고과율
팀장 A
조원 C
부팀장 B

요렇게 또 따로 때네줘야 합니다

제4정규화는
2정규화 된 테이블은 다대다 관계를 가질수 없다.

이건 따로 예를 안들어도 되겠죠?ㅋㅋ


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) 사용이 엄격하게 제한된다는 의미입니다.

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 (안재우)


     

    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

    너무나 많은 곳에 쓰이는 단어 인터페이스(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

    프로젝트 진행시 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

    + Recent posts