[swift1.2] Swift 프로토콜 지향 프로그래밍

Swift 2015. 8. 6. 00:57



WWDC 2015 세션중 "Protocol-Oriented Programming in Swift" 라는 흥미로운 세션이 있습니다. 애플에서 Standard Library 그룹의 리더를 맡고 있는 Dave Abrahams 라는 분이 발표한 세션입니다. 세션에서 제공하는 슬라이드와 InfoQ에서 이 세션을 정리한 아티클을 바탕으로 내용을 요약했습니다.


클래스는 멋집니다!


다음과 같은 멋진 특징들을 제공하지요.

  • 캡슐화 (Encapsulation)
  • 접근제어 (Access Cotrol)
  • 추상화 (Abstraction)
  • 네임스페이스 (Namespace)
  • 풍부한 문법 (Epressive Syntax)
  • 확장성 (Extensibility)

그런데...


구조체로도 다 할수 있습니다.

클래스는 훌륭합니다. 타입은 훌륭합니다!

사실 위 특징들은 모든 타입들의 특징이며 클래스는 그것을 구현하는 하나의 방법에 불과합니다. 그렇다면 클래스 사용으로 인한 단점은 무엇이 있을까요?


1. 암묵적인 참조(Reference) 공유

  • 두 객체가 동시에 어떤 객체를 참조하는 경우, 서로 그 사실을 모른채 그 객체를 변경할 수 있습니다.
  • 참조 공유를 방지하기 위해 참조하는 객체를 복사할 수 있지만, 그렇게 하면 효율성이 나빠집니다.
  • 참조를 공유하는 객체에 Race Conditions 이 발생할 수도 있습니다.
  • Lock을 사용하여 레이스 컨디션을 방지할수 있지만 효율성은 더 나빠집니다.
  • Lock을 잘못 사용하면 Deadlock 상태에 빠질 수 있습니다.
  • 잦은 Lock 사용은 코드를 복잡하게 합니다.
  • 복잡성은 더 많은 버그를 유발합니다.

Values Don't Share. (That's a good thing)


2. 상속 (비지니스에 관한 모든 것을 가지고 있습니다.)

  • 슈퍼 클래스를 하나 밖에 가질수 없기 때문에, 초기에 잘 선택해야합니다.
  • 슈퍼 클래스를 나중에 변경하는 것은 매우 어렵습니다.
  • 슈퍼클래스가 갖는 모든 저장속성은 서브클래스에도 (강제적으로) 상속됩니다.
  • 초기화 처리가 복잡해집니다.
  • 수퍼클래스의 불변성을 깨뜨리지 않을수 없게됩니다.
  • 언제 무엇을, 어떻게 재정의해야 하는지 (수퍼 클래스에 대해서)알아야 합니다.

More and more, we promote delegation.


3. 타입관계를 잃어버립니다.(Lost Type Relationships.)

  • 추상 수퍼클래스와 서브클래스의 구현코드가 함께 존재하게 됩니다.
  • 서브클래스 메소드에 접근하기 위해 수퍼클래스를  서브클래스로 다운캐스팅하면서 타입관계를 잃게됩니다.

  • 이진탐색 클래스 모델 Ordered 정의

class Ordered {
    func precedes(other: Ordered) -> Bool { fatalError("메소드를 구현해주세요.") }
}

class Number:Ordered {
    var value:Double = 0
    override func precedes(other: Ordered) -> Bool {
        return value < (other as! Number).value // 
    }
}  

func binarySearch(sortedKeys: [Ordered], forkey k: Ordered) -> Int {
    var lo = 0
    var hi = sortedKeys.count
    while hi > lo {
        let mid = lo + (hi - lo) / 2
        if sortedKeys[mid].precedes(k) { lo = mid + 1 }
        else { hi = mid }
    }
    return lo
}

as! ASubclass 는 타입 관계를 잃어버렸다는 신호
대부분 추상화를 위해 클래스를 사용하기 때문이다.


4. 좋은 추상화 메커니즘이란?

  • Value type을 지원합니다.(클래스 외에도)
  • 정적 타입관계를 지원합니다. (동적 디스패치 외에도)
  • 큰 덩어리로 뭉치지 않아야합니다.
  • Retroactive 모델링을 지원합니다.
  • 모델에 인스턴스 데이터를 강요하지 않아야 합니다.
  • 모델에 초기화의 부담이 없어야 합니다.
  • 무엇을 구현해야 하는지 명확해야 합니다.

