나름 정의하면 ajax는 Javascript로 XMLHttpRequest ActivX컨트롤을 통해서 서버와 비동기 통신으로 XML,JSON프로토콜,사용자지정포멧 등으로 데이타 주고받아 DHTML(XSLT)로 웹브라우저내에서 애플리케이션의 기능을 구현하는 기술을 총칭한다고 보면 되겠다. 더많은 ajax라는 용어에 대해 궁금하신 분은 -> http://ko.wikipedia.org/wiki/Ajax

 이 글은 위에서 정의한 ajax의 기술 중에 javascript의 확장된 기능(객체화)을 이용하여 클래스를 설계하는 방법에 대한 설명에 해당하므로 ajax의 포괄적인 의미와
충분히 구분을 가지기를 바란다.

 솔직히 필자도 자바스크립트를 많이 사용 했지만  function이 클래스 선언에 대응된다는 내용은 ajax라는 용어가 광범위하게 퍼진 후이고 객체화와 관련된 스크립트문법을 잘 모르는 부분이 많다. 그래서 본 사이트의 클래스들을 만들면서도 시행착오가 꽤나 많았고 조금 틀린 설명이 있더라도 양해 하시길 바란다.

javascript에 대한 간략한 문법을 먼저 설명 해 본다.
솔직히 script언어의 명세를 찾아볼 수도 있지만 특별히 많은 문법이 없어서 필자의 경우는 코딩을 하면다 이런저런 테스트를 다 해보면서 한다.
function Tab()
{
   var  member = "1";
}
으로 선언 하면 Tab이 하나의 클래스 선언에 해당한다? 라고 생각하지만 글을 읽어가면 아니라는것을 알게 될 것이다. 
뭐 기존의 컴파일러 언어들의 클래스하고 같다고 간단히 생각 할 수도 있지만 사정이 그렇지 못하다.
일반적으로 클래스 내에서 우리는 this라는 포인터를 사용한다. 왜? 이 클래스가 인스턴스화 되었을 때 자신의 포인터를 참조하기 위해서 일 것이다.(아님말구~)
하지만 자바스크립트는 컴파일러의 this처럼 function내에서 this를 확인 해 보면 현재 클래스가 아니라 아마도 window객체가 참조될 것이다.
초기에 필자는 (new Tab()).member하면 Tab의 멤버변수의 값인 1이 참조되는 줄 알았다.. 하지면 아니다 member는 전역변수가 된다. 아래의 예제와 함께 테스트 해보시라.

이거 참 거시기 같지 않은가? 이건 클래스가 아니고 window객체(클래스) 의 멤버함수이지 않은가? 멤버함수 맞다.
그렇다면 왜 클래스라고 하는가? 답은 클래스 처럼 new할 수 있기 때문이다. 한마디로 멤버함수 이면서 클래스 선언으로 사용 될 수 있게 설계를 해 놓은것으로 보면 되겠다. 함수 자체로 클래스정의를 하는것은 아님을 명심하자.

간단한 테스트를 위해 다음 코드와 주석을 보면,
<html>
<head>
<title>가이아타이틀</title>
<script>
function tab()
{
   //alert(this.document.title); //이 코드를 활성화 해보면 this가 window라는거 확인가능
  if(this == window)
     alert("dddd");
 return "1";
}
function initPage()
{
  alert(tab);        // 1) 오호라 놀라워라?
  alert(tab());     // 2) 누구나 아는 결과 "1"
  alert(new tab); // 3)좀 새로운 결과?

}
</script>
</head>

<body onload="initPage()">
<table>
<tr>
<td id="insObj"></td>
</tr>
</table>
</body>
</html>

1)의 결과는 무엇일까?
   난 처음에 object가 리턴될 줄 알았다. 하지만 그 결과는 놀랍다. tab함수의 선언에 해당하는 문자열이 리턴된다.
   한마디로 문자열이란 말인가? 필자도 모른다. 적어도 문자열은 아닌듯하다(간단히 다음코드로 테스트)
var strFun = "function test() { return 1; }";
function initPage()
{
  alert( strFun);
  alert( strFun()); //안먹는다, 당연하다. 단순한 변수에 ()를 붙여서 호출한다고 먹힐리가 없다.
}
결론적으로 alert(tab)을 하면 함수의 정의를 문자열로 뿌리기는 하지만 함수의 이름인 tab과 문자열과는 차이가 있다는 것이다.

