TogetherJS 소개

이 글은 Introducing TogetherJS에 대한 번역 및 편집본입니다.

TogetherJS란?

Mozilla Labs에서 공개한 실시간 협업 도구, TogetherJS를 소개합니다.

TogetherJS는 여러분이 현재 가지고 있는 웹사이트에 실시간 협업 도구를 더할 수 있도록 도와주는 서비스입니다. 여러분이 가진 웹사이트 혹은 웹어플리케이션에서 두 명 이상의 방문자끼리 서로의 마우스 커서의 위치나 클릭을 볼 수 있고 다른 방문자가 검색하고 있는 것을 트랙킹 할 수 있으며 함께 폼을 수정하거나 비디오를 볼 수도 있고 오디오 및 WebRTC를 통해 채팅도 가능합니다.
TogetherJS의 특징

  • 다른 사람의 마우스 커서와 클릭을 볼 수 있습니다.
  • 다른 사람의 스크롤이 위치한 곳을 볼 수 있습니다.
  • 다른 사람이 방문한 페이지를 볼 수 있습니다.
  • 다른 사람들과 문자 채팅이 가능합니다.
  • WebRTC를 이용한 음성 채팅이 가능합니다.
  • 여러 명이 동시에 폼 작성이 가능합니다(텍스트 필드, 체크박스 등).
  • 여러 명이 동시에 비디오 재생/일시정지/트랙이 가능합니다.
  • 해당 사이트에서 다중 페이지에 대한 세션이 지속됩니다.

설치 방법

TogetherJS의 기능 중 대다수가 여러분의 사이트에 어떠한 수정도 필요없이 설치할 수 있습니다. TogetherJS는 DOM을 제어하여 동작합니다. – 폼 필드를 감지하거나 CodeMirror 혹은 Ace 같은 에디터를 감지하거나 여러분의 페이지에 툴바를 설치하기도 합니다.

TogetherJS를 설치하려면 다음의 소스코드를 여러분의 페이지에 가져다 붙이기만 하면 됩니다.

<script src="https://togetherjs.com/togetherjs.js"></script>

그리고 사용자가 TogetherJS를 시작할 수 있도록 버튼을 만들어 주세요.

<button id="collaborate" type="button">Collaborate</button>
<script>
document.getElementById("collaborate")
  .addEventListener("click", TogetherJS, false);
</script>

TogetherJS가 동작하는 것을 보려면, jsFiddle에서 TogetherJS를 확인할 수 있습니다.

jsfiddle with Collaborate highlighted

Collaboration 버튼을 클릭하면 바로  TogetherJS가 시작합니다. 여러분도 앞으로 설명드릴 내용처럼 fiddles에 바로 TogetherJS를 사용해 보실 수 있습니다.

여러분의 어플리케이션에 적용하기

TogetherJS는 DOM을 감지하면서 여러가지 동작을 확인할 수 있지만 자바스크립트 어플리케이션과 동기화는 불가능합니다. 예를 들어, 자바스크립트를 통해 업데이트가 되는 어떤 리스트가 여러분의 페이지에 포함되어 있다면 해당 리스트는 양쪽의 사용자에게 동시에 동기화되지 않을 것입니다. 사람들은 이것들이 자동으로 업데이트가 되기를 바라겠지만 양쪽의 페이지에 DOM을 동기화하더라도 페이지 내부에서 동작하는 자바스크립트 객체들을 동기화할 수는 없습니다. Firebase 혹은 Google Drive Realtime API 같은 제품들과는 달리 TogetherJS는 여러분에게 실시간 지속성을 보장해주지는 않습니다. – 여러분의 사이트의 기능이나 지속성은 여러분의 몫이며 단지 브라우저 자체적인 세션만을 동기화 합니다.

그렇기 때문에 대규모의 자바스크립트 어플리케이션이라면 여러분은 세션을 동기적으로 세션을 유지하기 위한 코드를 추가로 작성해야 합니다. 하지만 사용하기 좀 더 쉽게 만들도록 노력하겠습니다!

예제를 제공하기 위해 간단한 그림 그리기 어플리케이션을 사용해보겠습니다. 여러분이 포크할 수 있고 직접 사용해 볼 수 있는 완성된 fiddle 예제 를 올려놓았습니다.

간단한 그림 그리기 어플리케이션

매우 간단한 그림 그리기 프로그램을 만들어 보겠습니다. 우선 단순한 canvas를 그려넣습니다.

<canvas id="sketch" 
        style="height: 400px; width: 400px; border: 1px solid #000">
