Skip to content

Commit 863683c

Browse files
authored
Merge pull request #288 from KevinChun/kevin/RTP-7/contracts
Observable contract doc has been translated
2 parents 90b3fb7 + ec8ed77 commit 863683c

File tree

2 files changed

+91
-4
lines changed

2 files changed

+91
-4
lines changed

documentation/ko/contract.markdown

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
layout: documentation
3+
title: ReactiveX - The Observable Contract
4+
id: contract
5+
---
6+
7+
<h1>Observable 계약</h1>
8+
<p>
9+
소스 문서나 이 사이트에서 제공하는 문서들을 읽다 보면 "Observable 계약"이란 용어가 자주 사용되는 것을 알것이다. Observable 계약이란 Observable을 공식적으로 정의하려는 시도로써, 2010 마이크로소프트가
10+
만든 ReactiveX의 .Net 버전인 RX.NET을 설명하는 <a href="https://go.microsoft.com/fwlink/?LinkID=205219"><cite>Rx Design Guidelines</cite></a>에서 비롯되었다.
11+
</p><p>
12+
이 페이지에서는 Observable 계약에 대한 내용을 정리해서 설명하려고 한다.
13+
</p>
14+
<h2>알림</h2>
15+
<p>
16+
Observable은 아래에서 설명하는 <i>알림</i>들을 통해 옵저버와 커뮤니케이션 한다:
17+
</p>
18+
<dl>
19+
<dt>OnNext</dt>
20+
<dd>Observable이 <i>배출</i>하는 항목을 옵저버에게 전달한다</dd>
21+
<dt>OnCompleted</dt>
22+
<dd>Observable이 성공적으로 작업을 완료했고 더 이상 항목을 배출하지 않음을 알린다</dd>
23+
<dt>OnError</dt>
24+
<dd>특정 오류 조건 때문에 Observable이 종료됐고 더 이상 항목을 배출하지 않음을 알린다</dd>
25+
<dt>OnSubscribe (선택사항)</dt>
26+
<dd>Observable이 옵저버로부터 Request 알림을 받을 준비가 됐음을 알린다(아래의 <i>역압</i>을 참조하자)</dd>
27+
</dl>
28+
<p>
29+
옵저버는 아래의 알림들을 통해 Observable과 커뮤니케이션 한다:
30+
</p>
31+
<dl>
32+
<dt>Subscribe</dt>
33+
<dd>옵저버가 Observable로부터 알림을 받을 준비가 됐음을 말한다</dd>
34+
<dt>Unsubscribe</dt>
35+
<dd>옵저버가 더 이상 Observable로부터 알림을 받고 싶지 않다는 것을 말한다</dd>
36+
<dt>Request (선택사항)</dt>
37+
<dd>옵저버가 특정 수 만큼의 추가 OnNext 알림만 받고 싶다는 것을 말한다(아래의 <i>역압</i>을 참조하자)</dd>
38+
</dl>
39+
<h2>알림 원칙에 관한 계약</h2>
40+
<p>
41+
Observable은 0개 이상의 OnNext 알림을 만들고 각각의 알림은 배출된 하나의 항목을 나타내며 OnCompleted나 OnError 알림 중 하나를 배출한다. 단, OnCompleted와 OnError 알림 둘 다 만들지는 않는다.
42+
OnCompleted나 OnError 알림을 배출한 후에는 다른 알림을 배출하지 않는다.
43+
</p><p>
44+
Observable은 항목을 배출하지 않을 수 있고, OnCompleted나 OnError 알림을 전달했다 해도 종료되지 않을 수 있다. 이 말은 즉, Observable은 아무 알림도 배출하지 않거나, OnCompleted 또는 OnError 알림만 배출할 수 있으며, 또는 OnNext 알리만 배출할 수도 있다는 것을 말한다.
45+
</p><p>
46+
Observable은 반드시 (병렬이 아닌)순차적으로 옵저버에게 알림을 보낸다. 그리고 이 알림은 다른 스레드를 통해 전달 되기도 한다. 하지만, 공식적으로 알림 간에는 <i>전후</i> 관계가 존재한다.
47+
</p>
48+
<h2>Observable 종료</h2>
49+
<p>
50+
만약 Observable이 OnCompleted나 OnError 알림을 보내지 않는다면, (실제로는 항목을 배출하지 않고 있어도)옵저버는 Observable이 여전히 실행 중이라고 판단하고 (Unscribe나 Request 같은)알림을 보내기도 한다. Observable이 OnCompleted나 OnError 알림을 발행하면 Observable은 자원을 반환하거나 실행을 종료 시키고, 이때 옵저버는 더 이상 Observable과의 커뮤니케이션을 시도하면 안된다.
51+
</p><p>
52+
OnError 알림은 반드시 발생한 오류에 대한 정보를 포함하고 있어야 한다(다시 말해서, OnError는 <code>null</code> 값을 가지고 있으면 안된다).
53+
</p><p>
54+
Observable은 종료 전에 Observable을 구독 중인 모든 구독자에게 OnCompleted나 OnError 알림을 중 하나를 꼭 보내야 한다.
55+
</p>
56+
<h2>구독과 해지</h2>
57+
<p>
58+
Observable은 옵저버로부터 Subscribe 알림을 받는 순간, 즉시 옵저버에게 알림을 보낼 수 있다.
59+
</p><p>
60+
옵저버가 Observable에게 Unsubsribe 알림을 보내면, Observable은 더 이상 옵저버에게 알림을 보내지 않을 것이다. 하지만, 옵저버가 Unsubscribe 알림을 보낸 후라 해도 구독 해지는 보장되지 않을 수 있다.
61+
</p><p>
62+
Observable이 OnError나 OnCompleted를 옵저버에게 보내면 구독은 종료된다. 이 경우, 옵저버는 더 이상 구독을 해지하기 위해 Observable에게 Unsubscribe 알림을 보낼 필요가 없다.
63+
</p>
64+
<h2>다중 Observer</h2>
65+
<p>
66+
이미 첫 번째 옵저버에게 항목을 배출 중인 Observable을 두 번째 옵저버가 구독하려 했을 때, 이 후 부터의 동작은 전적으로 Observable이 결정하는데 이때 Observable이 선택할 수 있는 옵션은, 두 번째 옵저버가 구독을 시작하는 시점부터 발행 중인 항목을 동일하게 두 번재 옵저버에게도 배출하거나, 아예 처음부터 두 번째 옵저버에게 항목을 다시 배출하거나, 아니면 아예 다른 순서대로 항목들을 두 번째 옵저버에게 배출할 수 있다. 일반적으로 같은 Observable을 두 개의 옵저버가 구독하는 경우, 동일한 순서대로 옵저버가 항목들을 구독 받도록 보장 할 수는 없다.
67+
</p>
68+
<h2>역압</h2>
69+
<p>
70+
역압(Backpressure)은 선택사항으로 ReactiveX의 모든 구현체가 역압을 포함하는 것은 아니며, 역압을 포함한다 해도 그 구현체의 모든 Observable이나 연산자가 역압을 수행하는 것도 아니다.
71+
만약 Observable을 구독하는 옵저버가 <i>Request</i> 알림을 구현하고 <i>OnSubscribe</i> 알림을 이해한다는 것을 Observable가 인지한다면 이 Observable은 역압을 구현 <em>할 수</em> 있다.
72+
</p><p>
73+
만약 Observable이 역압을 구현하고 옵저버가 이를 사용할 경우, Observable은 옵저버가 구독을 시작했더라도 항목을 즉시 배출하지는 않고 대신, 옵저버에게 OnSubscribe 알림을 보낸다.
74+
</p><p>
75+
옵저버는 OnSubscribe 알림을 받은 이후부터 구독 중인 Observable에게 Request 알림을 보낸다. 이 알림은 특정 갯수 만큼의 항목을 요청하며, 이 요청을 전달 받은 Observable은 정확히 요청 받은 갯수 만큼의 항목만 옵저버에게 발행한다. 하지만, 그 외에도 Observable은 OnCompleted나 OnError 알림을 보낼 수 있으며 옵저버가 아무런 항목도 요청하지 않아도 이 알림을 발행 할 수 있다.
76+
</p><p>
77+
역압을 구현하지 않는 Observable은, 역압이 지원되지 않는다는 사실을 OnError 통해 전달함으로써 옵저버가 보내온 Request 알림에 응답해야 한다.
78+
</p><p>
79+
옵저버의 Request 알림은 누적된다. 예를 들어, 옵저버가 Observable에게 Request 알림을 각각 3개, 5개 그리고 10개, 총 세 번 보냈다면 Observable은 아마도 옵저버에게 총 18개의 항목을 배출할 것이다. 하지만, 이렇게 전달된 Request 알림에 대해서 언제 Observable이 요청된 만큼의 항목을 응답으로 배출할 지는 문제 되지 않는다.
80+
</p><p>
81+
만약 요청된 갯수 보다 많은 항목들이 Observable에 의해 배출될 경우, 초과한 항목들을 버릴 것인지 아니면 오버플로우(overflow)에 대한 다른 전략을 사용할지는 Observable에 달렸다.
82+
</p>
83+
<h2>참고</h2>
84+
<ul>
85+
<li><a href="https://go.microsoft.com/fwlink/?LinkID=205219"><cite>Rx Design Guidelines</cite></a></li>
86+
<li><a href="http://xgrommx.github.io/rx-book/content/guidelines/index.html"><cite>RxJS Design Guidelines</cite></a></li>
87+
</ul>