2)의 경우는 누구나 아는 기본적인 함수 호출의 결과이다.
3)의 결과는 무엇일까?
   이 경우 초기에 필자는 그냥 object가 alert되는 줄 알았지만 결과는 좀 달랐다
   [object Object] 가 alert된다.
   호잉? 소문자 object, 대문자 Object ?? 도데체 이게 무슨 결과인가?
   처음 소문자 object는 알겠는대 그후의 Object는 도대체 무엇이란 말인가??
   혹시나 해서 alert(Object())라고 찍어본다. 어라..  또 object Object다? alert(new Object()) 와같이 new를 붙이면 어떤결과일까? 어라? 동일한결과??
   의혹이 증폭된다.. 도대체 Object라는 놈이 무엇이란 말인가??
   혹시나 싶어 alert(Object)를 찍어본다... 어라? function Object() { [native code] } 라는 결과가 나온다. 어라 이건 위에서 함수명만 찍었을 때와 비슷한 결과이다.
   음.. 결론을 내자면 잘 모르겠다..ㅎㅎㅎ 아시는분 댓글 부탁~~
   짐작을 하자면 new 함수명()으로 function을 new할 때 시스템 내장객체(함수) Object를 new해서 함수명에 해당하는 객체에 붙여버리는거 같다.
 
즉, 기존 함수객체는 window의 멤버함수이면서 클래스(객체)선언 이고 그 객체를 확장한다는 의미로 Object를 뒤에 붙여버리는듯 하다. 오호라 그럼 실제로 var tabObj =  new Tab()을하면 실재로 리턴되는것은 Object라는 것을 대충 짐작하게 될 것이다.
조금 달리말하면 객체의 형이 Tab인 default Object를 하나 만들어서 리턴해준다고 보면 되겠다.

실질적인 클래스(객체)정의
음... 그렇다면 실재적으로 new했을 때 리턴되는 Object형의 객체는 어떻게 사용하는 것인가????
누가 설계했는지 참 머리 좋다. 기존 단순한 함수기반 스크립트에서 객체로의 확장을 가능하게 설계를 한듯하다.
바로 prototype라는 키워드로 해당 함수가 객체화 되면 확장되는 Object를 채우게 될 객체의 명세를 정의(실질적인 클래스정의)하도록 해 놓은 것이다.
문법은 Tab.prototype = {,,,,} 이다.
참으로 간단하지만 참으로 강력한 문법이다.

 
괄호안은
멤버명 : 초기화값,
.... ,
멤버함수명 : function(파라메타,...)
{

},
.....
로 무한히 클래스 정의처럼 정의 해 가면 된다.
정의한 멤버함수 내에서 this.멤버명으로 값을 참조할 수 있고
var aTab = new Tab() // 실재로 Tab.prototype으로 정의된 녀석이 리턴된다는거 ~
aTab.멤버명 = 값
와 같이 값을 초기화 할 수도있다.

여기까지 이해 했다면 DHTML과 자바스크립트를 좀 다뤄보신 분이라면 어떤 DHTML컨트롤이라도 만들 수 있을 것이다.

본 사이트의 탭 구혀에 대한 본격적인 설명에 들어간다
1. 우선 탭을 구성하는 부분을 생각해 보자
   - 각 탭의 헤더(Header)와 바디(Body)가 한 쌍을 이룬다.(new Tab()했을 때 헤더도 생성하고 바디도 생성하면된다)
   - 각 헤더를 클릭하면 쌍에 해당하는 Body가 나타나고 나머지는 사라져야한다.(display속성이용)
2. 1번의 각 탭들을  담는 객체가 하나 필요하다.(TabGroup이라고 명명한다)
   - TabGroup은 각 탭들이 Add될때마다 배열에 각 탭객체를 담아서 관리한다.
   - 나중에 알게 되겠지만 각 탭이 클릭되었을 때 리턴될 콜백함수를 담을 변수도 빌요하다.
대충 이정도로 간단히 구현의 범위를 잡고 시작하면된다.

구현 1) 탭 객체를 정의한다
function Tab()
{
  ....//뭔가를 정의하고 싶을 것이다. 하지만 여기에 정의하는 변수들은 window전역 변수로 작동하므로 아무것도 정의 할 필요 없습니다.
}
또한 Tab(파라메타1,...)등으로 parameter를 넘겨서 뭔가를 초기화도 하고 싶겠지만 아~~~무 의미없습니다.
그냥 다음에 정의할 prototype을 정의하기 위한 중간 과정으로 보시면 됩니다.

