11-3. 새 포스트 생성시 실시간 전송

이제 서버쪽에서 웹소켓을 다루는 방법과, redis 를 데이터 전달 중간자 역할로써 구현하는 방법을 알아보았으니, 유저가 새 포스트를 작성했을 때 접속중인 모든 유저들에게 실시간으로 데이터를 전달해보겠습니다.

방법은 간단합니다. posts.controller 에서 redis publisher 를 만들고, write 함수가 실행 될 때, 포스트 내용을 발행하면 됩니다. 이 때 우리는, 데이터 형식을 편의상 리덕스 액션 형식과 동일하게 구성하겠습니다.

추가적으로, redis 쪽과 소켓쪽에서 데이터가 전송 될 때는 문자열 형태여야 하므로, JSON.stringify 로 한번 객체를 감싼다음에 발행하세요.

src/api/posts/posts.controller.js

(...)

const redis = require('redis');
const publisher = redis.createClient();

exports.write = async (ctx) => {
    (...)

    /* 포스트 정보 반환 */
    ctx.body = post;

    /* 데이터를 리덕스 액션 형식으로 전송 */
    publisher.publish('posts', JSON.stringify({
        type: 'posts/RECEIVE_NEW_POST',
        payload: post
    }));
};

(...)

그 다음엔, 웹 소켓쪽 코드를 조금 수정해주고, 불필요한 코드는 제거해주겠습니다.

src/ws/index.js

const Router = require('koa-router');

const redis = require('redis');

// 두개의 redis 클라이언트 생성
const subscriber = redis.createClient();

subscriber.subscribe('posts'); // posts 채널 구독

const ws = new Router();

ws.get('/ws', (ctx, next) => {
    // 구독자가 message 받을 때 마다 해당 소켓에 데이터 전달
    // 연결이 끊겼을 때 취소 할 수 있도록 따로 구분해줍니다
    const listener = (channel, message) => {
        // 메시지를 그대로 전달해줍니다
        ctx.websocket.send(message);
    };

    subscriber.on('message', listener);

    // 유저가 나갔을 때
    ctx.websocket.on('close', () => {
        subscriber.removeListener('message', listener);
    });
});

module.exports = ws;

구독자가 새 데이터를 받게되면 그 데이터를 그대로 유저에게 전달합니다. 그리고, 접속이 끊기게 되면 removeListener 르 통하여 이벤트 등록한것을 취소해주어야하는데요, 이 과정에서 만약에 상단코드에서 on('message', (channel, message) => {...}) 형식으로 익명함수로 만들어서 등록을 하면 취소를 할 수 없으니 따로 listener 라는 레퍼런스를 넣어서 담아주고, 접속종료시 이를 제거해주도록 하는 코드를 추가했습니다.

results matching ""

    No results matching ""