</canvas>

그리고 몇가지 사항들을 설정합니다.

// get the canvas element and its context
var canvas = document.querySelector('#sketch');
var context = canvas.getContext('2d');

// brush settings
context.lineWidth = 2;
context.lineJoin = 'round';
context.lineCap = 'round';
context.strokeStyle = '#000';

우리는 mousemove 이벤트에 대한  move() 핸들러를 등록하기 위하여 canvas의 mousedown과 mouseup 이벤트를 사용할 것입니다.

var lastMouse = {
  x: 0,
  y: 0
};

// attach the mousedown, mousemove, mouseup event listeners.
canvas.addEventListener('mousedown', function (e) {
    lastMouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    canvas.addEventListener('mousemove', move, false);
}, false);

canvas.addEventListener('mouseup', function () {
    canvas.removeEventListener('mousemove', move, false);
}, false);

그리고 나서 move() 함수는 그림이 그려질 선을 확인할 것입니다.

function move(e) {
    var mouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    draw(lastMouse, mouse);
    lastMouse = mouse;
}

그리고 마지막으로 선을 그릴 함수입니다.

function draw(start, end) {
    context.beginPath();
    context.moveTo(start.x, start.y);
    context.lineTo(end.x, end.y);
    context.closePath();
    context.stroke();
}

매우 간단한 그림 그리기 어플리케이션을 위한 충분한 코드가 완성되었습니다. 이 부분에서 여러분이 TogetherJS를 사용하여 다른 사람의 움직임과 마우스 커서, 그리고 클릭을 볼 수는 있지만 그림은 볼 수 없습니다. 그 부분을 수정해봅시다!

TogetherJS 붙이기

TogetherJS는 ‘허브’라는 것을 갖는데 이 ‘허브’에서는 세션을 통해 모든 사람들 사이에서 메시지가 반복적으로 왕복합니다. 이것은 메시지를 해석하지는 않고 또 다른 페이지에 있을 사용자가 보낸 메시지를 포함한 모든 사람의 메시지는 그저 왕복할 뿐입니다. TogetherJS에서는 또한 어플리케이션이 스스로 메시지를 전송할 수 있습니다.

TogetherJS.send({
  type: "message-type", 
  ...any other attributes you want to send...
})

메시지를 보내고(모든 메시지는 타입을 가져야 합니다) 받기:

TogetherJS.hub.on("message-type", function (msg) {
  if (! msg.sameUrl) {
    // Usually you'll test for this to discard messages that came
    // from a user at a different page
    return;
  }
});

메시지 타입은 명칭 공간을 사용하여 여러분의 어플리케이션 메시지가 잘못하여 TogetherJs 자체 메시지와 겹치지 않도록 합니다.

그려지는 그림을 동기화하기 위해 우리는 모든 선을 보면서 다른 사람에게 전송합니다.

function move(e) {
    var mouse = {
        x: e.pageX - this.offsetLeft,
        y: e.pageY - this.offsetTop
    };
    draw(lastMouse, mouse);
    if (TogetherJS.running) {
        TogetherJS.send({type: "draw", start: lastMouse end: mouse});
    }
    lastMouse = mouse;
}

전송하기 전에 우리는 TogetherJS가 동작하고 있는지(TogetherJS.running)를 확인합니다. 우리가 보내는 메시지는 자명해야 합니다.

다음으로 메시지를 수신해야 합니다.

TogetherJS.hub.on("draw", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    draw(msg.start, msg.end);
});

우리는 이 리스너를 등록할 때 TogetherJs가 동작하고 있는지 걱정할 필요가 없습니다. 왜냐하면 TogetherJs가 동작하고 있을 때에만 리스너가 불려질 것입니다.

이것으로 실시간으로 여러명이 협업하여 그림을 그리기 충분한 프로그램이 되었습니다. 하지만 우리가 놓친 것이 한 가지 있습니다: 제가 그림을 그리기 시작하고 나서 여러분이 들어온다면 여러분은 제가 그리는 선들만 볼 수 있으며 이미 그려진 그림은 볼 수 없을 것입니다.

이 문제를 다루기 위해 우리는 togetherjs.hello 메시지를 수신하게 되는데 이 메시지는 각 클라이언트들이 새로운 페이지를 열었을 때 보내는 메시지입니다. 우리가 이 메시지를 보게 될 때 우리는 우리의 canvas에 이미 그려진 그림을 다른 사용자에게 보내게 될 것입니다.