//참고로 visual studio 2008로 javascript를 작성 시 한글 주석달면 IE6.0에서 한글이 깨지면서 자바스크립트 오류를 일으킬 수 있으니 참고하세요
  이거때문에 엄청 시간 낭비T.T
Tab.prototype =
{
   header : null, //contain header object
   body : null, // contain body object
   // 나중에 세부적인 변수는 추가 하고....
   CreateTab : function()
   {
      //탭의 헤더와 바디를 new해서 header,body에 저장
      //
   }
}
위와 같이하면 대충 Tab은 정의 된듯하고 그다음 각 탭을 생성해서 저장 할 TabGroup이 필요하다
function TabGroup(){}
TabGroup.prototype =
{
    count : 0,
    arrayTab : new Array(),
    clickedTab : null,
    callBack : null,
    frame : null,
   AddTab : function(sID,sName) //필요한 parameter넘긴다. 속성으로 지정할지 함수parameter로 넘길지는 편한대로 하면된다.
   {
     //실재로 new Tab()으로 생성해서 arrayTab에 추가하겠죠
   }
}
우선 기본 클래스 정의는 이렇게 하면된다.
이 구조는 일반적인 클래스 설계하는 방법과 같다. 단지 자바스크립트의 특수한 문법이 조금 가미되었을 뿐임을 명심하자.

JSON(JavaScript Object Notation)의 객체정의와의 비교
JSON의 객체정의법
 - 객체는 {} 으로 묶은 문자열로 표현,
 - 객체내의 멤버와 초기값은 멤버명 : 초기값 형태로 표현
    var jsonObject = {};
    //alert(jsonObject );
이 코드를 실행 해보라 객체가 alert된다. 어라? 위에서 함수를 new해서 찍는거랑 같네?
그렇다. 함수를 언하는것과  JSON표기법을 사용하는것과 동일하다는 결론이 나온다.
즉 객체를 함수선언으로 new해서 사용 할 수도 있고 JSON표기법을 이용할 수도 있다는 말이되겠다.
다른 표현으로 설명하면 함수는 객체의 형(클래스)선언이고 JSON표기법은 객체를 바로 기술하는 표기법이다.(그래서 new없이 바로사용)


다음코드를 보자.
var jsonObject =
 { 
  field1 : "field1",
  func1 : function()
  {
   alert("1222");
  }
 };
이런식으로 정의하여 사용하면 속성과 메소드를 포함하는 인스턴스 jsonObject가 만들어진다.
한마디로 위에서 함수정의 객체의 prototype를 이용하여 객체를 확정한 후 new해서 사용하는것과 똑같는 결론이다.

위 코드를 일반 문자열로 묶은경우 eval을 이용하여 JSON객체화 하여 사용 할 수도 있다.
    var jsonStr2 = "{var1 : '111', var2 : '222'}";
    alert(eval('(' + jsonStr2 +')') );
이렇게 앞뒤로 괄호를 붙여서 사용하면 OK,
이것은 웹서비스같은데서 리턴되는 문자열을 JSON형식으로 만들어 리턴한 후 객체화 하여 사용할 때 유용한 방법이다.

객체를 중첩해서 사용가능하다.
    var jsonStr1 = {var1 : '111', var2 : { var2_Sub : 'sub2' }};
    alert(jsonStr1.var2 ); // jsonStr1[0]식으로 배열인덱스로도 접근가능하다.

또한 .을 이용하여 추가적으로 확장해 갈 수도 있다.
var jsonStr1 = {};
jsonStr1.var1 = '111';
jsonStr1.var2 = {};
jsonStr1.var2.var2_Sub = 'sub2';
이런식으 코딩도 가능하지만 그렇게 보기좋은 모양은 아닌듯 하다.

그러면 jsonObject내부에 있는 function()에 대해서 한번 확인해보고 넘어가자.
func1 : function() 으로 정의 된부분은 일반 함수선언과 무엇이 다른가? 뭐 똑같지 않은냐? 라고 생각하겠지만 달랐다.

