본문으로 건너뛰기

구독과 컴포넌트 수명주기

IOSignal JS 7.2.0 기준입니다. 클라이언트 API에서 메서드와 이벤트 전체 개요를 확인하세요.

두 가지 구독 방식과 용도​

listen()은 ready 핸들러 안의 구독 코드를 매번 작성하지 않도록 제공하는 간편 문법(syntactic sugar)입니다. 두 방식 중 앱의 제어 수준에 맞는 방식을 선택합니다.

방식적합한 용도연결·재접속 시 구독
수동 subscribe() + on()연결 상태에 따른 처리, 동적 구독, 구독·송신 순서의 정밀 제어앱이 ready 핸들러에서 등록
자동 listen(tag, handler)사용할 태그가 정해진 간단한 앱·CLI, 연결 상태별 코드를 줄이고 싶은 경우저장된 .channels를 이용해 라이브러리가 자동 등록

수동 방식: ready에서 구독과 송신 순서 제어​

const io = new IO();
const tag = 'channel1';
io.on('message', (receivedTag, ...args) => {
console.log(receivedTag, ...args);
});
io.on('ready', () => {
io.subscribe(tag);
io.signal(tag, io.cid + ' is ready.');
});
io.open('ws://localhost:7777');

수신 핸들러는 한 번 등록하고, ready마다 구독을 보내므로 재접속에도 대응합니다. IOSignal의 subscribe(tag)는 핸들러를 인자로 받지 않으므로 on(tag, handler) 또는 on('message', handler)로 수신을 처리합니다. 수동 subscribe() 자체는 재구독 목록 .channels에 태그를 저장하지 않습니다.

자동 방식: listen 한 줄로 태그와 핸들러 등록​

const io = new IO();
io.listen('channel1', (tag, ...args) => {
console.log(tag, ...args);
});
io.open('ws://localhost:7777');

일반 구독 태그의 listen()은 핸들러를 등록하고 태그를 .channels에 저장합니다. 최초 연결에서 CID를 받아 ready가 되는 처리 과정에 저장된 태그들을 자동 구독하며, 접속이 끊긴 뒤 재접속해도 같은 목록으로 재구독합니다. 따라서 구독만을 위한 on('ready', () => io.subscribe(...))는 필요하지 않습니다. 핸들러도 매번 다시 등록하지 않습니다.

이 자동화는 초기화 시 태그와 핸들러를 선언하는 용도입니다. listen() 호출 자체가 즉시 구독 패킷을 보내지는 않으므로 최초 ready 처리 전에 등록하세요. 이미 ready인 상태에서 새 태그를 즉시 구독하려면 핸들러 등록과 subscribe(tag)를 사용합니다. 구독 직후 송신처럼 순서를 직접 제어해야 할 때도 수동 방식을 사용하세요. 현재 코드는 ready 이벤트 핸들러 실행 후 저장 목록의 자동 구독을 전송하므로, ready 핸들러에서 바로 송신하는 코드가 자동 구독보다 먼저 실행될 수 있습니다.

unsubscribe(tag)는 서버 구독을 해제하고 저장 목록에서도 태그를 제거합니다. 직접 수신은 서버 구독 없이 on('@', handler), on('@topic', handler), listen('@', handler), listen('@topic', handler) 중 하나로 등록합니다. 직접 수신 핸들러는 ready 전후 어느 때든 메시지가 도착하기 전에 등록하면 됩니다. 직접 수신 해제는 off('@topic', handler)를 사용합니다. subscribe('@topic')와 unsubscribe('@topic')는 사용 오류로 TypeError를 발생시키며 서버로 전송하지 않습니다. 쉼표 목록에 직접 태그가 하나라도 있으면 전체 요청을 거부합니다. A@topic은 CID 발행 구독이므로 허용합니다.

link(component, tag, handler)의 첫 인자는 로컬 컴포넌트 식별자입니다. 서버 주소나 수신자 CID가 아닙니다. unlink(component, tag)와 unlinkAll(component)는 해당 컴포넌트가 등록한 핸들러만 제거합니다. 다른 컴포넌트가 같은 함수나 태그를 사용해도 함께 제거하지 않습니다. link로 등록한 핸들러의 해제에는 unlink를 사용합니다.

io.link('offer-panel', '@offer', (tag, message) => {
console.log(tag, message);
});
// 컴포넌트가 사라질 때
io.unlinkAll('offer-panel');

@ 및 @topic 링크는 로컬 리스너만 관리하며 서버 구독·해제 패킷을 보내거나 재접속 구독 목록에 추가하지 않습니다. 일반 채널과 A@topic 링크는 기존처럼 서버 구독과 재접속 구독을 관리합니다. 해당 구독을 공유하는 다른 링크나 listen 등록, 명시적인 subscribe 등록이 있으면 한 컴포넌트의 unlink가 그 구독을 해제하지 않습니다. 마지막 링크만 사용하던 구독은 해제합니다. 명시적 subscribe의 소유권은 현재 연결에만 해당하며, 재접속 자동 구독은 listen과 link의 저장 목록에 따릅니다.