TogetherJS.hub.on("togetherjs.hello", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    var image = canvas.toDataURL("image/png");
    TogetherJS.send({
        type: "init",
        image: image
    });
});

이제 우리는 새로운 init 메시지를 수신해야 합니다.

TogetherJS.hub.on("init", function (msg) {
    if (! msg.sameUrl) {
        return;
    }
    var image = new Image();
    image.src = msg.image;
    context.drawImage(image, 0, 0);
});

단 몇 줄의 TogetherJS 코드만으로 실시간 그림 그리기 어플리케이션을 만들어보았습니다. 물론 우리는 몇 가지 코드를 작성해야 했지만 여기에 TogetherJS가 자체적으로 제공하는 몇 가지가 있습니다.

Screenshot of invitation window

  • 사용자들에게 다른 사용자와 함께 세션을 공유하기 위한 URL을 제공합니다.
  • 우리의 hub server웹 소켓을 연결합니다. 이것은 클라이언트들간에 메시지를 왕복하는 역할을 합니다.

Screenshot of avatar/name setting

  • 사용자들은 사용자 이름과 아바타를 설정할 수 있고 현재 세션에 다른 누가 들어와 있는지 확인할 수 있습니다.
  • 현재 누가 들어와 있으며 나갔는지, 부재상태인지 확인할 수 있습니다.

Screenshot of chat window

  • 단순하지만 문자 채팅같은 필요한 기능들을 사용할 수 있습니다.
  • TogetherJS가 세션의 시작과 유지를 관리합니다.

이 예제에서 활용하지 않은 몇 가지

  • 우리는 고정된 크기의 canvas를 이용하였기 때문에 두 사용자마다 각각 다른 해상도를 고려할 필요가 없었습니다. 일반적으로 TogetherJS는 서로 다른 종류의 클라이언트를 제어하며  해상도에 의존적이지 않는 포지셔닝을 사용합니다.(심지어 반응형 디자인에서도 동작합니다.) 이에 대한 한가지 접근법으로 고정된 비율을 사용하는 것이 있으며 모든 그림의 위치에 높이/너비의 비율을 사용하는 것입니다.
  • 우리는 다른 어떤 그림 도구들을 사용하지 않았습니다. 아마도 여러분은 도구들마다 동기화시키는 일을 하고싶지 않을 것입니다. – 만약 제가 빨간 붓으로 그리는 동시에 여러분이 초록 붓으로 그리지 못할 이유는 없을 것입니다.
  • 하지만 canvas 초기화같은 것들은 동기화 되어야 합니다.
  • 우리는 저장혹은 불러오기 기능을 사용하지 않았습니다. 일단 그림 그리기 어플리케이션에서 저장과 불러오기 기능이 포함된다면, 동기화 측면에서 좀 더 고려해야 할 것입니다. 제가 그림 하나를 그려서 저장한 후 여러분의 세션에 들어가 불러오기를 한다면, 여러분의 이미지가 제 이미지를 덮어쓰게 될까요? 독립적인 URL이 각각 그림을 독립적으로 갖게 한다면 모두가 누구의 그림에 작업을 하려고 하는지 좀 더 분명해질 것입니다.

더 알고 싶나요?

  • TogetherJS의 설계가 궁금하신가요? technology overview를 읽어보세요;
  • jsFiddle에서 TogetherJs를 경험해보세요.
  • 문서에 있는 버튼을 눌러 저희를 찾으세요. 저희 중 누군가와 TogetherJS 세션에 대한 질문을 할 수 있는 “실시간 도움”을 받을 수 있습니다..
  • irc.moziila.org의 IRC 채널에서 #togetherjs를 찾으세요.
  •  GitHub에 있는 코드를 검색하고 난 후 버그나 요청 사항이 생기면 문제를 공유해주세요. 부끄러워하지 마세요! 저희는 많은 문제들에 대한 피드백을 정말 좋아합니다. – 아이디어, 잠재적 사용성(이러한 사용에 대해 문제가 될 수 있는 부분), 문서에서는 답을 찾을 수 없는 질문들(문서 내 오류도 포함됩니다) , 함께 사용하면 좋을 어플리케이션-
  • 트위터 팔로우 하기: @togetherjs.

어떤 사이트에 여러분은 TogetherJS를 설치하려고 하나요? 저희는 많은 답변들에 귀 기울이고 있습니다.

 

 

작성자: Hoony Chang

Web Programmer

Hoony Chang가 작성한 문서들…


댓글이 없습니다.

댓글 쓰기