jsonObject.func1()식으로 일반함수처럼 사용하는것은 똑같다.
그러나 일반함수 선언은 new해서 인스턴스화가 가능했지만 이녀석은 인스턴스화가 되지 않는다.
var obj = new jsonObject.func1(); 하면 어떤 결과가 나올까?
필자는 obj가 func1()의 object객체가 될 줄 알았지만 결과는 아니다. 그냥 jsonObject.func()를 호출하는 것일 뿐이었다.
결론은 멤버함수일 뿐이지 새로운 형(클래스)선언은 아니었다.
(어찌보면 당연하다 이미 jsonObject자체가 메모리에 인스턴스로 올라온것이니까)

여기서 재미난 것이 있다.. 우리가 보통 함수포인터라고 부렸던 콜백기능에 대해서 다을 알 것이다.
자바스크립트에도 그런 기능을 구현 할 수 있다는것에 처음에는 정말 놀라웠다. 다음코드를 보자.
var jsonObject =
 {
  field1 : "field1",
  func1 : function()
  { 
        var Me = this;
        return function()
        {
             //if(this == Me)
             alert("1222");
        }
  }
 };
var funcPointer = jsonObject.func1(); // 이녀석이 C#의 델리게이트 선언에 해당한다고 보면된다.
funcPointer();

이코드를 실행해보면 어떤 결과가 나올까? 1222가 alert된다.
func1을 호출했을 때 function정의를 리턴하면 그 함수의 포인터??(아마도)가 리턴되고 변수에 담아놨다가 콜백함수 처럼 호출 할 수가 있는 것이다. 참으로 놀라운 결과이다.

위 코드에서 주석으로 처리된 부분 //if(this == Me) 을 주석부분을 풀면 1222가 호출되지 않는다는것도 중요하다.
Me에 저장된 this포인터는 jsonObject이고 return function()내부에서의 this는 새로운 함수의 포인터라는 차이점이 있다.
콜백 function내부에서 jsonObject의 포인터를 사용하기 위해서는 위와같은 형식으로 Me변수를 정의하여 내부에서 사용해야함을 잊지말아야 할것이다.

그런데 함수포인터를 어떻게  사용하는 것일까?
C#의 delegate를 사용해 보신분들은 해당 event delegate에 함수를 +연산으로 add하는 것을 알고 있을 것이다.
이녀석도 똑 같다. 리턴된 함수포인터는 임의의 함수 형을 담을 수 있는 녀석이다.
다음과 같이 다른 임의의 함수를 대입만 하면 해당함수를 호출하게된다.
function funcCallBack() { alert('aaaa'); }
var jsonObject =
 {
  field1 : "field1",
  func1 : function()
  { 
        var Me = this;
        return function()
        {
             //if(this == Me)
             alert("1222");
        }
  }
 };
var funcPointer = jsonObject.func1();
funcPointer = funcCallBack ;
funcPointer();

음... 그렇다면 
      return function()
        {
             //if(this == Me)
             alert("1222");
        }
부분에 함수를 파라미터로 넘겨서  코딩을 해두면 어떠한가?
function funcCallBack() { alert('aaaa'); }
function initPage()
{
jsonObject =
 {
  field1 : "field1",
  func1 : function(callBack)
  { 
   var Me = this;
   return function()
   {
         //if(this == Me)
        callBack();
   }
  }
 };

    var test = jsonObject.func1(funcCallBack);
    test();
}
이런 형태의 코딩이 나오게 된다. 함수를 파라미터로 넘겨놓고 필요한 경우에 콜백이 되게 호출 할 수 있는 구조가 가능하다.
여기까지를 이해하면 콜백함수를 구현하는 방식은 다 이해된듯하다.
이제 또 중요한 것이 있다. 해당 콜백함수에 jsonObject의 포인터를 넘겨서 어느객체가 콜백을 호출했느냐를 판단을 해야 하는 경우가 있다.
그때 사용하는것이 apply함수이다.
함수가 호출될 때 호출객체를 바꿔치기 해주는일과  호출 파라미터를 배열형태로 넘기게 해준다는 정도만 알 뿐이다.
최종 콜백구현은 아래의 코드와 같다.
function funcCallBack(param1)

  // 여기에서 this포인터를 참조하게되면 콜백의 호출인 경우 아래 jsonObject의 포인터가된다.
  alert(param1);
}
function initPage()
{
jsonObject =
 {
  field1 : "field1",
  func1 : function(callBack)
  {
                  var Me = this;
   return function()
   {
      var arrArg = new Array();
      arrArg[0] = 'aaa';
      callBack.apply(Me, arrArg);

      if(this == Me)  //this point check
       alert("xxxxx");
   }
  }
 };

    var test = jsonObject.func1(funcCallBack);
    test();
}
여기까지의 내용을 이해했다면 당신은 이제 자바스크립트의 재미에 흠뻑빠져든 것이다.
물론 HTML DOM구조등 기존 자바스크립트 사용법은 다 이해하고 있다는 가정하에서이다.
하지만 스크립트 언어는 한계가 있다. 실재로 객체지향적으로 구현을 해 보면 느끼겠지만 제대로 작동하지 않는 속성이나 메소드도 있다.
객체가 중첩되고 중첩될 수록 그런경우는 더 많아지는것 같다. 물론 필자가 캐치하지 버그일 수도 있지만... 그런 버그를 많이 양산 한다는 것 또한 맘에 들지 않는 부분이다. 주저리주저리.....





