* Windows Script Host Object Model *

 

[WScript]

┣<WshShell>
┃ ┃
┃ ┠ WshShortcut
┃ ┃
┃ ┠ WshUrlShortcut
┃ ┃
┃ ┠ WshEnvironment
┃ ┃
┃ ┠ WshSpecialFolders
┃ ┃
┃ ┖ WshScriptExec


┣<WshArguments>
┃  ┃
┃  ┠ WshNamed
┃  ┃
┃  ┖ WshUnnamed


┣<WshController>
┃  ┃
┃  ┠ WshRemote
┃  ┃
┃  ┖ WshRemoteError


┗<WshNetwork>

 

* WSH Objects *

WSH 관련 작업은 한마디로 개체(object)를 생성하여 그 개체에서 사용가능한

Method 와 Property를 이용하는 것이라고 할 수 있다.

따라서 작업을 하려면 먼저 개체를 생성해야 하고, 가장 상위의 4개 개체는

주개체(Main Object)인 Wscript 개체를 통해 생성된다.

주개체는 기본적으로 생성되는 것으로 따로 생성하고 할 필요가 없다.

(다른 스크립트들과는 달리 WSH에서는 개체의 종류와 생성방법 등이 몇 개로 특정되어 있어

사용하기가 편하다.)

개체도 변수의 일종이므로 개체 생성방법 역시 변수처럼 Dim 으로 변수 선언 후 해당 변수에

CreateObject 로 할당하면 된다.

다만 개체는 변수가 개체변수라는걸 알리기위해 앞에 Set 을 해준다.

 

Wscript

   WSH의 메인 개체(오브젝트)

WshShell
   Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")

WshShortcut
   Dim Link : Set Link = WshShell.CreateShortcut(DeskTop & "\test.lnk")
WshSpecialfolders
   Access any of the Windows Special Folders

   Dim DeskTop : DeskTop = WshShell.SpecialFolders("Desktop") ' or AllUsersDesktop

WshURLShortcut
   Dim URL : Set URL = WshShell.CreateShortcut(DeskTop & "\Go Naver.url")
WshEnvironment
   Dim WshEnv : Set WshEnv = WshShell.Environment("Process")
WshScriptExec
   Dim oExec : Set oExec = WshShell.Exec("calc")
WshArguments
   Dim objArgs : Set objArgs = WScript.Arguments
WshNamed
WshUnnamed
WshNetwork
   Dim Net : Set Net = WScript.CreateObject ("WScript.Network")

WshController
   Dim Controller : Set Controller = WScript.CreateObject("WSHController")

WshRemote
WshRemoteError

 

메인 오브젝트(WScript)의 하위 오브젝트들인 WshShell,WshArguments,WshNetwork,

WshController,WshRemote 등은 메인 오브젝트(WScript)의 method 인 CreateObject 를

통해 생성되고, 각 오브젝트의 하위 오브젝트는 각 오브젝트에서 사용 가능한 적절한

method와 property 의 사용을 통해 생성된다.

 

- WScript : Windows 용

- CScript : cmd 용

 

* CScript 명령줄 사용예 *

 

CScript [host options...][script name][options and parameters]
CScript //nologo C:\Scripts\Qbackup.vbs
 

//?

 

//I               ;  Interactive mode(default). (대화창이나 에러메시지가 윈도에 표시된다)

//B              ;  Batch mode. ( 대화창이나 에러 메시지가 모두 프롬프트창에 표시된다.)

 

//T:nn          ; 타임아웃(일정시간이 지나면 스크립트 실행 중지. 초단위. 기본값은 무제한)

 

//NOLOGO   ; 배너 표시안함(기본값은 표시 ->  //LOGO )

 

//H:CScript   ; CScript.exe 를 스크립트 실행을 위한 기본 호스트로 지정.
//H:WScript   ; WScript.exe 를 스크립트 실행을 위한 기본 호스트로 지정.

; WSH의 기본 스크립트는 레지스트리값을 통해 확인할 수 있다.

; => HKEY_CURRENT_USER\Software\Microsoft\Windows Scripting Host\Settings

 

//S              ; Current User를 위해 현재 명령줄 옵션을 저장.

//E:engine   ; 스크립트를 지정된 스크립트엔진으로 실행.

                    (파일확장자가 달라도 스크립트 실행이 가능)
//D             ; 디버깅 중지.
//X             ; 디버깅하면서 스크립트 실행.
//JOB:<JobID>   ; .wsf 파일의 특정 JobID 를 실행.
//U             ; Enables you to use Unicode for redirected input/output (I/O) from the console.

 

- Object와 각 Object에 따른 Property -

 

* WScript object's Properties *

 

WScript.Name             '  Windows Script Host
WScript.FullName        '  C:\WINDOWS\System32\wscript.exe
WScript.Version           '  5.6
WScript.BuildVersion    '  8827
WScript.Path                '  CScript.exe or WScript.exe 파일의 경로 -> C:\WINDOWS\system32
WScript.ScriptFullName   '  현재 실행중인 파일의 full path & name -> C:\TEMP\test.vbs
WScript.ScriptName        '  현재 실행중인 파일의 이름 -> test.vbs

WScript.Interactive     ' 모드(interactive or batch) 표시. -> 1  or True

WScript.Interactive = False ' 배치모드로 전환된다.

 

WScript.StdErr
WScript.StdIn
WScript.StdOut

cf, StdIn, StdOut, and StdErr streams 는 CScript.exe 를 통해서만 액세스할 수 있다.

 

WScript.Arguments

WScript.Arguments.Named

WScript.Arguments.Unnamed

WScript.Arguments.Named.Item(이름)

WScript.Arguments.Unnamed.Item(순서)

 

myScript.vbs /c:arg1 /d:arg2

WScript.Arguments.Named.Item("c")   ' ->  arg1

myScript.vbs arg1 arg2

WScript.Arguments.Unnamed.Item(0)   ' ->  arg1  (zero-based index )

 

WScript Object는 기본적으로 생성되는 Object이므로 각 속성들 또한 아무곳에서나 사용가능..

 

* Shortcut object's Properties *

Shortcut Object는 WshShell Object의 CreateShortcut 메서드를 이용해 생성

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
Dim Desktop : Desktop = WshShell.SpecialFolders("Desktop")
Dim objLink : Set objLink = WshShell.CreateShortcut(Desktop & "\ScriptsFolder.lnk")

objLink.TargetPath = WScript.ScriptFullName
objLink.RelativePath = "C:\Scripts\"
objLink.WindowStyle = 1                   ' 1  ->  Activates and displays a window
objLink.Hotkey = "Ctrl+Alt+C"
objLink.IconLocation = "notepad.exe, 0"
objLink.Description = "Shortcut to Script Working Directory"
objLink.WorkingDirectory = Desktop
objLink.Arguments = "C:\myFile.txt"
objLink.Save
WScript.Echo objLink.FullName

 

* TextStream object's Properties *

FSO의 CreateTextFile, OpenTextFile, OpenAsTextStream 등의 Method를 이용해서 생성

AtEndOfLine

AtEndOfStream

Column

Line

Set FSO = CreateObject("Scripting.FileSystemObject")

Set f = FSO.OpenTextFile("c:\testfile.txt", ForReading)

do while f.AtEndOfStream <> True
    Wscript.Echo f.ReadLine
loop

 

* WshRemote object's Properties *

 

Dim Controller : Set Controller = WScript.CreateObject("WSHController")
Dim RemoteScript : Set RemoteScript = Controller.CreateScript("test.js", "remoteserver")
RemoteScript.Execute
Do While RemoteScript.Status <> 2
    WScript.Sleep 100
Loop

' Staus value :

' 0 : 원격스크립트 생성됨,but 아직 실행안됨

. 1 : 원격스크립트 실행중

' 2 : 원격스크립트 실행 끝남

 

* WshRemoteError object's Properties *

 

Dim RemoteError : Set RemoteError = RemoteScript.Error

RemoteError.Number
RemoteError.Line
RemoteError.Character
RemoteError.Description
RemoteError.Source
RemoteError.SourceText

 

* WshShell object's Properties *

 

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Echo WshShell.CurrentDirectory       '  C:\Temp

 

Dim WshEnv : Set WshEnv = WshShell.Environment("PROCESS")

WScript.Echo WshEnv("NUMBER_OF_PROCESSORS")

 

NUMBER_OF_PROCESSORS
PROCESSOR_ARCHITECTURE
PROCESSOR_IDENTIFIER
PROCESSOR_LEVEL
PROCESSOR_REVISION
OS
COMSPEC
HOMEDRIVE
HOMEPATH
PATH
PATHEXT
PROMPT
SYSTEMDRIVE
SYSTEMROOT
WINDIR
TEMP
TMP

 

Dim Desktop : Desktop = WshShell.SpecialFolders("Desktop")

AllUsersDesktop
AllUsersStartMenu
AllUsersPrograms
AllUsersStartup
Desktop
Favorites
Fonts
MyDocuments
NetHood
PrintHood
Programs
Recent
SendTo
StartMenu
Startup
Templates

 

cf, Environment 나 SpecialFolders property 에 의해 반환되는 객체는 컬렉션 객체이다.

따라서 Itme , count (number of items) 등을 이용할 수 있다.

 

WScript.Echo WshShell.SpecialFolders.Item("Programs")
' ->  C:\Documents and Settings\USER_ID\시작 메뉴\프로그램

 

* WshScriptExec object's Properties *

 

Dim oExec : Set oExec = WshShell.Exec("%comspec% /c dire")

If oExec.ExitCode <> 0 Then
     WScript.Echo "Warning: Non-zero exit code"
End If

' ExitCode : 대상 프로그램이 끝나지 않았으면 0, 끝나면 프로그램에서 반환된 값

 

* WshNetwork object's Properties *

 

Dim Net : Set Net = WScript.CreateObject("WScript.Network")
WScript.Echo "Domain = " & Net.UserDomain
WScript.Echo "Computer Name = " & Net.ComputerName
WScript.Echo "User Name = " & Net.UserName

 

 

Object의 종류와 그에 따른 속성들이 몇 개 안되므로 사용하기 편하다.

 

* WSH Methods index *

 

각 Method 에 대한 자세한 설명은 이 후 예문이 나올 때..

 

AddPrinterConnection
AddWindowsPrinterConnection
AppActivate
Close
ConnectObject
Count
CreateObject
CreateScript
CreateShortcut
DisconnectObject
Echo
EnumNetworkDrives
EnumPrinterConnections
Exec
Execute
Exists
ExpandEnvironmentStrings
GetObject
getResource
LogEvent
MapNetworkDrive
Popup
Quit
Read
ReadAll
ReadLine
RegDelete
RegRead
RegWrite
Remove
RemoveNetworkDrive
RemovePrinterConnection
Run
Save
SendKeys
SetDefaultPrinter
ShowUsage
Sign
SignFile
Skip
SkipLine
Sleep
Terminate  (WshScriptExec)
Verify
VerifyFile
Write
WriteBlankLines
WriteLine

 

아래 상수들은 VBScript에 들어 있으므로 사용하기 전에 정의하지 않아도 된다.

(Value 입력시 Value 대신 Constant 를 바로 사용가능하다는 뜻)

단, MsgBox 반환값은 코드에 명시적으로 상수로 선언해야 사용 가능.

* String Constants *

Constant     Value           Description
vbCr           Chr(13)        캐리지 리턴 (Carriage return)
vbLf            Chr(10)        라인 피드 (linefeed)
vbCrLf         Chr(13) & Chr(10)    캐리지 리턴-라인 피드 조합

vbNewLine  Chr(13) & Chr(10) 또는 Chr(10) 각 플랫폼 특정의 줄 바꿈 문자
vbNullChar   Chr(0)          값이 0인 문자 (Character having the value 0)
vbNullString  값이 0인 문자열.       길이가 0인 문자열("")과 다르며, 외부 프로시저 호출에 사용.
vbTab          Chr(9)        수평 탭 (Horizontal tab)

vbFormFeed    Chr(12)    폼 피드. Microsoft Windows에서는 사용되지 않습니다.
vbVerticalTab  Chr(11)    수직 탭. Microsoft Windows에서는 사용되지 않습니다.

* space(11) : 빈칸 11 개

* 줄바꿈 :
캐리지 리턴 Chr(13), 라인 피드 문자 Chr(10) 또는

캐리지 리턴-라인 피드 문자의 조합 Chr(13) & Chr(10) 을 사용하여 줄을 구분할 수 있다.
Msgbox "첫째 줄입니다. " & Chr(13) & Chr(10) & "둘째 줄입니다"

* 쌍따옴표(double quotation marks) 넣기 : Chr(34) 로 감싸기 or 쌍따옴표 두쌍으로 감싸기
내 이름은 "김팔봉"   ->  "내이름은 " & Chr(34) & "김팔봉" & Chr(34)
내 이름은 "김팔봉"   ->  "내이름은 " & """김팔봉"""

============================

* Tristate Constants *

Constant       Value  Description

vbUseDefault   -2     Use default from computer's regional settings.
vbTrue            -1     True
vbFalse           0      False

============================

* Color Constants *

Constant      Value        Description

vbBlack        &h00         Black
vbRed          &hFF         Red
vbGreen       &hFF00      Green
vbYellow      &hFFFF     Yellow
vbBlue         &hFF0000   Blue
vbMagenta   &hFF00FF   Magenta
vbCyan        &hFFFF00   Cyan
vbWhite        &hFFFFFF  White

============================

* Date and Time Constants *

Constant      Value  Description
vbSunday        1     Sunday
vbMonday       2     Monday
vbTuesday      3     Tuesday
vbWednesday  4     Wednesday
vbThursday     5     Thursday
vbFriday          6     Friday
vbSaturday      7     Saturday

vbUseSystemDayOfWeek 0

Use the day of the week specified in your system settings for the first day of the week.
vbFirstJan1        1  Use the week in which January 1 occurs (default).
vbFirstFourDays 2  Use the first week that has at least four days in the new year.
vbFirstFullWeek  3  Use the first full week of the year.

============================

* Date Format Constants *