Swift는 프로토콜 지향 프로그래밍 언어!


5. 프로토콜 지향 프로그래밍

  • Swift에서 새롭게 추상화를 생각할 때 첫 번째 포인트는 프로토콜!

이진탐색 프로토콜 모델 Ordered 변경해보겠습니다.
protocol Ordered {
    func precedes(other:Self) -> Bool
}    

struct Number : Ordered {
    var value:Double = 0
    func precedes(other:Number) -> Bool {
        return self.value < other.value 
    }
}

이진탐색 함수를 정의합니다.
func binarySearch<T:Ordered>(sortedKeys:[T], forKey k: T) -> Int {
    var lo = 0
    var hi = sortedKeys.count
    while hi > lo {
        let mid = lo + (hi-lo)/2 
        if sortedKeys[mid].precedes(k) { lo = mid + 1 }
        else { hi = mid }
    }
    return lo
}

Int 배열에 이진탐색 함수를 적용해 보겠습니다.
  • 먼저 Int가 프로토콜 Ordered를 구현해야합니다.
// Int형 Ordered 프로토콜 구현하기 

extension Int:Ordered {
    func precedes(other: Int) -> Bool {
        return self < other
    }
}
  • Int 배열에 이진탐색을 적용합니다.
// 1. 키 정렬 
var keys = [10, 30, 1, 4, 5, 6, 7, 8, 55, 20]
var sortedKeys = keys.sorted {  $0 < $1 }
// sortedKeys: [1, 4, 5, 6, 7, 8, 10, 20, 30, 55]

// 2. 찾을 키
var searchKey = 30
// 키 30의 index는 8.

// 3. 이진탐색 
var searchIndex = binarySearch(sortedKeys, forkey: searchKey)
// searchIndex: 8
Number 배열에도 이진탐색을 적용해보겠습니다.
// 1. 정렬된 Number 배열 생성  
var numbers = sortedKeys.map { return Number(value: Double($0)) }
// numbers: [1.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 20.0, 30.0, 55.0]

// 2. 찾을 키
var keyToSearch = 5.0

// 3. 이진탐색
var index = binarySearch(numbers, forkey: Number(value: keyToSearch))
// index: 2

프로토콜을 사용하면, 커스텀 Number 구조체 뿐만 아니라 기존 타입에도 이진탐색을 쉽게 적용할 수 있음을 알 수 있습니다.




Protocol 과 Category

Objective-C 2011. 3. 22. 23:53



이번 포스팅에서는 Protocol과 Category에 대해서 알아보자.  Protocol은 자바의 인터페이스에 유사한 개념이다. 
Protocol은 공식 프로토콜과 비공식 프로토콜이 있으며, 그 중 공식 프로토콜이 자바의 인터페이스에 해당한다.
Category는 상속의 대안으로 클래스를 변경하지 않고도, 새로운 기능(메서드)을 추가할 수 있는 메커니즘이다. 
프로토콜과 카테고리에 대해서 좀 더 자세히 알아보자. 


1. Protocol 이란? 
자바언어의  Interface에 해당하는 개념으로 @protocol 지시어를 사용하여 정의한다. @protocol 을 구현하는 모듈은
프로토콜이 규약하는 모든 메소드를 반드시 구현해야하는 프로토콜을 공식 프로토콜(Formal Protocol)이라고 하며, 
구현해도 되고 구현하지 않아도 되는 프로토콜을 비공식 프로토콜 (Informal Protocol)이라고 한다.  공식 프로토콜은 
@required 지시어를,  비공식 프로토콜은 @optional 지시어를 사용한다.  
(비공식 프로토콜은 런타임시에 비공식 프로토콜을 구현하는 메소드가 존재하는 경우에만 호출된다.)
공식프로토콜의 모든 메소드들이 구현되지 않으면 컴파일 시에 에러가 발생할 것이다.  2개 이상의 프로토콜을 구현할
경우 ,(콤마)를 구분자로  구현할 프로토콜을 <> 안에 나열한다.

 Objective-C 에서는 Java 와는 다르게 컴파일 타임에 프로토콜 할당에 대해 타입검사를 수행하지 않는다.
 런타임시 메시지가 호출될 때, 해당하는 메소드가 구현되지 않았다면 selector  exception 예외가 발생한다. 

