ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 인터프리트 언어로서의 자바
    혼자서 공부하기/자바 2007. 4. 3. 03:11
    728x90
    반응형
    SMALL

    인터프리트 언어로서의 자바 

     

     

     

     

     

    1.열기

     

      사내 강좌를 통해 자바를 처음 접했을 때 자바의 특성으로서 플랫폼 독립성, 다형성, 보안성, 단순성, 동적 링크 등을 소개받았다. 그 당시, 객체지향에 대해 문외한이었던 나로서는 낱말 조차 생소했던 그 개념들을 자바 또는 OO 프로그램 고유의 특성이라고  받아들였다. 그러한 특성들이 OO 프로그램에서 잘 나타난다는 점에서 당시 나의 생각이 틀렸던 것은 아닌 것 같다. 다만, 자바를 본격적으로 공부하면서, 그러한 특성들을 개별 프로그래밍 언어나 특정 방법론에 복속시켜 바라볼 문제는 아니라는 생각이 들었다. 자바의 작동 방식을 살펴보면서, 위에서 열거한 개념들 가운데 많은 것들이 인터프리팅 방식을 따름으로써, 좀더 유리하게 실현된다는 사실을 깨달을 수 있었던 것이다.

     

     

     

    2.컴파일 언어와 인터프리트 언어

     

      프로그래밍 언어는 실행 방식에 따라 크게 두 가지로 나눌 수 있다. 하나는 실행하기 전에 실행에 대한 모든 것들을 결정해 놓는 언어이며, 다른 하나는 실행 시점에 결정하는 언어이다. 알다시피 앞엣 것을 컴파일 언어라고 부르고 뒤엣 것을 인터프리트 언어라고 부른다. 컴파일 언어에서의 '컴파일'이란 원시코드를 목적코드로 변환하는 일련의 작업을 일컫는다. 컴파일 과정을 순서대로 나열하면 다음과 같다.

     

    1)원시코드 : 프로그래머들이 에디팅한 코드 

    2)어휘분석 : 사용 가능한 낱말들로 이루어졌는지 점검

    3)구분분석 : 낱말들의 연결이 타당한지 점검

    4)의미분석 : 연결된 문장의 의미가 옿은지 점검. 가령 함수의 리턴 타입대로 반환되는지 여부

    5)목적코드 : 머신코드로 변환

     

    쉽게 말해 소스코드의 유효성을 점검하고 이상이 없으면 기계어로 변환하는 일을 두고 컴파일 작업이라고 말한다. C와 같은 컴파일 언어에서는 컴파일(목적코드 생성) 작업 후, 링크 편집 과정을 거친다. 링크 편집이란 목적코드 내의 한 모듈에서, 참조하고 있는 다른 모듈의 상대적 위치를 결정하는 작업을 말한다. 링크 편집이 완료되면 로드모듈이라는 결과물이 만들어지는데, 로드모듈이 작성되었다는 것은 실행에 대한 모든 지침이 마련되었다는 것을 뜻한다. 그러니까, 변수 a의 데이터 타입이 런타임 이전에 이미 파일 내에 기록되어 있는 셈이다.

      컴파일 언어가 프로그램 전체를 번역한 후 실행된다면, 인터프리트 언어는 명령 줄 단위로 번역한 후 그 결과를 머신에 전달하는 방식을 취한다. 다음은 JVM 인터프리터와 관련한 예제이다.

     

     

    do {

       byte opcode = fetch an opcode;

       switch (opcode) {

         case opCode1 :

             fetch operands for opCode1;

             execute action for opCode1;

             break;

         case opCode2 :

             fetch operands for opCode2;

             execute action for opCode2;

             break;

         case ...

    } while (more to do)

                            

    Bent Thomsen <Language and Compliers> www.cs.auc.dk/~bt/SPOF04/SPOF04-13-2.ppt

     

    1)클래스로더가 클래스파일의 바이트코드를 가져온다.

    2)JVM은 메모리에서 바이트코드(opcode) 하나를 꺼내온다.

    3)가져온 바이트코드에 매핑되어 있는 동작을 찾아가서 수행한다.

      다른 클래스의 메소드를 호출하는 경우라면 해당 클래스를 메모리에 적재한 후 수행한다.

    4)인터프리트할 바이트코드가 없을 때까지 2)번과 3)번 과정을 반복한다.

     

    SWITCH/CASE 구문 자체가 말해주는 바대로, 명령줄 단위로 번역하고 실행하는 것이 인터프리팅 동작의 원리이다. 이와 같이 인터프리팅 언어는 명령줄 단위로 실행되기 때문에 개발분의 즉각적인 테스트가 가능하다. 또한 프로그램 전체가 로딩될 필요가 없기 때문에 컴파일 언어에 비해 메모리를 적게 사용할 수 있다.

     

     

     

    3.인터프리팅 또는 실행의 지연

     

      메모리 사용의 효율성, 디버깅의 편리성 등 인터프리트 언어에는 여러 가지 장점들이 있지만 자바에서는 인터프리팅이 갖는 '지연의 성질'에 주목했던 것으로 보인다. 명령의 실행을 늦춘다는 것은 그것이 행해지는 시점의 문맥에 맞추어 해석하고 판단할 수 있는 여지를 마련한다는 것을 의미한다. 하나의 명령어가 어디에서 번역될지, 하나의 변수가 어떤 데이터 타입으로 결정될지, 하나의 함수가 다른 함수를 언제 어떻게 링크할지 따위에 대해 인터프리트 언어는 보다 유연하게 결정할 수 있는 것이다.

     

    1) 플랫폼 독립성

    머신에 적재되어 실행되는 순간에 번역되고 실행되기 때문에, 컴파일 언어에 비해 플랫폼 독립성을 꾀하기 유리하다. 이 세상에 세 가지 종류의 컴퓨터(C1,C2,C3)가 있다고 가정해보자. 컴파일 언어로 짠 프로그램 P1이 모든 머신에서 작동하려면, C1 컴파일러 C2 컴파일러 C3컴파일러로 컴파일한 후 3벌의 목적파일을 각각의 기계에 배포하여야 한다. 프로그램 P2가 개발되어도 이 같은 과정은 반복되어야 한다. 반면 인터프리트 언어의 경우에는, C1, C2, C3 인터프리터 3개를 각 머신에 탑재하기만 한다면, P1 코드는 런타임에 각 인터프리트에 의해 기계에 알맞게 번역되어 동일하게 작동할 수 있다. 뿐만 아니라, 프로그램 P2가 개발되더라도 이제 배포만 하면 플랫폼에 관계없이 작동하게 된다.

     

    2) 다형성

    프로그램 내에 사용되는 이름들은 속성을 갖게 마련이다. 이름이란 변수, 상수, 함수, 매개변수 등의 식별자를 말하며 속성이란 값, 타입, 크기, 위치 등을 말한다. 바인딩이란 프로그램 내의 이름에 특정한 속성을 붙이는 일이다. 컴파일 언어에서 바인딩은 컴파일 타임에 이루어진다. 이렇게 정해진 이름과 속성은 로딩 과정에서 메모리에 그대로 적재되고 실행된다. 이에 비해 인터프리트 언어는 런타임 시점에 이름에 대한 속성을 결정할 수 있다. 앞엣 것은 정적 바인딩, 뒤엣 것은 동적 바인딩이라고 부른다.

    동적 바인딩은 객체지향 언어의 중대한 형질인 다형성을 실현하는 데 크게 기여한다. 그도 그럴것이, 데이터 타입이 실행 시점의 상황에 따라 여러 형태로 캐스팅되는 성질이 바로 다형성의 핵심 내용이기 때문이다. 객체지향에서 타입은 데이터뿐만 아니라 메소드도 아우른다. 따라서 철수.일하다() 라는 메소드는 그것에 어떤 타입이 할당되었느냐에 따라 다르게 수행될 수 있다. '철수' '교수' 타입이 할당되었다면 강의가 행해질 것이고, '운전자' 타입이 할당되었다면, 운전하기가 행해질 것이다. 컴파일 언어인 C++에서는 이를 위해 가상 함수라는 것을 특별히 사용해야 하지만 자바에서는 디폴트로 구현된다. 

     

    3) 동적 링크     

    동적 바인딩의 한 맥락이다. 모듈 A가 모듈 B를 호출할 때, A B의 상대적 참조값 또는 위치 정보를 알고 있어야 한다. 컴파일 언어에서는 런타임 이전에 링크 편집을 완료한다. 실행 시에는 이미 확정되어 있는 이러한 심볼 정보를 바탕으로하여 참조하고 있는 모듈들을 찾아가기만 하면 된다. 이 같은 정적 링크 방식은 프로그램 관리를 번거롭게 만드는 요인이 된다. B 모듈 중 참조값과 관련된 사항이 바뀌었다면, 바뀌는 대로 B는 물론 A도 재컴파일 및 링크하여야 한다는 것을 의미한다. 그렇게 하지 않는다면, 치명적인 오류가 발생할 수도 있다. 이에 반해 인터프리트어의 경우에는 실행 시점에 이르러 호출하는 함수들에 대한 참조값을 알아낸다. 이렇게 함으로써 인터프리트어는 컴파일 언어가 갖는 '관련된 모듈의 재컴파일 및 링크'라는 과정을 피할 수 있게 된다. 

     

    4) 보안성

    웹 서핑 중 브라우저를 통해 특정한 프로그램 코드가 자동으로 배포되고 실행된다면, 시스템은 항상 위험으로부터의 노출을 감내해야 한다. 왜냐하면 배포되는 코드를 통해 악의적인 데이터나 프로그램이 침투할 수 있기 때문이다. 인터프리트 언어가 갖는 '지연의 미덕', 코드를 해독하여 머신에 명령이나 데이터를 전달하기 전 보안을 체크할 수 있는 여지를 마련한다. A 시점에서는 integer 타입이던 변수가 B 시점에 이르러  포인터로 돌변하는 상황을 미연에 막을 수 있는 것이다.

     

    5) 수행 속도

    당연한 말이겠지만, 인터프리트 언어가 갖는 지연의 성질은, 수행 속도 면에서 걸림돌이 된다. 어떤 인터프리트 언어 A가 소스 코드를 번역하면서 수행한다고 가정하자. A는 컴파일 언어가 컴파일 시에 수행하는 코드 분석 작업, 링크 작업, 기계어 변환 작업 등을 런타임시에 모두 치루어야 할 것이다. 소스코드 내에 크고 긴Loop문이 있다고 할 때 그 과정은 Loop 횟수만큼 반복되어야 한다. 다행히 자바에서는 원시코드를 인터프리팅하는 게 아니라 반 기계어 형태인 바이트코드를 인터프리팅함으로써 오버헤더를 줄일 수 있다.

     

     

     

    4.닫기

     

      이상의 특징들이 모든 인터프리트 언어에서 동일하게 나타난다고 말할 수는 없다. 객체지향 방법론이나 크로스플랫폼 언어가 개발되기 전에도 인터프리트 방식은 존재했었다. 다만, 한 가지. 위에서 열거한 특징들은 컴파일 언어보다는 인터프리트 언어에서 나타나기 쉽다는 사실이다. 플랫폼 독립성, 유연성, 다형성, 보안성 등이 자바의 특성이기도 하지만, 인터프리팅 방식에서 잉태한 특성이기도 하다는 사실을 인지하는 것은 유익한 일이다. 왜냐하면 이러한 사실을 인식할 때, 우리는 자바를 자바 자체나 객체지향 언어의 맥락에서 뿐만아니라 '컴파일/인터프리트'라는 프로그래밍 언어의 이항대립항을 통해서도 바라보고 이해할 수 있기 때문이다.

    2차 출처 : 자바누리 자료실- 기술문서/매뉴얼
    1차 출처 : http://blog.naver.com/bigblogger

    728x90
    반응형
    LIST

    댓글

Designed by Tistory.