Hey, Scripting Guy!말 조심하세요

Microsoft Scripting Guys

남북 전쟁(구체적으로 Spotsylvania 전투) 중 북군의 John Sedgwick 장군은 남군의 저격수가 가끔씩 총을 쏘아대는 통에 부하들이 위축된 것을 보고 크게 실망했습니다. 전해져 오는 이야기에 따르면 Sedgwick이 부하들에게 "나는 그렇게 숨어 있는 제군들이 부끄럽다. 이 거리에서는 코끼리도 맞추지 못한다."라고 말했다고 합니다. 그렇게 말하고 난 잠시 후에 그는 전쟁 중에 전사한 최고 서열의 북군 장군이 되었다고 합니다. 남군의 저격수가 그 거리에서 코끼리를 맞추지는 못했을 것입니다. 그러나 불행하게도 Sedgwick 장군은 그들의 총에 맞고 말았습니다.

물론 이 이야기의 교훈은 두 말할 나위 없이 "누군가 너를 노리고 있으면 몸을 낮춰라."라는 것입니다. 그렇지 않습니까? 그렇지만 우리는 그렇게 생각하지 않습니다. 대신 우리가 얻은 교훈은 "내뱉은 말이 나를 따라다닐 수 있으므로 말 조심해야 한다."라는 것입니다. 이 교훈은 John Sedgwick 장군뿐만 아니라 다른 많은 사람들에게도 들어 맞는 이야기입니다. 예를 들어, 장기간 IBM 회장을 역임했던 Thomas Watson을 미국 역사에 남을 위대한 기업가 중 한 사람으로 기억하는 사람은 아무도 없습니다. 그 대신 Watson은 "컴퓨터에 대한 수요는 전세계적으로 5대 정도에 불과할 것이다."라고 말한 사람으로 기억되고 있습니다.

흥미롭게도 Watson이 실제로 이렇게 말했다는 증거는 없습니다. 기껏해야 다른 사람의 생각을 단순하게 언급했을 것이라고 추측하는 정도입니다. 그러나 누가 신경 씁니까? 결국 IBM 회장이 '컴퓨터 시장은 없다.'라고 말했을 것이라는 생각에서 우리는 이러한 우스운 일이 퍼지는 것은 막을 수 없다는 좋은 교훈을 얻었습니다.

Watson은 "성공하는 비결은 실패율을 두 배로 높이는 것이다."라는 말도 했습니다. Scripting Guy는 이 충고를 진심으로 받아들이고 있습니다.

그러니까 실패율을 두 배로 높이라는 말만큼은 중요하게 생각한다는 거죠.

이제 "VBScript 스크립트를 작성할 때는 .NET Framework에 액세스할 수 없다."는 말을 살펴봅시다. 스크립트 작성자는 Microsoft® .NET Framework에 액세스할 수 없다라는 말은 "이 거리에서는 코끼리도 맞추지 못한다."라는 말이나 "컴퓨터에 대한 수요는 전세계적으로 5대 정도에 불과할 것이다."라는 말과는 달리 그리 기억에 남을 만한 말은 아닙니다만, 사실과 거리가 멀다는 점만은 동일합니다. 물론 .NET Framework가 C# 및 Visual Basic® 개발자를 염두에 두고 설계되었다는 것과 VBScript에서 네이티브 .NET Framework 클래스를 인스턴스화할 수 없다는 것은 사실입니다. 그렇다고 해서 스크립트 작성자가 .NET Framework에 전혀 액세스할 수 없는 것은 아닙니다.

맞습니다. 여러분의 말처럼 대부분의 .NET Framework 클래스는 VBScript로 직접 가져올 수 없는 클래스입니다. 그러나 COM 호출 가능 래퍼를 갖고 있는 .NET 클래스가 상당히 많이 있습니다. 이는 곧 이러한 클래스에 COM 인터페이스가 있어 VBScript와 같은 스크립트 언어에서 액세스할 수 있다는 것을 뜻합니다. 믿기 어렵습니까? 그림 1에 표시된 레지스트리의 HKEY_CLASSES_ROOT 부분에서 System으로 시작하는 모든 종류의 클래스를 살펴보십시오.