@interface VenusAttacks : Game
...
@end

@class Thing;

@protocol Living
- (float)age;
- (float)health;
(NSDictionary*)healthInfo;
@end

@protocol Communicating
- (NSArray*)recipientsInRange;
- (void)sendMessage:(NSString*)message to:(id)recipient;
@end

@interface Thing : NSObject 
...
@end

@interface Character : Thing 
...
@end




1.1 비공식 프로토콜(Informal Protocol)
비공식 프로토콜은 모듈클래스가 반드시 구현하지 않아도 되는 프로토콜이다.
비공식 프로토콜은 (반드시 구현하지 않아도 되기 때문에) 유연하고 동적이지만,  추가적인 문서화와 프로그래머들 간에
(통일된 사용을 위해) 협조가 요구된다.  비공식 프로토콜에서는  메서드가 구현되었는지 검사하는 코드가 들어가며  
그 형태는 아래 코드와 같다. 자바에서는 윈도우 종료시 이벤트를 인터셉트 하기위해서,  해당하는 이벤트에 대한 리스너를
등록하고, 이벤트가 발생하면 리스너를 통해 통보받는다.  Objetive-C 에서는  delegate 가 윈도우 종료시 Notification 을
통보받는 메소드를 비공식 프로토콜로 선언하고 있다. 
 
BOOL shouldClose = YES;
if ([delegate respondsToSelector:@selector(windowShouldClose:)])
   shouldClose = [delegate windowShouldClose:self];
if (!shouldClose)
return;





1.2 공식프로토콜과 비공식 프로토콜의 조합(Combining Formal and Informal Protocols)

프로토콜은 비공식 프로토콜과 공식 프로토콜이 혼합되어 사용되어지는 경우가 많다.
프로토콜에 선언한 메소드는 디폴트로 공식 프로토콜이며, @required 이라는 지시어를 명시적으로 사용할 수 있다. 
비공식 프로토콜은 @optional  지시어를 사용한다.

다음은 TableDataSource 프로토콜이며, 테이블 행의 개수를 반환하는 메소드와 해당하는 열과 행의 셀객체를 반환하는 
메소드는  @required 로 , 테이블 특정 행과 열의 셀객체를 변경하는 메소드는 @optional 로 선언되어 있어서, 비공식 프로토콜이
구현되지 않았을 경우,  read-only 로 동작하게 된다. (구현 유무에 따라 동작용도를 변경할 수 있다. )

@protocol TableDataSource
@required
- (int)numberOfRowsInTable:(Table*)table;
        - (id)table:(Table*)table objectForColumn:(int)col row:(int)ro
@optional
- (void)table:(Table*) setObject:(id)object forColumn:(int)col row:(int)row;
@end

 





 
2. 카테고리(Categories)
클래스 정의 일부에 이름을 붙힌 조각이라 할 수 있다..  자바에서는 단일블럭에서 하나의 클래스 정의가 모두 이루어지지만, 
Objective-C에서는 한 클래스 정의를 카테고리를 사용하여 여러 파일에 분리하여 정의할 수 있다.
카테고리를 사용함으로써, 복잡한 클래스를 관련이 되어 있는 인스턴스 변수와 메소드들의 그룹으로 분리하여
복잡성을 줄이고,  프로그래머들이 독립적으로 개발할 수 있도록 해준다. 
이외에도 카테고리는 클래스 정의(@interface) 와 독립적으로 클래스 메소드를 추가할 수 있게하며,
클래스 구현의 일부를 은닉할 수 있는 메커니즘을 제공한다. 클래스와 카테고리는 별도의 헤더파일과 모듈파일에
저장될 수 있으며, 해당 클래스를 사용하는 클라이언트 클래스는 관련있는 헤더파일만을  import 하여 사용한다. 

// 카테고리를 사용하지 않고 단일 클래스에 정의한 경우

@interface RecipeBoxController : NSObject {
       NSMutableArray*recipes;
NSMutableDictionary*  recipeIndex;   
}
- (id)init;
- (Document*)newRecipe;
- (Document*)newShoppingList;
- (Document*)newShoppingListFromRecipes:(NSIndexSet*)recipeIndexes;
@end
@implementation RecipeBoxController
...
@end