Posted by Sting!

댓글을 달아 주세요

오늘 강좌는 Boxing과 Unboxing이라는 개념에 대해서 살펴볼 까 합니다. 이것은 일전의 "형 변환을 기반으로 하는 리플렉션"과 관련성이 있는 내용입니다. 그리하여 실질적인 내용을 따져보면 System.ValueType에 관한 특수한 리플렉션 기술이 Boxing과 Unboxing에 해당됩니다.

 

System.ValueType 형식은 메타 데이터 기반이 아닌 "낮은 수준"의 데이터 형식들의 추상 형식입니다. 여기로부터 파생되었다고 알려지는 주요 데이터 형식으로는, System.Byte, System.Int16, System.Int32, System.Int64, System.Float, System.Double 등이 있습니다. 하지만 이러한 데이터 형식들은 메타 데이터 기반이 아닙니다. 정확한 풀이로는 힙에 할당되며 크기 또한 자유자재로 변형될 수 있는 형식들입니다. 메타 데이터로 표기하는 것은 엄청난 오버로드를 수반하게 되므로 부적절합니다. 하지만 .NET Framework는 이를 매끄럽게 처리하게 되어있는데 그것이 Boxing과 Unboxing이라 불리우는 기술입니다.

 

Boxing과 Unboxing의 의미 풀이부터 해보도록 합니다. 두 단어 모두 Box 라는 키워드를 포함하는데, 쉽게 생각할 수 있습니다. 힙에 할당된 연속적인 데이터를 편리하게 관리하기 위하여 포장을 해놓는다 라는 의미에서 Box를 떠올리면 쉽습니다. 즉, 힙에 할당된 연속적인 데이터를 메타 데이터가 이해할 수 있는 형태로 포장해준다는 의미입니다. 그러면 실제 코딩을 살펴보도록 하지요.

 

int i = 123;

object o = (object)i;

 

위의 두 코드를 살펴보면, 사실 아무런 의미는 없습니다. 하지만 이것이 Boxing의 대표적인 예입니다. 이러한 코딩이 가능함으로서 얻을 수 있는 이점이 대단히 큽니다. Boxing을 가장 잘 활용하는 예는 ADO .NET 관련 클래스들입니다. 데이터 베이스 시스템이 질의에 대한 결과로 반환하는 데이터 형식을 한꺼번에 다루기 위한 방법으로 Boxing과 Unboxing을 복합적으로 활용합니다.

 

i 라는 변수에 123이라는 정수 값을 대입했습니다. 그 다음, o 라는 하나의 추상 객체를 선언하여 형식 변환을 취하였습니다. 코드 상에서는 분명히 형식 변환으로 표기되었습니다만 사실 이 둘은 형식 변환이 일어날 수 없는 관계입니다. object는 메타 데이터로 표기되는 데이터만을 다룰 수 있지만 int는 힙에 할당되는 연속적인 데이터 스트림입니다. 서로 관계가 없지만 이것이 가능했던 이유가 바로 Boxing입니다.

 

int x = (int)o; // Okay

long y = (int)o; // Okay

short z = (int)o; // Error!

 

x는 i와 같은 int 형식이고, y는 int 형식보다 큰 범위의 수를 다룰 수 있는 long 형식이며, z는 int 형식보다는 작은 범위의 수를 다루는 short 형식입니다. 세 동작 모두 object 형식을 int 형식으로 바꾸는 동시에 Unboxing을 수행하게 되었습니다. 즉, object 형식으로 포장된 데이터의 원래 내용물을 대입한 것입니다. 하지만 x, y와는 다르게 z는 컴파일 오류를 낼 것입니다.

 