Constant      Value  Description
vbGeneralDate  0  Display a date and/or time. ..determined by user system settings.
vbLongDate      1  long date format (specified in user computer's regional settings).
vbShortDate     2  short date format (specified in user computer's regional settings).
vbLongTime     3  long time format (specified in user computer's regional settings).
vbShortTime     4  short time format (specified in user computer's regional settings).

============================

* VarType Constants *

Constant     Value   Description

vbEmpty           0     Uninitialized (default)
vbNull              1     Contains no valid data
vbInteger          2     Integer subtype
vbLong            3     Long subtype
vbSingle          4     Single subtype
vbSingle          5     Double subtype
vbCurrency      6     Currency subtype
vbDate            7      Date subtype
vbString           8     String subtype
vbObject          9     Object
vbError           10     Error subtype
vbBoolean      11     Boolean subtype
vbVariant       12     Variant (used only for arrays of variants)
vbDataObject  13     Data access object
vbDecimal      14     Decimal subtype
vbByte           17     Byte subtype
vbArray       8192     Array

============================

* MsgBox Constants *

Constant              Value   Description
vbOKOnly                 0      Display OK button only.
vbOKCancel             1      Display OK and Cancel buttons.
vbAbortRetryIgnore    2      Display Abort, Retry, and Ignore buttons.
vbYesNoCancel        3      Display Yes, No, and Cancel buttons.
vbYesNo                  4      Display Yes and No buttons.
vbRetryCancel          5      Display Retry and Cancel buttons.
vbCritical                16      Display Critical Message icon.
vbQuestion             32      Display Warning Query icon.
vbExclamation         48      Display Warning Message icon.
vbInformation           64      Display Information Message icon.
vbDefaultButton1        0      First button is the default.
vbDefaultButton2     256      Second button is the default.
vbDefaultButton3     512      Third button is the default.
vbDefaultButton4     768      Fourth button is the default.
vbApplicationModal   0      Application modal.(응답해야 현재 프로그램 계속 실행 가능 )
vbSystemModal     4096     System modal.

cf, 조합이 가능하다

두개버튼(Yes,No) + 물음표 아이콘 + 선택커스의 기본위치가 두번째버튼(No) 인 경우

=> MsgBox "예,아니오 중 선택하세요", vbYesNo + vbQuestion + vbDefaultButton2

=> MsgBox "예,아니오 중 선택하세요", 4 + 32 + 256

=> MsgBox "예,아니오 중 선택하세요", 292


<반환값>

Constant  Value  Description

vbOK          1      OK button was clicked.
vbCancel    2      Cancel button was clicked.
vbAbort       3      Abort button was clicked.
vbRetry       4      Retry button was clicked.
vbIgnore     5      Ignore button was clicked.
vbYes        6      Yes button was clicked.
vbNo          7      No button was clicked.

cf, VBScript 에서 응답값(반환값)은 명시적으로 선언해야 문자열을 상수값으로 사용할 수 있다.

 

intButton = object.Popup (strText,[nSecondsToWait],[strTitle],[nType])

' [] 로 둘러싸인 부분은 옵션이다. (있어도 그만, 없어도 그만)
' cf. 반환값 없이 단독으로 쓰일 때는 괄호를 사용할 수 없다.
' Shell.Popup("안녕하세요", 0, "Hello", vbOkOnly)      =>   괄호로 둘러싸면 에러남..  

 

   - object : WshShell object.

   - strText : 메시지.

   - nSecondsToWait : Optional. 응답 기다릴 시간(second). (생략시 기본값은 0 ,무한정 기다림)
     지정되고 nSecond 동안 응답 없으면..  -> 메시지박스 사라지면서 -1 을 반환한다.

   - strTitle : Optional. 메시지박스 타이틀바에 나타낼 제목.(생략시 "Windows Script Host" )

   - nType : Optional. 버튼과 아이콘 타입.( 생략시 버튼타입은 0 -> vbOkOnly )

   - IntButton : 메시지박스 버튼 클릭시 반환되는 정수값.

=====================================================

 intButton = MsgBox (prompt [, button][, title][, helpfile, context])

 

   - title : 대화 상자의 제목 표시줄에 나타나는 문자식. (생략시 응용 프로그램 이름이 나타남)

   - helpfile, context : 대화상자에 도움말 제공하기위한 도움말 파일들.

      helpfile 이 지정되었다면 context 도 지정되어야 한다.(16bit 에서 사용불가)

 =====================================================

strReturn = InputBox ( prompt[, [title], [default], [xpos], [ypos]])

 

   - cf, 취소 버튼을 클릭하면 zero-length string("") 이 반환된다.

   - MsgBox, InputBox : VBScript 도구로 객체(object) 생성없이 단독으로 바로바로 사용 가능.

=====================================================

 

* Button Types *
Value     Description                             Constants
0           OK                                          vbOkOnly
1           OK, Cancel                              vbOkCancel
2           Abort, Retry, Ignore                   vbAbortRetryIgNore
3           Yes, No, Cancel                       vbYesNoCancel
4           Yes, No                                   vbYesNo
5           Retry, Cancel                           vbRetryCancel

 

* Icon Types *
Value      Description                              Constants
16          Show "Stop Mark" icon.              vbCritical
32          Show "Question Mark" icon.        vbQuestion
48          Show "Exclamation Mark" icon.   vbExclamation
64          Show "Information Mark" icon.     vbInformation

 

* Return value *
Value       Description
-1  <-       timeout(응답시간내 응답 없으면 반환되는 값)
1    <-       OK
2    <-       Cancel
3    <-       Abort
4    <-       Retry
5    <-       Ignore
6    <-       Yes
7    <-       No

cf, 반환값 상수는 명시적으로 상수로 선언해야 사용 가능.


 

>예문 보기


 

>접기

 

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")

Return = WshShell.RegRead(strRegName)

Return = WshShell.RegRead("HKCU\Software\Microsoft\Notepad\lfFaceName")  ' 굴림
Return = WshShell.RegRead("HKCU\Software\Winamp\") ' C:\Program Files\Winamp
Return = WshShell.RegRead("HKCU\Software\WinRAR\") ' 기본값 없어서 에러 발생.

- strRegName : key or value-name

 

' strRegName의 루트키 약자
    HKEY_CURRENT_USER         :   HKCU
    HKEY_LOCAL_MACHINE       :   HKLM
    HKEY_CLASSES_ROOT         :   HKCR
    HKEY_USERS                       :   HKEY_USERS
    HKEY_CURRENT_CONFIG      :   HKEY_CURRENT_CONFIG

 

' 레지스트 경로의 마지막에 백슬래시 \ 가 있으면 키, 없으면 값의 이름을 가리킨다.

' 키나 값이 존재하지 않을 경우, 값이 바이너리값인 경우 -> 에러 발생.

' 키의 default value 가 존재하지 않을 경우 -> 에러 발생.
' REG_SZ 값은 String 을 읽어온다.
' REG_DWORD 값은 dword 값이 아닌 실제 정수값을 읽어온다.
' REG_BINARY 값은 읽지 못한다. (에러 발생)
' REG_EXPAND_SZ 값은 String 문자열 그대로 읽어온다.
=========================================================

WshShell.RegWrite strRegName, anyValue [, strType]

- strRegName : key or value-name

' 키    추가 : strRegName에 \ 를 붙여준다.
' 이름 추가 : strRegName에 \ 를 붙이지 않음.
' strRegName에 \ 붙이고 Value 가 공백(zero-length string) 이면 빈 새 키가 생성된다

- anyValue
' value에 Dword 값 입력시에는 dowrd값이 아닌 실제 정수(십진수)로 입력해야 함.
' value에 쌍따옴표 포함된 String 입력시 다시 쌍따옴표로 감싸주거나 Chr(34) 를 이용한다.
' value에 경로문자 \가 포함된 String 입력시 \ 는 \\ 로 바꿔 입력할 필요가 없다.
' value에 환경변수 포함된 String 입력하면 변환된 값이 아닌 환경변수 문자열 그대로 입력된다.

- strType (Registry Data Type)
REG_SZ               : 문자열 (String)
REG_DWORD        : 정수 (Integer)
REG_EXPAND_SZ : 문자열 ( %comspec% 등과 같은 환경 변수를 포함하는 경우)
REG_BINARY        : 이진 문자열

' 값의 형식 지정하지 않으면 REG_SZ 로 인식
' REG_MULTI_SZ 값 입력은 지원되지 않음.

 

WshShell.RegWrite "HKCU\Software\AAA\", ""   ' 빈 새키 생성

WshShell.RegWrite "HKLM\...\ValName", 1000, "REG_DWORD" ' dword:000003e8 입력시

WshShell.RegWrite "HKCU\..", """%ProgramFiles%\..""", "REG_EXPAND_SZ"

 

Dim WshEnv : Set WshEnv = WshShell.Environment("Process")
Dim ProgramDir : ProgramDir = WshEnv("ProgramFiles")
WshShell.RegWrite "HKCU\..", Chr(34) & ProgramDir & "\some.txt" & Chr(34), "REG_SZ"

' REG_EXPAND_SZ타입은 %~%를 문자열 그대로 입력.

' 맞는 값으로 변환시켜 입력하려면 Environment 등을 이용하여 값을 얻어 입력해야 함.

=========================================================

WshShell.RegDelete strRegName

- strName : key or value-name

WshShell.RegDelete "HKCU\MyNewKey\"                ' 키    삭제 : 맨 뒤에 \ 를 붙여준다
WshShell.RegDelete "HKCU\MyNewKey\MyValue"    ' 이름 삭제 : 맨 뒤에 \ 를 붙이지 않음


 예문)

Dim WshShell : WshSet Shell = createobject ("wscript.shell")
Const vbYes = 6
Dim p : p = WshShell.Popup ("would you like to GO ON?:  ", 5, "go on qestion", vbYesNo+vbQuestion)

If p = vbYes Then
    MsgBox "ok"
Else
    set p = nothing
    Wscript.Quit
End If

 

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
Dim BtnCode : BtnCode = WshShell.Popup("Do you feel alright ?", 7, "Answer This Question:", 4 + 32)

Select Case BtnCode
   case 6   WScript.Echo "Glad to hear you feel alright."
   case 7   WScript.Echo "Hope you're feeling better soon."
   case -1  WScript.Echo "Is there anybody out there?"
End Select

 

Dim MyVar : MyVar = MsgBox ("안녕하십니까?", 65, "메시지 상자 예제")

' vbOKCancel(1) + vbInformation(64) = 65

 

Dim strReturn : strReturn = InputBox ("What is the sum of 1 + 5 * 9 / 3 ?  ", "The Math Game")
Dim TrimReturn : TrimReturn = Trim(strReturn)
If Len(TrimReturn) = 0 Then
    MsgBox "Sorry. You must enter a number to play this game."
    WScript.Quit
End If

If IsNumeric(TrimReturn) <> True Then
    MsgBox "Sorry. You must enter a number to play this game."
    WScript.Quit
End If

 

// JScript
var WshShell = WScript.CreateObject("WScript.Shell");
var BtnCode = WshShell.Popup("Do you feel alright?", 7, "Answer This Question:", 4 + 32);
switch(BtnCode) {
   case 6:
      WScript.Echo("Glad to hear you feel alright.");
      break;
   case 7:
      WScript.Echo("Hope you're feeling better soon.");
      break;
   case -1:
      WScript.Echo("Is there anybody out there?");
      break;
}

 

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")

Return = WshShell.RegRead(strRegName)

Return = WshShell.RegRead("HKCU\Software\Microsoft\Notepad\lfFaceName")  ' 굴림
Return = WshShell.RegRead("HKCU\Software\Winamp\") ' C:\Program Files\Winamp
Return = WshShell.RegRead("HKCU\Software\WinRAR\") ' 기본값 없어서 에러 발생.

- strRegName : key or value-name

 

' strRegName의 루트키 약자
    HKEY_CURRENT_USER         :   HKCU
    HKEY_LOCAL_MACHINE       :   HKLM
    HKEY_CLASSES_ROOT         :   HKCR
    HKEY_USERS                       :   HKEY_USERS
    HKEY_CURRENT_CONFIG      :   HKEY_CURRENT_CONFIG

 

' 레지스트 경로의 마지막에 백슬래시 \ 가 있으면 키, 없으면 값의 이름을 가리킨다.

' 키나 값이 존재하지 않을 경우, 값이 바이너리값인 경우 -> 에러 발생.

' 키의 default value 가 존재하지 않을 경우 -> 에러 발생.
' REG_SZ 값은 String 을 읽어온다.
' REG_DWORD 값은 dword 값이 아닌 실제 정수값을 읽어온다.
' REG_BINARY 값은 읽지 못한다. (에러 발생)
' REG_EXPAND_SZ 값은 String 문자열 그대로 읽어온다.
=========================================================

WshShell.RegWrite strRegName, anyValue [, strType]

- strRegName : key or value-name

' 키    추가 : strRegName에 \ 를 붙여준다.
' 이름 추가 : strRegName에 \ 를 붙이지 않음.
' strRegName에 \ 붙이고 Value 가 공백(zero-length string) 이면 빈 새 키가 생성된다

- anyValue
' value에 Dword 값 입력시에는 dowrd값이 아닌 실제 정수(십진수)로 입력해야 함.
' value에 쌍따옴표 포함된 String 입력시 다시 쌍따옴표로 감싸주거나 Chr(34) 를 이용한다.
' value에 경로문자 \가 포함된 String 입력시 \ 는 \\ 로 바꿔 입력할 필요가 없다.
' value에 환경변수 포함된 String 입력하면 변환된 값이 아닌 환경변수 문자열 그대로 입력된다.

- strType (Registry Data Type)
REG_SZ               : 문자열 (String)
REG_DWORD        : 정수 (Integer)
REG_EXPAND_SZ : 문자열 ( %comspec% 등과 같은 환경 변수를 포함하는 경우)
REG_BINARY        : 이진 문자열

' 값의 형식 지정하지 않으면 REG_SZ 로 인식
' REG_MULTI_SZ 값 입력은 지원되지 않음.

 

WshShell.RegWrite "HKCU\Software\AAA\", ""   ' 빈 새키 생성

WshShell.RegWrite "HKLM\...\ValName", 1000, "REG_DWORD" ' dword:000003e8 입력시

WshShell.RegWrite "HKCU\..", """%ProgramFiles%\..""", "REG_EXPAND_SZ"

 

Dim WshEnv : Set WshEnv = WshShell.Environment("Process")
Dim ProgramDir : ProgramDir = WshEnv("ProgramFiles")
WshShell.RegWrite "HKCU\..", Chr(34) & ProgramDir & "\some.txt" & Chr(34), "REG_SZ"

' REG_EXPAND_SZ타입은 %~%를 문자열 그대로 입력.

' 맞는 값으로 변환시켜 입력하려면 Environment 등을 이용하여 값을 얻어 입력해야 함.

=========================================================

WshShell.RegDelete strRegName

- strName : key or value-name

WshShell.RegDelete "HKCU\MyNewKey\"                ' 키    삭제 : 맨 뒤에 \ 를 붙여준다
WshShell.RegDelete "HKCU\MyNewKey\MyValue"    ' 이름 삭제 : 맨 뒤에 \ 를 붙이지 않음

 

' 레지스트리 읽어서 .reg 파일로 저장
Set WshShell = CreateObject("WScript.Shell")
sKey = "HKEY_CURRENT_USER\Software\Microsoft\Notepad"

fName = "c:\TEMP\FirstPage.reg"
sCmd = "regedit /e/a " & Chr(34) & fName & Chr(34) & " " & Chr(34) & sKey & Chr(34)
WshShell.Run "%comspec% /c " & sCmd, 0, True

Set WshShell = Nothing
'================================================================
' 레지스트리 파일 읽어서 Program Files 경로 변경 후 병합하기

Option Explicit

'On Error Resume Next
'Err.Clear

 

Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
Dim ProgramDir : ProgramDir = Shell.Environment("Process").Item("ProgramFiles")

 

Const FindLong = "C:\\Program Files"
Const FindShort = "C:\\PROGRA~1"

 

Dim ProgArray, ProgLong, ProgShort
ProgArray = Split (ProgramDir, "\")
ProgLong = ProgArray(1)
ProgShort = ProgArray(1)

 

If Len(ProgLong) > 8 Then
    ProgShort = Left(ProgLong, 6) & "~1"    ' PROGRA~1
End If

 

Dim RepLong : RepLong = ProgArray(0) & "\\" & ProgLong
Dim RepShort : RepShort = ProgArray(0) & "\\" & ProgShort
' 레지파일의 경로 구분자는 \가 아닌 \\

 

Dim RegFile : RegFile = "install.reg"
Dim ts, strLine, newLine
Dim newReg : newReg = ""

 

If FSO.FileExists(RegFile) Then
    Set ts = FSO.OpenTextFile(RegFile, 1)  ' 1 => ForReading
    Do Until ts.AtEndOfStream
        strLine = ts.ReadLine
        newLine = Replace(strLine, FindLong, RepLong, 1, -1, 1)
        newLine = Replace(newLine, FindShort, RepShort, 1, -1, 1)
        newReg = newReg & newLine & vbCrLf
    Loop
    ts.Close

    Dim fTmp : fTmp = FSO.GetAbsolutePathName(FSO.GetTempName)
    FSO.CreateTextFile(fTmp)
    Dim getTmp : Set getTmp = FSO.GetFile(fTmp)
    Dim tsTmp : Set tsTmp = getTmp.OpenAsTextStream(2, True)  ' Const ForWriting = 2
    tsTmp.Write(newReg): tsTmp.Close
    Shell.Run "%COMSPEC% /C regedit /s " & Chr(34) & fTmp & Chr(34), 0, True
    FSO.DeleteFile fTmp, True
End If


Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

'================================================================

' 프로그램 설치되었는지 여부 검사하기

Set WshShell = CreateObject("WScript.Shell")
If WshShell.RegRead("HKCR\.BMP\\") = "ACDC_BMP" Then
   WScript.Echo "ACDSee installed."
Else
   WScript.Echo "You can install ACDSee."
End If
         
Set WshShell = Nothing

 

 

- [Method] SendKeys

Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.SendKeys string[, wait]

string   : 필수. 입력된 문자식을 보냅니다.
Wait   : 선택. 부울 값은 대기 모드로 지정합니다.
  False (기본값)이면 키가 입력이 되면 컨트롤은 바로 프로시저에 반환됩니다.
  True 이면 프로시저에게 컨트롤이 반환되기 전에 반드시 키가 입력되어야 합니다.

--------------------------------------------------------------------------

 

* 문자 입력 : 그 문자 자체를 표시.
    예) ABC   => "ABC"

 

* 기호 문자 입력 : 중괄호({})로 묶어준다.
    예) 덧셈 기호를 입력   =>  {+}

    더하기 기호   plus sign           +
    삽입 기호      caret                 ^
    퍼센트 기호   percent sign      %
    생략 기호      and tilde            ~
    괄호                                    ( )

 

 cf, 대괄호([ ]) :  대괄호는 그냥 입력이 가능하지만, 다른 응용프로그램에서 특수하게

                        인식될수 있으므로 중괄호로 묶어준다.
                        [  =>  {{}         ] => {}}

 

* 특수 키 입력
키                               코드
백스페이스                   {BACKSPACE}, {BS} 또는 {BKSP}
Break                          {BREAK}
Caps Lock                   {CAPSLOCK}
Del 또는 Delete             {DELETE} 또는 {DEL}
아래쪽 화살표               {DOWN}
End                             {END}
Enter                           {ENTER} 또는 ~
Esc                             {ESC}
Help                            {HELP}
Home                          {HOME}
Ins 또는 Insert              {INSERT} 또는 {INS}
왼쪽 화살표                  {LEFT}
Num Lock                    {NUMLOCK}
Page Down                 {PGDN}
Page Up                     {PGUP}
Print Screen                {PRTSC}
오른쪽 화살표              {RIGHT}
Scroll Lock                 {SCROLLLOCK}
Tab                            {TAB}
위쪽 화살표                 {UP}
F1      {F1}
F2      {F2}
F3      {F3}
F4      {F4}
F5      {F5}
F6      {F6}
F7      {F7}
F8      {F8}
F9      {F9}
F10    {F10}
F11    {F11}
F12    {F12}
F13    {F13}
F14    {F14}
F15    {F15}
F16    {F16}


* Shift,Ctrl,Alt 와 일반 키를 동시에 누를 경우 : 아래 문자를 입력할 키 앞에 붙여준다.

     Shift    +
     Ctrl     ^
     Alt      %

 조합키 누른채 다른 여러 키를 입력해야 한다면 여러 키들을 괄호로 묶어준다.
     Shift + ( E + C...)        =>      "+(ec)"
     (Shift +  E)  + C          =>      "+ec"

     Alt + F4                     =>      "%{F4}"

* 키 반복 입력 : 반복되는 키를 지정할 때는 {keystroke number}의 형식으로 나타낸다.

  (키와 숫자 사이에 반드시 공백 필요)
  
    왼쪽 화살표키를 42회 입력    =>   {LEFT 42}
    H를 10 번 입력                    =>   {h 10}

    Ctrl+X 를 10번 입력하는 식으로 특수키와 일반키의 조합을 여러번 입력하는건 안된다.

        alt + ctrl + del  => Shell.Sendkeys("%^{DEL}") x
                                 Shell.Sendkeys("%^+{DEL}") o

 

* 참고 *
Microsoft Windows 내에서 실행되지 않는 응용 프로그램에 SendKeys를 사용하여 키를

입력할 수 없다.
Sendkeys는 또한 PRINT SCREEN key {PRTSC} 를 다른 응용 프로그램에 보낼 수 없다.

 

 

 

-  [Method] Run, Exec

Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
intError = WshShell.Run (strCommand [, intWindowStyle] [, bWaitOnReturn])

 

WshShell.Run "%windir%\notepad" & WScript.ScriptFullName

' cf, 반환값 없이 단독 실행시에는 괄호로 묶지 않는다.


intError = WshShell.Run("notepad " & WScript.ScriptFullName, 1, True)
intError = WshShell.Run ("setup.exe", 1, true)

 

- object : WshShell object.
- strCommand : String value indicating the command line you want to run.
- intWindowStyle : Optional. Integer value indicating the appearance of the program's window.

 

* intWindowStyle :
0    Hides the window and activates another window.
1    Activates and displays a window.

     If the window is minimized or maximized, the system restores it to its original size and position.
     An application should specify this flag when displaying the window for the first time.
2   Activates the window and displays it as a minimized window.
3   Activates the window and displays it as a maximized window.
4   Displays a window in its most recent size and position.

     The active window remains active.
5   Activates the window and displays it in its current size and position.
6   Minimizes the specified window and activates the next top-level window in the Z order.
7   Displays the window as a minimized window. The active window remains active.
8   Displays the window in its current state. The active window remains active.
9   Activates and displays the window.

    If the window is minimized or maximized, the system restores it to its original size and position.
     An application should specify this flag when restoring a minimized window.
10  Sets the show-state based on the state of the program that started the application.


- bWaitOnReturn : Optional. (true / false)

Boolean value indicating whether the script should wait for the program to finish executing
before continuing to the next statement in your script.
If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program.
If set to false (the default), the Run method returns immediately after starting the program,
automatically returning 0 (not to be interpreted as an error code).

- intError : Error code ( integer ).

-----------------------------------------------------------------------------------

Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
Dim oExec : Set oExec = WshShell.Exec("calc")

Do While oExec.Status = 0
     WScript.Sleep 100
Loop

WScript.Echo oExec.Status

 

' Status Return Values

'     0  : The job is still running.
'     1  : The job has completed.

-----------------------------------------------------------------------------------

' Run 과 Exec 의 가장 큰 차이

'=> Run 은 실행만 하지만, Exec는 실행과 동시에 객체(object)를 생성한다.

'    따라서 Exec를 통한 실행은 생성된 객체를 이용한 후속 작업이 용이하다.

 

Set FSO = Wscript.CreateObject("Scripting.FileSystemObject")
Set Shell = Wscript.CreateObject("Wscript.Shell")
TempName = FSO.GetTempName
TempFile = TempName

Shell.Run "cmd /c ping -n 3 -w 1000 157.59.0.1 >" & TempFile, 0, True

Set TextFile = FSO.OpenTextFile(TempFile, 1)
Do While TextFile.AtEndOfStream <> True
    strText = TextFile.ReadLine
    If Instr(strText, "Reply") > 0 Then
        Wscript.Echo "Reply received."
        Exit Do
    End If
Loop

TextFile.Close
FSO.DeleteFile(TempFile)

 

' 아래는 동일한 결과는 가지는 Exec 를 통한 실행이다.

' 실행을 통해 반환되는 StdOut 에 접근하기위해 임시파일 만들고 할 필요가 없다.

 

Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim ExecObject : Set ExecObject = Shell.Exec ("cmd /c ping -n 3 -w 1000 157.59.0.1")
Do While Not ExecObject.StdOut.AtEndOfStream
    strText = ExecObject.StdOut.ReadLine
Loop

 

 

 

-  [Method] Sign, SignFile, Verify, VerifyFile

Sign
   Signs a script stored in a string.

SignFile
   Signs a script using a digital signature.

 

Verify
   Verifies a digital signature retrieved as a string.

VerifyFile
   Verifies the digital signature encapsulated in a script.

 

 

-  [Method] CreateObject, GetObject

CreateObject
   Creates an object specified by the strProgID parameter.

 

CreateScript
   Creates a WshRemote object (an object that represents an instance of a script

   running in a remote process).

 

CreateShortcut
   Creates an object reference to a shortcut or URLshortcut.

 

 

ConnectObject
   Connects an object's event sources to functions with a given prefix.

 

DisconnectObject
   Disconnects a previously connected object from Windows Script Host.

 

 

GetObject
   Retrieves an Automation object from a file or an object specified by the strProgID parameter.

 

 

 [Method] MapNetworkDrive

 

MapNetworkDrive
   Maps the share point specified by strRemoteName to the local resource name strLocalName.

 

 

EnumNetworkDrives
   Returns the current network drive mappings.

EnumPrinterConnections
   Returns the current network printer mappings.

 

 

RemoveNetworkDrive
   Removes the current resource connection denoted by strName.

 

RemovePrinterConnection
   Removes the current resource connection denoted by strName.

 

 

 

AddPrinterConnection
   Adds a DOS-style printer connection to your computer.

 

AddWindowsPrinterConnection
   Adds a Windows-style printer connection to your computer.

SetDefaultPrinter
   Sets the default printer to the remote printer specified.

 

 

 

 

-  [Method] ExpandEnvironmentStrings

* 환경변수값 알아내기 *

strReturn = WshShell.ExpandEnvironmentStrings(strString)
 
- strReturn : an environment variable's expanded value.
- strString : name of the environment variable.

- Remarks :
    The ExpandEnvironmentStrings method expands environment variables
    defined in the PROCESS environment space only.


'Visual Basic Script
Set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Echo "WinDir is " & WshShell.ExpandEnvironmentStrings("%WinDir%")
 

//JScript
var WshShell = WScript.CreateObject("WScript.Shell");
WScript.Echo("WinDir is " + WshShell.ExpandEnvironmentStrings("%WinDir%"));


예문)

 

=================================================================

Set WshShell = WScript.CreateObject("WScript.Shell")

' C:
SystemDrive = WshShell.ExpandEnvironmentStrings("%SystemDrive%")

' C:\WINDOWS
SystemRoot = WshShell.ExpandEnvironmentStrings("%SystemRoot%")

' C:\WINDOWS
WinDir = WshShell.ExpandEnvironmentStrings("%WinDir%")

' C:\WINDOWS\system32\cmd.exe
comspec = WshShell.ExpandEnvironmentStrings("%comspec%")

' C:\Documents and Settings\USER
UserProfile = WshShell.ExpandEnvironmentStrings("%UserProfile%")

' C:\Documents and Settings\All Users
AllUsersProfile = WshShell.ExpandEnvironmentStrings("%AllUsersProfile%")

' C:\Documents and Settings\USER\Application Data
AppData = WshShell.ExpandEnvironmentStrings("%AppData%")

' C:\Program Files
ProgramFiles = WshShell.ExpandEnvironmentStrings("%ProgramFiles%")

' C:\DOCUME~1\USER\LOCALS~1\TEMP
Temp = WshShell.ExpandEnvironmentStrings("%Temp%")
Tmp = WshShell.ExpandEnvironmentStrings("%Tmp%")


WScript.Echo Tmp

 

* MakeList.vbs *

' [1] 인자로 폴더경로만 입력받는 경우
Option Explicit

Dim Shell : Set Shell = Wscript.CreateObject("Wscript.Shell")
Dim FSO : Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

Const OutName = "FileList.txt"   ' 목록을 작성하여 저장할 txt 파일 - 고정

If Wscript.Arguments.Count = 1 Then
    Dim ArgPath : ArgPath = WScript.Arguments(0)
    Dim OutFile : OutFile = FSO.BuildPath(ArgPath, OutName) ' BuildPath - 완전한 경로 생성
    If FSO.FolderExists(ArgPath) Then ' 경로는 쌍따옴표 Chr(34) 로 감싸준다.
        Shell.Run "%comspec% /c Dir " & Chr(34) & ArgPath & Chr(34) _
        & " > " & Chr(34) & OutFile & Chr(34) & " /b /n /-d"
    Else  ' cmd.exe dir <directory> /b /n /-d    (파일명만 목록으로 출력됨)
        WScript.Echo "** Source directory not found ** " & ArgPath
    End If
Else
    WScript.Echo "사용 형식 : MakeList.vbs <source path>"
    WScript.Echo "사용 예문 : MakeList.vbs c:\temp"
End If

Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

====================================================================

' [2] 인자로 폴더경로와 결과저장 파일을 받는 경우

Option Explicit

Dim Shell : Set Shell = Wscript.CreateObject("Wscript.Shell")
Dim FSO : Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

If Wscript.Arguments.Count = 2 Then  ' 인자가 두 개 여야 함
    Dim ArgPath : ArgPath = WScript.Arguments(0)
    Dim OutFile : OutFile = WScript.Arguments(1)
    If FSO.FolderExists(ArgPath) Then
If Left(OutFile, InstrRev(OutFile, "\")) = "" or FSO.FolderExists(Left(OutFile, InstrRev(OutFile, "\"))) Then
    Shell.Run "%comspec% /c Dir " & Chr(34) & ArgPath & Chr(34) & " > " _

    & Chr(34) & OutFile & Chr(34) & " /b /n /-d"
Else
    WScript.Echo "** Destination path not found ** " & Left(OutFile, InstrRev(OutFile, "\"))
End If
    Else
        WScript.Echo "** Source directory not found ** " & ArgPath
    End If
Else
    WScript.Echo "사용 형식 : MakeList.vbs <source path> <destination file>"
    WScript.Echo "사용 예문 : MakeList.vbs c:\temp c:\test.txt"
End If

Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

====================================================================

예문)

 

 

-폴더내 파일목록 작성

 

* MakeList.inf *

; MakeList.vbs 복사  +  레지스트리 등록

; .vbs 파일과 .inf 파일이 동일한 폴더내에 있어야 함.

[Version]
Signature="$Windows NT$"

 

[DefaultInstall]
CopyFiles = Add_File
AddReg    = List_Reg

 

[DestinationDirs]
Add_File   = 11    ;  system32

 

[Add_File]
MakeList.vbs,,,0x00000010    ; 0x00000010  =>  COPYFLG_NO_OVERWRITE

 

[List_Reg]
HKCR,"Directory\shell\VB.List\",,,"Print File &List"
HKCR,"Directory\shell\VB.List\command\",,,"wscript.exe ""%11%\MakeList.vbs"" ""%1"""

;   [HKEY_CLASSES_ROOT\Directory\shell\VB.List]
;   @="Print File &List"
;   [HKEY_CLASSES_ROOT\Directory\shell\VB.List\command]
;   @="\"C:\\WINDOWS\\system32\\MakeList.vbs\" \"%1\""

 

 

<프로그램 설치를 위한 세가지 작업>

1. 폴더 복사 (폴더  -> C:\Program Files\폴더)

2. 바로가기 생성 (시작메뉴, 바탕화면)

2. 레지스트리 병합 (regedit /s install.reg)

 

 

 

- Install, Uninstall

* Install.vbs *

 

Option Explicit

On Error Resume Next
Err.Clear

Dim Shell : Set Shell = WScript.CreateObject ("WScript.Shell")
Dim FSO : Set FSO = WScript.CreateObject ("Scripting.FileSystemObject")

 

Const ProgID = "flyExplorer"  ' flyExplorer 1.63 을 설치하는 경우

' 프로그램명은 바뀌지 않으므로 상수 Const 로 선언해버린다.

 

Dim LinkDir : LinkDir = Shell.SpecialFolders("Programs") & "\" & ProgID
Dim ExeDir : ExeDir = Shell.Environment("Process").Item("ProgramFiles") & "\" & ProgID
Dim DeskDir : DeskDir = Shell.SpecialFolders("Desktop")
Dim UnKey : UnKey = "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" & ProgID & "\"

' ProgID => 복사할 폴더명, 프로그램 폴더에 생성될 폴더명, 시작메뉴 폴더명


If Not FSO.FolderExists(LinkDir) Then FSO.CreateFolder LinkDir End If
FSO.CopyFolder ProgID, ExeDir, True

 

' 바로가기 파일은 .lnk 확장자를 가진다.

Dim ExeLink : Set ExeLink = Shell.CreateShortcut(LinkDir & "\flyExplorer.lnk")
'ExeLink.HotKey = "CTRL + SHIFT + F"
ExeLink.TargetPath = ExeDir & "\flyExplorer.exe"
ExeLink.WorkingDirectory = ExeDir
ExeLink.Save
Set ExeLink = Nothing

 

Dim DeskLink : Set DeskLink = Shell.CreateShortcut(DeskDir & "\flyExplorer.lnk")
DeskLink.TargetPath = ExeDir & "\flyExplorer.exe"
DeskLink.Save
Set DeskLink = Nothing

 

Dim UnLink : Set UnLink = Shell.CreateShortcut(LinkDir & "\Uninstall flyExplorer.lnk")
UnLink.TargetPath = ExeDir & "\uninstall.vbs"
UnLink.Save
Set UnLink = Nothing

 

Shell.Run "regedit /s install.reg"

 

Shell.RegWrite UnKey & "DisplayName", "flyExplorer v1.63"
Shell.RegWrite UnKey & "UninstallString", "wscript """ & ExeDir & "\uninstall.vbs"""

' 제어판 삭제 메뉴를 위한 레지스트리 정보(DisplayName, UninstallString  -> 필수 요소)

' uninstall.vbs 실행을 위해 c:windows\system32\wscript.exe 를 이용한다.

 

Set Shell = Nothing
Set FSO = Nothing

WScript.Quit
============================================================================

* Uninstall.vbs *

 

Option Explicit

' On Error Resume Next
' Err.Clear

' 실제 적용시에는 위 두줄 앞의 ' 가 없어야 에러나도 계속 진행하게 됨.

 

Dim Shell : Set Shell = WScript.CreateObject ("WScript.Shell")
Dim FSO : Set FSO = WScript.CreateObject ("Scripting.FileSystemObject")

 

Const ProgID = "flyExplorer"  ' flyExplorer 1.63

 

Dim LinkDir : LinkDir = Shell.SpecialFolders("Programs") & "\" & ProgID
Dim ExeDir : ExeDir = Shell.Environment("Process").Item("ProgramFiles") & "\" & ProgID
Dim DeskLink : DeskLink = Shell.SpecialFolders("Desktop") & "\flyExplorer.lnk"

Dim UnKey : UnKey = "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" & ProgID & "\"

 

If MsgBox ("flyExplorer 1.63을 제거하시겠습니까?   ", 33, "Uninstall - " & ProgID) = 1 Then
    Call DelReg("HKCU\Software\flyExplorer\")
    Call DelReg(UnKey)
    Call DelFile(DeskLink)
    Call DelFolder(LinkDir)
    Call DelFolder(ExeDir)
End If

 

Sub DelReg(key)
    On Error Resume Next ' 키나 값이름이 존재하지 않으면 에러 -> 이걸 출력 못하게 함.
    Shell.RegDelete key
End Sub
Sub DelFolder(fold)
    If FSO.FolderExists(fold) Then
        FSO.DeleteFolder fold, True
    End If
End Sub
Sub DelFile(file)
    If FSO.FileExists(file) Then
        FSO.DeleteFile file, True
    End If
End Sub

 

Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

----------------------------

<WinRAR-SFX 설명문>

Path=flyExplorer

SavePath
Setup=install.vbs
TempMode
Silent=1
Overwrite=1

 

 

 

- 폴더(파일)명 일괄변경

* ReNamer.vbs *

 

입력 1. 대상 폴더 경로의 마지막에 \ 가 있으면 파일명 변경, 없으면 폴더명 변경.

입력 2. 찾을 단어, 바꿀 단어 를 입력받는다.

       - 쉼표로 구분

       - 바꿀 단어는 공백이 올 수 있다( = 특정 문자 제거)

       - 찾을 단어가 숫자 0 이라면 맨 앞 접두어 삽입으로 간주한다.

 

Option Explicit

'On Error Resume Next
'Err.Clear

Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

Dim TargetPath, fileMode

 

TargetPath = InputBox ("대상 폴더의 절대경로를 입력해 주세요." _
    & vbCrLf & "마지막에 \가 있으면 파일명 변경, " _
    & vbCrLf & "없으면 폴더명 변경입니다.  "  _
    & vbCrLf & vbCrLf & "예) C:\Temp  또는   C:\Temp\", "Parent Path")

' InputBox 는 Popup 과는 달리 오브젝트(WshShell)없이 단독으로 사용 가능.

 

Call CheckNull(TargetPath)
TargetPath = Trim(TargetPath)

 

' 기본은 폴더명 변경 , 경로 마지막에 \ 가 있으면 파일명 변경

' \ 가 붙은 경우, 대상 폴더의 경로를 얻기 위해 마지막 \ 는 제거해 줘야 한다.
fileMode = False
If Right(TargetPath, 1) = "\" Then
    TargetPath = Left(TargetPath, Len(TargetPath)-1) ' 마지막 \ 제거
    fileMode = True
End If

Call CheckRoot(TargetPath)

If fileMode = True Then
    Call RepFiles
Else
    Call RepFolders
End If

 

'[함수화]*******************************
Sub CheckRoot(s)
    If Trim(s) = "" Then ' 경로 입력 안했거나 취소버튼 누른 경우
        WScript.Quit
    ElseIf Len(s) <= 3 Then ' C  C:  C:\  등의 경우
        Shell.Popup "루터 디렉토리는 대상 폴더가 될 수 없습니다.  ", 3, "Path Error", vbOkOnly
        WScript.Quit
    ElseIf Not FSO.FolderExists(s) Then
        Shell.Popup "경로가 존재하지 않습니다.  ", 3, "Path Error", vbOkOnly
        WScript.Quit
    End If
End Sub
Sub CheckNull(s)
    If Trim(s) = "" Then
        Shell.Popup " 입력값 없음  ", 1, "Input Empty", vbOkOnly
        WScript.Quit
    End If
End Sub
Sub CheckRest(s)
    If InStr(1, s, ",", 1) <= 0 Then ' s 에서 쉼표가 위치한 곳(순서가 <= 0 는 말은 없다는 뜻)
        Shell.Popup "찾을 단어와 바꿀 단어를 쉼표로 구분하여 입력해 주세요.  ", 3, "Input Error", vbOkOnly
        WScript.Quit
    End If
End Sub

 

'[파일명 변경]***************************
Sub RepFiles
    Dim inputStr : inputStr = InputBox ("* 파일명 변경 *" & vbCrLf _
    & "찾을 단어와 바꿀 단어를 쉼표로 구분하여 입력해 주세요." & vbCrLf & vbCrLf _
    & "교체) target words, new words" & vbCrLf _
    & "삭제) target words," & vbCrLf _
    & "접두어 삽입) 0, insert words", "파일명 변경")
    Call CheckNull(inputStr)
    Call CheckRest(inputStr)
    Dim StrArray : StrArray = Split(inputStr, ",", -1, 1)  ' 쉼표로 구분(배열을 생성)
    Dim FindStr : FindStr = LTrim( StrArray(0) )  ' 단어 왼쪽 공백만 없앤다.
    Call CheckNull(FindStr)
    Dim RepStr : RepStr = LTrim( StrArray(1) ) ' 바꿀 단어는 Null Check 안함.

    Dim objFold : Set objFold = FSO.GetFolder(TargetPath)
    Dim fcoll : Set fcoll = objFold.Files

    ' Folder.files 와 Folder.subfolders는 콜렉션 객체를 생성한다.
    Dim f1, oName, nName, oPath, nPath
    For Each f1 in fcoll
        oName = f1.name  ' 하위 파일의 이름
        If IsNumeric(FindStr) Then ' 찾을 문자가 숫자 0 이면 접두어 삽입 모드
            nName = RepStr & oName
        Else
            nName = Replace(oName, FindStr, RepStr, 1, -1, 1)
        End If
        oPath = TargetPath & "\" & oName
        nPath = TargetPath & "\" & nName
        If Not FSO.FileExists(nPath) Then ' 같은 이름 있으면 변경 안함
            FSO.MoveFile oPath, nPath
        End If
    Next
    Set objFold = Nothing
    Set fcoll = Nothing
End Sub

 

'[폴더명 변경]***************************
Sub RepFolders

    Dim inputStr : inputStr = InputBox ("* 폴더명 변경 *" & vbCrLf _
    & "찾을 단어와 바꿀 단어를 쉼표로 구분하여 입력해 주세요." & vbCrLf & vbCrLf _
    & "교체) target words, new words" & vbCrLf _
    & "삭제) target words," & vbCrLf _
    & "접두어 삽입) 0, insert words", "폴더명 변경")
    Call CheckNull(inputStr)
    Call CheckRest(inputStr)

    Dim StrArray : StrArray = Split(inputStr, ",", -1, 1)  ' 쉼표로 구분(배열을 생성)
    Dim FindStr : FindStr = LTrim( StrArray(0) ) ' 단어 왼쪽 공백만 없앤다.
    Call CheckNull(FindStr)
    Dim RepStr : RepStr = LTrim( StrArray(1) )

    Dim objFold : Set objFold = FSO.GetFolder(TargetPath)
    Dim dcoll : Set dcoll = objFold.SubFolders
    Dim d1, oName, nName, oPath, nPath
    For Each d1 in dcoll
        oName = d1.name  ' 하위 폴더의 이름
        If IsNumeric(FindStr) Then
            nName = RepStr & oName
        Else
            nName = Replace(oName, FindStr, RepStr, 1, -1, 1)
        End If
        oPath = TargetPath & "\" & oName
        nPath = TargetPath & "\" & nName
        If Not FSO.FolderExists(nPath) Then ' 같은 이름 있으면 변경 안함
            FSO.MoveFolder oPath, nPath
        End If
    Next
    Set objFold = Nothing
    Set dcoll = Nothing
End Sub


Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

 

WSH - ex) 코덱박사 슈퍼코덱팩 자동설치

* AutoInstall.vbs *

 

Option Explicit

On Error Resume Next 

Err.Clear


Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
Dim COMSPEC : COMSPEC = Shell.ExpandEnvironmentStrings("%COMSPEC%")

Dim ExeFile : ExeFile = "Super_20060524.exe"   ' 파일명 바꾸면 설치 에러남

 

If MsgBox ("코덱박사 슈퍼 코덱팩 v20060524 을 설치하시겠습니까?   " , 36, "Setup - SuperCodec") = 6 Then
 Shell.Run COMSPEC & " /c " & ExeFile & " & Exit", 0

 'cmd창 숨기고 설치창 활성화.  뒤에 ,true 붙이면 안됨
 Wscript.Sleep 3000
 Shell.AppActivate "코덱박사 슈퍼 코덱팩 v20060524"  '활성창 타이틀
 Wscript.Sleep 800
 Shell.SendKeys "~", True ' 엔터키

 Wscript.Sleep 1000
 Shell.SendKeys "~", True
 Wscript.Sleep 1000
 Shell.SendKeys "{TAB}", True
 Wscript.Sleep 500
 Shell.SendKeys "{right}", True
 Wscript.Sleep 500
 Shell.SendKeys "~", True

 Wscript.Sleep 1000
 Shell.SendKeys "~", True
 Wscript.Sleep 1000
 Shell.SendKeys "~", True
 Wscript.Sleep 1000

 Shell.SendKeys "{TAB}", True
 Wscript.Sleep 500
 Shell.SendKeys "{END}", True '맨아래칸 이동은 {down} 쓸 필요없이 바로 {END} 로..
 Wscript.Sleep 1000
 Shell.SendKeys " ", True ' PCClear는 설치요소에서 제거 ( " " -> 스페이스키)
 Wscript.Sleep 1000

 Shell.SendKeys "{TAB}", True
 Wscript.Sleep 500
 Shell.SendKeys "{right}", True
 Wscript.Sleep 500
 Shell.SendKeys "~", True

 Wscript.Sleep 1000
 Shell.SendKeys "~", True

 Wscript.Sleep 1000
 Shell.SendKeys "~", True

 Wscript.Sleep 3000

 Shell.SendKeys "~", True ' GomPlayer 발견 - 최적화할까요?  => yes

 ' GomPlayer , KMPlayer 등 미디어재생 소프트웨어를 먼저 설치해야 한다.
 Wscript.Sleep 3500
 Shell.SendKeys "~", True ' nomal
 Wscript.Sleep 1000
 Shell.SendKeys "~", True ' 2 channel
 Wscript.Sleep 1000
 Shell.SendKeys "~", True ' 환경설정

 ' Call DelStartup() ' 한글Windows에서는 하면 안됨...


Else
    Shell.Popup "코덱박사 슈퍼 코덱팩 v20060524 설치가 취소되었습니다.   ", 3, "Cancle", 48
    WScript.Quit
End if

 

' 영문Windows에는 "시작프로그램"이라는 폴더가 없다. ( Start Menu 가 있다 )

Sub DelStartup()

    Dim KorStartMenu : KorStartMenu = Shell.SpecialFolders("Programs") & "\시작프로그램"
    If FSO.FolderExists(KorStartMenu) Then
        FSO.DeleteFolder KorStartMenu
    End If
End Sub

 

Set Shell = Nothing
Set FSO = Nothing

WScript.Quit

 

 

 

-
WSH - ex) 곰플레이어 1.9 자동설치

 

* AutoInstall.vbs *

 

Option Explicit

On Error Resume Next
Err.Clear

 

Dim Shell : Set Shell = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")

Dim WshEnv : Set WshEnv = Shell.Environment("Process")
Dim ProgramDir : ProgramDir = WshEnv("ProgramFiles")
Dim COMSPEC : COMSPEC = Shell.ExpandEnvironmentStrings("%comspec%")

' COMSPEC 지정할 필요없이 바로 Shell.Run "%comspec%~ 해도 됨..

 

Const ExeFile = "GOM.EXE"  '고정된 이름은 변수가 아닌 상수로 지정해도 무방..

 

If MsgBox ("곰플레이어 1.9를 설치하시겠습니까?  ", 36, "Setup - GomPlayer") = 6 Then

    Shell.Run COMSPEC & " /c " & ExeFile & " & Exit", 0

    ' 0 => cmd창 숨기고 설치창 활성화.   뒤에 ,true 붙이면 안됨
    Wscript.Sleep 3000
    Shell.AppActivate "곰플레이어 설치"
    Wscript.Sleep 800
    Shell.SendKeys "~", True ' next [엔터]
    Wscript.Sleep 800
    Shell.SendKeys "~", True ' 동의
    Wscript.Sleep 1000

    Shell.SendKeys "{TAB}", True ' 구성요소 (모든 동영상 확장자 등록 체크)
    Wscript.Sleep 500
    Shell.SendKeys "{DOWN}", True
    Wscript.Sleep 500
    Shell.SendKeys "{DOWN}", True
    Wscript.Sleep 500
    Shell.SendKeys "{DOWN}", True
    Wscript.Sleep 500
    Shell.SendKeys " ", True
    Wscript.Sleep 800
  
    Shell.SendKeys "~", True
    Wscript.Sleep 1000
    Shell.SendKeys "{DEL}", True  ' delete 키
    Wscript.Sleep 800
    Shell.SendKeys ProgramDir & "\GomPlayer", True ' 설치경로 변경( c:\prog~\Gomplayer )
    Wscript.Sleep 800
    Shell.SendKeys "~", True
    Wscript.Sleep 6500
    Shell.SendKeys "{TAB}", True
    Wscript.Sleep 800
    Shell.SendKeys "~" , True

Else
    Shell.Popup "곰플레이어 설치가 취소되었습니다.   ", 3, "Cancle", 48
    WScript.Quit
End if

 

' 바로가기 폴더(아이팝) 지우고 GomPlayer 새로 생성
Dim Programs : Programs = Shell.SpecialFolders("Programs") ' or AllUsersPrograms
Dim OldShortDir : OldShortDir = Programs & "\아이팝 (www.ipop.co.kr)"
Dim NewShortDir : NewShortDir = Programs & "\GomPlayer"

FSO.DeleteFolder OldShortDir
FSO.CreateFolder NewShortDir

 

Dim ExeLink : Set ExeLink = Shell.CreateShortcut(NewShortDir & "\곰플레이어.lnk")
ExeLink.HotKey = "CTRL+SHIFT+G"
ExeLink.TargetPath = ProgramDir & "\GomPlayer\Gom.exe"
ExeLink.WorkingDirectory = ProgramDir & "\GomPlayer"
ExeLink.Save

Set ExeLink = Nothing

 

Dim ManLink : Set ManLink = Shell.CreateShortcut(NewShortDir & "\곰매니저.lnk")
ManLink.TargetPath = ProgramDir & "\GomPlayer\GomMgr.exe"
ManLink.WorkingDirectory = ProgramDir & "\GomPlayer"
ManLink.Save

Set ManLink = Nothing

 

Dim UnLink : Set UnLink = Shell.CreateShortcut(NewShortDir & "\곰플레이어 제거.lnk")
UnLink.TargetPath = ProgramDir & "\GomPlayer\Uninstall.exe"
UnLink.Save

Set UnLink = Nothing

 

' _ad_temp_.ini 파일이 을 읽기전용으로 속성 변경.

' 최초 실행 전이라면 _ad_temp_.ini 파일이 아직 생성되지 않았음.

' _ad_temp_.ini 파일이 없는 상태라면 Gom.exe 를 실행시키야 환경설정창이 뜬다.
Dim iniFile : iniFile = ProgramDir & "\GomPlayer\_ad_temp_.ini"

Dim WizFile
If FSO.FileExists(iniFile) Then
    WizFile = "GomWiz.exe"
Else
    WizFile = "Gom.exe"
End If
 
Dim WizExec : Set WizExec = Shell.Exec(ProgramDir & "\GomPlayer\" & WizFile)
Wscript.Sleep 1000
Shell.AppActivate "언어 선택"
Shell.SendKeys "~" , True
Wscript.Sleep 800
Shell.AppActivate "곰플레이어 환경 설정 길잡이"
Wscript.Sleep 800
Shell.SendKeys "~" , True  ' 일반 모드
Wscript.Sleep 800
Shell.SendKeys "~" , True  ' 자체 코덱, 2채널 스피커
Wscript.Sleep 800
Shell.SendKeys "~", True

Wscript.Sleep 800
Shell.SendKeys "~" , True
Wscript.Sleep 800
Shell.SendKeys " " , True  ' 곰플레이어 실행 - 체크해제
Wscript.Sleep 800
Shell.SendKeys "~" , True
Wscript.Sleep 1500
Shell.SendKeys "{ESC}" , True  ' 곰플레이어 끄기

 

' WizExec 작업이 완전히 끝나야 다음으로 넘어간다.

' Run 과 Exec 의 차이 : Exec는 결과가 오브젝트로 생성되므로 이걸 다시 이용할 수 있다.

Do While WizExec.Status <> 1
 WScript.Sleep 100
Loop

 

Call SetReadOnly(iniFile)

 

Shell.Run  "regedit /s config.reg"

'Shell.Popup  "곰플레이어 1.9 설치가 완료되었습니다.   ", 3


'_ad_temp_.ini 파일을 읽기전용으로..
Sub SetReadOnly(f)
   Dim f1 : Set f1 = FSO.CreateTextFile(f, true) ' 덮어쓰면서 생성
   Dim f2 : Set f2 = FSO.GetFile(f1)
   f2.Attributes = 1
   Set f1 = Nothing
   Set f2 = Nothing
End Sub


Set Shell = Nothing
Set FSO = Nothing
Set WshEnv = Nothing
Set WizExec = Nothing

WScript.Quit

------------------------------

<config.reg>

Windows Registry Editor Version 5.00

; 옵션설정 - 업데이트 자동확인(x), 비슷한 파일명 열기(x), 재생시에만 맨위

[HKEY_CURRENT_USER\Software\GRETECH\GomPlayer\OPTION]
"bActiveMsg"=dword:00000000
"bCheckUpdate"=dword:00000000
"bNotifyUpdate"=dword:00000000
"bNotifyMinorUpdate"=dword:00000000
"bNotifySimilarFile"=dword:00000000
"idMenuLang"=dword:00000412
"idAudioLang"=dword:00000412
"idSubtitlesLang"=dword:00000412
"nOnTopMode"=dword:00000002

 

cf, 곰플레이어 2.0 버전 이상은 자동설치시 픽~ (Kill Processor).f

이 글은 스프링노트에서 작성되었습니다.

.

'Computer > ASP' 카테고리의 다른 글

Wscripting  (0) 2012.08.10
zip,unzip 컴포넌트  (0) 2012.08.10
xmlhttp 를 통한 데이터 교환  (0) 2012.08.10
asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29


asp_zip_unzip.zip


 

백수다보니 할짓이 없어서 쓸데없는 글 하나 남깁니다.
데브피아 질문&답변 게시판 보면 가끔, 아주 가끔씩 올라오는 질문중 하나가
asp로 서버에 압축을 하거나, 압축풀기를 어떻게 하냐는겁니다.

몇년동안 개발하면서 그러한 작업은 필요한적이 없어서 별로 생각해본 기회가없었는데
오늘 문득 그런 질문글을보니 간편하게 컴퍼넌트로 만들면 어떨까 하는 생각이 들어서
대강 대강 어디서 소스구해서 테스트해보고 나름대로 이 정도면 간단한 예제용으로 괜찮다싶어서 글 올립니다.

원랜 가장 간단한 예제형식으로 압축/압축해제만 가능한 컴퍼넌트를 직접 만들어볼까했는데 내공이 존내 부족하다보니 지레겁부터먹고 그냥 코드구루에 아주 잘 만들어진 컴퍼넌트만 이용했습니다.-_-

돌아다니다보니 이것 저것 압축관련 모듈, 예제들이 많이 있었는데 그 중에서 코드구루에 있던 예제가 괜찮아서
그 예제 이용합니다. 원랜 거기에 VB용으로 예제 있던것 그냥 asp로 제가 바꾼것 뿐입니다.
뭐...이렇게 말하니 몇분간 VB -> asp용으로 포팅하고선 뚝딱 끝낸듯 싶지만 제가 머리가 안좋아서 오랫동안 삽질했습니다.

제가한 삽질을 다른분들은 하기싫다면 아래 예제 잘 보시면 될겁니다(아마도;;)

  • 1. 제가 첨부한 파일을다운 받으신후 zip32.dll과 unzip32.dll을 윈도우 system32 디렉토리 안에 넣습니다.
    windows 2000계열 -> c:\winnt\system32
    windows 9x, XP계열 -> c:\windows\system32
  • 2. 웹서버의 루트에서 폴더 하나 생성합니다. 저의 경우 "ziptest"로 폴더 생성했습니다.
    아마 c:\inetput\wwwroot\ziptest 이런식의 폴더구조가 될겁니다.
  • 3. 이 생성한 ziptest에 권한을 줘야합니다. 이것때문에 압축이안되거나 압축해제가 안되서 꽤나 오랫동안 삽질했습니다.
    windows 2000 계열이라면 단순히 ziptest 폴더 속성 권한에서 everyone 사용자 추가한후에 읽기/쓰기 권한주면 될텐데
    windows xp를 제가 이용한지 몇일 안된지라 windows 2000처럼 폴더권한 바꾸는 방법을 몰라서 헤맸습니다.
    xp에선 그냥 폴더 속성에 "공유"탭 누른후에 "네트워크에서 이 폴더 공유", "네트워크 사용자가 내 파일을 변경할 수 있음"
    이 2개 옵션에 체크하고선 확인만 누르면 되더군요 -_-
  • 4. 첨부파일중에 CGZipLibrary.dll 파일을 ziptest 폴더 안에 둡니다.
    뭐 이 dll파일은 아무대나 둬도 상관없지만 그냥 여기다 둡니다. -_-
    CGZipLibrary.dll 이 파일을 레지스트리에 등록해야합니다. 혹 깜빡하시는 분들을 위해서
    RegSvr32 c:\inetpub\wwwroot\ziptest\CGZipLibrary.dll 이렇게 해서 등록합니다.
  • 5. 아래 asp 소스코드를 이용해서 압축/ 압축풀기를 하면 끝! 입니다.
<%
    '=====================================================
    ' 압축
    '=====================================================
    Dim oZip
    Set oZip = CreateObject("CGZipLibrary.CGZipFiles")

    oZip.AddFile "C:\Inetpub\wwwroot\default.asp"
    oZip.AddFile "C:\Inetpub\wwwroot\test.txt"
    'oZip.AddFile "C:\Inetpub\wwwroot\*.*"      ' 이렇게하면 wwwroot폴더안의 모든파일/폴더 압축
    oZip.ZipFileName = "C:\Inetpub\wwwroot\ziptest\test.zip"
    oZip.UpdatingZip = False
    
    If oZip.MakeZipFile <> 0 Then
        response.write oZip.GetLastMessage
    End If

    Set oZip = Nothing

    '=====================================================
    ' 압축 해제
    '=====================================================
    Dim oUnZip
    Set oUnZip = CreateObject("CGZipLibrary.CGUnzipFiles")
    
    oUnZip.ZipFileName = "C:\Inetpub\wwwroot\ziptest\test.zip"
    oUnZip.ExtractDir = "C:\Inetpub\wwwroot\ziptest\extractfolder"
    If oUnZip.Unzip <> 0 Then
        response.write oUnZip.GetLastMessage
    End If
    Set oUnZip = Nothing
%>

참고한 정보들 입니다.

코드구루 zip/unzip 관련 글

http://www.codeguru.com/vb/gen/vb_graphics/fileformats/article.php/c6743/

위의 url에서 압축관련 모듈을 다운받으면 VB에서 실행해볼 수 있습니다. 압축풀면 CGZipLibrary.dll 파일이 있을텐데 제가 올린 파일과 코드구루에 있는 CGZipLibrary.dll 파일이 아주 쪼금 틀립니다. 코드구루의 CGZipLibrary.dll 은 압축할때 디렉토리 경로까지 압축을 해버려서 제가 코드 수정해서 재컴파일한겁니다. 수정한 부분은 아래와 같습니다.

CGZipFiles.cls 파일에서 MakeZipFile 함수를 보면 iIgnorePath 부분 변수 사용한곳이있는데 그곳의 값을 '1' 로 바꾼후 재컴파일 한겁니다. 이게 0,1 두가지 옵션이 있는데 '0' 일경운 디렉토리 경로까지 압축하고 '1' 일경우엔 경로무시합니다.

이 글은 스프링노트에서 작성되었습니다.


.

'Computer > ASP' 카테고리의 다른 글

Wscripting  (0) 2012.08.10
zip,unzip 컴포넌트  (0) 2012.08.10
xmlhttp 를 통한 데이터 교환  (0) 2012.08.10
asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29

 set xmlhttp = Server.CreateObject("Microsoft.XMLHTTP")
 
xmlhttp.open "GET", url, False
xmlhttp.setRequestHeader "Content-Type","text/plain"
xmlhttp.send


if xmlhttp.status = 200 then
    reText = xmlhttp.responsebody

    Set objStream = Server.CreateObject("ADODB.Stream")

    objStream.open
    objStream.Position = 0
    objStream.Type = 1
    objStream.Write reText
    objStream.Position = 0
    objStream.Type = 2
    objStream.Charset = "euc-kr"
    reText = objStream.ReadText

    reText = trim(reText)
    objStream.close

    set objStream = nothing
    set xmlhttp = nothing

이 글은 스프링노트에서 작성되었습니다.

.

'Computer > ASP' 카테고리의 다른 글

Wscripting  (0) 2012.08.10
zip,unzip 컴포넌트  (0) 2012.08.10
xmlhttp 를 통한 데이터 교환  (0) 2012.08.10
asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29

 <%

'****************************************************************************************
'*
'*  URLTools.asp 는 공개 Include File 입니다. 상업적, 비상업적인 목적으로 어디서나
'*  자유롭게 사용하실 수 있습니다.
'*
'*  다만, 기능 추가나 에러 수정을 목적으로 Code 를 수정하셨을 때는, 제게 수정된 내용과
'*  목적에 대하여 적은 메일을 보내주셔서 제가 수정사항을 반영할 수 있도록 해주시면 감사하
'*  겠습니다. 또한, 이런식으로 수정된 Code 는 그 내용과 이유를 정리하여 제 홈페이지의
'*  내용에 추가하도록 하겠습니다. 연락처는 다음과 같습니다.
'*
'*  Homepage URL : http://www.egocube.pe.kr/
'*  E-Mail       : songgun@egocube.pe.kr
'*
'****************************************************************************************


'****************************************************************************************
'*
'*  형 식 : Function
'*  정 의 : Public Function URLEncode(URLStr)
'*  설 명 : URLStr 인자로 입력받은 문자열을 URLEncoding 한다.
'*  작 성 : 송원석
'*  날 짜 : 2001.12.03
'*
'****************************************************************************************
Public Function URLEncode(URLStr)

    Dim sURL                '** 입력받은 URL 문자열
    Dim sBuffer             '** Encoding 중의 URL 을 담을 Buffer 문자열
    Dim sTemp               '** 임시 문자열
    Dim cChar               '** URL 문자열 중의 현재 Index 의 문자

    Dim Index

    On Error Resume Next

    Err.Clear
    sURL = Trim(URLStr)     '** URL 문자열을 얻는다.
    sBuffer = ""            '** 임시 Buffer 용 문자열 변수 초기화.


    '******************************************************
    '* URL Encoding 작업
    '******************************************************

    For Index = 1 To Len(sURL)
        '** 현재 Index 의 문자를 얻는다.
        cChar = Mid(sURL, Index, 1)

        If cChar = "0" Or _
           (cChar >= "1" And cChar <= "9") Or _
           (cChar >= "a" And cChar <= "z") Or _
           (cChar >= "A" And cChar <= "Z") Or _
           cChar = "-" Or _
           cChar = "_" Or _
           cChar = "." Or _
           cChar = "*" Then

            '** URL 에 허용되는 문자들 :: Buffer 문자열에 추가한다.
            sBuffer = sBuffer & cChar

        ElseIf cChar = " " Then
            '** 공백 문자 :: + 로 대체하여 Buffer 문자열에 추가한다.
            sBuffer = sBuffer & "+"
        Else
            '** URL 에 허용되지 않는 문자들 :: % 로 Encoding 해서 Buffer 문자열에 추가
            sTemp = CStr(Hex(Asc(cChar)))

            If Len(sTemp) = 4 Then
                sBuffer = sBuffer & "%" & Left(sTemp, 2) & "%" & Mid(sTemp, 3, 2)
            ElseIf Len(sTemp) = 2 Then
                sBuffer = sBuffer & "%" & sTemp
            End If
        End If
    Next


    '** Error 처리
    If Err.Number > 0 Then
        URLEncode = ""
        Exit Function
    End If

    '** 결과를 리턴한다.
    URLEncode = sBuffer
    Exit Function

End Function


'****************************************************************************************
'*
'*  형 식 : Function
'*  정 의 : Public Function URLDecode(URLStr)
'*  설 명 : URLStr 인자로 입력받은 문자열을 URLDecoding 한다.
'*  작 성 : 송원석
'*  날 짜 : 2001.12.03
'*
'****************************************************************************************
Public Function URLDecode(URLStr)

    Dim sURL                '** 입력받은 URL 문자열
    Dim sBuffer             '** Decoding 중의 URL 을 담을 Buffer 문자열
    Dim cChar               '** URL 문자열 중의 현재 Index 의 문자

    Dim Index
    Dim s,bUnicode

    On Error Resume Next

    Err.Clear
    sURL = Trim(URLStr)     '** URL 문자열을 얻는다.
    sBuffer = ""            '** 임시 Buffer 용 문자열 변수 초기화.

    '******************************************************
    '* URL Decoding 작업
    '******************************************************
    '한글이 입력되는 경우가 2가지 있음
    '    "%C0%DA" ->일반
    '    "%uC911" ->유니코드 chr 대신 chrW 사용

    Index = 1
   
    '?,%가 없다면 검색할 필요없음
    if instr(1,pURL,"?",1) > 0 OR instr(1,pURL,"%",1) > 0 then
        Do While Index <= Len(sURL)
            cChar = Mid(sURL, Index, 1)
            If cChar = "+" Then       
                '** '+' 문자 :: ' ' 로 대체하여 Buffer 문자열에 추가한다.
                sBuffer = sBuffer & " "
                Index = Index + 1           
            ElseIf cChar = "%" Then       
                '** '%' 문자 :: Decoding 하여 Buffer 문자열에 추가한다.
               
                '유니코드인지 판단한 후에 일반문자인지 한글인지 구분함
                bUnicode = false
               
                s = Mid(sURL, Index + 1, 5)
                bUnicode = boolUnicode(s)
               
                if bUnicode = true then
                    cChar = Mid(sURL, Index + 2, 2)
                else
                    cChar = Mid(sURL, Index + 1, 2)
                end if
   
                If CInt("&H" & cChar) < &H80 Then
                    '** 일반 ASCII 문자
                    sBuffer = sBuffer & Chr(CInt("&H" & cChar))
                    Index = Index + 3
                Else
                    '** 2 Byte 한글 문자
                    cChar = Replace(Mid(sURL, Index + 1, 5), "%", "")
                   
                    '유니코드인경우 맨앞의 u자를 제거해야 함
                    if bUnicode = true then        'C0DA
                        cChar = mid(cChar,2,4)
                        sBuffer = sBuffer & ChrW(CInt("&H" & cChar))
                    else                        'uC911
                        sBuffer = sBuffer & Chr(CInt("&H" & cChar))
                    end if
                    Index = Index + 6
                End If
            Else
                '** 그 외의 일반 문자들 :: Buffer 문자열에 추가한다.
                sBuffer = sBuffer & cChar
                Index = Index + 1
            End If
        Loop
    else
        sBuffer = ""
    end if
   
    '** Error 처리
    If Err.Number > 0 Then
        URLDecode = ""
        Exit Function
    End If

    '** 결과를 리턴한다.
    URLDecode = sBuffer
    Exit Function

End Function

'****************************************************************************************
'*  형 식 : Function
'*  정 의 : Public Function boolUnicode(s)
'*  설 명 : s 인자로 입력받은 문자열을 기준으로 유니코드인지 판단한다.
'*  작 성 : kimyh
'*  날 짜 : 2007.01.25
'****************************************************************************************
Function boolUnicode(s)
    'true = 유니코드(%uC911)     false=일반(%C0%DA) 형식으로 문자열이 잘리므로
    '첫번째 %를 제거하여 %가 발견되지 않으면 유니코드로 판단
   
    tmp = false
    if instr(1,s,"%",1) <= 0 then tmp = true
    boolUnicode = tmp
   
End Function


'---------------------------------------------------------------------
'    URLEncodeUTF8 (아스키 -> UTF8)
'    Devpia.com 고일호(n4kjy)님 - 2002-07-24
'---------------------------------------------------------------------
Public Function URLEncodeUTF8(byVal szSource)

    Dim szChar, WideChar, nLength, i, result
    nLength = Len(szSource)

    szSource = Replace(szSource," ","+")

    For i = 1 To nLength
        szChar = Mid(szSource, i, 1)

        If Asc(szChar) < 0 Then            
            WideChar = CLng(AscB(MidB(szChar, 2, 1))) * 256 + AscB(MidB(szChar, 1, 1))

            If (WideChar And &HFF80) = 0 Then
                result = result & "%" & Hex(WideChar)
            ElseIf (WideChar And &HF000) = 0 Then
                result = result & _
                "%" & Hex(CInt((WideChar And &HFFC0) / 64) Or &HC0) & _
                "%" & Hex(WideChar And &H3F Or &H80)
            Else
                result = result & _
                "%" & Hex(CInt((WideChar And &HF000) / 4096) Or &HE0) & _
                "%" & Hex(CInt((WideChar And &HFFC0) / 64) And &H3F Or &H80) & _
                "%" & Hex(WideChar And &H3F Or &H80)
            End If
        Else
            result = result + szChar
        End If
    Next
    URLEncodeUTF8 = result
End Function


'---------------------------------------------------------------------
'    URLDecodeUTF8 (UTF8 --> 아스키 )
'    mongmong - 2003. 10 (URLEncodeUTF8 참조)
'---------------------------------------------------------------------
Public Function URLDecodeUTF8(byVal pURL)
    Dim i, s1, s2, s3, u1, u2, result
    pURL = Replace(pURL,"+"," ")
   
    '?,%가 없다면 검색할 필요없음
    if instr(1,pURL,"?",1) > 0 OR instr(1,pURL,"%",1) > 0 then
            For i = 1 to Len(pURL)
                if Mid(pURL, i, 1) = "%" then
                    s1 = CLng("&H" & Mid(pURL, i + 1, 2))
       
                    '2바이트일 경우
                    if ((s1 AND &HC0) = &HC0) AND ((s1 AND &HE0) <> &HE0) then
                        s2 = CLng("&H" & Mid(pURL, i + 4, 2))
       
                        u1 = (s1 AND &H1C) / &H04
                        u2 = ((s1 AND &H03) * &H04 + ((s2 AND &H30) / &H10)) * &H10
                        u2 = u2 + (s2 AND &H0F)
                        result = result & ChrW((u1 * &H100) + u2)
                        i = i + 5
       
                    '3바이트일 경우
                    elseif (s1 AND &HE0 = &HE0) then
                        s2 = CLng("&H" & Mid(pURL, i + 4, 2))
                        s3 = CLng("&H" & Mid(pURL, i + 7, 2))
       
                        u1 = ((s1 AND &H0F) * &H10)
                        u1 = u1 + ((s2 AND &H3C) / &H04)
                        u2 = ((s2 AND &H03) * &H04 +  (s3 AND &H30) / &H10) * &H10
                        u2 = u2 + (s3 AND &H0F)
                        result = result & ChrW((u1 * &H100) + u2)
                        i = i + 8
                    end if
                else
                    result = result & Mid(pURL, i, 1)
                end if
            Next
    else
        result = ""
    end if
    URLDecodeUTF8 = result
End Function
%>

이 글은 스프링노트에서 작성되었습니다.

.

'Computer > ASP' 카테고리의 다른 글

zip,unzip 컴포넌트  (0) 2012.08.10
xmlhttp 를 통한 데이터 교환  (0) 2012.08.10
asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29
성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29

안녕하세요. 마리입니다. ^^;

 

이 팁은 ADO와 SQL에 관한 팁입니다. 많은 페이징 쿼리가 있지만....

 

성능때문에 말들이 참 많았죠? 이 팁 또한 그러한 말들 중에 대안을 내 놓은 그런 팁인듯 합니다.

 

참고 많이 하시구요. 어려우신 부분은 질문을 해주세요. 맨 아래쪽 SP가 진국인데...

 

초보분들이 보시기에는 복잡한 듯 합니다.

 

 

SQL Server에서 사용할 수 있는 서버측 페이징기법 

Andrew Rosca 

웹 애플리케이션은 일반적으로 사용자에게 많은 양의 정보를 제공하기 위해 페이징 기법을 사용한다. 
예를 들어 인터넷 검색엔진은 사용자의 쿼리 결과로 대용량의 결과값을 반환한다. 
이 때 검색엔진이 한번에 결과값 전체를 반환하게 되면 결과값을 받는 클라이언트측 시스템에 과부하가 발생할 수 있다. 
하지만 페이징 기법을 사용하게 되면, 반환되는 결과값을 클라이언트측과 서버측 양쪽에서 관리할 수 있을 만큼의 고정된 크기의 블록으로 구분하여 한 번에 이동시키는 정보의 양을 줄일 수 있다. 애플리케이션에서는 한 번 에 소수의 레코드만 사용자에게 보내게 되며, 결과값 중에서 사용자가 필요로 하는 정보만 반환하게 된다. 

페이징 기법을 사용하면 데이터를 사용자가 좀 더 이해하고 표현하기 쉽게 해 줄 뿐만 아니라, 대량의 정보를 조회하고 표현하기 위해서 시스템에 불필요한 과부하가 발생하여 결국 시스템의 성능에 악영향을 미치지 않도록 통제하기 때문에 전체적인 시스템 성능을 향상시키게 된다.
정상적으로 시스템에 반환된 결과값 레코드가 페이징되었다면, 검색엔진을 사용하는 사용자는 대부분 맨 처음 한 페이지 또는 일부 페이지만 조회하게 될 것이다. 

불행하게도 많은 프로그래머들이 페이징 관련해서 성능측면에서 매우 중요한 고려사항에 대해서 잘 모르고 있다. 
IIS와 SQL Server를 사용하는 환경에서는, 
AbsolutePage, PageSize, PageCount와 같은, 
표준 ADO RecordSet 페이징 기능을 사용하는 것이 가장 일반적인 페이징 기법이다. 
소량(수십 또는 수백 레코드 정도)의 데이터에 대해서는 이러한 기능을 사용하면 정상적으로 동작하고, 시스템의 성능측면에서도 부하를 발생시키지 않는다. 하지만 레코드 수가 증가하게 되면, 이러한 기능을 사용하게 되면 효율성이 감소하게 되고 전체적인 애플리케이션의 성능에 악영향을 미치게 된다. 

대량의 발주정보를 조회해야 하는 구매조달관련 애플리케이션, 수 천명의 회원이 동시에 접속하는 미팅 웹사이트, 고객의 검색조건에 따라 수백 개의 상품의 정보를 표시해야 하는 대규모 전자상거래 웹사이트와 같이, 대용량 데이터를 처리해야 하는 애플리케이션의 경우에는 좀 더 개선된 서버측 페이징 기술이 필요하게 된다. 이번 호의 기사에서는 수백만 개의 행정보를 포함하는 테이블에서도 사용할 수 있는 페이징 기법에 대해서 소개하고자 한다. 


ADO RecordSet 페이징 기법의 한계 


대용량의 레코드를 페이징하기 위해서 ADO RecordSet의 페이징기법을 사용할 때 발생하는 문제의 원인은 ADO에서 데이터를 처리하는 방법 때문이다. 
ADO 기술구조에서는 데이터베이스에서 정보를 조회하기 위해 서 조회의 대상이 되는 데이터에 대한 포인터를 관리해야 할 필요가 있다.
데이터에 대한 포인터를 커서 라고 하며, 클라이언트측(예를 들어 ASP 페이지)에서는 각 레코드를 건별로 조회하게 된다. 

ADO RecordSet 개체는 서버측 커서(기본값)와 클라이언트측 커서 유형을 지원한다.
서버측 커서를 사용하게 되면 모든 데이터는 그대로 SQL Server에 두고, 해당 데이터가 필요한 시점에 순서에 따라 각 레코드를 조회하게 된다.
클라이언트측 커서를 사용하게 되면 필요한 모든 데이터를 클라이인트로 전송한 다음, 클라이언트측 커서를 사용하여 클라이언트측 버퍼 메모리에 있는 데이터를 레코드별로 조회하게 된다. 
검색엔진 예제에서처럼 쿼리의 결과값 중에서 일부분만을 표시하거나 사용해야 하는 경우라면 SQL 서버가 클라이언트에서 요청하는 페이지만 전송하고 전체 결과값 중 나머지 레코드는 데이터베이스 서버에 그대로 남겨두게 되는, 서버측 커서를 사용하는 것이 효율적이다.
서버측 커서를 사용하게 되면 클라이언트로 전송되는 레코드 수가 특정 페이지를 구성하는 20~30 레코드 정도로 제한된다는 것이다. 

PageCount 와 같은 일부 레코드셋 페이징 기능을 사용하기 위해서는 클라이언트측 커서를 사용해야 한다.
클라이언트 커서를 사용할 수 있도록 ADO를 설정하기 위해서는 RecordSet의 ClientLocation 속성을 adUseServer에서 adUseClient로 변경해 주면 된다.
[리스트 1]의 VB 코드는 RecordSet 개체에서 클라이언트측 커서와 서버측 커서를 사용하는 방법에 대한 예제가 나타나 있다. ClientLocation 속성을 asUseClient 로 변경하게 되면, 사용자 쿼리의 결과로 반환되는 데이터에서 필요로 하는 페이지 수를 판단하기 위해 결과값 전체가 클라이언트로 전송된다. 

예를 들어 데이터베이스로부터 5000 레코드를 반환하는 쿼리를 실행했다고 가정하자.
애플리케이션에서 서버측 커서를 사용하게 되면 반환되는 레코드를 한 페이지당 20 레코드씩으로 페이징하고, 사용자가 1 페이지만 보고 있는 경우라면 애플리케이션에서는 클라이언트로 맨 처음 페이지를 구성하는 20 레코드만을 전송하면 된다.
그 다음 사용자가 두번째 페이지로 이동하면 애플리케이션에서는 21~40번 레코드만 클라이언트로 전송하게 된다. 반면에 클라이언트측 커서를 사용하게 되면 ADO에서는 비록 사용자가 단지 첫 페이지에 해당하는 20 레코드만 필요한 경우라도 5000 레코드 전체를 클라이언트로 전송하게 된다.
이렇게 전체 레코드를 전송하게 되면 결과값이 사용자에게 나타나는 시간이 지연되게 되고, 반환되는 레코드 수가 매우 많은 경우에는 성능에 심각한 악영향을 미칠 수 있다. 

다른 페이징 기법 

ADO RecordSet 페이징 기법과 관련한 문제가 애플리케이션의 성능에 영향을 미치게 되었기 때문에 필자는 수천 레코드를 페이징해야 하는 웹 애플리케이션에서 사용할 수 있는 다른 페이징 기법을 찾아 보았다. 

SQL 서버의 인덱스를 활용하여 전체 결과집합 중에서 상위의 레코드를 선택하는 방법을 소개하고자 한다. 

다음은 Northwind 데이터베이스의 Orders 테이블에서 상위 10개의 레코드를 선택하는 쿼리이다.

SELECT TOP 10 * FROM Orders 

위의 구문을 활용하면 전체 결과집합에서 10 개의 레코드 단위로 결과값이 반환되게 할 수 있다.
주어진 페이지에 해당하는 레코드만 선택하기 위해서는, 한 페이지에 몇 개의 레코드를 포함시킬 것인지 결정하고, 실제 사용자가 몇 번째 페이지의 정보를 조회하기를 원하는지에 대한 페이지 카운트를 알고 있어야 한다.
예를 들어 한 페이지에 10 개의 레코드가 포함되고, 사용자가 전체 결과값 집합 중에서 3 페이지를 조회하고자 하는 경우라면 다음과 같은 쿼리를 사용하면 된다. 

SELECT TOP 10 * FROM Orders WHERE OrderID NOT IN (SELECT TOP 20 OrderID FROM Orders) 

위의 쿼리는 맨 처음 20 개의 레코드 이후에 존재하는 10개의 레코드, 즉 21~30번까지의 레코드를 반환한다. 위의 쿼리를 절차코드로 일반화하게 되면 다음과 같이 표현할 수 있다. 

SELECT TOP page_size * FROM Orders WHERE OrderID NOT IN (SELECT TOP (page_size * (current_page - 1)) OrderID FROM Orders) 

위의 쿼리는 대량의 레코드를 반환하는 경우라도 잘 동작하지만, 반환할 페이지의 숫자가 많아질수록 전체적인 성능은 감소하게 된다.
문제의 원인은 IN 연산자에 포함되는 쿼리의 결과값이 많아지면서 비효율성이 증가하기 때문이다. 예를 들어 한 페이지당 10개의 레코드를 반환하는 결과집합 중에서 500번째 페이지를 조회하기 위해 쿼리를 실행하게 되면, IN 연산자의 대상이 되는 서브쿼리에는 다음과 같은 문장이 포함되게 된다. 

(SELECT TOP 4990 OrderID FROM Orders) 

마지막 10개의 레코드를 조회하기 위해 서버에서는 4990 개의 OrderID와 각 OrderID를 비교해야만 한다.
불필요한 비교작업이 많이 발생하게 된다. 
물론 SQL Server의 경우에는 이러한 경우 데이터를 좀 더 빠르고 효율적인 방법으로 검색하기 위해서 인덱스를 사용하여 빠르게 쿼리를 처리하게 된다.
(OrderID가 기본키로 설정되어 있기 때문에, SQL Server는 기본적으로 인덱스를 사용하게 된다.) 
조회하고자 하는 페이지 수가 증가함에 따라 성능면에서 느려지게 된다고 하더라도 이러한 조회성능의 감소현상은 조회하고자 하는 페이지 수가 매우 큰 경우에만 인식할 수 있게 된다.
이러한 점증적인 성능의 감소현상은 대부분의 경우 사용자가 맨 처음부분의 일부 페이지만 조회하게 되고, 맨 처음부분의 일부 페이지를 조회 할 경우에는 매우 빠른 성능을 보장할 수 있기 때문에 크게 중요한 관심의 대상이 되지 않는다.
애플리케이션이션에서 적절하게 데이터를 정렬하고 필터링한다면 사용자는 찾고자 하는 정보를 거의 한 두 페이지 이내에서 찾게 된다. 만약 맨 처음 부분의 페이지에서 필요로 하는 데이터를 찾지 못한 경우에는 대부분의 사용자는 예제에서처럼 500 페이지까지 원하는 데이터를 찾고자 계속 다음 페이지를 찾아보는 것이 아니라 다른 정렬 및 필터링 조건으로 새로운 쿼리를 하게 된다. 

앞에서 언급한 것과 같이 검색작업을 수행할 때, 테이블의 기본키가 어떤 컬럼에 설정되었는지가 매우 중요한 역할을 하게 된다.
기본키에는 각 레코드를 유일하게 식별할 수 있는 컬럼이 포함되어야 하며, 쿼리를 실행할 때 기본키를 기준으로 해당 레코드를 쿼리의 결과값으로 선택할 것인지 무시할 것인지를 판단하게 된다.
앞의 일반화된 쿼리에는 정렬 및 기본키에 관련한 WHEHE 절이나 ORDER BY 절 내용이 누락되어 있다. 목록 2에는 이러한 요소를 포함시킨 일반화된 쿼리가 나타나 있다. 

정렬은 일반적으로는 비효율적인 작업이며, 쿼리의 성능을 저하시키는 원인이 되기도 한다.
SQL 서버의 경우, 인덱스가 설정된 컬럼에 대해서는 매우 효율적으로 정렬 및 필터링 작업을 할 수 있고, SQL 서버가 항상 기본키 컬럼에는 인덱스를 생성하기 때문에 쿼리를 좀 더 최적화하여 빠르게 실행한다.
기본키에 설정된 인덱스를 최대한 활용하기 위해서, [리스트 3]과 같이 테이블의 전체 컬럼을 선택하지 않고, 먼저 기본키의 조건으로 대상이 되는 레코드를 검색한 다음에 결과값에 포함되어 있는 기본키값으로 다시 해당 레코드에 대한 전체 컬럼을 찾아오게 할 수도 있다.
테이블에 기본키 인덱스가 설정되어 있고, 인덱스가 설정된 필드에 대해서만 정렬 및 필터링 작업을 하게 되면, 조회하고자 하는 레코드를 찾기 위해 인덱스 페이지만을 사용하게 된다. 이렇게 쿼리의 결과값에 필요한 전체 필드가 인덱스에 포함되어 있는 경우를 커버된 인덱스라고 한다.
동일한 쿼리를 실행시킨 경우라도 해당 쿼리가 커버된 인덱스를 사용하는 경우가 일반 테이블에 대해서 쿼리하는 경우보다 더 빠르게 된다. 맨 마지막으로 선택된 결과값에 해당하는 나머지 정보를 조회하기 위한 작업을 수행할 때에는(즉, SELECT * 부분), 기본키 인덱스를 사용하여 SQL Server가 해당 인덱스를 바로 찾을 수 있기 때문에 매우 효율적으로 쿼리를 수행하게 된다. 

[리스트3]에 나타나 있는 쿼리는 결과집합 중에서 특정 페이지를 매우 효율적이고, 단순한 방법으로 조회하게 된다. 물론, GROUP BY나 HAVING 절을 추가하여 사용할 수도 있다. 
쿼리를 좀 더 단순화하기 위해서 [리스트 4]와 같이 SELECT_WITH_PAGING 라는 저장 프로시저를 생성하여, 기능을 캡슐화하였다. 

SELECT_WITH_PAGING 저장프로시저에는 fields_to_return (string), primary_key (string), table_name (string), page_number (integer, default 1), page_size (integer), get_record_count (true/false), filter_conditions (string), sort_columns (string), group_by (string)와 같은 매개변수(데이터형)가 입력되게 된다. 

예를 들어 한 페이지당 레코드 수를 10개로 지정하고 Northwind 데이터베이스의 Order 테이블으로부터 주문일자로 정렬하여 CustomerID, ShipName을 조회한 다음, 결과값 중 세번째 페이지를 조회하기 위해서는 다음 문장을 실행하면 된다. 

EXEC SELECT_WITH_PAGING 'CustomerID, ShipName', 'OrderID', 'Northwind.dbo.Orders', 3, 10, 1, '', 'OrderDate' 

위의 쿼리를 실행하게 되면 입력된 조건에 따라 필터링되어 반환되는 전체 레코드 수가 두번째 레코드셋으로 반환된다. 전체 레코드 수는 사용자에게 전체 페이지 수를 표시하려고 할 때 유용하게 사용되며, 대부분의 경우 사용자는 단순하게 이전페이지 또는 다음페이지로 표시되는 것보다는 전체 페이지 수 중에서 현재 조회하고 있는 페이지의 번호를 표시하는 방법을 더 선호한다. 
조건에 해당하는 전체 레코드 수를 조회하기 위해서 필자는 여섯번째 매개변수를 1로 설정하였다. 
만약 여섯번째 매개변수를 설정하지 않으면 데이터베이스로부터 페이지당 레코드로 제한된 10개의 레코드만을 반환하게 되기 때문에 전체 레코드 수가 몇 개인지는 알 수 없게 된다. 

table_name 매개변수에는 두 개 또는 그 이상의 테이블에 대한 조인을 설정하는 문장이 올 수도 있고, 필요에 따라 서브쿼리도 올 수 있다.
예를 들어, 다음 두 문장은 table_name 매개변수에 모두 사용될 수 있다. 

'Northwind.dbo.Orders A JOIN Northwind.dbo.Customers B ON A.CustomerID = B.CustomerID' '(SELECT * FROM Northwind.dbo.Orders WHERE OrderDate > ''8/1/1996'') AS tbl' 

이번 호의 기사에서 소개한 페이징 기법은 레코드의 수가 매우 많은 경우에 서버측 페이징을 처리하기 위해 매우 단순하고, 효율적으로 사용할 수 있으며, 필자의 경우에는 수백만 행이 포함되어 있는 테이블에 대해서도 사용한 경험이 있다. 예를 들어 2천 5백만 레코드가 있는 테이블에 대해서 맨 처음 일부 페이지를 조회하는 쿼리를 실행할 때, ADO RecordSet 페이징 기법을 사용했을 때에는 거의 40초가 걸렸으나 이번 호에 소개한 저장프로시저를 사용한 경우에는 1초로 수행시간을 단축할 수 있었다.
이처럼 이번 호에 소개한 페이징 기법은 조회의 대상이 되는 데이터양이 많아서 ADO RecordSet 페이징 기법을 사용하게 되면 성능상 문제가 발생할 수 있는 상황에서 유용한 대안으로 사용할 수 있다. 


[리스트 1] ClientLocation 속성을 변경하는 코드 
Dim objConn As ADODB.Connection 
Dim objRS As ADODB.Recordset 
' 연결 생성 
Set objConn = New ADODB.Connection 
objConn.Open "Driver=SQL Server; Server=localhost; Database=Northwind" 
Set objRS = New ADODB.Recordset 
   ' 클라이언트측 커서를 사용하게 하는 옵션 
objRS.CursorLocation = adUseClient 
   ' 서버측 커서를 사용하게 하는 옵션 
   objRS.CursorLocation = adUseServer 
objRS.Open "SELECT * FROM Orders", objConn, adOpenStatic, 
adLockOptimistic 
   ' 이 문장은 페이징을 위해서 필요하지만, 서버측 커서를 사용하는 경우에는 에러의 원인이 된다. 
   Debug.Print "Total records: " & objRS.RecordCount 

[리스트 2] 정렬을 위한 조건절을 지정한 일반화된 페이징 쿼리 
SELECT TOP page_size * FROM table WHERE primary_key NOT IN 
    (SELECT TOP page_size * (page_number - 1) primary_key FROM table 
     WHERE filter_conditions 
     ORDER BY sort_field) 
AND filter_criteria 
ORDER BY sort_field 




[리스트 3] 기본키에 검색조건을 먼저 설정하는 일반화 쿼리 
SELECT * FROM table WHERE primary key IN 
    (SELECT TOP page_size primary_key FROM table
     WHERE primary_key NOT IN

          (SELECT TOP page_size * (page_number - 1) primary_key FROM table 
           WHERE filter_conditions ORDER BY sort_field) AND filter_criteria 
     ORDER BY sort_field) 
ORDER BY sort_field 


[리스트 4] SELECT_WITH_PAGING 저장 프로시저 
CREATE PROCEDURE SELECT_WITH_PAGING ( 
@strFields varchar(4000), 
@strPK varchar(100), 
@strTables varchar(4000), 
@intPageNo int = 1, 
@intPageSize int = NULL, 
@blnGetRecordCount bit = 0, 
@strFilter varchar(8000) = NULL, 
@strSort varchar(8000) = NULL, 
@strGroup varchar(8000) = NULL) 
/* 매개변수에 따라 반환되는 결과값을 특정 페이지로 정의하거나 전체 행을 모두 반환할 수 있도록 설정한다. */ 
AS 
DECLARE @blnBringAllRecords bit 
DECLARE @strPageNo varchar(50) 
DECLARE @strPageSize varchar(50) 
DECLARE @strSkippedRows varchar(50) 
DECLARE @strFilterCriteria varchar(8000) 
DECLARE @strSimpleFilter varchar(8000) 
DECLARE @strSortCriteria varchar(8000) 
DECLARE @strGroupCriteria varchar(8000) 
DECLARE @intRecordcount int 
DECLARE @intPagecount int 
/* 페이징 조건 정규화 의미있는 페이징 조건이 입력되지 않은 경우, 페이징하지 않고 좀 더 효율적인 방법으로 쿼리를 실행시키기 위해 blnBringAllRecords 플래그를 사용 */ 
IF @intPageNo < 1 
SET @intPageNo = 1 
SET @strPageNo = CONVERT(varchar(50), @intPageNo) 
IF @intPageSize IS NULL OR @intPageSize < 1 
?- 페이징하지 않고 전체 행을 반환 
   SET @blnBringAllRecords = 1 
ELSE 
   BEGIN 
     SET @blnBringAllRecords = 0 
     SET @strPageSize = CONVERT(varchar(50), @intPageSize) 
     SET @strPageNo = CONVERT(varchar(50), @intPageNo) 
     SET @strSkippedRows = CONVERT(varchar(50), @intPageSize * (@intPageNo - 1)) 
   END 
/* 정렬 및 필터링 조건 정규화 정렬 및 필터링 조건이 지정되지 않으면, 필터링이나 정렬작업이 수행되지 않도록 하여 쿼리의 성능을 향상시킴.*/ 
IF @strFilter IS NOT NULL AND @strFilter != '' 
   BEGIN 
     SET @strFilterCriteria = ' WHERE ' + @strFilter + ' ' 
     SET @strSimpleFilter = ' AND ' + @strFilter + ' ' 
   END 
ELSE 
   BEGIN 
     SET @strSimpleFilter = '' 
     SET @strFilterCriteria = '' 
   END 
IF @strSort IS NOT NULL AND @strSort != '' 
   SET @strSortCriteria = ' ORDER BY ' + @strSort + ' ' 
ELSE 
   SET @strSortCriteria = '' 
IF @strGroup IS NOT NULL AND @strGroup != '' 
   SET @strGroupCriteria = 'GROUP BY' + @strGroup + ' ' 
ELSE 
   SET @strGroupCriteria = '' 
/* 실제 조회작업을 시작 */ 
IF @blnBringAllRecords = 1 -- 페이징 하지 않고 단순한 SELECT 문장만을 실행 
   BEGIN 

     EXEC ( 
               'SELECT ' + @strFields + 'FROM' + @strTables + @strFilterCriteria + 
               @strGroupCriteria + @strSortCriteria 
               ) 
   END -- 전체 레코드를 반환. 
ELSE -- 지정된 페이지를 반환 
   BEGIN 
     IF @intPageNo = 1 -- 맨 처음 페이지를 찾기 때문에 서브쿼리가 없어서 가장 효율적으로 실

                                 행된다.
        EXEC ( 
                  'SELECT TOP' + @strPageSize + ' ' + @strFields + 'FROM' + @strTables + 
                  @strFilterCriteria + @strGroupCriteria + @strSortCriteria 
                 ) 
     ELSE -- 특정 페이지를 선택하기 위해 서브쿼리 구조를 실행한다. 
        EXEC ( 
                   'SELECT' + @strFields + 'FROM' + @strTables + 'WHERE' + @strPK + 'IN' + ' 
                        (SELECT TOP' + @strPageSize + ' ' + @strPK + 'FROM' + @strTables + 
                       ' WHERE' + @strPK + 'NOT IN' + ' 
                            (SELECT TOP' + @strSkippedRows + ' ' + @strPK + 'FROM' + @strTables + 
                             @strFilterCriteria + @strGroupCriteria + @strSortCriteria + ') ' + 
                             @strSimpleFilter + 
                             @strGroupCriteria + 
                         @strSortCriteria + ') ' + 
                    @strGroupCriteria + 
                    @strSortCriteria 
                 ) 
   END -- 특정 페이지를 지정한 경우 
/* 전체 레코드 수를 반환하도록 지정된 경우 */ 
IF @blnGetRecordCount = 1 
IF @strGroupCriteria != '' 
    EXEC ( 
               'SELECT COUNT(*) AS RECORDCOUNT FROM (SELECT COUNT(*) FROM' + 
                @strTables + @strFilterCriteria + @strGroupCriteria + ') AS tbl (id) 
             ) 
ELSE 
    EXEC ( 
               'SELECT COUNT(*) AS RECORDCOUNT FROM' + @strTables + @strFilterCriteria

               + @strGroupCriteria) 
GO 

출처 : SQL2000 매거진



출처 http://cafe.naver.com/headstudy/713.

'Computer > ASP' 카테고리의 다른 글

xmlhttp 를 통한 데이터 교환  (0) 2012.08.10
asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29
성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29
URLEncode  (0) 2011.11.29

 
1. 모든 ASP 코드 페이지 첫줄에 다음과 같은 코드를 추가합니다
<% @LANGUAGE='VBSCRIPT' CODEPAGE='65001' %>
 
2. Meta 테그를 다음과 같이 추가 합니다.
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
 
3. 에디트플러스나 울트라 에디터에서 수정후 저장할 때 반드시 Encoding 방식을 UTF-8 로 저장합니다
 
4.DB Insert/Update 시 숫자 타입을 제외한 모든 대상에 N을 추가 합니다
Insert [into] table_name [(column_list)] Value N[data_value]
 
5.DB like 검색시 N 추가
 
6. 파일 첨부 DEXT Upload사용(영문으로 설치)
  1. SET uploadform = Server.CreateObject("DEXT.FileUpload")
  2.  uploadform.DefaultPath = Server.MapPath(ESP_BBS_DATA)
  3.  uploadform.CodePage = 65001
  4.  wFileSize = 0
  5.  rAttachment = uploadform("txtAttachFile")
  6.  
  7.  If Len(rAttachment) > 0 Then
  8.   wFileName =  uploadform("txtAttachFile").FileName
  9.   wFileSize =  uploadform("txtAttachFile").FileLen
  10.  
  11.   response.write uploadform.DefaultPath
  12.   rAttachment = uploadform.SaveAs(uploadform.DefaultPath & "" & wFileName , False)
  13.   rAttachment = UploadForm.LastSavedFileName
  14.  End If
7. 파일 다운로드 

  1. <% @LANGUAGE='VBSCRIPT' CODEPAGE='65001' %>
  2. <%
  3.  'Response.Charset = "UTF-8"
  4.  filepath = Request.QueryString("txtFilepath") '// form으로 파라메터 전달해야 함.
  5.  filename = Request.QueryString("txtFilename")'// form으로 파라메터 전달해야 함.
  6.  
  7.  If filepath = "" Then
  8.   filepath=server.MapPath( Request.QueryString("txtFilename"))
  9.   filename = Mid(filepath, InStrRev(filepath, "")+1)
  10.  Else
  11.   filepath=server.MapPath(filepath)
  12.   filename =  Request.QueryString("txtFilename")
  13.   If filename = "" Then
  14.    filename = Request.QueryString("txtattachment")
  15.   End If
  16.  End If
  17.  
  18.  filepath = filepath &"" & filename
  19. Call FileDown
  20. %>
  21.  
  22. <%
  23. Sub FileDown
  24. ' 참고http://www.taeyo.pe.kr/Lecture/20_TIps/Danny03.asp
  25.  
  26.  Response.Buffer = False
  27.  Response.ContentType = "application/x-msdownload"
  28.  'ContentType 를 선언합니다.
  29.  'server.HTMLEncode
  30.  'server.URLPathEncode
  31.  Response.AddHeader "Content-Disposition","attachment; filename=" & server.URLPathEncode(filename) '//server.URLPathEncode 사용해야만 파일명 재대로 출력
  32.  '헤더값이 첨부파일을 선언합니다.
  33.  Set objStream = Server.CreateObject("ADODB.Stream")
  34.  'Stream 을 이용합니다.
  35.  objStream.Open
  36.  '무엇이든 Set 으로 정의했으면 열어야 겠지요^^
  37.  objStream.Type = 1
  38.  objStream.LoadFromFile filepath
  39.  '절대경로 입니다.
  40.  download = objStream.Read
  41.  Response.BinaryWrite download
  42.  '이게 보통 Response.Redirect 로 파일로 연결시켜주는 부분을 대신하여 사용된 것입니다.
  43.  Set objstream = nothing
  44.  '초기화시키구요.
  45. End Sub
  46. %>
  47.  
  48. <%
  49. Sub DEXTDown   ' DEXT.FileDownload 는 일본어 OS에 영문으로 설치시 한글파일 찾지 못함.(DextUpload 2.0까지는 그랬음)
  50.  'On Error Resume Next
  51.  Response.Buffer = False
  52.  Response.AddHeader "Content-Disposition","inline;filename=" &  server.URLPathEncode(filename)
  53.  set objFS = Server.CreateObject("Scripting.FileSystemObject")
  54.  
  55.  set objF = objFS.GetFile(filepath)
  56.  
  57.  Response.AddHeader "Content-Length", objF.Size
  58.  set objF = nothing
  59.  set objFS = nothing
  60.  Response.ContentType = "application/x-msdownload"
  61.  Response.CacheControl = "public"
  62.  Set objDownload = Server.CreateObject("DEXT.FileDownload")
  63.  objDownload.Download filepath
  64.  Set uploadform = Nothing
  65. End Sub
  66. %>

8. Cdo Mail 발송
  1. Dim iMsg
  2. Dim iConf
  3. Dim Flds
  4. Dim strHTML
  5. Const cdoSendUsingPort = 2 '1:로컬, 2:외부 smtp
  6. set iMsg = CreateObject("CDO.Message")
  7. set iConf = CreateObject("CDO.Configuration")
  8. Set Flds = iConf.Fields
  9. Flds.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = cdoSendUsingPort
  10. Flds.item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25  '포트번호
  11. Flds.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "localhost"
  12. Flds.Item("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 10
  13. Flds.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") =  "" 'ID
  14. Flds.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") =  "" '암호
  15.  
  16. Flds.Update
  17. Set iMsg.Configuration = iConf
  18. iMsg.To = "xxxx@xxx.ccx" 'ToDo: Enter a valid email address.
  19. iMsg.From = "xxxx@xxx.ccx"  'ToDo: Enter a valid email address.
  20. iMsg.Subject = "This is a test CDOSYS message (Sent via Port 25)"
  21.  
  22. 'iMsg..TextBody = strHTMLMsg '// 텍스트
  23. iMsg.HTMLBody = strHTML  '// HTML 제목 깨짐 발생..
  24.  
  25. iMsg.BodyPart.Charset="UTF-8" '/// 한글을 위해선 꼭 넣어 주어야 합니다.
  26. iMsg.HTMLBodyPart.Charset="UTF-8" '/// 한글을 위해선 꼭 넣어 주어야 합니다.
  27. iMsg.Send
  28. End With
  29. Set iMsg = Nothing
  30. Set iConf = Nothing
  31. Set Flds = Nothing 
 
9. ASP에서 배달 확인/ 읽음 확인 구현 방법 http://tong.nate.com/windeo/5767827
  1. <%
  2. Set oMsg = CreateObject("CDO.Message")
  3. oMsg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
  4. ‘ 생성되는 메시지가 SMTP pickup 디렉터리가 아닌 SMTP 서비스로 전송되게 합니다.
  5. oMsg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "이름"
  6. oMsg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "xxxxx"
  7. oMsg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "seo-msg-01"
  8. ‘ 생성되는 메시지의 서버, 사서함 및 암호
  9. oMsg.Configuration.Fields.Update
  10.  
  11. oMsg.From = "smpark@microsoft.com"
  12. oMsg.To = "smpark@microsoft.com"
  13.  
  14. oMsg.Subject = "읽음 확인 및 배달 확인"
  15. oMsg.DSNOptions = 14
  16. ‘ 이 메시지의 배달 상태 확인(delivery status notification:DSN)값으로 14는 배달 성공, 실패 및 지연시
  17. ‘ 확인메시지 생성
  18. oMsg.Fields("urn:schemas:mailheader:return-receipt-to") = smpark@microsoft.com <mailto:smpark@microsoft.com>
  19. ‘ 받는 사람이 이 메시지를 열었을 때 읽음 확인 메시지가 여기에서 지정된 사람에게 보내집니다.
  20. oMsg.Fields("urn:schemas:mailheader:disposition-notification-to") = smpark@microsoft.com <mailto:smpark@microsoft.com>
  21. ‘ MDN(Message Disposition Notification)은 이 메시지의 확인 메시지가 리턴 될 수신자를 지정합니다.
  22. ‘ MDN에 대하여는 Request for Comments (RFC) 2298에 자세히 설명됩니다.
  23. oMsg.TextBody = " SMTP 서버를 통한 읽음 확인 및 배달 확인 메시지"
  24. oMsg.Fields.Update
  25. oMsg.Send
  26.  
  27. Set oMsg = Nothing
  28. %>




출처 http://blog.naver.com/lowsky/21899479.

'Computer > ASP' 카테고리의 다른 글

asp 용 UTF8 컨버터  (0) 2012.08.10
효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29
성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29
URLEncode  (0) 2011.11.29
ASP 서버 변수 출력  (0) 2011.11.29

Microsoft 컨설팅 서비스, 수석 컨설턴트, Len Cardinal
Microsoft IIS Performance 지도자, George V. Reilly
Microsoft Corporation
개발자 기술 엔지니어
Nancy Cluts의 기사 에서 발췌
최종 수정일: 2000년 4월
요약: 이 기사는 ASP 응용 프로그램 및 VBScript를 최적화하기 위한 팁을 소개합니다.
목차
소개
팁 1: 웹 서버에서 자주 사용되는 데이터 캐시
팁 2: 응용 프로그램 및 세션 개체에서 자주 사용되는 데이터 캐시
팁 3: 웹 서버의 디스크 상에서 데이터 및 HTML 캐시
팁 4: 응용 프로그램 또는 세션 개체에서 활발하지 않은 구성 요소 캐싱 방지
팁 5: 응용 프로그램 또는 세션 개체에서 데이터베이스 연결 캐시 금지
팁 6: 세션 개체의 현명한 사용
팁 7: COM 개체에서 코드 간략화
팁 8: 늦은 리소스 획득, 이른 해제
팁 9: 안정성과 성능을 교환하는 종속 프로세스 실행
팁 10: Option Explicit 사용
팁 11: 서브루틴 및 함수에서 지역 변수 사용
팁 12: 자주 사용되는 데이터를 스크립트 변수로 복사
팁 13: 배열 재정의 방지
팁 14: 응답 버퍼링 사용
팁 15: 일괄 처리 인라인 스크립트 및 Response.Write 문
팁 16: 긴 이동을 시작하기 전에 Response.IsClientConnected 사용
팁 17: 태그를 사용한 개체 인스턴스화
팁 18: ADO 및 다른 구성 요소를 위한 TypeLib 바인딩 사용
팁 19: 사용자 브라우저의 유효성 검사 기능 이용
팁 20: 루프에서 문자열 연결 방지
팁 21: 브라우저 및 프록시 캐싱 사용 
팁 22: 가능한 한 Response.Redirect대신 Server.Transfer 사용
팁 23: 디렉터리 URL에서 후행 슬래시 사용
팁 24: 서버 변수 사용 방지
팁 25: 최신 및 최고급으로 업그레이드
팁 26: 웹 서버 조정
팁 27: 성능 테스트
팁 28: 리소스 연결 읽기
소개
성능은 하나의 기능입니다. 성능을 향상시킬 수 있도록 디자인하거나 나중에 응용 프로그램을 다시 작성해야 합니다. 그러면 ASP(Active Server Pages) 응용 프로그램의 성능을 최대로 발휘할 수 있는 훌륭한 전략에는 어떤 것이 있을까요?
이 기사는 ASP 응용 프로그램 및 Visual Basic?? Scripting Edition(VBScript)을 최적화할 팁을 제공합니다. 이 기사에서는 여러 가지 덫과 함정들을 설명합니다. 이 기사에 열거된 제안은 http://www.microsoft.com 및 다른 사이트에서 검사했으며 매우 잘 작동하였습니다. 이 기사는 사용자가 VBScript 및/또는 JScript, ASP 응용 프로그램, ASP 세션 및 다른 ASP 고유 개체(요청 응답 및 서버)와 같은 ASP 개발을 기본으로 이해하고 있다는 전제 하에 쓰여진 것입니다.
ASP 성능은 ASP 코드 그 자체에 많은 영향을 받습니다. 여기서 우리는 기사에 있는 모든 지혜를 다루는 대신 성능과 관련된 리소스를 열거합니다. 이러한 링크는 ActiveX?? Data Objects(ADO), Component Object Model (COM), 데이터베이스 및 Internet Information Server (IIS) 구성을 포함하는 ASP와 비ASP 주제를 모두 다룹니다. 우리가 선호하는 링크가 있으니 잘 살펴 보십시오.
팁 1: 웹 서버에서 자주 사용되는 데이터 캐시
전형적인 ASP 페이지는 백 엔드 데이터 공간에서 데이터를 검색하고 그 결과를 HTML(Hypertext Markup Language)로 복사합니다. 데이터베이스의 속도와 관계없이 메모리에서 데이터를 검색하는 것은 백 엔드 데이터 공간에서 데이터를 검색하는 것보다 매우 빠릅니다. 로컬 하드 디스크에서 데이터를 읽는 것도 데이터베이스에서 데이터를 검색하는 것보다 더 빠릅니다. 따라서 웹 서버에 있는 데이터를 메모리 또는 디스크에 캐싱하면 성능을 향상시킬 수 있습니다.
캐싱은 시간과 공간을 교환하는 전통적인 방법입니다. 캐시를 올바로 사용하면 성능이 매우 향상된 것을 알 수 있습니다. 캐시를 사용하는 것이 효과적이려면 자주 다시 사용되는 데이터가 있어야 하고 이 데이터를 다시 계산하는 비용이 (적당히) 높아야 합니다. 부실한 데이터를 모두 캐시하는 것은 메모리 낭비입니다.
자주 변경되지 않는 데이터는 데이터베이스 시간 초과와 동시성을 갖을 염려가 없기 때문에 캐싱하기에 적합합니다. 콤보 상자 목록, 참조표, DHTML 스크랩, XML(eXtensible Markup Language) 문자열, 메뉴 항목 및 (데이터 소스 이름(DSN), 인터넷 프로토콜(IP) 어드레스 및 웹 경로를 포함하는)사이트 구성 변수가 캐싱하기에 적합한 것입니다. 데이터 자체보다는 데이터의 프리젠테이션을 캐시할 수 있다는 것을 참조하십시오. ASP 페이지가 자주 변경되고 캐시 비용이 비싸다면(예: 전체 제품 카탈로그) 매번 다시 패인팅하기 보다는 HTML을 미리 생성하도록 하십시오.
데이터를 캐시해야 할 곳은 어디이며 어떤 캐싱 정책이 있습니까? 종종 웹 서버의 메모리 또는 웹 서버의 디스크에서 데이터를 캐시합니다. 다음 두 팁은 이 옵션을 다룹니다.
팁 2: 응용 프로그램 및 세션 개체에서 자주 사용되는 데이터 캐시
ASP 응용 프로그램 및 세션 개체는 메모리 안에 캐싱을 편리하게 해주는 컨테이너를 제공합니다. 응용 프로그램 및 세션 개체에 모두 데이터를 지정할 수 있고 이 데이터는 HTTP 호출 사이에 메모리에 남아 있을 것입니다. 세션 데이터는 각 사용자별로 저장되는 반면 응용 프로그램 데이터는 모든 사용자가 공유합니다.
어느 지점에서 데이터를 응용 프로그램 또는 세션에 로드할까요? 일반적으로 데이터는 응용 프로그램 또는 세션이 시작할 때 로드됩니다. 응용 프로그램 또는 세션이 시작할 때 데이터를 로드하려면 Application_OnStart() 또는 Session_OnStart()에 각각 적당한 코드를 추가합니다. 이러한 함수는 Global.asa에 있어야 하며 없을 때는 이 함수를 추가할 수 있습니다. 가장 필요할 때 데이터를 로드할 수도 있습니다. 이렇게 하려면 데이터가 있는지 확인하고 없을 경우 데이터를 로드하도록 ASP 페이지에 몇 가지 코드를 추가하십시오.(또는 재사용할 수 있는 스크립트 함수 작성) 이것은 필요하다는 것을 알 때 까지 계산을 하지 않는 지연 평가라는 전형적인 성능 기술의 예입니다. 예를 들면 다음과 같습니다.
<%Function GetEmploymentStatusList Dim d d = Application("EmploymentStatusList") If d = "" Then ' FetchEmploymentStatusList function (not shown) ' fetches data from DB, returns an Array d = FetchEmploymentStatusList() Application("EmploymentStatusList") = d End If GetEmploymentStatusList = dEnd Function%>
데이터가 필요한 각 청크를 위해 유사한 함수를 작성할 수 있습니다.
어떤 형식으로 데이터를 저장해야 합니까? 모든 스크립트 변수가 가변형이기 때문에 모든 가변 형식을 저장할 수 있습니다. 예를 들어, 문자열, 정수형 또는 배열을 저장할 수 있습니다. 일반적으로 ADO 레코드 집합의 내용을 이러한 변수 형식 중 하나로 저장할 수 있습니다. ADO 레코드 집합에서 데이터를 얻기 위해 한번에 한 필드에서 수동으로 데이터를 VBScript 변수에 복사할 수 있습니다. ADO 레코드 집합 영구 함수인 GetRows(), GetString()  또는 Save()  (ADO 2.5) 중 하나를 사용하면 더 빠르고 쉽습니다. 이 기사에서는 전체를 자세히 설명하지는 않지만 레코드 집합 데이터의 배열을 반환하기 위해 GetRows()를 사용하는 한가지 함수의 예를 들면 다음과 같습니다.
' Get Recordset, return as an ArrayFunction FetchEmploymentStatusList Dim rs Set rs = CreateObject("ADODB.Recordset") rs.Open "select StatusName, StatusID from EmployeeStatus", _ "dsn=employees;uid=sa;pwd=;" FetchEmploymentStatusList = rs.GetRows() " Return data as an Array rs.Close Set rs = NothingEnd Function
위의 예제를 더 구체화하면 배열이 아닌 목록을 위한 HTML을 캐시할 수도 있습니다. 단순한 예를 들면 다음과 같습니다.
' Get Recordset, return as HTML Option listFunction FetchEmploymentStatusList Dim rs, fldName, s Set rs = CreateObject("ADODB.Recordset") rs.Open "select StatusName, StatusID from EmployeeStatus", _ "dsn=employees;uid=sa;pwd=;" s = "" & vbCrLf rs.Close Set rs = Nothing ' See Release Early FetchEmploymentStatusList = s ' Return data as a StringEnd Function
올바른 조건에서는 응용 프로그램 또는 세션 범위에서 ADO 레코드 집합 그 자체를 캐시할 수 있습니다. 다음과 같은 두 가지 주의 사항이 있습니다.
이러한 두 가지 요구 사항을 충족시킬 수 없다면 ADO 레코드 집합을 캐시하지 마십시오. 아래 있는 Non-Agile Components 및 Don't Cache Connections 팁에서는 응용 프로그램 및 세션 범위에서 COM 개체를 저장하는 것이 위험하다는 것을 설명합니다.
응용 프로그램 또는 세션 범위에서 데이터를 저장하면 이 데이터는 체계적으로 데이터를 변경하거나, 세션이 만료되거나, 웹 응용 프로그램이 다시 시작할 때까지 저장된 곳에 남아 있게 됩니다. 데이터를 업데이트하려면 어떻게 해야 할까요? 응용 프로그램 데이터를 수동으로 업데이트하려면 데이터를 업데이트하는 관리자 전용 ASP 페이지로 이 데이터를 호출할 수 있습니다. 그렇지 않으면 함수를 통해 주기적으로 데이터를 자동으로 새로 고칠 수 있습니다. 다음 예제에서는 캐시한 데이터를 타임 스탬프와 함께 저장하고 일정 기간이 지난 후 데이터를 새로 고칩니다.
<%' error handing not shown...Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds' Function to return the employment status listFunction GetEmploymentStatusList UpdateEmploymentStatus GetEmploymentStatusList = Application("EmploymentStatusList")End Function' Periodically update the cached dataSub UpdateEmploymentStatusList Dim d, strLastUpdate strLastUpdate = Application("LastUpdate") If (strLastUpdate = "") Or _ (UPDATE_INTERVAL < DateDiff("s", strLastUpdate, Now)) Then ' Note: two or more calls might get in here. This is okay and will simply ' result in a few unnecessary fetches (there is a workaround for this) ' FetchEmploymentStatusList function (not shown) ' fetches data from DB, returns an Array d = FetchEmploymentStatusList() ' Update the Application object. Use Application.Lock() ' to ensure consistent data Application.Lock Application("EmploymentStatusList") = d Application("LastUpdate") = CStr(Now) Application.Unlock End IfEnd Sub
또 다른 예는 응용 프로그램 데이터가 있는 World's Fastest ListBox  를 참조하십시오.
세션 또는 응용 프로그램 개체에서 큰 배열을 캐싱하는 것은 바람직하지 않습니다. 배열의 어떤 요소에 액세스하기 전에 스크립팅 언어의 기능이 전체 배열을 임시로 복사할 것을 요구합니다. 예를 들어, 미국 우편 번호와 지역 기상대를 연결하는 10만개의 요소가 있는 문자열 배열을 캐시할 경우 ASP는 우선 10만개 기상대를 모두 임시 배열에 복사한 후에야 하나의 문자열을 추출할 수 있습니다. 이 경우에는 기상대를 저장하거나 사전 구성 요소 중 하나를 사용하기 위한 사용자 정의 메서드가 있는 사용자 정의 구성 요소를 작성하는 것이 좋습니다.
중요한 것을 놓치지 않기 위해 한 마디 덧붙이자면 배열은 메모리에 인접한 키 데이터 쌍을 빨리 조회하고 저장할 수 있도록 합니다. 사전을 인덱싱하는 것은 배열을 인덱싱하는 것 보다 느립니다. 자신의 상황에서 최상의 성능을 제공하는 데이터 구조를 선택해야 합니다.
팁 3: 웹 서버의 디스크 상에서 데이터 및 HTML 캐시
때때로 데이터가 너무 많아서 메모리에서 캐시할 수 없는 경우가 있습니다. "너무 많다"는 것은 판단력에 근거한 것으로 캐시할 항목의 수와 이 항목을 검색하는 빈도뿐 아니라 소비할 메모리의 양과도 관계가 있습니다. 어떤 경우든 메모리에서 캐시하기에 데이터가 너무 많을 때는 웹 서버의 하드 디스크 상에서 텍스트 또는 XML 파일로 데이터를 캐시할 수도 있습니다. 상황에 가장 적합한 캐싱 정책을 세우기 위해 데이터를 캐싱하는 데 메모리와 디스크를 같이 사용할 수 있습니다.
단일 ASP 페이지의 성능을 측정할 때는 디스크에서 데이터를 검색하는 것이 데이터베이스에서 데이터를 검색하는 것보다 느릴 수도 있다는 것을 참조하십시오. 그러나 캐싱은 데이터베이스 및 네트워크에서 로드를 줄여줍니다. 로드가 높을 때 캐싱은 전체적인 성능을 향상시킵니다. 다중 테이블 조인 또는 복잡한 저장 프로시저와 같은 부담이 큰 쿼리의 결과를 캐싱하거나 큰 결과 집합을 캐싱하는 경우 캐싱은 매우 효과적입니다. 언제나 처럼 경쟁하는 여러 가지 계획을 테스트하십시오.
ASP 및 COM은 디스크 캐싱 계획을 세우기 위한 몇 가지 도구를 제공합니다. ADO 레코드 집합 Save() 및 Open() 함수는 디스크에서 레코드 집합을 저장 및 로드합니다. 앞서 언급한 응용 프로그램 데이터 캐싱 팁으로부터 예제 코드를 다시 작성하기 위해 이러한 메서드를 사용할 수 있습니다. 위의 팁에서는 파일로의 Save() 함수가 응용 프로그램 개체에 작성하는 코드를 대신합니다.
파일로 작업하는 다른 몇 가지 구성 요소가 있습니다.
  • FileSystemObject를 스크립트  하면 파일을 생성, 읽기 및 작성할 수 있습니다.
  • Internet Explorer와 함께 제공되는 Microsoft?? XML 파서인 MSXML은 XML 문서를 저장 및 로드할 수 있도록 합니다.
  • The LookupTable 개체(예제, MSN에서 사용)는 디스크에서 단순한 목록을 로드하는 데 가장 적합합니다.
마지막으로 디스크에 데이터 자체보다는 데이터의 프리젠테이션을 캐싱하도록 하십시오. 미리 렌더링된 HTML은 디스크에 .htm 또는 .asp 파일로 저장되고 하이퍼링크로 이 파일을 직접 가리킬 수 있습니다. XBuilder  , 또는 Microsoft?? SQL Server™ Internet publishing features와 같은 상업용 도구를 사용하여 HTML 생성 과정을 자동화할 수 있습니다. 그 대신 .asp 파일에 HTML 조각을 포함할 수도 있습니다. FileSystemObject를 사용하여 디스크에서 HTML 파일을 읽거나 빠른 렌더링을 위해 XML을 사용  할 수도 있습니다.
팁 4: 응용 프로그램 또는 세션 개체에서 활발하지 않은 구성 요소 캐싱 방지
응용 프로그램 또는 세션 개체에 있는 데이터를 캐싱하는 것은 바람직하지만 COM 개체를 캐싱하는 것은 심각한 위험이 될 수 있습니다. 자주 사용하는 COM 개체를 응용 프로그램 또는 세션 개체에 넣고 싶어지는 경우가 있습니다. 그러나 불행히도 Visual Basic 6.0과 그 이전 버전으로 작성된 모든 COM 개체를 포함하여 많은 COM 개체들이 응용 프로그램 또는 세션 개체에 저장되면 심각한 병목현상을 일으킬 수 있습니다.
특히 구성 요소가 활발하지 않다면 세션 또는 응용 프로그램 개체에서 캐시할 때 성능에 병목 현상이 발생합니다. 활발한 구성 요소는 FTM(Free-threaded marchaler)이 모인 ThreadingModel=Both로 표시된 구성 요소 또는 ThreadingModel=Neutral로 표시된 구성 요소입니다.(Neutral 모델은 Windows?? 2000 and COM+에 새로 도입된 것입니다.) 다음과 같은 구성 요소는 활발하지 않습니다.
  • 빈 스레드 구성 요소(FTM을 모으지 않는 경우)
  • 아파트 스레드 구성 요소
  • 단일 스레드 구성 요소
구성된 구성 요소(Microsoft Transaction Server (MTS)/COM+ 라이브러리 및 서버 패키지/응용 프로그램)는 중립 스레드를 제외하면 활발하지 않습니다. 아파트 스레드 구성 요소 및 다른 활발하지 않은 구성 요소는 페이지 범위에서 가장 잘 실행됩니다.(즉, 단일 ASP 페이지에서 만들고 없앱니다.)
IIS 4.0에서는 ThreadingModel=Both가 표시된 구성 요소가 활발한 것이었습니다. 그러나 IIS 5.0에서는 이것이 더 이상 충분하지 않고 Both가 표시될 뿐 아니라 FTM을 모아야 합니다. 활발함에 대한 기사  는 Active Template Library로 작성된 C++ 구성 요소가 FTM을 모으는 방법을 설명합니다. 구성 요소가 인터페이스 포인터를 캐시할 때 이 포인터는 활발하거나 COM GIT(Global Interface Table)에 저장되어야 한다는 것을 주의하십시오. FTM을 모으기 위해 양쪽 스레드 구성 요소를 컴파일할 수 없다면 그 구성 요소를 ThreadingModel=Neutral로 표시할 수 있습니다. 대신 IIS가 활발함 검사를 수행하지 않게 하려면(따라서 활발하지 않은 구성 요소를 응용 프로그램 또는 세션 범위에 저장하려면) 메타베이스에 AspTrackThreadingModel을 True로 설정할 수 있습니다. AspTrackThreadingModel을 변경하는 것은 바람직 하지 않습니다.
응용 프로그램 개체에서 Server.CreateObject로 작성된 활발하지 않은 구성 요소를 저장하려고 하면 IIS 5.0은 오류를 표시합니다. 이때 Global.asa에서 를 사용하여 이 오류를 피해갈 수 있지만 이렇게 하면 아래에 설명하는 마샬링 및 직렬화가 될 수 있기 때문에 바람직 하지 않습니다.
활발하지 않은 구성 요소를 캐시하면 어떤 문제가 발생합니까? 활발하지 않은 구성 요소를 세션 개체에서 캐시하면 ASP 작업자 스레드로의 세션을 "잠금"으로 만듭니다. ASP는 서비스가 요청하는 작업자 스레드를 유지합니다. 일반적으로 새로운 요청은 처음 사용할 수 있는 작업자 스레드가 처리합니다. 스레드에 대한 세션이 잠기면 요청은 관련 스레드를 사용할 수 있을 때까지 대기해야 합니다. 이해를 돕기 위해 비유를 하자면 다음과 같습니다. 수퍼 마켓에 가서 야채를 사고 3번 계산대에서 계산을 했다면 그 이후에는 수퍼 마켓에서 야채 값을 지불 할 때마다 다른 계산대가 더 한가하거나 비어있어도 3번 계산대에서만 지불할 수 있습니다.
응용 프로그램에 활발하지 않은 구성 요소를 저장하면 성능에 더욱 나쁜 영향을 줍니다. ASP는 활발하지 않은 응용 프로그램 범위 구성 요소를 실행하기 위해 특별한 스레드를 작성해야 합니다. 이것은 두 가지 결과를 초래합니다. 모든 호출이 이 스레드로 마샬링되어야 하고 모든 호출이 직렬화됩니다. 마샬링이 되면 매개 변수는 메모리 공유 영역에 저장되어야 하고, 특별한 스레드에는 비용이 많이 드는 컨텍스트 전환이 이루어지고, 구성 요소의 메서드를 실행하고, 결과가 공유 영역으로 마샬링되며, 비용이 많이 드는 다른 컨텍스트 전환이 컨트롤을 원래 스레드로 돌려주게 됩니다. 직렬화되면 모든 메서드가 한번에 하나씩 실행됩니다. 두 개의 다른 ASP 작업자 스레드가 공유된 구성 요소에서 동시에 실행 메서드가 될 수는 없습니다. 이렇게 하면 특히 다중 프로세서 컴퓨터에서 일관성이 없어집니다. 더욱 나쁜 것은 모든 활발하지 않은 응용 프로그램 범위 구성 요소가 하나의 스레드("Host STA")를 공유하기 때문에 직렬화의 영향이 더욱 뚜렷해지는 것입니다.
너무 복잡합니까? 여기에 몇 가지 일반적 규칙이 있습니다. Visual Basic (6.0) 및 이전 버전에서 개체를 작성할 때는 이 개체를 응용 프로그램 또는 세션 개체에서 캐시하지 마십시오. 개체의 스레딩 모델을 모르는 경우에는 캐시하지 마십시오. 활발하지 않은 개체는 캐싱하지 말고 각 페이지에서 그 개체를 작성하고 릴리스해야 합니다. 이 개체는 ASP 작업자 스레드에서 직접 실행하기 때문에 마샬링 및 직렬화가 일어나지 않습니다. COM 개체가 IIS 상자에서 실행하고 개체를 초기화하고 없애는 데 시간이 오래 걸리지 않는다면 적합한 성능입니다. 단일 스레드 개체는 이런 방법으로 사용하지 마십시오. VB이 단일 스레드 개체를 만들 수 있으므로  주의하십시오! 단일 스레드 개체를 이 방식으로 사용해야 한다면(Microsoft Excel 스프레드시트처럼) 높은 처리 속도를 기대하지는 마십시오.
ADO 레코드 집합이 빈 스레드로 표시되면 ADO 레코드 집합을 안전하게 캐시할 수 있습니다. ADO를 빈 스레드로 표시하려면 일반적으로 Program FilesCommonSystemADO 디렉터리에 있는 Makfre15.bat 파일을 사용합니다.
주의: Microsoft Access를 데이터베이스로 사용하는 경우에는 ADO를 빈 스레드로 표시하지 마십시오. ADO 레코드 집합의 연결도 끊어야 합니다. 일반적으로 사용자 사이트에서 ADO 구성을 제어할 수 없다면(예를 들어, 고유한 구성을 관리하는 고객에게 웹 응용 프로그램을 판매한 독립적 소프트웨어 공급업체(ISV: independent software vendor)의 경우) 레코드 집합을 캐싱하지 않는 것이 더 좋을 것입니다.
사전 구성 요소도 활발한 개체입니다. LookupTable은 데이터 파일에서 데이터를 로드하며 구성 정보뿐 아니라 콤보 상자 데이터에 유용합니다. Duwamish Books  의 PageCache 개체는 Caprock 사전과 같은 사전 기능을 제공합니다. 이러한 개체 또는 그 파생물은 효과적인 캐싱 정책의 기초를 형성할 수 있습니다. 스크립팅 사전 개체는 활발한 개체가 아니며 응용 프로그램 또는 세션 범위에 저장해서는 안된다는 것을 주의하십시오.
팁 5: 응용 프로그램 또는 세션 개체에서 데이터베이스 연결 캐시 금지
ADO 연결을 캐싱하는 것은 일반적으로 좋지 않은 전략입니다. 응용 프로그램에 하나의 연결 개체가 저장되고 전체 페이지에서 사용된다면 모든 페이지가 이 연결을 사용하려고 경쟁하게 될 것입니다. 연결 개체가 ASP 세션 개체에 저장된 경우에는 모든 사용자를 위해 데이터베이스 연결이 작성될 것입니다. 이것은 연결 풀링의 이익을 상쇄시키며 웹 서버와 데이터베이스에 불필요한 높은 스트레스를 주게 됩니다.
데이터베이스 연결을 캐싱하는 대신 ADO를 사용하는 모든 ASP 페이지에서 ADO 개체를 작성하고 없앱니다. IIS에는 내장된 데이터베이스 연결 풀링이 있기 때문에 이렇게 하는 것이 효과적입니다. 좀더 자세히 말하자면 IIS 는 OLEDB 및 ODBC 연결 풀링을 자동화합니다. 따라서 각 페이지에서 연결을 작성하고 없애는 것이 더 효과적이라는 것을 확인할 수 있습니다.
연결된 레코드 집합은 참조를 데이터베이스 연결에 저장하기 때문에 응용 프로그램 또는 세션 개체에서 연결된 레코드 집합을 캐시하면 안됩니다. 하지만 연결이 끊어진 레코드 집합은 데이터 연결에 대한 참조를 갖지 않기 때문에 안전하게 캐시할 수 있습니다. 레코드 집합의 연결을 끊기 위해서는 다음과 같은 두 단계를 밟아야 합니다.
Set rs = Server.CreateObject("ADODB.RecordSet") rs.CursorLocation = adUseClient ' step 1 ' Populate the recordset with data rs.Open strQuery, strProv ' Now disconnect the recordset from the data provider and data source rs.ActiveConnection = Nothing ' step 2
연결 풀링에 대한 자세한 정보는 ADO 및 SQL 서버 참조에 있습니다.
팁 6: 세션 개체의 현명한 사용
지금 까지 응용 프로그램 및 세션에서 캐싱의 장점을 지지해왔으므로 이제는 세션 개체를 방지하도록 제한하려고 합니다. 앞으로 논의하겠지만 세션을 분주한 사이트에서 사용하면 몇 가지 위험이 있습니다. 분주하다는 것은 일반적으로 초당 수백 페이지가 요청되거나 수천명의 동시 사용자가 있는 사이트를 의미합니다. 이 팁은 전반적으로 측정해야 하는 사이트 즉, 로드를 받아들이거나 내결함성을 구현하기 위한 다중 서버를 사용하는 사이트에 특히 유용합니다. 인트라넷 사이트와 같은 소규모 사이트에서 세션의 편리함은 오버헤드 만큼의 가치가 있습니다.
간단히 말해서 ASP는 자동으로 웹 서버에 접근하는 모든 사용자를 위한 세션을 작성합니다. 각 세션은 약 10 KB의 메모리 오버헤드(세션에 저장된 모든 데이터의 상단에 있는)를 갖고 있어서 모든 요청을 약간 늦춥니다. 세션은 구성할 수 있는 시간 제한 기간동안 유효하며 이 제한 시간은 일반적으로 20분입니다.
세션에 관한 가장 큰 문제는 성능이 아닌 확장성입니다. 세션은 여러 웹 서버들을 걸치지 않기 때문에 일단 하나의 서버에 세션이 만들어지면 그 데이터는 그 서버에 있습니다. 이것은 웹 그룹에서 세션을 사용하면 각 사용자의 요청이 사용자의 세션이 있는 서버로 향하도록 정책을 만들어야 한다는 것을 의미합니다. 이런 것을 사용자를 웹 서버에 "고정"시킨다고 합니다. "고정 세션"이라는 용어는 여기서 유래한 것입니다. 세션이 디스크에 계속 남아있지 않기 때문에 "고정된" 사용자는 웹 서버가 작동을 중지하면 세션 상태를 잃어버리게 됩니다.
고정 세션을 구현하기 위한 정책은 하드웨어 및 소프트웨어 솔루션을 포함합니다. Windows 2000 Advanced Server에 있는 Network Load Balancing  및 Cisco의 Local Director와 같은 솔루션은 약간의 확장성을 희생하여 고정 세션을 구현할 수 있습니다. 이러한 솔루션은 완전하지 않습니다. 이러한 상황에서 자신의 소프트웨어 솔루션을 실행하는 것은 바람직하지 않습니다(우리는 ISAPI 필터 및 URL 맹글링(mangling)과 같은 것을 사용해 왔습니다).
응용 프로그램 개체도 서버를 걸치지 않기 때문에 웹 그룹들 사이에 응용 프로그램 데이터를 공유하거나 업데이트해야 할 경우에는 백 엔드 데이터베이스를 사용해야 합니다. 그러나 읽기 전용 응용 프로그램 데이터를 웹 그룹에서 여전히 사용할 수 있습니다.
작동 시간(장애 조치 및 서버 유지 관리)이 증가는 것 외에 다른 이유가 없다면 대부분 업무용 사이트는 적어도 두 개의 웹 서버에 배포하기를 원합니다. 따라서 업무용 응용 프로그램을 만들 때는 개별적 웹 서버에 사용자 상태를 저장하는 상태 관리 기술뿐 아니라 "고정 세션"을 구현하거나 단순히 세션을 방지해야 합니다.
세션을 사용하지 않는다면 세션을 반드시 꺼야 합니다. Internet Services Manager를 통해 사용자 응용 프로그램의 세션을 끌 수 있습니다.(ISM 설명서 참조) 세션을 사용하려면 몇 가지 방법으로 성능에 영향을 최소화해야 합니다.
세션이 필요하지 않은 컨텐츠(도움말 화면, 방문자 영역 등)를 세션이 꺼진 별도의 ASP 응용 프로그램으로 옮길 수 있습니다. 각 페이지를 기초로 해당 페이지에 세션 개체가 필요 없다는 것을 알리기 위해 다음과 같은 지시어를 ASP 페이지 상단에 놓을 수 있습니다.
<% .EnableSessionState=False %>
이 지시어를 사용하게 되는 이유 중 하나는 세션이 프레임셋과 관심있는 문제를 만드는 것입니다. ASP는 언제나 한번에 한 세션에서 하나의 요청만이 실행되도록 보장합니다. 따라서 브라우저가 한 사용자를 위해 여러 페이지를 요청하면 한번에 단지 하나의 ASP 요청만이 세션에 전달되기 때문에 세션 개체에 액세스할 때 멀티스레딩 문제를 방지합니다. 그러나 불행하게도 프레임셋에 있는 모든 페이지는 동시에 페인트되지 않고 차례로 순차적 방법으로 페인트됩니다. 모든 프레임을 페인트하려면 오래 기다려야 합니다. 이야기의 교훈은 다음과 같습니다. 어떤 프레임셋 페이지가 세션에 의지하지 않는 다면 ASP가 @EnableSessionState=False 지시어를 사용하도록 하십시오.
세션 개체를 사용하지 않고 세션 상태를 관리할 많은 옵션이 있습니다. 상태가 작은 양일 때(4 KB 미만)는 nulls, QueryString 변수 및 숨겨진 형식 변수를 사용하는 것이 바람직합니다. 쇼핑 카드처럼 데이터의 양이 많은 경우는 백 엔드 데이터베이스가 더 적합합니다. 웹 서버 그룹에서 상태 관리 기술에 대해 다룬 많은 글들이 있습니다. 자세한 내용은 세션 상태 참조를 참조하십시오.
팁 7: COM 개체에서 코드 간략화
VBScript 또는 JScript가 많을 때는 이 코드를 컴파일된 COM 개체에 옮겨서 성능을 향상시킬 수 있습니다. 컴파일된 코드는 해석된 코드보다 더 빨리 실행됩니다. 컴파일된 COM 개체는 스크립트가 사용하는 "늦은 바인딩"보다 더 효율적으로 COM 개체 메서드를 불러오는 방법인 "이른 바인딩"을 통해 다른 COM 개체에 액세스할 수 있습니다.
COM 개체에서 코드를 캡슐화하는 것은 여러 가지로 유리합니다.(성능을 제외하고)
  • COM 개체는 프리젠테이션 논리와 비즈니스 논리를 분리하는 데 유용합니다.
  • COM 개체는 코드를 재사용 할 수 있도록 합니다.
  • VB, C++ 또는 Visual J++로 작성된 코드는 ASP로 작성된 것보다 디버그하기 쉽다는 것을 많은 개발자들이 알아냈습니다.
COM 개체는 초기 개발 시간 및 다른 프로그래밍 기술의 필요 등과 같은 단점들이 있습니다. 작은 양의 ASP를 캡슐화하면 성능이 향상되기 보다는 떨어질 수 있습니다. 일반적으로 작은 양의 ASP 코드가 COM 개체로 싸여질 때 성능이 떨어집니다. 이런 경우에는 COM 개체를 작성하고 불러오는 오버헤드가 컴파일된 코드의 이익보다 더 커집니다. ASP 스크립트와 COM 개체를 어떻게 조합해야 최상의 성능이 나오는지는 시행착오를 통해서 알 수 있습니다. Microsoft가 Windows 2000/Windows NT?? 4.0상의 IIS 5.0/IIS 4.0에서 스크립트와 ADO 성능을 상당히 향상시켰다는 것을 참조하십시오. IIS 5.0이 등장하면서 ASP 코드 위에 컴파일된 코드를 사용하여 얻을 수 있었던 성능 향상의 이익이 줄어들었습니다.
ASP에서 COM 개체를 사용하여 얻을 수 있는 이익과 손해에 대한 자세한 논의는 ASP 구성 요소 지침  및 COM과 Microsoft Visual Basic 6.0으로 작성된 분산형 응용 프로그램 프로그래밍  을 참조하십시오. COM 구성 요소를 배포하려면 구성 요소들의 스트레스를 테스트  하는 것이 특히 중요합니다. 사실 모든 ASP 응용 프로그램은 어떤 경우에도 스트레스를 테스트해야 합니다.
팁 8: 늦은 리소스 획득, 이른 해제
이 팁은 간단합니다. 일반적으로 리소스를 늦게 획득해서 일찍 해제하는 것이 가장 바람직합니다. 파일 핸들 및 다른 리소스뿐 아니라 COM 개체에도 해당됩니다.
ADO 연결 및 레코드 집합은 이 최적화에 가장 적합합니다. 레코드 집합을 다 사용한 후 즉, 이 데이터로 테이블을 페인팅했다면 페이지 끝까지 대기하지 말고 즉시 이 데이터를 해제하십시오. VBScript 변수를 Nothing으로 설정하는 것이 가장 좋습니다. 레코드 집합이 단순히 범위를 벗어나게 하지는 마십시오. 관련된 명령 및 연결 개체를 모두 해제하십시오.(레코드 집합에서 Close()를 호출하거나 레코드 집합을 Nothing으로 설정하기 전의 연결을 호출하는 것을 잊지 마십시오) 이렇게 하면 데이터베이스가 리소스를 다루는 시간을 줄여주며 가능한 빨리 데이터베이스 연결을 연결 풀로 해제합니다.
팁 9: 안정성과 성능을 교환하는 종속 프로세스 실행
ASP와 MTS/COM+에는 모두 안정성과 성능을 교환할 수 있는 구성 옵션이 있습니다. 응용 프로그램을 만들거나 배포할 때는 이러한 교환을 이해해야 합니다.

ASP 옵션

ASP 응용 프로그램은 세가지 중 한가지 방법으로 실행되도록 구성할 수 있습니다. IIS 5.0에는 이러한 옵션을 설명하기 위해 "격리 수준"이라는 용어를 도입했습니다. 낮음보통높음의 세가지 격리 수준 값이 있습니다.
  • 낮은 격리. 이것은 모든 IIS 버전에서 지원되며 가장 빠릅니다. 이것은 주요 IIS 프로세스인 Inetinfo.exe에서 ASP를 실행합니다. ASP 응용 프로그램이 작동을 중지하면 IIS도 작동을 중지합니다.(IIS 4.0에서 IIS를 다시 시작하기 위해 웹 마스터는 InetMon과 같은 도구를 사용하여 사이트를 모니터하고 실패한 서버를 다시 시작하기 위해 배치 파일을 실행시킵니다. IIS 5.0에는 안정적인 재시작  이 도입되어 실패한 서버를 자동으로 다시 시작합니다.)
  • 보통 격리. ASP가 IIS 프로세스 밖에서 실행하기 때문에 독립 프로세스라고 하는 새로운 수준을 IIS 5.0에 도입했습니다. 보통 격리에서는 보통으로 실행하도록 구성된 모든 ASP 응용 프로그램이 단 하나의 프로세스 공간을 공유합니다. 이렇게 하면 하나의 상자에서 여러 개의 독립 프로세스 ASP 응용 프로그램을 실행하는 데 필요한 프로세스의 수를 줄일 수 있습니다. 보통은 IIS 5.0에서 기본 격리 수준입니다.
  • 높은 격리. IIS 4.0과 IIS 5.0에서 지원되는 높은 격리도 독립 프로세스입니다. ASP이 작동을 중지해도 웹 서버는 계속 작동합니다. ASP 응용 프로그램은 자동으로 다음 ASP 요청을 다시 시작합니다. 높은 격리를 사용하면 High로 실행하도록 구성된 각 ASP 응용 프로그램은 각자 고유한 공간에서 실행합니다. 이렇게 하면 ASP 응용 프로그램을 다른 ASP 응용 프로그램으로부터 보호합니다. 이 것의 단점은 각 ASP 응용 프로그램에 대해 개별적인 프로세스를 해야 한다는 것입니다. 하나의 상자에 십여 개의 응용 프로그램을 호스트해야 할 때 오버헤드가 많이 추가될 수 있습니다.
어떤 옵션이 가장 최선일까요? IIS 4.0에서는 독립 프로세스를 실행하면 성능이 급격히 떨어졌습니다. IIS 5.0에서는 독립 프로세스 ASP 응용 프로그램을 실행하는 비용을 최소화하기 위해 많은 작업을 해야 했습니다. 사실 대부분 테스트에서 IIS 5.0에서의 독립 프로세스 ASP 응용 프로그램이 IIS 4.0에서의 종속 프로세스 응용 프로그램보다 빨리 실행했습니다. 하지만 여전히 두 플랫폼 모두에서 종속 프로세스(낮은 격리 수준)가 최고의 성능을 발휘하고 있습니다. 그러나 상대적으로 적중률이 낮거나 최대 처리량이 낮은 경우 낮은 격리 수준을 사용하는 것은 별로 유리하지 않습니다. 따라서 각 웹 서버에 초당 수백 또는 수천 페이지가 필요하지 않다면 낮은 격리 수준을 사용하고 싶지 않을 것입니다. 언제나 처럼 여러 구성으로 테스트를 한 다음 어떤 교환을 할지를 정하십시오.
참고: 독립 프로세스(보통 또는 높은 격리) ASP 응용 프로그램을 실행할 때 이 응용 프로그램은 NT4에 있는 MTS 및 Windows 2000에 있는 COM+에서 실행됩니다. 즉, NT4에서는 Mtx.exe에서 실행되고 Windows 2000에서는 DllHost.exe에서 실행됩니다. 이러한 프로세스가 작업 관리자에서 실행되는 것을 알 수 있습니다. 또한 독립 프로세스 ASP 응용 프로그램을 위해 IIS가 MTS 패키지 또는 COM+ 응용 프로그램을 구성하는 방법도 알 수 있습니다.

COM 옵션

비록 ASP 옵션과 완전히 일치하지는 않지만 COM 구성 요소도 세 개의 구성 옵션을 갖고 있습니다. COM 구성 요소는 구성되지 않거나, 라이브러리 응용 프로그램으로 구성되거나, 서버 응용 프로그램으로 구성될 수 있습니다. 구성되지 않는다는 것은 구성 요소가 COM+과 함께 등록되지 않는다는 의미입니다. 구성 요소는 호출자의 프로세스 공간에서 실행될 것입니다. 즉, 종속 프로세스입니다. 라이브러리 응용 프로그램도 종속 프로세스지만 보안, 트랜잭션 및 컨텍스트 지원과 같은 COM+의 혜택을 받습니다. 서버 응용 프로그램은 그들만의 프로세스 공간에서 실행하도록 구성됩니다.
라이브러리 응용 프로그램보다 구성되지 않은 구성 요소가 약간 유리하다는 것을 알 수 있을 것입니다. 또한 서버 응용 프로그램보다 라이브러리 응용 프로그램은 매우 큰 성능의 이익이 있다는 것을 알 수 있을 것입니다. 이것은 라이브러리 응용 프로그램은 ASP와 같은 프로세스에서 실행하지만 서버 응용 프로그램은 그들 고유의 프로세스에서 실행하기 때문입니다. 프로세스간 호출은 종속 프로세스보다 비용이 많이 듭니다. 또한 프로세스간에 레코드 집합과 같은 데이터를 전달할 때 모든 데이터를 두 프로세서 사이에서 복사해야 합니다.
위험! COM 서버 응용 프로그램을 사용할 때 ASP와 COM간에 개체를 전달하려면 개체가 "marshal-by-value" 즉 MBV를 구현하는지 확인해야 합니다. MBV를 구현하는 개체는 한 프로세스에서 다른 프로세스로 자신을 복사합니다. 이것은 개체가 작성자의 프로세스에 남아있고 다른 프로세스가 이 개체를 사용하기 위해 반복적으로 작성하는 프로세스를 호출하는 다른 방법보다 효율적입니다. 연결이 끊어진 ADO 레코드 집합은 marshal-by-value를 구현하지만 연결된 레코드 집합은 그렇지 않습니다. Scripting.Dictionary는 MBV를 구현하지 않으면 프로세스간에 전달되면 안됩니다. 마지막으로 VB 프로그래머에게 보내는 메시지입니다. 매개 변수 ByVal을 전달하여 MBV를 구현할 수 없습니다. MBV는 원래 구성 요소 작성자만이 구현할 수 있습니다.

무엇을 해야 합니까?

성능과 안정성을 합리적으로 교환하는 구성을 추천한다면 다음과 같습니다.
  • IIS 4.0에서, ASP의 낮은 격리 수준과 MTS 서버 패키지를 사용하십시오.
  • IIS 5.0에서, ASP의 보통 격리 수준과 COM+ 라이브러리 응용 프로그램을 사용하십시오.
이것은 매우 일반적인 지침입니다. 호스팅 회사는 일반적으로 보통 또는 높은 격리 수준에서 ASP를 실행하지만 단일 목적 웹 서버는 낮은 격리 수준에서 실행할 수 있습니다. 교환을 측정하고 어떤 구성이 가장 적합한지 스스로 결정하십시오.
팁 10: Option Explicit 사용
.asp 파일에서 Option Explicit을 사용하십시오. .asp 파일의 상단에 위치하는 이 지시어는 개발자가 사용할 모든 변수를 선언하도록 합니다. 이렇게 하면 변수를 잘 못 입력하거나 불필요한 새 변수를 만드는 것을 방지할 수 있기 때문에(예를 들어, MyXMLStirng=대신MyXLMString=…) 많은 프로그래머가 응용 프로그램을 디버깅할 때 유용하다고 생각합니다.
아마 선언된 변수가 선언되지 않은 변수보다 빠르다는 것을 알아낸 것이 더 중요할 수도 있습니다. 보이지 않는 상태에서 스크립팅 실행 시간은 선언되지않은 변수를 사용할 때 마다 이 변수를 이름으로 참조합니다. 반면 선언된 변수는 컴파일 시간 또는 실행 시간에 서수로 지정됩니다. 그 다음 선언된 변수는 이 서수에 의해 참조됩니다. Option Explicit은 반드시 변수 선언을 하도록 하기 때문에 모든 변수가 선언되고 빨리 액세스할 수 있습니다.
팁 11: 서브루틴 및 함수에서 지역 변수 사용
지역 변수는 서브루틴 및 함수에서 선언된 변수입니다. 함수 또는 서브루틴안에서 지역 변수 액세스는 전역 변수 액세스보다 빠릅니다. 또한 지역 변수를 사용하면 코드가 더 깔끔하기 때문에 가능하면 지역 변수를 사용하는 것이 좋습니다.
팁 12: 자주 사용되는 데이터를 스크립트 변수로 복사
ASP에서 COM 개체에 액세스할 때는 자주 사용되는 개체 데이터를 스크립트 변수에 복사해야 합니다. 이렇게 하면 스크립트 변수에 액세스하는 것과 비교했을 때 상대적으로 비용이 많이 드는 COM 메서드 호출을 줄여줍니다. Collection 및 Dictionary 개체에 액세스할 때도 이 기술이 비용이 많이 드는 조회를 줄여줍니다.
일반적으로 한번 이상 개체 데이터에 액세스하려면 이 데이터를 스크립트 변수에 복사합니다. 이렇게 해서 가장 최적화되는 것은 요청 변수입니다.(Form 및 QueryString 변수) 예를 들어, 사용자의 사이트가 UserID로 불리는 QueryString 변수를 전달할 때 이 UserID가 특정 페이지에서 12번 참조된다고 가정해 보십시오. 요청("UserID")을 12번 호출하는 대신 UserID를 ASP 페이지 상단에서 변수로 지정하고 이 페이지에서 이 변수를 사용하면 11번의 COM 메서드 호출을 절약할 수 있습니다.
실제로 COM 속성 또는 메서드에 액세스하는 것은 비용이 너무 많이 듭니다. 매우 일반적인 코드를 보여주는 예제가 있습니다.
Foo.bar.blah.baz = Foo.bar.blah.qaz(1)If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...
이 코드는 다음과 같이 실행됩니다.
  1. 변수 Foo는 전역 개체로 확인됩니다.
  2. 변수 bar는 Foo의 구성원으로 확인됩니다. 이것은 COM 메서드 호출이 됩니다.
  3. 변수 blah는 Foo.bar의 구성원으로 확인됩니다. 이것 역시 COM 메서드 호출이 됩니다.
  4. 변수 qaz는 foo.bar.blah의 구성원으로 확인됩니다. 물론 COM 메서드 호출이 됩니다.
  5. Foo.bar.blah.quaz(1)를 불러옵니다. 또 하나의 COM 메서드 호출입니다. 그림을 이해하시겠습니까?
  6. baz를 확인하기 위해 1-3 단계를 다시 합니다. 이 시스템은 qaz 호출이 개체 모델을 변경한 것을 모르기 때문에 baz를 확인하려면 1-3 단계를 다시 해야 합니다.
  7. baz를 Foo.bar.blah의 구성원으로 확인합니다. 속성을 입력합니다.
  8. . 1-3 단계를 다시 실행하고 zaq를 확인합니다.
  9. 1-3 단계를 다시 실행하고 abc를 확인합니다.
여기서 알 수 있듯이 이것은 매우 비효율적입니다. VBScript에서 이 코드를 작성하는 더 빠른 방법은 다음과 같습니다.
Set myobj = Foo.bar.blah ' do the resolution of blah ONCEMyobj.baz = myobj.qaz(1)If Myobj.zaq = Myobj.abc Then '...
VBScript 5.0 이상을 사용하는 경우 With문을 사용하여 이것을 작성할 수 있습니다.
With Foo.bar.blah .baz = .qaz(1) If .zaq = .abc Then '... ...End With
이 팁은 VB 프로그래밍에서도 작동한다는 것을 참조하십시오.
팁 13: 배열 재정의 방지
배열을 재정의하지 않도록 하십시오. 물리적인 메모리 크기에 제약이 있는 컴퓨터를 사용하는 경우 성능에 관한한 최악의 경우에 배열의 초기 정의를 설정하는 것이 가장 좋습니다. 그렇지 않으면 정의를 가장 적합하게 설정하고 필요한 경우에는 재정의합니다. 이것은 불필요한 몇 MB의 메모리를 직접 할당해야 한다는 것을 의미하지는 않습니다.
다름 코드는 정의 및 재정의의 불필요한 사용을 보여줍니다.
<% Dim MyArray()Redim MyArray(2)MyArray(0) = "hello"MyArray(1) = "good-bye"MyArray(2) = "farewell"...' some other code where you end up needing more space happens, then ...Redim Preserve MyArray(5)MyArray(3) = "more stuff"MyArray(4) = "even more stuff"MyArray(5) = "yet more stuff"%>
배열을 확장하기 위해 재정의하는 것보다는 처음에 정확한 사이즈(이 경우에는 5)로 배열을 정의하는 것이 훨씬 바람직합니다. 약간의 메모리가 낭비될 수 있지만(모든 요소의 사용을 중단하지 않으면) 속도가 빨라집니다.
팁 14: 응답 버퍼링 사용
"응답 버퍼링"을 켜면 전체 한 페이지 정도의 출력을 버퍼할 수 있습니다. 이렇게 하면 브라우저에 쓰는 양을 최소화하여 전체적으로 성능이 향상됩니다. 각 쓰기에는 많은 오버헤드(회선으로 가는 데이터의 양 및 IIS에)가 있기 때문에 쓰기가 적을수록 바람직합니다. TCP/IP는시작이 느리고 Nagling  알고리즘(네트워크 정체를 최소화하는 데 사용)을 사용하기 때문에 작은 블록을 여러 개 전송하는 것 보다는 데이터의 큰 블록을 몇 개 전송하는 것이 더 효율적입니다.
응답 버퍼링을 켜는 방법은 두 가지가 있습니다. 첫째, Internet Services Manager를 사용하여 전체 응용 프로그램에 응답 버퍼링을 켤 수 있습니다. 이것은 바람직한 접근법이며 IIS 4.0 및 IIS 5.0에 있는 새로운 ASP 응용 프로그램을 위해 초기값으로 응답 버퍼링이 켜집니다. 두번째는 페이지 단위를 기초로 한 것으로서 ASP 페이지의 상단에 다음과 같은 코드 줄을 넣어 응답 버퍼링을 사용할 수 있습니다.
<% Response.Buffer = True %>
이 코드 줄은 브라우저에 응답 데이터를 쓰기 전에 실행해야 합니다.(즉, ASP 스크립트에 HTML이 나타나기 전 및 Response nulls 컬렉션을 사용하여 nulls가 설정되기 전에) 일반적으로 전체 응용 프로그램에 응답 버퍼링을 켜놓는 것이 가장 좋습니다. 이렇게 하면 모든 페이지에 위의 코드 줄을 넣지 않아도 됩니다.

Response.Flush

응답 버퍼링에 대한 한가지 공통적인 불만은 전체 페이지가 생성될 때까지 기다려야 무언가를 볼 수 있기 때문에 사용자는 ASP 페이지의 응답 시간이 느리다고 느끼는 것입니다.(전체 응답 시간이 향상되었음에도 불구하고) 오래 걸리는 페이지에서는 Response.Buffer = False를 설정하여 응답 버퍼링을 끌 수 있습니다. 하지만 이것 보다는 Response.Flush 메서드를 사용하는 것이 더 훌륭한 전략입니다. 이 메서드는 ASP가 브라우저로 페인트한 모든 HTML을 플러시합니다. 예를 들어, 천 개의 행(row)이 있는 테이블 중 백 개 행을 페인트한 다음 ASP는 페인트한 결과를 브라우저로 보내기 위해 Response.Flush를 호출할 수 있습니다. 이렇게 하면 나머지 행이 준비되기 전에 사용자는 우선 백 개 행을 볼 수 있습니다. 이러한 기술은 데이터를 브라우저로 점차적으로 프리젠테이션하는 것과 결합된 응답 버퍼링을 제공합니다.
(위의 행이 천 개인 테이블의 예에서 많은 브라우저는 닫는 태그가 나타나야만 테이블을 페인팅한다는 것을 참조하십시오. 대상 브라우저가 이것을 지원하는지 확인하십시오. 이렇게 하려면 테이블을 행을 적게 갖는 여러 개의 테이블로 나눈 다음 각 테이블 다음에Response.Flush를 호출해 보십시오. 새로운 Internet Exploer 버전은 테이블을 완전히 다운로드하기 전에 테이블을 페인트하며 테이블의 열(column)의 폭을 지정하면 특히 빨리 페인트합니다. 이렇게 하면 Internet Explorer가 모든 셀의 컨텐츠 폭을 측정하여 열의 폭을 계산하지 않도록 도와줍니다.)
응답 버퍼링에 대한 또 하나의 불만은 큰 페이지를 생성할 때 서버 메모리를 많이 사용한다는 것입니다. 큰 페이지를 생성하는 지혜는 제외하고 이 문제는 Response.Flush를 신중히 사용하여 해결할 수 있습니다.
팁 15: 일괄 처리 인라인 스크립트 및 Response.Write 문
VBScript 구문 <% = expression %>은 "expression"의 값을 ASP 출력 스트림에 씁니다. 응답 버퍼링을 켜지 않으면 이 문(statement)이 여러 작은 패킷으로 네트워크를 통해 브라우저로 데이터를 쓰게 됩니다. 이 과정은 매우 느립니다. 작은 양의 스크립트 및 HTML을 여기 저기 배치하면 스크립트 엔진과 HTML간의 전환이 일어나서 성능이 떨어집니다. 그러므로 다음과 같은 팁을 사용하십시오. 가깝게 모여있는 인라인 식(expression)을 Response.Write를 한 번 호출하는 것으로 교체합니다. 예를 들어 다음의 예제처럼 행의 필드마다 응답 스트림에 쓰기가 하나 있고 행마다 VBScript 및 HTML 사이에 많은 스위치가 있습니다.
<% For Each fld in rs.Fields %> <%Next While Not rs.EOF%> <% For Each fld in rs.Fields %> <% Next <% rs.MoveNext Wend %>
<% = fld.Name %>
<% = fld.Value %>
아래에 있는 더 효율적인 코드는 행마다 응답 스트림에 쓰기가 하나 있습니다. 모든 코드는 하나의 VBScript 블록에 포함됩니다.
<% For each fld in rs.Fields Response.Write ("" & vbCrLf) Next While Not rs.EOF Response.Write ("") For Each fld in rs.Fields %>Response.Write("" & vbCrLf) Next Response.Write "" Wend%>
" & fld.Name & "
" & fld.Value & "
이 팁은 응답 버퍼링을 사용할 수 없을 때 더 큰 효과가 있습니다. 응답 버퍼링을 사용하는 것이 가장 바람직 하며 그런 다음Response.Write를 일괄 처리하면 성능이 향상되는지 살펴 봅니다.
(이 특정 예제에서 테이블의 본문을 작성하는 중첩 루프(While Not rs.EOF)는 GetString  를 신중하게 호출하여 교체할 수 있습니다.)
팁 16: 긴 이동을 시작하기 전에 Response.IsClientConnected 사용
인내심이 부족한 사용자는 요청을 실행하기도 전에 ASP 페이지를 중단할 수 있습니다. 사용자가 Refresh를 누르거나 서버에 있는 다른 페이지로 이동하면 ASP 요청 대기열의 끝에 새로운 요청이 놓이고 연결이 끊어진 요청은 대기열의 가운데 놓입니다. 서버에 로드가 높을 때(요청 대기열이 길고 따라서 응답 시간도 길어집니다.) 이런 상황이 발생하며 이것은 상황을 더욱 악화시킵니다. 사용자가 더 이상 연결되어있지 않으면 ASP 페이지를 실행할 수 없습니다.(특히 느리고 큰 ASP 페이지) Response.IsClientConnected 속성을 사용하여 이러한 상태를 확인할 수 있습니다. 이것이 False를 반환하면 Response.End를 호출하고 나머지 페이지를 중지해야 합니다. 사실 IIS 5.0은 이러한 것을 모두 집대성합니다. ASP가 새로운 요청을 실행하려고 할 때마다 그 요청이 대기열에서 얼마나 오래 있었는지를 알기 위해 확인합니다. 이 요청이 대기열에 3초 이상 있었다면 ASP는 클라이언트가 여전히 연결되어 있는지 확인한 다음 연결되어 있지 않을 때는 즉시 요청을 종료합니다. 이 3초 제한 시간을 조정하려면 메타베이스에서 AspQueueConnectionTestTime 설정을 사용할 수 있습니다.
실행 시간이 매우 긴 페이지가 있다면 중간에 Response.IsClientConnected를 확인하고 싶을 수도 있습니다. 응답 버퍼링을 사용하고 있다면 사용자에게 무언가가 진행중이라는 것을 알리기 위해 중간에 Response.Flush를 사용하는 것도 좋습니다.
참고 IIS 4.0에서는 우선 Response.Write를 실행하지 않으면 Response.IsClientConnected가 정확하게 실행되지 않습니다. 버퍼링을 사용하고 있다면 Response.Flush를 사용해야 합니다. IIS 5.0에서는 이렇게 하지 않아도 Response.IsClientConnected가 잘 작동합니다. 어떤 경우에나 Response.IsClientConnected는 약간의 비용이 들기 때문에 적어도 500 밀리초(초당 12 페이지의 처리량을 유지하려면 이것도 긴 시간입니다.)가 소요되는 작업 앞에만 사용해야 합니다. 일반적인 경험에 따라 테이블의 행(row)을 페인팅할 때와 같이 복잡한 루프의 모든 반복에 호출하지 마십시오. 대신 테이블의 20번째 또는 50번째 행에서 호출하십시오.
팁 17: 태그를 사용한 개체 인스턴스화
모든 코드 경로에서 사용되지 않는 개체를 참조해야 한다면(특히 서버 혹은 응용 프로그램 범위 개체) Server.CreateObject 메서드를 사용하기 보다는 Global.asa에서 태그를 사용하여 개체를 선언하십시오. Server.CreateObject는 즉시 개체를 만듭니다. 이 개체를 나중에 사용하지 않는다면 결국 리소스를 낭비하는 것입니다. 태그는 objname을 선언하지만 이 개체의 메서드 또는 속성 중 하나가 처음 사용될 때까지 objname은 실제로 만들어지지 않습니다.
이것은 지연 평가의 또 다른 예입니다.
팁 18: ADO 및 다른 구성 요소를 위한 TypeLib 선언 사용
ADO를 사용할 때 개발자는 ADO의 다양한 상수에 액세스하기 위한 adovbs.txt를 포함합니다. 이 파일은 상수를 사용할 모든 페이지에 포함되어야 합니다. 이 상수 파일은 매우 커서 모든 ASP 페이지의 컴파일 시간 및 스크립트 크기에 상당한 오버헤드를 추가합니다.
IIS 5.0은 구성 요소의 형식 라이브러리에 바인딩하는 기능을 도입했습니다. 이 기능을 사용하면 형식 라이브러리를 한번 참조하여 이것을 모든 ASP 페이지에 사용할 수 있습니다. 각 페이지는 상수 파일을 컴파일할 필요가 없기 때문에 구성 요소 개발자는 ASP에서 사용할 VBScript #include 파일을 작성하지 않아도 됩니다.
ADO TypeLib를 액세스하려면 다음 문(statement) 중 하나를 Global.asa에 포함해야 합니다.
또는
팁 19: 사용자 브라우저의 유효성 검사 기능 이용
최신 브라우저는 XMLDHTMLJava  애플릿 및 원격 데이터 서비스  (Remote Data Service)와 같은 기능을 지원을 개발해왔습니다. 이러한 기능을 최대한 이용하십시오. 이러한 기술을 사용하면 데이터 캐싱뿐 아니라 클라이언트 쪽 유효성 검사를 실행하여 웹 서버로의 왕복 이동을 줄일 수 있습니다. 스마트 브라우저를 사용하면 브라우저가 사용자를 위해 약간의 유효성 검사를 할 수 있습니다.(예를 들어, POST를 실행하기 전에 신용 카드가 해당 금액을 사용할 수 있는지  확인할 수 있습니다.) 다시 강조하지만 이 기능을 가능한 많이 이용하십시오. 클라이언트 쪽 왕복 이동을 줄이기 때문에 서버가 액세스하는 백 엔드 리소스뿐 아니라 네트워크 소통량(비록 브라우저로 보내지는 초기 페이지가 더 크더라도)과 웹 서버의 스트레스를 줄일 수 있습니다. 게다가 사용자는 새로운 페이지를 자주 반입할 필요가 없기 때문에 경험이 향상됩니다. 하지만 이것은 서버 쪽 유효성 검사까지 해주지 않기 때문에 서버쪽 유효성 검사하는 것을 잊지 마십시오. 이것은 브라우저가 클라이언트쪽 유효성 검사 루틴을 실행하지 않거나 해킹과 같은 이유로 잘못된 데이터가 클라이언트에서 오는 것을 방지합니다.
대부분은 "브라우저 독립적" HTML을 작성하여 만들어졌습니다. 이것은 성능을 향상시키는 기능이 있는 일반적인 브라우저를 개발자가 이용할 수 없도록 합니다. 매우 성능이 높은 사이트는 반드시 브라우저 "범위"를 언급해야 하며 일반적인 브라우저를 위해 페이지를 최적화하는 것이 바람직합니다. 브라우저 기능 구성 요소(Browser Capabilities Component)를 사용하여 ASP에서 브라우저 기능을 쉽게 검색할 수 있습니다. Microsoft FrontPage와 같은 도구는 사용자가 대상으로 선택한 브라우저 및 HTML 버전에서 실행되는 코드를 설계할 수 있도록 도와줍니다. 자세한 내용은 When is Better Worse? Weighing the Technology Trade-Offs  를 참조하십시오.
팁 20: 루프에서 문자열 연결 방지
많은 사람들이 다음과 같이 루프 안에 문자열을 작성합니다.
s = " " & vbCrLfFor Each fld in rs.Fields s = s & " "NextWhile Not rs.EOF s = s & vbCrLf & " " For Each fld in rs.Fields s = s & " " Next s = s & " " rs.MoveNextWends = s & vbCrLf & "
" & fld.Name & "
" & fld.Value & "
" & vbCrLfResponse.Write s
이러한 접근에는 몇 가지 문제가 있습니다. 우선 반복적으로 문자열을 연결하면 시간이 제곱으로 걸립니다. 다시 말해 루프를 실행하는 데 걸리는 시간은 레코드 수와 필드 수를 곱한 값의 제곱에 비례합니다. 간단한 예제가 이것을 더욱 명확하게 합니다.
s = ""For i = Asc("A") to Asc("Z") s = s & Chr(i)Next
첫번째 반복에서 하나의 문자로된 문자열 "A"을 얻습니다. 두번째 반복에서 VBScript는 문자열을 재할당하고 두 문자("AB")를 s로 복사해야 합니다. 세번째 반복에서 VBScript는 s를 다시 재할당하고 3개 문자를 s로 복사합니다. N번째(26번째) 반복에서 s를 재할당하고 N개 문자를 s로 복사합니다. 이것이 N*(N+1)/2 복사본이 있는 1+2+3+…+N의 합계입니다.
위의 레코드 집합 예제에서 100개 레코드와 5개 필드가 있다면 내부 루프는 100*5 = 500번 실행되고 모든 복사와 재할당을 하는 데 걸린 시간은 500*500 = 250,000에 비례할 것입니다. 이것이 적절한 크기의 레코드 집합을 위한 복사입니다.
이 예제에서 문자열 연결을 Response.Write() 또는 인라인 스크립트(<% = fld.Value %>)와 교체하여 코드를 향상시킬 수 있습니다. 응답 버퍼링이 켜있다면(켜있어야 함) Response.Write는 응답 버퍼의 끝에 데이터를 추가할 뿐이기 때문에 교체하는 것이 빠릅니다. 재할당이 포함되지않기 때문에 매우 효과적입니다.
ADO 레코드 집합을 HTML 테이블로 변환하는 특별한 경우에는 GetRows 또는 GetString  을 사용하도록 하십시오.
JScript에서 문자열을 연결하는 경우 += 연산자를 사용하는 것이 바람직합니다. 예를 들어 s = s + "some string"이 아닌 s += "some string"을 사용하십시오.
팁 21: 브라우저 및 프록시 캐싱 사용
ASP는 브라우저와 프록시에서 기본으로 캐싱을 사용하지 않습니다. 잠재적으로 시간에 민감한 정보를 가지고있는 ASP 페이지는 본질적으로 동적이기 때문에 이해할 수 있는 부분입니다. 모든 뷰에서 새로 고침이 필요 없는 페이지의 경우 브라우저와 프록시 캐싱을 사용해야 합니다. 이를 통해 브라우저와 프록시는 일정 길이의 시간동안 페이지의 "캐시된" 복사본을 사용할 수 있으며 사용자가 이를 제어할 수 있습니다. 캐싱은 서버의 부하를 크게 줄일 수 있으며 사용자의 이용도를 향상시킬 수 있습니다.
어떤 종류의 동적 페이지에 캐싱을 사용할까요? 밑에 몇 가지 예를 나타내었습니다.
  • 날씨가 매 5분 마다 업데이트되는 일기예보 페이지.
  • 하루에 두 번 업데이트되는 뉴스 또는 출판물을 게시하는 홈 페이지.
  • 근간이 되는 통계를 몇 시간마다 업데이트하는 뮤츄얼 펀드 성과 목록.
브라우저와 프록시의 캐싱을 사용하면 웹 페이지에 기록되는 방문자수가 줄어들게 됩니다. 모든 페이지 뷰를 정확하게 측정하거나 광고를 게시하려는 경우에는 브라우저와 프록시의 캐싱이 실망스러울 것입니다.
브라우저 캐싱은 웹 서버에서 브라우저로 보내는 HTTP "Expires" 헤더로 제어합니다. ASP는 두 가지 간단한 메커니즘을 제공하여 이 헤더를 보냅니다. 몇 분 후에 페이지가 만료되도록 설정하려면 Response.Expires 속성을 설정하십시오. 다음 예는 브라우저가 컨텐츠를 10분 후에 만료하도록 지시합니다.
<% Response.Expires = 10 %>
Response.Expires를 음수 또는 0으로 설정하면 캐싱을 사용할 수 없게 됩니다. -1000(하루가 약간 넘음)과 같이 큰 음수를 사용하여 서버와 브라우저 클럭 사이의 불일치를 해결하십시오. 두 번째 속성인 Response.ExpiresAbsolute를 사용하면 컨텐츠가 만료되는 특정 시간을 설정할 수 있습니다.
<% Response.ExpiresAbsolute = #May 31,2001 13:30:15# %>
만료 설정을 위해 Response 개체를 사용하는 것 외에 일반적으로 HTML 파일의 섹션 내에 태그를 작성할 수도 있습니다. 프록시는 아닐지라도 일부 브라우저는 이 지시에 따라 작동합니다.
마지막으로, Response.CacheControl 속성을 사용하여 HTTP 프록시가 캐시하기에 컨텐츠가 유효한지의 여부를 나타낼 수 있습니다. 이 속성을 "Public"으로 설정하면 프록시가 컨텐츠를 캐시할 수 있게 됩니다.
<% Response.CacheControl = "Public" %>
이 속성은 "Private"이 기본으로 설정되어 있습니다. 어떤 사용자에 특정한 데이터를 보여주는 페이지에 대해서는 프록시 캐싱을 사용하지 않아야 합니다. 캐싱을 설정하면 프록시는 어떤 사용자 소유의 페이지를 다른 사용자에게 제공하기 때문입니다.
팁 22: 가능한 한 Response.Redirect 대신 Server.Transfer 사
Response.Redirect는 브라우저가 다른 페이지를 요청하도록 지시합니다. 이 기능을 종종 사용하여 사용자를 로그온 또는 오류 페이지로 다시 연결시킵니다. 다시 연결되면 새 페이지 요청이 강제되기 때문에 결과적으로 브라우저는 웹 서버에 두 번 왕복해야 하며 웹 서버는 추가 요청을 처리해야 합니다. IIS 5.0은 동일 서버상에서 다른 ASP 페이지로 실행을 전달하는Server.Transfer라는 새 기능을 도입합니다. 이 기능으로 브라우저와 웹 서버 간의 불필요한 왕복을 피할 수 있기 때문에 결과적으로 전체 시스템이 향상될 뿐만 아니라 사용자에게는 빠른 반응 시간을 제공하게 됩니다. Server.Transfer 및 Server.Execute에 관한 내용이 있는 New Direction in Redirection  을 살펴보십시오.
IIS 5.0 및 ASP 3.0의 새 기능을 전부 수록한 IIS 5.0에서 ASP 이용  도 참조하십시오.
팁 23: 디렉터리 URL에서 후행 슬래시 사용
관련 팁은 디렉터리를 가리키는 URL에서 후행 슬래시(/)를 사용하는 것입니다. 후행 슬래시를 생략하면 브라우저는 서버에 요청하여 디렉터리를 요구하고 있다는 응답을 받습니다. 그러면 브라우저는 URL에 슬래시를 첨가하여 두번째 요청을 하며 이때서야 서버가 그 디렉터리(또는 기본 문서가 없거나 디렉터리 브라우징을 사용할 수 없는 경우 디렉터리 목록)에 대한 기본 문서로 응답합니다. 슬래시의 첨가는 처음의 쓸데없는 왕복을 제거합니다. 편리한 사용을 위해서는 표시 이름에 후행 슬래시를 생략하고 싶을 것입니다.
예를 들어, 다음을 작성하십시오.
http://msdn.microsoft.com/workshop
이것은 웹 사이트에서 홈페이지를 가리키는 URL에도 적용됩니다. 이 아니라 을 사용하십시오.
팁 24: 서버 변수의 사용을 피함
서버 변수에 액세스하면 웹 사이트가 서버에 특별한 요청을 하게 되어 요청한 것만이 아니라 모든 서버 변수를 수집하게 됩니다. 곰팡이 쓴 다락방에 있는 폴더의 특정 물건을 가져와야 하는 것과 같습니다. 그 하나의 물건을 원하는 경우, 그 물건에 액세스하기 전에 우선 다락방에 가서 폴더를 찾아야 합니다. 서버 변수를 요청할 때도 마찬가지입니다. -performance hit은 서버 변수를 처음 요청할 때 발생합니다. 다른 서버 변수에 대한 계속된 요청은 performance hit을 유발하지 않습니다.
비한정 Request 개체(예, Request("Data"))에 절대 액세스하지 마십시오. Request.nullsRequest.FormRequest.QueryString 또는Request.ClientCertificate에 있지 않은 항목의 경우, Request.ServerVariables에 대한 암시적 호출이 있습니다.Request.ServerVariables 집합은 다른 집합보다 훨씬 느립니다.
팁 25: 최신 및 최고급으로 업그레이드.
시스템 구성 요소는 일정하며 최신 및 최고급으로 업그레이드하는 것이 좋습니다. Windows 2000  (및 그에 따른 IIS 5.0, ADO 2.5, MSXML 2.5, Internet Explorer 5.0, VBScript 5.1및 JScript 5.1)으로 업그레이드하는 것이 가장 바람직합니다. IIS 5.0 및 ADO 2.5은 다중 프로세서 컴퓨터에서 극적인 성능 향상을 수행합니다. Windows 2000에서 ASP 는 4개 이상의 프로세서로 훌륭하게 확장하며 반면 IIS 4.0에서는 ASP가 두 프로세서 이상으로 잘 확장되지 않습니다. Windows 2000으로 업그레이드한 후 응용 프로그램에서 스크립트 코드와 ADO를 많이 사용하면 할 수록 더욱 큰 성능 향상을 보게 될 것입니다.
Windows 2000으로 업그레이드할 수 없는 경우에는 최신 버전의 SQL Server  , ADO  , VBScript 및 JScript  , MSXMLInternet Explorer  그리고 NT4 Service Pack으로 업그레이드할 수 있습니다. 이 모두가 성능을 향상시킬 뿐 아니라 신뢰도도 높입니다.
팁 26: 웹 서버 조정.
사이트 성능을 향상시킬 수 있는 몇 가지 IIS 튜닝 매개 변수가 있습니다. 예를 들면, IIS 4.0의 경우 ASP ProcessorThreadMax 매개 변수(IIS 문서 참조)를 증가시켜서 상당한 이득을 얻는 경우가 종종 있습니다. 데이터베이스 또는 화면 스크레퍼와 같은 다른 미들웨어 제품과 같은 백 엔드 리소스를 기다리는 경향이 있는 사이트에서는 특히 큰 이득을 얻습니다. IIS 5.0의 경우 ASP Thread Gating을 사용하는 것이AspProcessorThreadMax에 대한 최적 설정을 찾는 것보다 더 효과적입니다..
아래 Tuning IIS 튜닝을 참조하십시오
최적 구성 설정은 (기타 인자들 중)사용하는 응용 프로그램 코드, 이를 실행하는 하드웨어 그리고 클라이언트 작업 부하로 결정합니다. 최적 설정을 찾는 유일한 방법은 성능 테스트를 실시하는 것이며 다음 팁에서 설명합니다.
팁 27: 성능 테스트
앞서 언급했듯이, 성능은 하나의 기능입니다. 사이트의 성능을 향상시키려면, 성능 목표를 설정한 다음 목표에 도달할 때까지 조금씩 향상시키십시오. 프로젝트의 끝 부분을 위해 모든 성능 테스트를 아껴두지 마십시오. 종종, 프로젝트의 끝에서는 필요한 구조 변경을 하기에 너무 늦으며 따라서 고객을 실망시키게 됩니다. 성능 테스트를 일상 테스트의 부분으로 만드십시오. 성능 테스트는 ASP 페이지나 COM 개체와 같은 개별 구성 요소 또는 사이트 전체에 대해 수행할 수 있습니다.
많은 사람들이 하나의 브라우저를 사용하여 페이지를 요청함으로써 웹 사이트 성능을 테스트합니다. 이렇게 하면 사이트의 반응성에 대해 좋은 느낌을 받을 수 있지만 부하가 있는 상태에서 사이트의 성능을 평가하는 데 아무 도움이 못됩니다.
일반적으로 성능을 정확하게 측정하기 위해서는 전용 테스트 환경이 필요합니다. 이러한 환경에는 프로세서 속도, 프로세서 수, 메모리, 디스크, 네트워크 구성 등의 관점에서 프로덕션 하드웨어와 닮은 하드웨어가 있어야 합니다. 다음으로 동시 사용자의 수, 클라이언트의 요청 빈도, 그들이 열어보는 페이지의 형태 등 클라이언트의 작업 부하를 정의해야 합니다. 여러분의 사이트에서 실제적인 사용 데이터에 액세스가 없는 경우, 추정할 필요가 있습니다. 마지막으로, 예상한 클라이언트 작업 부하를 시뮬레이션할 수 있는 도구가 필요합니다. 이러한 도구를 구비하면 "N 명의 동시 사용자가 있는 경우 필요한 서버는 몇 대인가?"와 같은 질문에 답할 수 있습니다. 또한 병목현상을 무시하고 최적화를 위해 이를 공격 목표로 삼을 수 있습니다
 
 
28. 관련 리소스 링크를 읽어보십시오.

다음은 몇 가지 아주 유용한 성능 관련 리소스 링크들입니다. Developing Scalable Web Applications은 반드시 읽어보는 것이 좋습니다.

리소스

ASP 스크립트 최적화

IIS 조정

ADO 및 SQL Server

ASP 구성 요소 및 스레딩 모델 

딕셔너리 구성 요소

세션 상태

성능 및 확장성 

도구

문서

ASP 웹 사이트

ASP 스타일

XML

ASP 스크립트 최적화

Developing Scalable Web Applications

Got Any Cache? 저자: Nancy Winnick Cluts

Maximizing the Performance of Your Active Server Pages 저자: Nancy Winnick Cluts

15 Seconds: Performance Section

Enhancing Performance in ASP - Part I 저자: Wayne Plourde

When is Better Worse? Weighing the Technology Trade-Offs 저자: Nancy Winnick Cluts

Speed and Optimization Resources 저자: Charles Carroll

IIS 조정

The Art and Science of Web Server Tuning with Internet Information Services 5.0

Leveraging ASP in IIS 5.0 저자: J.D. Meier

Tuning IIS 4.0 for High Volume Sites 저자: Michael Stephenson

Tuning Internet Information Server Performance 저자: Mike Moore

Navigating the Maze of Settings for Web Server Performance Optimization 저자: Todd Wanke

Managing Internet Information Server 4.0 for Performance 저자: Hans Hugli

ADO 및 SQL Server

Top Ten Tips: Accessing SQL Through ADO and ASP 저자: J.D. Meier

Improve the Performance of your MDAC Application 저자: Suresh Kannan

Pooling in the Microsoft Data Access Components 저자: Leland Ahlbeck 및 Don Willits

SQL Server: Performance Benchmarks and Guides

Improving the Performance of Data Access Components with IIS 4.0 저자: Leland Ahlbeck

Microsoft Data Access Components (MDAC) and ActiveX Data Objects (ADO) Performance Tips 저자: Leland Ahlbeck

Microsoft SQL Server 7.0 Practical Performance Tuning and Optimization - The Server Perspective 저자: Damien Lindauer

Microsoft SQL Server 7.0 Practical Performance Tuning and Optimization - The Application Perspective 저자: Damien Lindauer

Accessing Recordsets over the Internet 저자: Dino Esposito

ASP 구성 요소 및 스레딩 모델

ASP Component Guidelines 저자: J.D. Meier

Q243548: INFO: Design Guidelines for VB Components under ASP

Threading Models Explained 저자: Nancy Winnick Cluts

So Happy Together? Using ActiveX components with Active Server Pages 저자: Nancy Winnick Cluts

Developing Active Server Components with ATL 저자: George Reilly

Agility in Server Components 저자: Neil Allain

Building High-Performance Middle-Tier Components with C++ 저자: Jon Flanders

Active Server Pages and COM Apartments 저자: Don Box

House of COM: Active Server Pages 저자: Don Box

House of COM: Contexts 저자: Don Box

House of COM: Performance Trade-offs of the Windows 2000 Component Execution Environment 저자: Don Box

Building COM Components That Take Full Advantage of Visual Basic and Scripting 저자: Ivo Salmre

Component Design Principles for MTS

딕셔너리 구성 요소

Creating a Page Cache Object 저자: Robert Coleridge

Abridging the Dictionary Object: The ASP Team Creates a Lookup-Table Object 저자: Robert Carter

Caprock Dictionary

Site Server Commerce Edition에는 딕셔너리 구성 요소가 들어 있습니다.

세션 상태

Q175167: HOWTO: Persisting Values Without Sessions

Q157906: HOWTO: How To Maintain State Across Pages with VBScript

XML-based Persistence Behaviors Fix Web Farm Headaches 저자: Aaron Skonnard

House of COM: Stateless Programming 저자: Don Box

성능 및 확장성

Blueprint for Building Web Sites Using the Microsoft Windows DNA Platform

Server Performance and Scalability Killers 저자: George Reilly

Microsoft Visual Studio Scalability Center

Fitch & Mather Stocks 2000

Tuning the FMStocks Application

High-Performance Visual Basic Apps 저자: Ken Spencer

Duwamish Books, Phase 4

Top Windows DNA Performance Mistakes and How to Prevent Them 저자: Gary Geiger 및 Jon Pulsipher

Building from Static HTML to High-Performance Web-Farms 저자: Shawn Bice

도구

Microsoft Web Application Stress Tool

I Can't Stress It Enough -- Load Test Your ASP Application 저자: J.D. Meier

Windows DNA Performance Kit

Monitoring Events in Distributed Applications Using Visual Studio Analyzer 저자: Mai-lan Tomsen

문서

Professional Active Server Pages 3.0, Wrox Press. (특히, Chapter 26:Optimizing ASP Performance, 저자: George Reilly 및 Matthew Gibbs 참조)

Microsoft Internet Information Services 5.0 Resource Guide(Windows 2000 Server Resource Kit와 함께 제공됨), Microsoft Press.

Microsoft Internet Information Server Resource Kit (for IIS 4.0), Microsoft Press.

Programming Distributed Applications with COM and Microsoft Visual Basic 6.0 저자: Ted Pattison, Microsoft Press.

Effective COM 저자: Don Box, Keith Brown, Tim Ewald, Chris Sells 및 Addison-Wesley.

Developing Web Usability: The Practice of Simplicity 저자: Jakob Nielsen, New Riders.

ASP 웹 사이트

Microsoft TechNet for IIS

LearnASP.com

4GuysFromRolla.com

15Seconds.com

AspToday.com

Asp101.com

AspLists.com. 여기에는 다음과 같은 특수 메일 목록이 들어 있습니다.

  • Fast Code!
  • ASP Advanced
  • Not NewbieState Management
  • Scalability
  • Visual Basic Components
  • XML
  • C++/ATL Component Building

UseIt.com: Web Usability

ASP 스타일

ASP Best Practices 저자: George Reilly

ASP Quick Lessons 저자: Charles Carroll

Planning for ASP 저자: John Meade

ASP Guidelines 저자: J.D. Meier

XML

Inside XML Performance 저자: Chris Lovett

Inside MSXML3 Performance 저자: Chris Lovett

.

'Computer > ASP' 카테고리의 다른 글

효율적인 페이징 기법  (0) 2011.11.29
ASP 에서 UTF-8 처리  (0) 2011.11.29
성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29
URLEncode  (0) 2011.11.29
ASP 서버 변수 출력  (0) 2011.11.29
펌) 페이징 쿼리문 비교  (0) 2011.11.29
URLEncode는 HTTP/URL에서 사용할 수 없는 공백, &, ?, %등의 기호를 URL을 통해 전송해야 할 경우, URL 대체 문자로 문자열을 변환하는 메소드[각주:1]이다.



URL 대체 문자는 아래와 같다.

공백             + 또는 %20
'                  %27
!                  %21
#                 %23
$                 %24
%                %25
&                %26
(                 %28
)                 %29
=                 %30
 .
  1. 객체지향 프로그래밍(OOP)에서 메쏘드는 클래스의 일부분으로 정의되어, 그 클래스의 모든 객체에 포함되어야 하는 프로그램된 절차다. 클래스(즉 객체)는 하나 이상의 메쏘드를 가질 수 있다. 객체의 메쏘드는 그 객체에게 알려진 자료에만 접근이 가능하므로, 응용프로그램의 객체 집합체 내에서 데이터의 무결성을 확실하게 한다. 메쏘드는 여러 개의 객체들에서 재사용될 수 있다. 출처 http://k.daum.net/qna/openknowledge/view.html?qid=38Uts [본문으로]

'Computer > ASP' 카테고리의 다른 글

ASP 에서 UTF-8 처리  (0) 2011.11.29
성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29
URLEncode  (0) 2011.11.29
ASP 서버 변수 출력  (0) 2011.11.29
펌) 페이징 쿼리문 비교  (0) 2011.11.29
펌) ASP 성능 향상 TIP.  (0) 2011.11.29




ASP 에서 서버 변수를 출력하여 보려고 할때 사용하면 좋다.








  1. <%
  2. 'servervariables 컬렉션값 출력하기
  3. for each key in request.servervariables
  4.  response.write "<tr><td>"&key&"</td><td>"
  5.  
  6.  if request.servervariables(key) = "" then
  7.   response.write "&nbsp;" & vbcrlf        
  8.  else
  9.   response.write request.servervariables(key) & vbcrlf
  10.  end if
  11.  
  12.  response.write "</td></tr><tr>"
  13. next
  14. %>
 .

'Computer > ASP' 카테고리의 다른 글

성능 및 스타일 향상을 위한 25 ASP 팁  (0) 2011.11.29
URLEncode  (0) 2011.11.29
ASP 서버 변수 출력  (0) 2011.11.29
펌) 페이징 쿼리문 비교  (0) 2011.11.29
펌) ASP 성능 향상 TIP.  (0) 2011.11.29
펌) dext업로드 컴포넌트에 대해서..  (0) 2011.11.29

출처 : http://www.knhead.pe.kr

 

 

 

제가 어느 페이징이 제일 빠를까.. 고민 하다가.. 테스트로 만들어 보았습니다.
총.. 6가지..입니다..

간단하게 쿼리를 설명해드리겠습니다.

1. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]

  1번 리스트는 이 쿼리 구문을 써서 했고요. 현제 개시물까지 이동을 Rs.Move(이동할수) 로 처리 했습니다.

2. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]    - 1번과 동일

  1번과 쿼리구문은 동이하고요. 레코드셋의 AbsolutePage를 이용해서 페이징을 했습니다.

3. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]

   WHERE [글번호필드] NOT IN (SELECT TOP [제거할 게시물수] [글번호필드] FROM [테이블명])
   예전에 태요 사이트에서 보았던 쿼리 구문입니다.. NOT IN 때문에.. 문제시 되었던 쿼리구문이죠.

4. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]
   WHERE [글번호] IN (SELECT TOP [페이지출력 갯수] [글번호] FROM
   (SELECT TOP [불러올 총 게시물수] [글번호] FROM [테이블 명]) AS A ORDER BY [글번호])
   ORDER BY [글번호] DESC

   이 쿼리 구문은 3번의 쿼리 구문의 문제점을 보완한 구문입니다. NOT IN 대신에 IN을 사용 했습니다.

5. SELECT TOP [페이지 출력갯수] [출력 필드명] FROM [테이블 명]
   WHERE [글번호] <= (SELECT MIN([글번호])
   FROM (SELECT TOP [제거할 게시물수] + 1 [글번호] FROM [테이블명]) AS A)

   5번째 쿼리 구문은 IN, NOT IN이 아닌 출력할 마지막 글번호 바로 앞이 글번호를 찾아서 처리를 해주는
   쿼리 구문입니다.

6. SELECT TOP [페이지 출력갯수] [출력 필드명] FROM [테이블명]
   WHERE [글번호] <= (SELECT MIN([글번호])
   FROM (SELECT TOP [제거할 게시물수] + 1 [글번호]
   FROM [테이블명] WHERE [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호]) AS A
   WHERE [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호])
   AND [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호]

   6번재 쿼리는.. 글에 인덱스(가칭)라는 필드를 하나 더 추가 해서.. 글 기본 2000개마다 (가변적입니다)
   인덱스를 증가 시켰습니다. 즉 2000개를 하나의 묶음으로 만든것입니다.
   그 인덱스를 기준으로 처리를 해주었습니다.(기본 개념은 영어 사전 입니다 ㅡㅡ;) 


위와 같이 간단한 기본 쿼리 구문을 설명? 했습니다.
게시물은 100만개를 넣고 테스트를 했습니다.
테스트 게시판을 보시려면.. 맨위에 각 게시판을 링크를 걸었습니다.
서버가 구려서.. 제대로 될지 모르지만..
제 노트북
(CPU : p4-1.8, RAM : 768Mb, 컴팩 프리자리오 2820AP, 환경 : 윈도우2003 MSSQL2000)
에서 테스트 해본 봐로는 처음페이지(1), 마지막 페이지(50000) 처리 시간이 아래와 같습니다.(단위 ms)

1 : 320    12289.06
2 : 273    11476.56
3 : 289    4406.25
4 : 289    2695.31
5 : 289    1218.75
6 : 7.81    23.44

엄청난 차이가 나죠??
기본적으로 글번호에 Clustered Index, 인덱스번호, 글깊이에 Non Clustered Index를 걸어 두었습니다.
엄청난 차이로 인해 테스트로 만든 저 또한 입이 쩍 벌어 집니다 ㅡㅡ;;

위 페이징 로직은 여기 저기서 줏어 듣고 ㅡㅡ; 확장 시킨 것입니다.

제가 내공 수위가 낮은 관계로 정확한 테스트를 행했는지 모르지만..
페이징으로 고생하시는 분들을 위해.. 간략하게 만들어 봤습니다.

기본 테스트는 제 홈페이지에서 해보시면 되구요.

테스트 asp파일은 [이곳] 에서 다운 받을수 있습니다.

제 홈에 있는 페이징 방법이 6번의 인덱스와 not in 으로 만들었습니다.
(그때는 걍.. 2000개 안쪽에서 처리 해주는 것이라 not in을 썻습니다 게시판이 필요 하시면..
  다운 받으셔서 저장 프로시저늬 리스트 부분을 수정 하시면. .더욱 쾨적하게 사용 하실수 있을것입니다)

p.s 서버가 구려서 노트북 보다는 성능이 낮게 나오네요. ㅡㅡ;
     궁금하신 점이나 문의 사항은 제 홈페이지의 테스트 게시판 버그 리포트에 적어 주시기 바랍니다.

.

'Computer > ASP' 카테고리의 다른 글

URLEncode  (0) 2011.11.29
ASP 서버 변수 출력  (0) 2011.11.29
펌) 페이징 쿼리문 비교  (0) 2011.11.29
펌) ASP 성능 향상 TIP.  (0) 2011.11.29
펌) dext업로드 컴포넌트에 대해서..  (0) 2011.11.29
펌) asp에서 디비작업 최적화하기  (0) 2011.11.29

+ Recent posts

티스토리 툴바