다음 카테고리는 리스트 설정하고 획득하는 역할만을 수행한다.
// Category 를 사용하여 클래스를 분리 
@interface RecipeBoxController (ShoppingLists)
- (Document*)newShoppingList;
- (Document*)newShoppingListFromRecipes:(NSIndexSet*)recipeIndexes;
@end

@implementation RecipeBoxController (ShoppingLists)
...
@end




2.1 카테고리 사용하여 조직하기(Using Categories for Organization)
거대한 클래스를 다룰수 있는 기능적인 단위로 나누는 것이 카테고리의 주요한 용도이다.  이 개념은 한 클래스를 
모듈화 할 수 있게하며, 각 모듈간에 캡슐화와 의존성을 줄여준다. 빌터패턴이 카테고리를 사용하여 얻을 수 있는 응용의 한
예이다. 자바에서 빌드에서 복잡한 객체 생성의 과정이 별도 클래스로 분리되는데, 
Objective-C에서는 별도의 객체생성과정이 메인 클래스 정으로부터 카테고리를 사용하여 분리될 수 있다. 


 

  2.2 메서드 은닉 (Hiding Methods)
카테고리의 또 다른 사용용도는 클래스의 일부를 은닉하는 것이다. 자바에서는 private, protect 키워드를 사용하여
내부 데이터를 은닉한다.  아래는 카테고리를 사용하여 메소드 일부를 은닉하는 예이다.  Private 이름으로 선언된 카테고리는
컴파일러에게 무시되며, 해당 클래스를 사용하는 클라이언트 클래스는 카테고리의 메소드들을 볼 수 없다. 
두개의 클래스 선언을 별도의 헤더 파일로 분리할 수도 있다.  이때, 클라이언트 클래스는 ToasterController.h 헤더파일만을  
import 하여 사용하면 된다. 카테고리의 헤더파일은 관례적으로  (클래스이름+카테고리이름.h) 이라는 형태를 갖는다.
아래에서는 ToasterController+Private.h 라는 이름을 갖을 것이다.
이런한 개념을 확장하여 Objectiv-C 에서는 extension 이라는 개념을 제공한다.

@interface ToasterController : NSObject {
   @private
float darkness;
}
- (void)setDarkness:(float)level;
- (void)startToasting
- (void)stopToasting
@end

@interface ToasterController (Private)
- (float)darkness
- (CarrierState)carrierPosition;
- (NSTimeInterval)cycleTime;
- (void)setCycleTime:(NSTimeInterval)cycleTime;
- (void)finishedToasting:(NSTimer*)timer;

 
2.2 외부 클래스 확장 (Augmenting Foreign Class)
카테고리를 사용하여 원 클래스에 어떠한 변경을 하지 않고도, 새로운 메소드를 정의할 수 있다. 
아래 코드는 Foundation Framework 의 NSArray 클래스에  카테고리를 사용하여, 배열의 첫번째 요소를 얻는
(id)firstObject 메소드를 추가하고 있다.  

* 만일 카테고리와 클래스가 동일한 메소드를 구현한다면, 카테고리 메소드가 클래스의 메소드를 대체하게 되어, 본 클래스의
메소드를 호출하지 못하게 된다.  동일한 메소드를 구현하는 카테고리가 2개 이상 있게되면 런타임에 무엇이 호출될지는 예측할 수 없다.
@interface NSArray (MyCollectionAdditions)
- (id)firstObject;
@end
@implementation NSArray (MyCollectionAdditions)
- (id)firstObject {
   return ([self objectAtIndex:0]);
}
@end




2.3 Extesions
Extension 은 익명 카테고리이다. 다만 Extension은 클래스의 @implementaion 구현부아 아닌  클래스의 @interface 정의부를
분리하기 위해 사용한다. extension 의 @interface 지시어는 비어있는 카테고리 이름을 사용한다.  extensions 내에 선언된 메소드들은 동일하게 @implentation  에서 모두 구현되어져야 한다. 카테고리와 extension은 컴파일 타임에만 프로그래머와 컴파일러로부터 메소드 선언을 은닉할 수 있으며, 런타임시에는 introspection(리플렉션)을 사용하면 노출될 수 있다. 