x는 손실 변환이 일어나지 않았으며 원래의 형식 그대로를 수용하였습니다. y는 원래의 i가 요구하던 정수 범위보다 더 큰 정수 범위를 지원하게 되어 확장 변환이 일어났습니다. 이 경우 두 가지 의미로 해석이 가능한데, 말 그대로 가능성을 위하여 예약된 확장 변환일 수 있지만 반대로 불필요한 공간이 더 많이 할당된 오버헤드 변환이기도 합니다. 하지만 z는 컴파일 오류를 냅니다. 손실 변환으로 다루어질 수도 있겠지만 Unboxing의 정의에 의하면 원래 가지고 있던 데이터 형식보다 범위가 더 적어졌으므로 메모리 구조와는 일치하지 않는 것으로 해석됩니다.

 

int a = o as int; // Error

 

형 변환에 사용하는 as 키워드로 변환을 시도해 보았습니다. 하지만 오류가 나게됩니다. 왜 일까요? as 형식으로 형변환이 가능하다는 것은 메타 데이터에 한정된 내용입니다. 따라서, System.ValueType으로부터 상속받은 모든 형태의 값 형식에서는 as로 형변환을 하거나 as로 Unboxing되지 않게 되었습니다.

 

as를 사용하고자 하였던 의도가 예외를 Throw 하지 않고 null을 대입하려 했던 것이었다면 null을 대입하지 않는 대신 다음과 같은 방법으로 처리하는게 좋습니다.

 

try { int a = (int)o; }

catch { /* 예외 처리 코드 */ }


Posted by Sting!

댓글을 달아 주세요

메모리영역

C# 2008. 12. 9. 19:22
출처 바람처럼 어디론가 나만의 여행을 가고 싶다 | 바람향기
원문 http://blog.naver.com/aroma_guy/20006951137

메모리 영역

 

- 코드(Code)영역

코드 자체를 구성하는 메모리 영역. 즉 프로그램 명령이 위치하는 곳으로 기계어로 제어되는 메모리 영역이다.

 

- 데이터(Data)영역

데이터가 보관된다. 예를 들면 전역변수(global), 정적변수(static), 그 외 초기화된 각종 배열과 구조체, 자료들이 저장된다.

 

- 스택(Stack)영역

프로그램이 자동으로 사용하는 임시 메모리 영역에 해당합니다. 즉 자동 변수를 저장하거나 함수로 인수를 보낼 때, 복귀 번지를 저장할 때 등에 사용된다. 스택 사이즈는 각 프로세스마다 할당된다. 하지만 프로세스가 메모리에 로드될 때 스택 사이즈가 고정되어 있어, 런타임시에 스택 사이즈를 바꿀 수는 없다. 참고로 VC++6.0에서는 Project Settings에서 스택 사이즈를 바꿀 수 있다.

 

- 힙(Heap)영역

프로그래머가 스스로 할당한 메모리 영역(동적 메모리 영역)을 뜻한다. 즉 C의 함수 중에 메모리를 할당하는 함수인 malloc() 등을 사용하여 할당된 메모리가 힙 영역에 해당된다. 메모리 모델에 따라서 사용하는 함수가 달라지는데, 메모리 할당 때는 malloc(), farmalloc() 함수를 사용하고 재할당 때는 realloc() 함수를, 메모리 해제 시는 free()나 farfree() 함수를 사용한다.

 

Posted by Sting!

댓글을 달아 주세요

메모리 영역

C# 2008. 12. 9. 19:18

언어 책을 보면 스택이나 힙, 큐, 데크라는 말이 나옵니다. 물론 이 말의 뜻을 몰라도 프로그램 짜는데 어려움은 없습니다. 모든 것은 컴파일러라 알아서 해주니까요. 그렇지만 용어의 의미도 모르고 프로그램을 만들려면 조금 답답합니다.

이들 용어는 사용하는 곳에 따라서 의미가 조금 다릅니다. 자료 구조에서 사용할 때와 메모리에서 사용할 때 의미가 조금씩 다릅니다. 자료 구조론에서는 스택과 큐, 데크 등의 용어를 사용합니다. 반면 프로그램을 만들 때는 스택과 힙이라는 용어를 많이 사용합니다.