documentation/ko/implement-operator.markdown

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class myOperator<T> implements Operator<T> {
5151

5252
@Override
5353
public void onNext(T item) {
54-
/* 이 예제는 전달된 항목을 간단히 변환한 후 전달하는 코드를 구현하고 있다 */
54+
/* 이 예제는 전달된 항목을 간단히 변환한 후 전달하는 코드를 구현한다 */
5555
if(!s.isUnsubscribed()) {
5656
transformedItem = myOperatorTransformOperation(item);
5757
s.onNext(transformedItem);
@@ -67,15 +67,15 @@ public class myOperator<T> implements Operator<T> {
6767
* 구현할 연산자는 구독자에게 항목을 배출하기 전에(혹은 알림을 보내기 전에) 반드시 [구독자의 `isUnsubscribed( )` 상태](Observable#unsubscribing)를 체크해야 한다. 구독자가 없는데도 항목을 배출하기 위해 시간을 낭비할 필요가 없다.
6868

6969
* 구현할 연산자는 Observable 계약이 가진 핵심 원칙을 따라야 한다:
70-
* 연산자는 구독자의 [`onNext( )`](Observable#onnext-oncompleted-and-onerror) 메서드를 수도 없이 호출할 수도 있다. 그렇지만, 절대 중복된 호출이 있어서는 안된다.
71-
* 연산자는 구독자의 [`onCompleted( )`](Observable#onnext-oncompleted-and-onerror)[`onError( )`](Observable#onnext-oncompleted-and-onerror) 중 하나를 호출 할 수 있다. 하지만 둘 모두를 호출해서는 안되며 반드시 둘 중 하나를 한번만 호출해야 한다. 그리고 그 후에는 구독자의 [`onNext( )`](Observable#onnext-oncompleted-and-onerror)를 호출하지 않을 수도 있다.
70+
* 연산자는 구독자의 [`onNext( )`](Observable#onnext-oncompleted-and-onerror) 메서드를 수도 없이 많이 호출할 있다. 하지만, 절대 중복된 호출이 발생하면 안된다.
71+
* 연산자는 구독자의 [`onCompleted( )`](Observable#onnext-oncompleted-and-onerror)[`onError( )`](Observable#onnext-oncompleted-and-onerror) 중 하나를 호출한다. 하지만 둘 모두를 호출해서는 안되며 반드시 둘 중 하나만 한번 호출해야 한다. 그 후에는 구독자의 [`onNext( )`](Observable#onnext-oncompleted-and-onerror)를 호출하지 않을 것이다.
7272
* 만약 구현하는 연산자가 위의 두 원칙을 보장할 수 없다면, [`serialize( )`](Observable-Utility-Operators#serialize) 연산자 호출를 추가해서 올바르게 행동하도록 강제할 수 있다.
7373
* 구현하는 연산자 내에서 블럭킹(blocking) 방식을 사용하지 않는다.
7474
* 대부분의 상황에서는 새로운 연산자를 만들 때 완전히 새로운 것을 만들기 보다는 기존의 확장 가능한 연산자를 결합시켜 구현하는 것이 가장 좋은 방법이다. RxJava 역시도 표준 연산자들을 결합하여 새로운 연산자들을 만들었는데, 아래의 연산자들을 그 예로 들 수 있다:
7575
* [`first( )`](Filtering-Observables#wiki-first-and-takefirst) 연산자는 [`take(1)`](Filtering-Observables#wiki-take)`.`[`single( )`](Observable-Utility-Operators#wiki-single-and-singleordefault)를 활용해 만들어 졌다.
7676
* [`ignoreElements( )`](Filtering-Observables#wiki-ignoreelements) 연산자는 [`filter(alwaysFalse( ))`](Filtering-Observables#wiki-filter)를 사용해 만들어 졌다
7777
* [`reduce(a)`](Mathematical-and-Aggregate-Operators#wiki-reduce) 연산자는 is [`scan(a)`](Transforming-Observables#wiki-scan)`.`[`last( )`](Filtering-Observables#wiki-last)를 사용해 만들어 졌다
78-
* 만약 (예를 들어, predicates와 같이) 함수나 람다 식을 파라미터로 사용한다면, 이것이 오류를 발생시킬 수 있기 때문에 오류가 발생할 경우를 고려해서 코드를 구현해야 하고 오류가 발생하면 오류를 잡아서 `onError( )` 메서드를 호출해 구독자에게 오류가 발생했음을 알려야 한다.
78+
* 만약 (예를 들어, predicates와 같이) 함수나 람다 식을 파라미터로 사용한다면, 이것이 오류를 발생시킬 수 있기 때문에 오류가 발생할 경우를 대비해서 코드를 구현해야 하고 오류가 발생하면 try/catch 절로 오류를 잡아서 `onError( )` 메서드를 호출해 구독자에게 오류가 발생했음을 알려야 한다.
7979
* 일반적으로, 항목들을 배출하는 코드를 구현하기 위해 노력을 기울이기 보다는 그 전에 앞서 오류 조건을 먼저 파악하고 구독자에게 이를 알리는 것이 좋다.
8080
* ReactiveX의 일부 구현체에서는 구현한 연산자의 &ldquo;역압&rdquo; 전략에 대해 꼼꼼히 체크할 필요가 있다. (그 예로 D&aacute;vid Karnok의 <a href="http://akarnokd.blogspot.hu/2015/05/pitfalls-of-operator-implementations_14.html">Pitfalls of Operator Implementations (part 2)</a> 글을 참고하기 바란다.)
8181

0 commit comments

Comments
 (0)