@interface CaseDocument : NSObject {
@private
   CaseNumber caseNumber;
}
- (CaseNumber)caseNumber;
@end
@interface CaseDocument()
- (void)setCaseNumber:(CaseNumber)number;
@end
@implementation CaseDocument
- (CaseNumber)caseNumber { return (caseNumber); }
- (void)setCaseNumber:(CaseNumber)number { caseNumber = number; }



 
 

'Objective-C' 카테고리의 다른 글

Objective-C 문자열 조작 메서드  (0) 2011.04.29
다중인자를 갖는 PerformSelector 메시지  (0) 2011.03.23
Protocol 과 Category  (0) 2011.03.22
Objective-C 훑어보기  (2) 2011.03.20
[Cocoa] Cocoa Design Pattern  (0) 2011.03.20
HMAC-SHA1 구현  (0) 2011.03.03

[FTP] (1) FTP(File Transmission Protocol) 프로토콜 이해

네트워크로그 2011. 3. 9. 01:44



응용계층 프로토콜에 한 종류인 FTP에 대해 알아보고,  C언어를 사용하여 간단한 FTP 프로그램을 만들어보자.  

 


1. FTP 란? 

FTP 는 2대의 컴퓨터 간에 파일 전송을 위한 애플리케이션 프로토콜로 RFC 959에 정의되어 있다. 

Transport  계층 프로토콜로 TCP를 사용하며,  클라이언트/서버 모델 구성을 가지고 있으며,  FTP 서버는

21번 포트에서 FTP 클라이언트의 접속을 기다린다. FTP는 텔넷과는 달리,  클라이언트와 서버간에 2개의 

커넥션을 맺어 통신을 한다. 제어 명령을 송수신하는 PI(Protocol Interpreter) 프로세스와, 데이터를 송수신하는

DTP(Data Transmission Process) 로 구성된다. 





2. Active 모드 vs Passive 모드 

데이터를 전송하는 방식에 따라 Active 모드와 Passive 모드가 존재한다. 서버를 기준으로 했을 때,  서버가 

클라이언트에 접속하여 데이터를 송수신하는 것을  Active 모드라 하며,  클라이언트가 서버에 접속하여 

데이터를 송수신하는 것이 Passive 모드이다. 

 




3.  FTP  애플리케이션의 구조 

FTP 애플리케이션의 구조는 다음과 같다. 



 

 알툴즈의  알 FTP 와 같이 그래픽 유저 인터페이스를 제공하는 FTP 클라이언트도 있는가 하면, 유닉스/리눅스에서와 같이   

터미널에서 동작하는  텍스트 인터페이스의 FTP 클라이트도 존재한다. 하지만 어떤 클라이언트 형태는 RFC959에 정의된 

FTP 프로토콜에 따라 내부적으로 FTP 서버와 통신하게 된다. 

 

FTP 클라이언트 인테페이스를 통해, FTP 명령을 치면 클라이언 PI와 서버 PI간에 통신이 이루어진다. 작업디렉토리에 파일목록

출력과 데이터 업로드, 다운로드와 같은 작업들은 PI 를 통해 초기화가 이루어지면, 실제 데이터 전송은 서버와 클라이언트의 DTP 

간에 별도의 커넥션을 통해 이루어진다.

 PI와 DTP는 구조상에  개념이며, 반드시 FTP 클라이어트가 2개의 프로세스로 구성되어야  하는 것은 아니다. 

한 개의 프로세스여도, 프로토콜 전송 주소와 포트, 절차만을 준수하면 이상없이 서버와 통신할 수 있다. 

 




4.  FTP 명령 / 명령을 완료하기 위해 전송되는 프로토콜


FTP 클라이언트에서 사용할 수 있는 명령들은 다음과 같다. 더 많지만 자주 사용되는 명령들만을 간추려 보았다. 
 

커맨드 기능 프로토콜 
 open
<아이피 주소 또는 호스트명>
 해당 주소의 FTP 서버로 접속한다. 접속이 성공하면 Name과 Password를