그림 1 레지스트리에 있는 System 클래스

그림 1** 레지스트리에 있는 System 클래스 **(더 크게 보려면 이미지를 클릭하십시오.)

이들 클래스의 대부분은 .NET Framework 클래스이며 VBScript를 통해 인스턴스화할 수 있습니다.

앞에서 말했던 것처럼 말입니다.

물론 전날 밤 TV 광고를 보고 제품을 구매한 적이 있는 사람이라면 누구나 알 수 있듯이 무언가를 '할 수 있다'**는 것이 그것을 반드시 해야 한다는 것을 의미하지는 않습니다. 일반적으로 그러한 제품을 매장에서 판매하지 않는 이유가 있는 것처럼 말이죠. 즉, 스크립트에서 System.ContextMarshalException 클래스의 인스턴스를 만들 수 있습니다. 그러나 우리는 여러분이 인스턴스를 왜 만들려고 하는지 그리고 인스턴스를 만들어 무슨 작업을 수행하려는 것인지 모르겠습니다.

그러나 일부 .NET Framework 클래스에서는 인스턴스를 만드는 것이 유용한 경우도 있습니다. 예를 들어, 스크립트 세계에 근거 없이 떠도는 이야기 중 하나는 항목 목록을 쉽게 정렬할 수 있는 방법이 없다는 것입니다. 목록을 사전순으로 정렬하려면 연결이 끊어진 레코드 집합을 사용하거나 다음 버블 정렬 코드와 같이 매우 복잡한 정렬 함수를 직접 만들어야 합니다. 속이 뒤틀리는 사람은 다음 단락으로 이동해도 좋습니다.

For i = (UBound(arrNames) - 1) to 0 Step -1
    For j= 0 to i
        If UCase(arrNames(j)) > 
          UCase(arrNames(j+1)) Then
            strHolder = arrNames(j+1)
            arrNames(j+1) = arrNames(j)
            arrNames(j) = strHolder
        End If
    Next
Next

머리 아프게 들여다볼 필요는 없습니다. 우리가 작성한 코드이기는 하지만 우리도 뭐가 뭔지 잘 모르겠습니다.

이런 상황에서 .NET Framework를 어떻게 사용할 수 있겠습니까? 그 대답을 찾기 위해 다음과 같은 매우 간단하고 짧은 스크립트를 살펴보겠습니다.

Set DataList = CreateObject _
      ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()

For Each strItem in DataList
    Wscript.Echo strItem
Next

위에서 볼 수 있는 것처럼 이 코드에서는 .NET Framework 클래스인 System.Collections.ArrayList의 인스턴스를 만듭니다. 그런 다음 Add 메서드를 사용하여 항목 5개를 목록에 추가합니다. 이 코드는 모든 것이 올바르고 아무 문제 없는 것으로 보이나 순서에 상관없이 무작위(B, C, E, D, A)로 항목을 추가했기 때문에 항목을 사전순(A, B, C, D, E)으로 표시해야 할 필요가 있습니다. 이제 버블 정렬 코드를 추가하면 될 것 같은데 맞습니까?

틀렸습니다. 미안하지만 틀린 것은 틀린 것입니다. 버블 정렬 코드를 추가할 필요 없이 다음과 같이 ArrayList의 Sort 메서드를 호출하기만 하면 됩니다.

DataList.Sort()

이게 다입니다. 단 한 줄의 코드로 배열 목록의 모든 항목을 정렬할 수 있습니다.

확인해 볼까요? 정말 확인해 보라구요? 좋습니다. 여러분 중에 의심 많은 분들이 있을 거라 생각하고 목록의 모든 항목에 대해 루프를 돌면서 각 항목의 값을 화면에 표시하는 For Each 루프를 스크립트에 넣어 보겠습니다.

