사용자 정의 포트

사용자 정의 포트

사용자 정의(custom) 포트는 프로그래머가 직접 입력·출력 동작을 구현한 포트예요. make-input-portmake-output-port 같은 함수로, Racket의 표준 포트 추상화 뒤에 자신만의 데이터 소스나 대상(파일, 소켓, 메모리, 프로세스 파이프 등)을 연결할 수 있어요.

이 절에서는 사용자 정의 포트를 만드는 함수들과 prop:input-port·prop:output-port 같은 속성을 다뤄요.

출처: Racket Reference

본문

사용자 정의 포트는 포트가 수행하는 저수준 읽기·쓰기 동작을 콜백으로 지정해 만든 포트예요. 이렇게 하면 Racket의 포트 기능(문자·바이트 읽기, 라인 읽기, 직렬화, 포트 복제 등)을 그대로 활용하면서, 실제 데이터 전달은 직접 제어할 수 있어요.

procedure

(make-input-port name in [get-in count-avail! close]) → input-port?
  • name : (or/c string? #f)
  • in : (-> evt? bytes?) — 포트가 사용 가능할 때 데이터를 읽는 프로시저
  • get-in : (-> (or/c bytes? eof #f)) — (선택) 데이터를 얻어오는 프로시저
  • count-avail! : (-> void?) — (선택) 사용 가능한 바이트 수를 알려주는 콜백
  • close : (-> any) — (선택) 포트를 닫을 때 호출되는 콜백

이름 name을 가진 사용자 정의 입력 포트를 만들어요.

  • in은 포트의 기본 콜백으로, 포트가 읽기 가능한 상태일 때 호출되어 바이트 문자열을 돌려줘요.
  • get-in이 주어지면, in 대신 이 프로시저가 데이터를 얻어오는 데 사용돼요. get-in은 바이트 문자열, eof(더 이상 없음), 또는 #f(아직 없음)를 돌려줘요.
  • count-avail!은 포트 버퍼의 사용 가능 바이트 수를 갱신하는 데 쓰여요.
  • close는 포트가 닫힐 때 호출되어 외부 자원을 정리하게 해줘요.

procedure

(make-output-port name out [count-avail! close]) → output-port?
  • name : (or/c string? #f)
  • out : (-> bytes? any/c) — 데이터를 쓸 때 호출되는 프로시저
  • count-avail! : (-> void?) — (선택)
  • close : (-> any) — (선택)

이름 name을 가진 사용자 정의 출력 포트를 만들어요.

  • out은 포트에 데이터를 쓸 때 호출되는 프로시저로, 쓸 바이트 문자열을 받아요.
  • close는 포트가 닫힐 때 호출되어 남은 버퍼를 플러시하고 자원을 정리하게 해줘요.

사용자 정의 포트와 연결되는 주요 속성들:

  • prop:input-port — 값을 사용자 정의 입력 포트로 사용할 수 있게 하는 구조체 타입 속성이에요. 속성 값은 (cons (cons in get-in) (cons count-avail! close)) 형태의 데이터예요.
  • prop:output-port — 값을 사용자 정의 출력 포트로 사용할 수 있게 하는 구조체 타입 속성이에요. 속성 값은 (cons out (cons count-avail! close)) 형태예요.

값이 포트처럼 동작하게 하려면, 그 값의 구조체 타입에 prop:input-portprop:output-port 속성을 붙여요.

(struct my-input (in get-in count-avail! close)
  #:property prop:input-port
             (λ (self)
               (values (my-input-in self)
                       (my-input-get-in self)
                       (my-input-count-avail! self)
                       (my-input-close self))))

포트 동작에 영향을 주는 내용:

  • 위치 관련 속성prop:port-name, prop:port-local-name, prop:port-path 속성으로 포트의 이름·경로 같은 메타데이터를 제공할 수 있어요.
  • 닫기(close)close 콜백은 포트가 닫힐 때 void 이상이라면 어떤 결과든 돌려줄 수 있어요. 포트를 닫은 뒤 쓰기·읽기를 시도하면 오류가 발생해요.
  • 입출력 포트make-input-portmake-output-port 콜백을 모두 가진 값은 prop:input-portprop:output-port를 함께 붙여 양방향 포트로 만들 수 있어요.

사용자 정의 포트의 전형적인 쓰임:

  • 가상 파일 — 메모리 안의 바이트 문자열을 파일처럼 읽고 쓰는 포트.
  • 프로토콜 래퍼 — 소켓 위에 특정 인코딩이나 줄바꿈 변환을 적용하는 포트.
  • 지연 생성 — 필요할 때만 데이터를 만들어내는 포트(예: 무한 시퀀스를 읽는 스트림).

procedure

(port-write p) → void?

사용자 정의 출력 포트 p의 쓰기 콜백을 실행해요.

procedure

(port-read p) → (or/c bytes? eof #f)

사용자 정의 입력 포트 p의 읽기 콜백을 실행해요.

복잡한 포트 구현(여러 사용자 정의 포트를 연결한 것 등)에는 make-input-port·make-output-port의 세부 계약과 prop:input-port·prop:output-port의 정확한 데이터 형태가 중요해요. 각 함수의 계약을 확인해 구현하면 돼요.

더 알아보기