입력하여  로그인할 수 있다.

 커넥트

 USER

 PASS

 SYST

 pwd  현재 원격(서버) 작업 디렉토리를 얻어온다.  PWD
 cd <디렉토리>  원격 작업 디렉토리를 변경한다   CWD
 ls  현재 원격 작업디렉토리의 파일목록을 얻어온다.

 PASV

 LIST

 hash  파일 업로드/다운로드시 1024바이트 단위로 해시문자 출력 옵셥을 on/off  한다.    
 get <파일명>   서버에 파일을 로컬로 다운로드한다. 

 PASV

 GET

 put <파일명>  로컬 파일으로 서버로 업로드한다. 

 PASV

 PUT

 quit/bye  FTP를 종료한다.   QUIT
 !<쉘명령>  셀 이스케이프. 쉘 명령을 수행하고, FTP 로 되돌아온다.   
ascii / binary  파일을 아스키 또는 바이너리로 전송한다.   TYPE I./A
 ?  FTP 명령 사용법을 출력한다.   

 

  커맨드는 텍스트 기반 FTP 클라이언트에서 사용자게 터미널을 통해 입력받는 명령이며, 이러한 명령의 기능을 수행하기 위해

 클라이언트는 서버에게  한개 이상의 프로토콜을  전송하게 된다. 클라이언트가 서버에게 전송하는 프로토콜은 텍스트이며, 

프토토콜의 종결문자로 \r\n을 사용한다.  다음은 몇가지 FTP 프로토콜이다. 

 


4.1 FTP 프로토콜

커맨드 내용 비고
 USER 사용자명  FTP 계정에 사용자 명을 전송한다   
 PASS 비밀번호  FTP 계정에 사용자 비밀번호를 전송한다  
 SYST  FTP 서버에 운영체제 종류를 문의한다.   
 PWD  현재 작업디렉토리 경로를 얻어온다.   
 CWD 디렉토리  인자로 주어진 디렉토리로 현재 작업디렉토리를 변경한다    
 PASV  passive 모드로 전환한다. 서버는 클라이언트의 접속을 기다릴 주소와 포트를 쉼표를 구분자로 하여 (127,0,0,1,234,13) 의 포맷으로 응답해준다.   
 LIST  현재 작업 디렉토리의 파일목록을 얻어온다.   
 GET 파일명  원격 작업디렉토리 상에 파일을 로컬로 다운로드 한다.   
 PUT 파일명   로컬의 파일을 원격 작업디렉토리로 업로드 한다.   
 RETR  로컬로 파일 다운로드시 클라이언트가 서버에게 데이터 전송시작을 요청한다.   
 STOR  파일 업로드시 클라이언트가 서버에게 데이터 전송시작을 요청한다.   
 PORT h0,h1,h2,h3,p0,p1   Active 모드로 데이터 전송시  서버에게 클라이언트가 대기할 주소와 포트를 쉼표를 구분자로 전송한다. p0, p1은 2바이트 포트의 각 바이트의 십진수값이다  
 QUIT  연결을 종료한다.   


 


4.2  데이터 전송모드

데이터 전송은 passive 모드와  active 모드로 전송할 수 있으며, 그 개념상에 차이는 이전에 설명했다. active 모드로 데이터 

전송시  클라이언트는   PORT 명령을 통해 서버가 접속할 수 있도록 클라이언트가 대기할 주소와 포트번호를 전송한다. 


 

PORT 202,13,180,230,4,103 


 앞에 2개의 수는 IP 를 구성하고 있는 수들이며, 4, 103은 2바이트 포트번호의 각 바이트를 십진수로 표현한 값(4x256 + 103)이다.

 즉 위 프로토콜을 해석하면  202.13.180.230 주소, 1127 포트에서 대기할 테니 여기로 서버는 접속하시오 ~~ 라는 의미가 

되겠다.  이렇게  서버가 클라이언트에게 접속하면, 클라이언트는 바로 데이터를 전송하면 된다. 

 passive 모드에서는 클라이언트는 PASV 프르토콜을 전송하여 passive 모드로 데이터를 전송받겠다는 것을 서버에게 알리면, 

서버는 위와 통일한 포맷으로 서버가 대기할 주소와 포트번호를 알려준다. 클라이언트는 이 값을 읽어들여 해당 주소로 접속한다. 

이후 LIST, RETR, STOR 을 전송하여 실제 데이터 전송을 시작해달라고 요청하게 된다. 

 

다음은 이를 나타내고 있는 그림이다. 



 




로봇 프로토콜

