From 20c24d1d3f630a63f540a77dbbc2a7ba1f110cac Mon Sep 17 00:00:00 2001 From: Chanmin Date: Wed, 22 May 2024 07:28:55 +0900 Subject: [PATCH] [Ko]: Fix incorrect translation in "Using_server-sent_events" doc. (#19123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(SSE): Fix incorrect korean translation * docs: Server-Sent Events 문서를 한글화한다 * chore: sourceCommit 업데이트 * docs: Server-sent events 의 진입 페이지를 최신화한다 * Update files/ko/web/api/server-sent_events/using_server-sent_events/index.md Co-authored-by: Jongha Kim * Update files/ko/web/api/server-sent_events/using_server-sent_events/index.md Co-authored-by: Jongha Kim --------- Co-authored-by: Jongha Kim --- files/ko/web/api/server-sent_events/index.md | 21 ++-- .../using_server-sent_events/index.md | 109 ++++++++++-------- 2 files changed, 76 insertions(+), 54 deletions(-) diff --git a/files/ko/web/api/server-sent_events/index.md b/files/ko/web/api/server-sent_events/index.md index b16500caf373d8..ae6361f3655bcb 100644 --- a/files/ko/web/api/server-sent_events/index.md +++ b/files/ko/web/api/server-sent_events/index.md @@ -1,15 +1,19 @@ --- title: Server-sent events slug: Web/API/Server-sent_events +l10n: + sourceCommit: e4c0939929e1b3e1fa3fd3da82b827fca3ed4c79 --- -{{DefaultAPISidebar("Server Sent Events")}} +{{DefaultAPISidebar("Server Sent Events")}} {{AvailableInWorkers}} 전통적으로 웹페이지는 새로운 데이터를 받기 위해 서버로 요청을 보내야만 합니다; 서버로 데이터를 요청하는 방식입니다. 하지만 Server-Sent Events 방식으로 웹페이지의 요청 없이도 언제든지 서버가 새로운 데이터를 보내는 것이 가능합니다. 이렇게 보내진 메시지는 웹페이지 안에서 *[Events](/ko/docs/DOM/event) + 데이터*로 다룰 수 있습니다. -## 기본 & 사용하기 +> **참고:** 현재 Firefox는 서비스 워커에서 server-sent events 의 사용을 지원하지 않습니다 (전용 및 공유 워커에서는 지원됩니다). [Firefox bug 1681218](https://bugzil.la/1681218)를 참고하세요. -Server-Sent Events를 배우려면 다음 글을 읽어보세요: [Server-Sent Events 사용하기](/ko/docs/Web/API/Server-sent_events/Using_server-sent_events). +## 개념 및 사용법 + +server-sent events의 사용법을 배우기 위해서는 [server-sent events 사용하기](/ko/docs/Web/API/Server-sent_events/Using_server-sent_events) 를 참고하세요. ## 인터페이스 @@ -28,6 +32,7 @@ Server-Sent Events를 배우려면 다음 글을 읽어보세요: [Server-Sent E ### 도구 +- [Mercure: SSE 기반의 실시간 통신 프로토콜 (발행-구독)](https://mercure.rocks) - [Node.js를 위한 EventSource 폴리필](https://github.com/EventSource/eventsource) - Remy Sharp의 [EventSource 폴리필](https://github.com/remy/polyfills/blob/master/EventSource.js) - Yaffle의 [EventSource 폴리필](https://github.com/Yaffle/EventSource) @@ -36,12 +41,10 @@ Server-Sent Events를 배우려면 다음 글을 읽어보세요: [Server-Sent E ### 관련 주제 -- [AJAX](/ko/docs/AJAX) -- [JavaScript](/ko/docs/JavaScript) -- [WebSockets](/ko/docs/WebSockets) +- [서버로부터 데이터 페칭하기](/ko/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data) +- [JavaScript](/ko/docs/Web/JavaScript) +- [WebSockets](/ko/docs/Web/API/WebSockets_API) ### 그 외 자료 -- SSE로 구현된 [Twitter 어플리케이션](http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/)과 [깃허브에 공개된 소스코드](https://github.com/mozilla/webowonder-demos/tree/master/demos/friends%20timeline). -- [HTML5와 Server-sent events](http://dsheiko.com/weblog/html5-and-server-sent-events) -- [Asp.net을 이용한 Server-Sent Events](http://rajudasa.blogspot.in/2012/05/html5-server-sent-events-using-aspnet.html) +- server-sent events와 함께 동작하는 [담벼락/피드 소셜 어플리케이션 제작](https://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/)에 대한 글과 [GitHub에 있는 코드](https://github.com/mozilla/webowonder-demos/tree/master/demos/friends%20timeline)입니다. diff --git a/files/ko/web/api/server-sent_events/using_server-sent_events/index.md b/files/ko/web/api/server-sent_events/using_server-sent_events/index.md index 6e5d43d9125525..40acbc3fc1e479 100644 --- a/files/ko/web/api/server-sent_events/using_server-sent_events/index.md +++ b/files/ko/web/api/server-sent_events/using_server-sent_events/index.md @@ -1,43 +1,53 @@ --- title: Server-Sent Events 사용하기 slug: Web/API/Server-sent_events/Using_server-sent_events +l10n: + sourceCommit: c669fa7426d621482ca4c2d980c476cc5f8b62df --- {{DefaultAPISidebar("Server Sent Events")}} -[Server-Sent Events](/ko/docs/Web/API/Server-sent_events)를 사용하는 웹 애플리케이션 개발은 매우 간단하다. 웹 애플리케이션으로 스트림 이벤트를 보내는 약간의 코드가 서버 상에 필요하지만, 웹 애플리케이션 측은 [웹 소켓](/ko/docs/Web/API/WebSockets_API)에서 이벤트를 다루는 방식과 거의 차이가 없다. +[server-sent events](/ko/docs/Web/API/Server-sent_events)를 사용하는 웹 애플리케이션을 개발하는 것은 간단합니다. 서버 측에서는 프론트엔드로 이벤트를 스트리밍하는 약간의 코드가 필요하지만, 클라이언트 측 코드는 들어오는 이벤트를 처리하는 부분에서 [웹소켓](/ko/docs/Web/API/WebSockets_API)과 거의 동일하게 작동합니다. 이는 단방향 연결이기 때문에 클라이언트에서 서버로 이벤트를 보낼 수는 없습니다. -## 서버에서 이벤트 받기 +## 서버로부터 이벤트 수신하기 -Server-Sent Event API는 [`EventSource`](/ko/docs/Server-sent_events/EventSource) 인터페이스에 포함돼 있다. 이벤트를 전달 받기 위해서 서버로 접속을 시작하려면 우선, 이벤트를 생성하는 서버측 스크립트를 URI로 지정하여 새로운 [`EventSource`](/ko/docs/Server-sent_events/EventSource) 객체를 생성한다. 예를 들어: +server-sent event API는 {{domxref("EventSource")}} 인터페이스에 포함돼 있습니다. + +## `EventSource` 인스턴스 생성하기 + +이벤트 수신을 시작하기 위해 서버와의 연결을 열기 위해서는 이벤트를 생성하는 스크립트의 URL을 사용하여 새 `EventSource` 객체를 만들면 됩니다. 다음은 예시 코드입니다. ```js -var evtSource = new EventSource("ssedemo.php"); +const evtSource = new EventSource("ssedemo.php"); ``` -이벤트를 생성하는 스크립트가 다른 도메인에 존재할 경우엔 URI와 옵션 딕셔너리를 모두 지정하여 새로운 [`EventSource`](/ko/docs/Server-sent_events/EventSource) 객체를 생성한다. 클라이언트 스크립트가 example.com에 있는 경우라면: +이벤트를 생성하는 스크립트가 다른 오리진에 호스팅되어 있다면, URL과 옵션 딕셔너리를 모두 사용하여 새로운 `EventSource` 객체를 만들어야 합니다. `example.com` 에 클라이언트 스크립트가 있는 경우를 예시로 들어 보겠습니다. ```js -var evtSource = new EventSource("//api.example.com/ssedemo.php", { +const evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true, }); ``` -이벤트 소스를 생성 했다면 `message` 이벤트에 대한 핸들러를 등록하여 서버로부터의 메시지 수신을 시작할 수 있다. +### `message` 이벤트 수신하기 + +서버애서 보낸 [`event`](#event) 필드가 없는 메시지는 `message` 이벤트로 수신됩니다. 메시지 이벤트를 수신하기 위해서는 {{domxref("EventSource.message_event", "message")}} 이벤트를 위한 핸들러를 추가해야 합니다. ```js evtSource.onmessage = function (e) { - var newElement = document.createElement("li"); - var eventList = document.getElementById("list"); + const newElement = document.createElement("li"); + const eventList = document.getElementById("list"); - newElement.innerHTML = "message: " + e.data; + newElement.textContent = "message: " + e.data; eventList.appendChild(newElement); }; ``` -위 코드는 입력 메시지(즉, `event` 필드를 갖고 있지 않은 서버로부터의 알림)를 수신하여 그 메시지의 텍스트를 document의 HTML에 있는 목록에 추가한다. +위 코드는 서버로부터 전송된 메시지 이벤트를 감지하고 메시지의 텍스트를 문서의 HTML에 있는 목록에 추가합니다. -또는 `addEventListener()`를 사용하여 이벤트를 기다릴 수도 있다. +### 사용자 지정 이벤트 수신하기 + +`event` 필드를 갖는 서버의 메시지들은 `event` 에 명시된 이름의 이벤트로 수신됩니다. 예를 들면 아래와 같습니다. ```js evtSource.addEventListener("ping", function (event) { @@ -48,30 +58,32 @@ evtSource.addEventListener("ping", function (event) { }); ``` -앞서 소개한 코드와 비슷하지만 `event` 필드에 "ping"이 설정된 메시지가 서버로부터 보내졌을 때만 자동으로 호출된다는 점이 다르다. +이 코드는 서버가 `event` 필드가 `ping` 으로 설정된 메시지를 보낼 때마다 호출되며, `data` 필드의 JSON을 파싱하여 그 정보를 출력합니다. -> **Warning:** When **not used over HTTP/2**, SSE suffers from a limitation to the maximum number of open connections, which can be especially painful when opening multiple tabs, as the limit is _per browser_ and is set to a very low number (6). The issue has been marked as "Won't fix" in [Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=275955) and [Firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=906896). This limit is per browser + domain, which means that you can open 6 SSE connections across all of the tabs to `www.example1.com` and another 6 SSE connections to `www.example2.com` (per [Stackoverflow](https://stackoverflow.com/a/5326159/1905229)). When using HTTP/2, the maximum number of simultaneous _HTTP streams_ is negotiated between the server and the client (defaults to 100). +> **주의:** **HTTP/2 를 사용하지 않을 때** SSE는 활성화된 연결의 최대 개수 제한으로 인한 한계를 겪을 수 있으며, 이 제한은 브라우저당 적용될 뿐만 아니라 매우 낮은 수(6)로 설정되어 있어 특히 여러 탭을 열 때 문제를 겪을 수 있습니다. 이 문제는 [Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=275955)과 [Firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=906896)에서 수정되지 않을 것으로 표시되었습니다. 이 제한은 브라우저와 도메인별로 적용되므로 `www.example1.com` 에 대해 모든 탭에서 6개의 SSE 연결을 열 수 있고, `www.example2.com` 에 대해서도 6개의 SSE 연결을 열 수 있습니다. (출처: [Stackoverflow](https://stackoverflow.com/a/5326159/1905229)). HTTP/2를 사용할 때는 동시에 열 수 있는 HTTP 스트림의 최대 개수가 서버와 클라이언트 간에 협상되며, 기본값은 100입니다. ## 서버에서의 이벤트 송신 -이벤트를 송신하는 서버 사이드의 스크립트는 MIME 타입 `text/event-stream`을 사용해 응답할 필요가 있다. 각 알림은 두 개의 줄 바꿈으로 끝나는 텍스트 블럭으로 전송된다. 이벤트 스트림의 형식에 관한 자세한 내용은 [Event stream format](#event_stream_format)을 참고한다. +이벤트를 보내는 서버 측 스크립트는 MIME 타입 `text/event-stream` 을 사용하여 응답해야 합니다. 각 알림은 두 개의 줄바꿈으로 끝나는 텍스트 블록으로 전송됩니다. 이벤트 스트림 형식에 대한 자세한 내용은 [이벤트 스트림 형식](#이벤트_스트림_형식)을 참조하세요. -다음은 우리가 사용하고 있는 PHP 코드 예다. +여기서 사용하고 있는 예제의 {{Glossary("PHP")}} 코드는 다음과 같습니다. ```php date_default_timezone_set("America/New_York"); -header("Content-Type: text/event-stream\n\n"); +header("X-Accel-Buffering: no"); +header("Content-Type: text/event-stream"); +header("Cache-Control: no-cache"); $counter = rand(1, 10); -while (1) { - // "ping" 이벤트를 초당 송신 +while (true) { + // 매 초 "ping" 이벤트를 전송합니다. echo "event: ping\n"; $curDate = date(DATE_ISO8601); echo 'data: {"time": "' . $curDate . '"}'; echo "\n\n"; - // 간단한 메시지를 랜덤 간격으로 송신 + // 무작위 주기로 간단한 메시지를 전송합니다. $counter--; @@ -80,19 +92,26 @@ while (1) { $counter = rand(1, 10); } - ob_end_flush(); + if (ob_get_contents()) { + ob_end_flush(); + } flush(); + + // 클라이언트가 연결을 중단한 경우(페이지를 닫은 경우) 루프를 중단합니다. + + if (connection_aborted()) break; + sleep(1); } ``` -위 코드는 이벤트 타입이 "ping"인 이벤트를 초당 생성한다. 각 이벤트 데이터는 이벤트가 생성된 시각의 ISO 8601 형식의 타입스탬프를 포함하는 JSON 객체다. 또, 랜덤한 간격으로 간단한 메시지(이벤트타입 없는)를 송신한다. -The loop will keep running independent of the connection status, so a check is included -to break the loop if the connection has been closed (e.g. client closes the page). +위의 코드는 매초 "ping" 이벤트 타입의 이벤트를 생성합니다. 각 이벤트의 데이터는 이벤트가 생성된 시점의 ISO 8601 타임스탬프를 포함하는 JSON 객체입니다. 무작위 주기로 이벤트 타입이 없는 간단한 메시지가 전송됩니다. 루프는 연결 상태와 상관없이 계속 실행되므로, 연결이 종료되었는지(예: 클라이언트가 페이지를 닫은 경우) 확인하여 루프를 중단하는 체크가 포함되어 있습니다. + +> **참고:** 이 글에 나온 코드를 사용하는 전체 예제는 GitHub에서 확인할 수 있습니다 — [PHP를 사용한 간단한 SSE 데모](https://github.com/mdn/dom-examples/tree/main/server-sent-events)를 참조하세요. ## 에러 핸들링 -문제가 발생한 경우(네크워크 타임아웃이나 [접근 제약](/ko/docs/HTTP/Access_control_CORS)과 관련한 문제)에는 오류 이벤트를 생성한다. `EventSource` 갹채에 `onerror` 콜백을 등록하면 에러를 프로그램으로 대처할 수 있다. +네트워크 타임아웃 또는 [접근 제어](/ko/docs/HTTP/Access_control_CORS)와 관련된 문제 등 문제가 발생할 때 에러 이벤트가 생성됩니다. `EventSource` 객체에 `onerror` 콜백을 구현하여 프로그래밍적으로 이를 처리할 수 있습니다. ```js evtSource.onerror = function (e) { @@ -102,7 +121,7 @@ evtSource.onerror = function (e) { ## 이벤트 스트림 닫기 -기본적으로는 클라이언트와 서버 사이의 연결이 닫히면 연결이 재시작된다. 연결은 `.close()` 메서드로 종료한다. +기본적으로 클라이언트와 서버 간의 연결이 닫히면 연결이 다시 시작됩니다. 연결은 `.close()` 메서드로 종료됩니다. ```js evtSource.close(); @@ -110,38 +129,38 @@ evtSource.close(); ## 이벤트 스트림 형식 -이벤트 스트림은 텍스트 데이터의 단순한 스트림으로 [UTF-8](/ko/docs/Glossary/UTF-8)을 사용하여 인코딩 해야만 한다. 이벤트 스트림 내부 메시지는 두 개의 줄바꿈 문자로 구분된다. 행 선두에 있는 콜론은 본질적으로 주석으로 나타내며 무시된다. +이벤트 스트림은 [UTF-8](/ko/docs/Glossary/UTF-8)을 사용하여 인코딩해야 하는 간단한 텍스트 데이터의 스트림입니다. 이벤트 스트림의 메시지는 두 개의 개행 문자로 구분됩니다. 줄의 첫 번째 문자가 콜론이면 사실상 주석으로 취급되어 무시됩니다. -> **참고:** **노트:** 주석 행은 연결이 타임아웃 되는 것을 방지하기 위해 사용할 수 있다. 서버는 연결을 유지하기 위해 정기적으로 주석을 송신할 수 있다. +> **참고:** 주석 라인은 연결이 시간 초과되는 것을 방지하기 위해 사용할 수 있습니다. 서버는 연결을 유지하기 위해 주기적으로 주석을 보낼 수 있습니다. -각 메시지는 필드를 나열한 하나 이상의 텍스트 행으로 구성된다. 각 필드는 "필드명, 그 다음 콜론, 이어서 필드의 값에 해당하는 텍스트 데이터"로 나타낸다. +각 메시지는 해당 메시지의 필드를 나열하는 하나 이상의 텍스트 라인으로 구성됩니다. 각 필드는 필드 이름, 콜론, 그 필드 값에 해당하는 텍스트 데이터로 표시됩니다. ### 필드 -다음과 같은 필드명이 사양에 정리돼 있다. +수신된 각 메시지는 다음과 같은 필드 중 하나를 포함하며, 각 필드는 한 줄에 하나씩 나열됩니다. - `event` - - : 이벤트 타입이다. 이 필드가 지정돼 있는 경우, 이벤트는 브라우저 내에서 이벤트명에 해당하는 이벤트 리스너로 전달된다. 웹 사이트의 소스 코드에서는 이름이 붙여진 이벤트를 받기 위해서 `addEventListener()`를 사용한다. 메시지에서 이벤트 명이 지정되 있지 않은 경우는 `onmessage` 핸들러가 호출된다. + - : 이벤트를 설명하는 이벤트 유형을 식별하는 문자열입니다. 이 값이 지정되어 있다면 브라우저는 지정된 이벤트 이름에 대한 리스너에게 이벤트를 발생시킵니다. 웹 사이트 소스 코드가 이름을 갖는 이벤트를 수신하기 위해서는 `addEventListener()` 를 사용해야 합니다. 메시지에 이벤트 이름이 지정되지 않은 경우 `onmessage` 핸들러가 호출됩니다. - `data` - - : 메시지의 데이터 필드다. `EventSource`가 `data:`로 시작된다. 복수의 연속된 행을 전달 받은 경우에는 [그것을 연결해](http://www.w3.org/TR/eventsource/#dispatchMessage) 각 항목의 사이에 개행 문자를 삽입한다. 이때, 마지막의 줄바꿈은 제외된다. + - : 메시지의 데이터 필드입니다. `EventSource` 가 `data:` 로 시작하는 연속된 여러 줄을 받게 되면 이를 연결하여 각 줄 사이에 개행 문자를 삽입합니다. 끝에 있는 개행 문자는 제거됩니다. - `id` - - : 메시지의 데이터 필드다. `EventSource`가 data:로 시작된다. 복수의 연속된 행을 전달 받은 경우에는 그것을 연결해 각 항목의 사이에 개행 문자를 삽입한다. 이때, 마지막의 줄바꿈은 제외된다. + - : [`EventSource`](/ko/docs/Web/API/EventSource) 객체의 마지막 이벤트 ID 값을 설정하는 이벤트 ID입니다. - `retry` - - : 이벤트 송신을 시도할 때에 사용하는 재연결 시간(reconnection time)이다. 이 값은 정수여야 하며 재연결 시간을 밀리초 단위로 지정한다. 정수가 아닌 값이 지정되면 이 필드는 무시된다. + - : 재연결 시간입니다. 서버와의 연결이 끊어지면 브라우저는 재연결을 시도하기 전에 지정된 시간을 기다립니다. 이 값은 밀리초 단위의 정수여야 합니다. 정수가 아닌 값이 지정된 경우 이 필드는 무시됩니다. -이 필드명 외의 다른 필드는 모두 무시된다. +이를 제외한 모든 필드 이름은 무시됩니다. -> **참고:** **노트:** 행에 콜론이 포함되지 않으면 행 전체가 필드명으로 인식되며 값은 빈문자열로 취급한다. +> **참고:** 콜론을 포함하지 않는 줄의 경우 전체 줄이 빈 값 문자열과 함께 필드 이름으로 처리됩니다. -### 예 +### 예시 #### 데이터만 있는 메시지 -아래 예에서는 세 개의 메시지가 송신되고 있다. 최초의 메시지는 콜론 문자로 시작되고 있다. 주석이다. 앞서 설명한 바와 같이 코멘트는 메시지가 정기적으로 송신되지 않을 가능성이 있을 경우 킵얼라이브 용으로 사용할 수 있다. +다음 예제에서는 세 개의 메시지가 전송됩니다. 첫 번째는 콜론 문자로 시작하기 때문에 주석으로 간주됩니다. 앞서 언급한 대로 이는 keep-alive 메커니즘으로 메시지가 정기적으로 전송되지 않을 수 있을 때 유용할 수 있습니다. -두 번째 메시지는 값이 "some text"인 data 필드를 갖고있다. 세 번째 메시지는 값이 "another message\nwith two lines"인 data 필드를 갖고 있다. 값에 줄 바꿈 문자가 있음을 주의하라. +두 번째 메시지에는 값이 "some text" 인 데이터 필드가 포함되어 있습니다. 세 번째 메시지에는 값이 "another message\nwith two lines" 인 데이터 필드가 포함되어 있습니다. 개행 특수 문자가 값에 포함되어 있음에 유의하세요. -``` +```bash : this is a test stream data: some text @@ -152,9 +171,9 @@ data: with two lines #### 이름이 있는 이벤트 -아래 예에서는 이름이 있는 이벤트를 몇개 송신하고 있다. 각각의 이벤트는 `event` 필드로 지정된 이벤트 명을 갖고 있고 또, 클라이언트에서 필요한 데이터를 포함하는 적절한 JSON 문자열을 값으로 갖는 `data` 필드도 있다. 물론 `data` 필드는 임의의 문자열 데이터를 가질 수 있다. 꼭 JSON 일 필요는 없다. +이 예제는 이름이 지정된 이벤트를 보냅니다. 각 이벤트는 `event` 필드에 명시된 이벤트 이름과 클라이언트가 이벤트에 대한 작업을 수행하기 위해 필요한 데이터를 포함한 적절한 JSON 문자열 값을 가진 `data` 필드를 가지고 있습니다. 물론 `data` 필드에는 JSON이 아니더라도 모든 문자열 데이터를 가질 수 있습니다. -``` +```bash event: userconnect data: {"username": "bobby", "time": "02:33:48"} @@ -168,11 +187,11 @@ event: usermessage data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."} ``` -#### 조합형 +#### 혼합형 -이름 없는 메시지 또는, 이름이 있는 이벤트만 사용해야 하는 경우는 없다. 그리고 이것을 하나의 이벤트 스트림 내에서 혼합해 표현할 수 있다. +이름이 없는 메시지나 타입이 있는 이벤트만 사용할 필요는 없습니다. 하나의 이벤트 스트림에서 이를 혼합하여 사용할 수 있습니다. -``` +```bash event: userconnect data: {"username": "bobby", "time": "02:33:48"}