먼저 우리가 보통 스택과 큐, 힙을 말할 때는 C나 C++의 메모리 구조와 관련된 용어로 사용 합니다. C/C++에서 메모리는 다음과 같은 계층을 이룹니다.

1. 코드(code) 영역
2. 데이터(data) 영역
3. 힙(heap) 영역
4. 스택(stack) 영역

코드 영역은 코드 자체를 구성하는 메모리 영역입니다. 즉 프로그램 명령이 위치하는 곳으로 기계어로 제어되는 메모리 영역입니다. 하위 메모리라고 부르는 가장 낮은 쪽에 있는 메모리 영역입니다. 이 부분은 기계어 부분이므로 프로그래머가 신경 쓸 이유가 없습니다.

데이터 영역에는 데이터가 보관됩니다. 예를 들면 전역(global) 변수, 정적(static) 변수, 그외 초기화된 각종 배열과 구조, 자료들이 저장됩니다.

힙 영역은 프로그래머가 스스로 할당한 메모리 영역을 뜻합니다. 즉 터보C의 함수 중에 메모리를 할당하는 함수인 malloc() 등을 사용하여 배정한 메모리가 힙 영역에 해당합니다. 메모리 모델에 따라서 사용하는 함수가 달라지는데 메모리 할당 때는 malloc() farmalloc() 함수를 사용하고 재배정 때는 realloc() 함수를, 메모리 해제 때는 free()나 farfree() 함수를 사용합니다.

스택 영역은 프로그램이 자동으로 사용하는 임시 메모리 영역에 해당합니다. 즉 자동 변수를 저장하거나 함수로 인수를 보낼 때, 복귀 번지를 저장할 때 등에 사용합니다.

스택과 힙은 사용 용도에 따라서 조금씩 다른 의미로 사용합니다. 예컨대 버퍼 메모리에서 스택고 힙이라는 용어를 사용하면 버퍼 메모리를 구성하는 두 가지 방식을 뜻합니다. 이때 스택은 후입선출(LIFO=Last In First Out) 방식의 버퍼를 말하고, 힙은 선입선출(FIFO=First In First Out) 방식의 버퍼를 뜻합니다.

스택의 경우 후입선출 방식이므로 동작 과정이 푸시(push)와 팝(pop)의 과정으로 이루어집니다. 이를 통해 동작이 한 쪽 끝(top)에서만 일어납니다. 다시 말해서 자료가 들어가는 구멍(입구)과 나오는 구멍(출구)이 하나입니다. 이 때문에 맨 마지막에 들어간 것이 제일 먼저 나오는 겁니다.

큐(Queue)는 프로그램 언어에서 보면 자료 구조의 한 형태로 순차 목록의 한 형태를 뜻합니다. 원소의 삽입은 뒤(rear)에서 이루어지고 삭제는 앞(front)에서 이루어지는 자료 구조를 뜻합니다. 메모리에 적용할 경우 큐는 선입선출 방식을 뜻합니다. 이 때문에 힙과 큐를 혼동해서 사용하기도 합니다. 의미는 같지만 큐는 자료 구조론에서 사용하는 용어고, 힙은 메모리 관련 용어로 사용한다고 보면 됩니다.

데크(Deque)는 Double Ended QUEue의 줄임말로 스택과 큐의 동작 방식을 복합한 방식입니다. 자료 구조에서 선형구조의 목록을 뜻하는 용어로 목록의 양 쪽 끝에서 삽입과 삭제가 가능한 방식입니다.

데크는 입출입 형태에 따라서 한 쪽을 제한할 수 있습니다. 입력 제한 데크라는 방식은 scroll이라고 하는데, 삽입(input)은 목록의 한 쪽 끝에서 이루어지고, 삭제(출력,output)는 목록의 양 쪽 끝에서 이루어지는 방식입니다. 반대로 출력 제한 데크가 있습니다. 출력 제한 데크는 shelf라고 하는데 삽입은 양 쪽 끝에서 이루어지고, 삭제는 목록의 한 쪽 끝에서 이루어지는 방식을 뜻합니다.


Posted by Sting!

댓글을 달아 주세요

블로그 결정...

잡담... 2008. 12. 9. 19:16
티스토리 써야겠다~
Posted by Sting!

댓글을 달아 주세요