검색엔진로그 2011. 3. 7. 23:51


인터넷을 돌아다니며 사이트 정보를 수집하는 크롤러는 자신이 관심 있는 모든 웹문서들을 수집한다. 
하지만 사이트 호스트 입장에서는, 보호하고 싶은 자료들도 있을 텐데... 크롤러를 대비해서 모든 문서를 별도로
관리하기란 여간 번거로운 일이 아니다.  호스트는 로봇배제파일과 로봇프로토콜을 사용하여 크롤러(로봇 )에게
노출하고, 숨길 페이지들을 명시해 줄 수 있다.  그럼 로봇배체 파일과 로봇 프로토콜에 대해서 알아보자


1. 로봇 배제파일과 로봇 프로토콜이란?

특정 웹크롤러에게 사이트 내 수집대상에서 제외할 페이지를  명시한 파일을 로봇배제 파일이라고 한다. 

이 로봇 파일은 해당 웹사이트의 루트 위치에 robots.txt 라는 이름으로 존재하며, 이 파일이 따르는 프로토콜을

로봇 프로토콜이라고 한다.  크롤러가 반드시 이 프로토콜을 따르도록 하는 규제는 없으며, 양심적인 크롤러라면

이 프로토콜을 따를 것이다. 프로토콜은 크롤러의 종류를 명시하는 User-agen 항목과 사이트 내 수집을 배제할 

페이지 패턴을 나타내는 Disallow 로 구성된다. 



2. 로봇 프토토콜  

User-agent: *<= 크롤러의 이름, *는 모든 크롤러에 해당함    

Disallow: /<= 수집배제할 페이지 패턴, 모든 페이지에 대한 수집을 금함


위 로봇 프로토콜은 모든 크롤러의 모든 페이지 접근을 제한하고 있다. 

User-agent: *

Disallow: /

User-agent: Googlebot

Disallow: /cgi-bin/

Disallow: /privatedir/


 

위 로봇 프로토콜은 Googlebot  크롤러만 수집을 허용하며, 명시한 2개의 패턴을 갖는 자원으로의 접근들은 제한한다.

로봇 프로토콜은  표준은 아니지만  구글 크롤러만 인식할 수 있는 Allow 항목을 지원한다. 

User-agent: *

Disallow: /

User-agent: Googlebot

Allow: /

 구글 크롤러만 수집을 허용하는 로봇 프로토콜이다. Allow 항목은 표준이 아니기 때문에, 반드시 필요한 경우가 아니면

사용하지 않는 것이 좋다. 



  3. 로봇 메타태그

웹호스트가 robots.txt 파일의 업로드를 허용하지 않는데도, 특정 페이지의 수집을 허용하고 싶지 않을 때,  robots.txt 대신에

로봇 메타태그를 사용할 수 있다. 로봇 메타태그는 일반적인 html의  메타태그와 유사하게 HEAD 섹션에 기술된다. 


 

(no)index는 크롤러에게 페이지 인덱싱을 허용할 지 말지를 결정한다.   noindex 또는 index 값을 갖을 수 있다. 

(no)follow는 크롤러에게 페이지 상에 존재하는 링크를 따라가서 수집하게 할지 말지를 결정한다.  nofollow 또는 follow 값을 갖는다.


<meta name="robots" content="noindex,follow" />
 인덱싱과 링크를 통한 이동을 허용하지 않는다.



<meta name="robots" content="noindex,follow" />
 인덱싱을 허용하지 않지만, 링크를 타고 가는 것을 허용한다. 



<meta name="robots" content="index,nofollow" />
 인덱싱을 허용하지만, 링크를 크롤하지 못하게 한다. 

  

<meta name="robots" content="none">
 noindex, nofollow 와 동일함 

 

 

4. 몇가지 잘 알려진 로봇 식별자들

ip는 검색엔진들이 사용하는 주소이며, 로봇 식별자는 웹사이트 방문시 전송하는 로봇의 이름이다. 일반적으로 로봇의 이름에 버전이 붙는다. n은 여러가지 수가 올 수 있음을 의미한다. 

홈페이지로봇 식별자IP address
www.google.com Googlebot c<nn>.googlebot.com
www.naver.com dloader(NaverRobot) / dumrobo 211.218.151.209
www.daum.net RaBot 210.183.28.46
... ... ...