VisualWorksTutorial1:Page05

From 흡혈양파의 번역工房
Jump to navigation Jump to search

cincom_tutorial_vwlogo
cincom_tutorial_cincomlogo

웹로그 통계 레슨 4
외부파일 불러오기와 문자열의 해부

cincom_tutorial_stlogo

| 목차 | 레슨3 | 레슨5 |
cincom_tutorial_openbook 앞에 있었던 워크샵에서는 특정 디렉토리에 있는 웹서버의 로그파일 장소를 찾아 VisualWorks의 파일 에디터에서 그 파일을 표시했습니다. 파일을 "한 번에" 표시했습니다만 "Hit"을 카운트 하기 위해서는 파일을 1행씩 읽어올 필요가 있습니다.
cincom_tutorial_certificate 이 레슨에서는 "종료할 때까지 특정 처리를 반복하는" 루프의 실행방법을 학습하겠습니다. 구체적으로 그 순서는 "파일을 1행 1행 불러와서, 파일 끝부분까지 도달했을 때 종료를 전달"과 같은 반복입니다. 그중에 각 행에서 IP 어드레스를 골라냅니다.
cincom_tutorial_steps 1. Workspace에 있는 텍스트를 아래와 같이 수정해주십시오. 그리고 텍스트 전체를 반전시키고 <오퍼레이트 클릭>실행을 선택해주십시오.
| myFile myStream | 
myFile := 'ws000101.log' asFilename. 
myStream := myFile readStream. 
myStream inspect. 
myStream close.


새로운 Inspect 화면이 표시됩니다. 화면 타이틀은 an EncodeStreaman(ExternalReadStream)이며, 왼쪽 뷰에는 self 이외에 일곱가지 프로퍼티가 표시됩니다. 여기서 중요한 것은, 문자의 Stream으로써 시퀸셜 파일을 취급하고 있다는 것입니다. 그림 4-1을 참조.

그림 4-1. VisualWorks의 Inspect 화면에서 Stream으로써 로그파일을 표시
cincom_tutorial_lightbulb
VisualWorks의 표준 디렉토리에 로그파일을 두지 않으면 파일지정을 할 때 "절대경로" 가 필요하게 됩니다. 앞으로 파일참조가 요구될 때, 샘플코드에서는 파일 이름만(절대경로가 아닌)을 사용하겠습니다. 파일을 제대로 참조할 수 있는가는 올바른 경로 지정에 달려있습니다. VisualWorks의 표준 디렉토리에 파일을 두는 이점은, 파일 경로를 지정할 필요가 없기 때문에, Workspace에 이 레슨 코드를 카피해서 그대로 이용할 수 있습니다.
cincom_tutorial_steps 2. Inspector 화면 왼쪽 뷰에 표시된 lineEndCharacter를 클릭(반전)해주십시오.

오른쪽 뷰에는 Core.Character cr이라는 lineEndCharacter의 값이 표시됩니다. Linux/UNIX에서는 Core.Character lf라고 표시될 것입니다. 레슨 마지막에 이 정보를 사용할 것이니 기억해두시기 바랍니다.


3. Inspector 화면을 닫아주십시오.

cincom_tutorial_question 그러면, 이 코드를 한줄씩 분석해보겠습니다.


| myFile myStream |

최초 행에서는 두 가지 임시 변수가 선언되어 있습니다. 스페이스(반각공백)로 변수를 끝맺으며, Pipe문자(세로줄)로 변수를 둘러쌉니다.


myStream := myFile readStream.

이 행은 Smalltalk의 특징을 잘 나타내고 있습니다. 대입식(colon equal 심볼을 포함)에 있어 Smalltalk는, 우선 우측을 평가하고 좌측에 그 값을 대입합니다. 그러므로 readStream 메시지는 myFile객체에 전송되었습니다. 이 의미는 "Stream"(파일을 컴퓨터에서 다룰 수 있도록 함)으로서 로그파일을 취급하며, myStream 임시 변수에 Stream을 대입합니다.