For Each strItem in DataList
    Wscript.Echo strItem
Next

이제 까다로운 질문을 하나 하겠습니다. 이 스크립트를 실행하여 어떤 결과를 얻을 것 같습니까?

바로 아래와 같이 나타납니다.

A
B
C
D
E

문제 없이 잘 되었네요. 그렇죠?

여기에 만족하지 않는 분도 계시는 것 같군요. 문제 없이 잘 되었다고 말하고 있기는 하지만 여러분이 진짜로 원했던 것은 이 값들을 내림차순으로 표시하는 것이었군요. 즉, A-Z 순서로 된 목록이 아니라 Z-A 순서로 된 목록을 원하는 것이죠? 내림차순 정렬이 잘 안 된다면 한번 생각해 보죠.

좋아요, 문제 없습니다. 모든지 주문만 하십시오.

Set DataList = CreateObject _
      ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()
DataList.Reverse()

For Each strItem in DataList
    Wscript.Echo strItem
Next

맞습니다. 이 코드는 조금 전에 본 스크립트와 거의 동일합니다. 그러나 한 가지 중요한 부분이 추가되었습니다. 추가된 한 줄을 찾아 보십시오. Sort 메서드 바로 뒤에 다음과 같은 한 줄이 추가되었습니다.

DataList.Reverse()

보이십니까? 오름차순으로 목록을 정렬한 후 배열에 있는 모든 항목의 순서를 역순으로 바꿔주는 Reverse 메서드를 호출했습니다. 어떤 결과가 나올까요? 그 결과는 다음과 같습니다.

E
D
C
B
A

정말 신기하지 않습니까?

잠깐만! 또 있습니다. VBScript 배열에서 항목을 제거해 본 적이 있습니까? 없다고요? 괜찮습니다. 항목을 제거하라고는 하지 않겠습니다. 대신 .NET Framework ArrayList에서 항목을 제거하는 것이 얼마나 쉬운지 보여 드리겠습니다. 문자 D가 마음에 들지 않으세요? 제거하죠, 뭐. 다음 스크립트에서는 배열 목록을 만들고 정렬한 다음 D 항목을 제거합니다.

Set DataList = CreateObject _
  ("System.Collections.ArrayList")

DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"

DataList.Sort()
DataList.Remove("D")

For Each strItem in DataList
    Wscript.Echo strItem
Next

다시 한번 Sort 메서드 바로 뒤에 있는 줄을 살펴보십시오.

DataList.Remove("D")

여기에서는 Remove 메서드를 사용하여 D와 동일한 항목을 제거했습니다. 다음은 스크립트가 실행된 결과입니다.

A
B
C
E

이제 D가 삭제되었죠?

그리고 가장 중요한 부분을 간과하지 마십시오. 바로 배열의 크기나 차원을 변경하지 않고도 항목을 제거할 수 있다는 것입니다. 정말 멋지지 않습니까? 물론 배열의 크기나 차원을 변경하지 않고도 배열에 항목을 추가할 수도 있습니다. 스크립트 작업이 수월해지지 않았습니까?

안 믿을 수도 있겠지만 지금까지의 내용은 .NET Framework ArrayList로 수행할 수 있는 작업의 일부에 불과합니다. 자세한 내용은 .NET Framework SDK의 ArrayList 항목(영문)을 참조하십시오.

ArrayList가 스크립트 작성자에게 그렇게 유용합니까? 이렇게 말하고 싶군요. .NET Framework ArrayList가 있는데 기본 제공 VBScript 배열을 왜 굳이 사용하려고 하는지 모르겠습니다. 여기에서 사용한 목록과 같이 매우 간단한 항목 목록만 아니라면 ArrayList가 매우 유용할 것입니다.

그동안 Scripting Guy는 스크립트 작성자에게 유용하거나 유용하지 않은 클래스를 찾기 위해 .NET Framework를 꼼꼼히 살펴보지는 않았지만 현재 열심히 조사 중입니다. 자세한 내용은 전체 .NET Framework SDK(영문)를 참조하십시오. SDK를 볼 때마다 스크립트 작성자가 사용할 수 있는 새롭고 흥미로운 것을 발견하게 됩니다.

예를 들어 임의 번호를 생성할 수도 있습니다. VBScript 임의 번호 생성기를 사용하여 1-100 사이의 임의 번호를 생성하고 싶습니까? 다음과 같은 코드를 사용하면 쉽게 해결할 수 있습니다.

Randomize
Wscript.Echo Int((100 - 1 + 1) * Rnd + 1)

수식을 외우셨습니까? 외우지 않았더라도 걱정하지 마십시오. .NET Framework의 System.Random 클래스를 사용하면 훨씬 간단하고 쉽게 해결할 수 있습니다.

Set objRandom = CreateObject("System.Random")
Wscript.Echo objRandom.Next_2(1,100)

설명하지 않아도 바로 알 수 있을 것입니다. 그렇다고 하더라도 TechNet Magazine에서는 칼럼니스트가 매월 정보를 기재해야 한다고 생각하기 때문에 간단하게 설명하겠습니다. TechNet Magazine의 정책 때문에 우리가 고생해야 하는 이유를 모르겠습니다.

위에서 볼 수 있는 것처럼 이 코드에서는 System.Random 클래스의 인스턴스를 만든 다음 2개의 매개 변수를 전달하는 Next_2 메서드를 호출합니다.

  • 1은 범위의 첫 번째 숫자입니다. 앞에서 1-100 사이의 임의 번호를 생성하기로 한 것을 기억하시죠?
  • 100은 범위에서 가장 큰 숫자입니다.

이제 다 했습니다.

마지막 질문에 대한 답을 할 시간이 된 것 같군요. 예, 마음에 드셨군요. 도대체 스크립트 작성자가 .NET Framework에 액세스할 수 없다고 말한 사람이 누구입니까? 솔직히 처음 시작할 때 시간이 부족할 것이라고 생각했는데 정말 그렇네요. 다음 달에 뵙겠습니다.

기다리고 기다리던 시간

2월이 다가오는데 무엇이 생각나십니까? 발렌타인 데이? 아니요. 오, 이런... 구정이 생각나신다고요? 아니죠. 2월에는 우리가 그렇게도 기다리던 세계 제1의(아마도 세계에서 유일한) 국제 스크립트 경쟁 대회인 2007 Winter Scripting Games가 열립니다. 올해의 행사는 그 어느 때보다도 성대하게 열릴 것이며, 다음 4가지 부문으로 진행될 것입니다.

  • 초급 VBScript
  • 고급 VBScript
  • 초급 Windows PowerShell™
  • 고급 Windows PowerShell

자세한 내용은 2007 Winter Scripting Games 홈 페이지(영문)를 참조하십시오.

뭐라고요? 아, 감사합니다. 여러분도 새해 복 많이 받으세요.

Windows PowerShell 다운로드

이제는 Windows PowerShell 1.0을 다운로드할 수 있습니다. 그것도 무료로 말입니다. 정말 좋은 기회 아닌가요? 지금 바로 소프트웨어를 다운로드(영문)하십시오.

Microsoft Scripting Guys는 Microsoft의 업무를 담당하는, 정확히 말하면 Microsoft에 고용된 직원입니다. 이들은 야구를 하거나, 감독하거나, 관람하는 등의 일상적인 다른 활동을 하지 않을 때 TechNet 스크립트 센터를 운영합니다. 자세한 내용은 https://www.microsoft.com/korea/technet/scriptcenter/default.mspx에서 확인하십시오.

© 2008 Microsoft Corporation 및 CMP Media, LLC. All rights reserved. 이 문서의 전부 또는 일부를 무단으로 복제하는 행위는 금지됩니다..