myStream inspect.

Stream을 inspect하듯 Smalltalk에 지시합니다.(즉, <오퍼레이트>메뉴의 메뉴 항목에 있는 Inspector와 같지만, 이것은 프로그램에서 호출하는 방법입니다.(Cool!!!)


myStream close.

Inspector 화면을 표시하는 동안, Smalltalk 먼저 진행하여 파일을 물리적으로 닫습니다.(파일도 함께 닫는건 좋은 생각인것 같습니다.)


스트림을 사용하는 이점은, lineEndCharacter를 결정함으로 인해 1행 1행 파일을 읽을 수 있습니다. 그러면, 파일 첫행을 불러와 봅시다.

cincom_tutorial_steps 4. 아래와 같이 텍스트를 수정하십시오. 그리고 텍스트 전체를 반전시키고 <오퍼레이트 클릭>실행을 선택해주십시오.

UNIX/Linux 유저는 cr lf(소문자 엘과 에프)로 변경해주십시오.

| myFile myStream myLine | 
myFile := 'ws000101.log' asFilename. 
myStream := myFile readStream. 
myLine := myStream upTo: Character cr. 
myLine inspect. 
myStream close.


타이틀이 a ByteStringInspector 화면이 표시됩니다. Inspector 화면에서는 파일의 최초행이 표시됩니다. 그림 4-2 참조

그림 4-2. 로그파일 최초행


5. Inspector 화면의 기본 탭을 선택합니다.

왼쪽 뷰의 self 아래로는 숫자가 연속적으로 이어집니다. 그 번호는 1에서 122까지 있습니다. 이것은 파일 맨 처음행의 내용인 122문자를 나타냅니다.(문자 하나하나가 각각의 번호에 대응)

그림 4-3. 122문자에서 구성되는 로그파일의 최초행
cincom_tutorial_question 위 코드에서 네 번째 행을 설명합니다. 여기서는 많은 일들이 일어납니다.
myLine := myStream upTo: Character cr.

세 번째 행에서는 myFile 객체에 readStream 메시지를 송신함으로써 Smalltalk는 Filename 객체를 Stream 객체로 변환했습니다. 파일 전체 내용은 문자의 스트림폼 안에 있습니다. 그러면, 템퍼러리 변수 mySteam에 격납된 스트림에 대해서 생각해봅시다.


네 번째 행에서는 myStreamStream 객체에 upto:메시지를 송신하고 있습니다. 여기서 주의해야할 점이 있습니다. 이 메시지에 있는 콜론 ":" 이 의미하는 것은, 그 뒤에 파라메터를 지정한다는 의미입니다. 이 행을 일본어로 번역하면 "문자(Character)cr에 다다를 때까지 (up to)myStream의 모든 문자를 취득하여 myLine에 대입하라"가 됩니다. copy문과 닮았습니다. upTo:메시지는 "나는 어디서 멈춰야 하나요?"라는 것을 알고싶어 합니다. 문자 cr은 carriage return(종종 cr)을 의미합니다. carriage return은 통상적으로 행의 맨 마지막이나 다음 행의 개시를 나타내며, 이러한 예시처럼 일반적인 경우엔 행과 행 사이에 있습니다.


4행째는 4 squared 3 + 4와 비교해서 조금 복잡합니다. 이 문이 파라메터를 포함하고 있는 것 뿐만 아니라, 객체(myStream), 클래스(Character)나 두 개의 매시지(upTo:, cr)를 포함하고 있습니다. Smalltalk에서 이 행을 어떻게 해석하는가(즉 어떤 메서드를 최초에 평가 하는가)를 이해하기 위해서 구문 입문서를 참조해 주시기 바랍니다. 입문서에는 Smalltalk에서 사용되며, 폭넓게 수용되고 있는 네이밍 규약에 대한 정보를 포함하고 있습니다.


파일 맨 처음행을 읽어왔습니다. 다음은, 이 행에서 IP 어드레스를 뽑아낼 필요가 있습니다. 이 파일은 "콤마 구분"이기 때문에, 이 파일의 모든 "Field"는 콤마에 의해 구분되어 있습니다. IP 어드레스는 각 행의 맨 처음 필드에 있으니, 맨 처음 콤마에 "이를 때까지(upto)" 행의 문자를 읽어들일 필요가 있습니다. 그러면 도전해봅시다.

cincom_tutorial_dominoes.gif 입문서 : 구문(신텍스)
cincom_tutorial_steps 6. 아래와 같이 텍스트를 수정해주십시오. 그리고 모든 텍스트를 반전시키고 <오퍼레이트 클릭>실행을 선택해주십시오.
| myFile myStream myLine addrIP | 
myFile := 'ws000101.log' asFilename. 
myStream := myFile readStream. 
myLine := myStream upTo: Character cr. 
addrIP := myLine copyUpTo: $,. 
addrIP inspect. 
myStream close.


새로운 Inspector 화면이 표시됩니다. 화면 타이틀은 a ByteString입니다. IP 어드레스(구체적으로는 209.67.247.201)의 바이트 문자열 값이 표시됩니다. 기본탭을 클릭하면 IP 어드레스 14문자에 대응(문자 하나하나가 각 숫자에 대응)하는 1~14까지의 숫자가 표시됩니다.

그림 4-4. IP 어드레스 추출에 성공


7. Inspector 화면을 닫아주십시오.

cincom_tutorial_question 위 코드에서 5행 부분을 설명하겠습니다.
addrIP := myLine copyUpTo: $,.


지금 템퍼러리 변수 myLine에는 최초행의 문자열이 들어가 있습니다. 그리고 그 문자열에서 콤마($,)에 다다를때까지 (up to)문자열을 취득하여 템퍼러리 변수 addrIP에 격납합니다. 즉, copyUpTo:메시지를 String 객체인 myLine(a Bytestring의 인스턴스인)에 부여하여, 파라메터 $,를 넘깁니다. 콤마 앞에 달러마크($)를 사용함으로써 Smalltalk에 “콤마라는 문자”라는 것을 전달할 수 있습니다. Smalltalk에서의 콤마는 특별한 의미(사실은 메시지에서)를 가지고 있습니다만, 달러마크를 사용함으로써 메시지가 아닌, 콤마 문자로써 취급할 수 있게 됩니다.


기본적으로는 같은 것을 실행하는 두개의 다른 메시지를 사용했습니다. copyUpTo:메시지는 특정 파라메터에 "다다를때 까지(up to)" 요소를 복사했습니다. 두 가지 다른 메시지를 사용한 이유는, 각자 다른 객체가 각각을 가지고 있기 때문입니다. upTo:메시지는 Stream 객체에서 사용되는 것에 반해, copyUpTo: 메시지는 String 객체에서 사용됩니다.


다음과 같이 생각할 수도 있습니다. "사용하고 있는 클래스를 고려하지않고 '파라메터에 다다를때까지 요소가 복사됨'이라는 같은 메시지가 있으면 곤란하지 않을까?" 답은 "괜찮다"입니다. 그 개념은 다형성(polymorphism)이라 불리며, 객체지향의 기본 개념입니다. 지금은 Stream 객체에서는 upTo: 메시지, String 객체에서는 copyUpTo: 메시지라는 것을 기억해둔다면 충분합니다.

cincom_tutorial_dominoes.gif 입문서 : 다형성(polymorphism)


IP 어드레스를 취득하였습니다. 하지만 다른 행에도 IP 어드레스가 포함되어 있습니다. 파일을 1행 1행 루프시켜 IP 어드레스는 모으는 방법이 필요합니다. 단지 1행을 추가하는 것 만으로 실행할 수 있습니다.

cincom_tutorial_steps 8. 아래와 같이 코드를 수정해주십시오. 그리고 텍스트 전체를 반전시기고 <오퍼레이트 클릭>실행을 선택해주십시오.
| myFile myStream myLine addrIP | 
myFile := 'ws000101.log' asFilename. 
myStream := myFile readStream. 
[ myStream atEnd ] whileFalse: [ 
myLine := myStream upTo: Character cr. 
addrIP := myLine copyUpTo: $,. 
Transcript show: addrIP.]. 
myStream close.


텍스트(숫자)가 VisualWorks 메인 화면 흰색 장소에 표시됩니다. 이전 레슨을 떠올려 보세요. 이 부분은 System Transcript라고 불리우며, 레슨 2에서 설명한 Smalltalk 화면 표시방법 네 가지중 하나입니다.


그림 4-5. 트랜스크립트에서 IP 전체를 표시
cincom_tutorial_question 몇 줄만 가지고 실행 될거라 상상이나 하셨나요?
[ myStream atEnd ] whileFalse: [

단 1행의 코드로 많은 것을 처리했기에 좀 더 설명이 필요할 것입니다. 자세히 알고 싶은 분은 루프(제어구조) 입문서를 읽어주십시오.

cincom_tutorial_dominoes.gif 입문서 : 루프(제어구조)
cincom_tutorial_certificate 정리

이 연습을 통해서 토픽의 설명이나 Smalltalk에 관련된 개념을 대부분 연습했습니다. 이 연습을 통해 익힌 대처법에 대한 평가를 할 좋은 기회입니다. 이 연습을 끝내기 전에 해야할 일이 한 가지 있습니다. 이 웹 사이트의 특정 1일 Hit수를 세는 것입니다. 다음 워크샵에서 그것을 하겠습니다. 그 방법의 요점을 정리해 봅시다.


우선, 파일 여는 법을 알아야 합니다. 그리고, 파일을 1행 1행 읽어오는 방법을 알아야 합니다. 더욱이 그 행에서 데이터를 유출하는 방법을 알아야 합니다. 동시에 이것(System Transcript에 웹서버 로그파일의 IP 어드레스를 전부 표시하는 순서)을 하는 대신 "작은 코드로 테스트 – 작동시킴 – 다음으로 진행"이라는 방법을 실행했습니다. 다른 프로그래밍 언어에서는 이렇게 할 수 없습니다. 에디터에서 전부 코드를 쓰고 컴파일해서 실행시킬 필요가 있습니다. 보통, 코드를 처음 실행할 때, 정말 이게 작동할거라고는 생각하지 않을것입니다. 동작하지 않는다면 처음으로 돌아가 에디터에서 문제를 해결(노력)해서 컴파일한 후 재실행할 것입니다. 그리고 당신은 언젠가 제대로 동작하는 프로그램을 얻을 때 까지 몇 번이고 그런 절차를 계속할 것입니다.


Smalltalk에서는 "작은 코드로 테스트 – 작동시킴 – 다음으로 진행"작업이 더욱 증가합니다. 작은 코드 덩어리를 만들어 작동시키고, 하나의 유닛으로써 그것들을 서로 연결시킵니다. 이것이 Smalltalk에 있어서 매우 효율적인 개발 방법입니다. 이 레슨에서 작은 코드 덩어리를 작성하면서 뒤로 되돌아가거나 다시 테스트하지 않았을 것입니다.


파일에서 IP 어드레스를 유출하는 방법을 이해했으니, 다음 워크샵에서는 그것을 모으고 정렬해서 세기로 합시다.

아래와 같은 내용을 학습하였습니다

  • 1행 1행 파일을 불러오기
  • 문자열에서 데이터를 취득
  • 루프 실행
  • 코드 블록문
  • 특정 문자(콤마)의 특별한 의미를 무효화 시키기(오버라이트)
  • 파일에 억세스하기 위해 Stream 클래스를 사용
  • 이론식을 평가

| 목차 | 레슨3 | 레슨5 |