Browse Source

Merge pull request #3240 from reactkr/translate-ko-release

Korean translation for docs
main
Paul O’Shannessy 10 years ago
parent
commit
86d5291203
  1. 1
      _config.yml
  2. 30
      docs/01-why-react.ko-KR.md
  3. 126
      docs/02-displaying-data.ko-KR.md
  4. 210
      docs/02.1-jsx-in-depth.ko-KR.md
  5. 56
      docs/02.2-jsx-spread.ko-KR.md
  6. 68
      docs/02.3-jsx-gotchas.ko-KR.md
  7. 86
      docs/03-interactivity-and-dynamic-uis.ko-KR.md
  8. 190
      docs/04-multiple-components.ko-KR.md
  9. 231
      docs/05-reusable-components.ko-KR.md
  10. 164
      docs/06-transferring-props.ko-KR.md
  11. 151
      docs/07-forms.ko-KR.md
  12. 147
      docs/08-working-with-the-browser.ko-KR.md
  13. 150
      docs/08.1-more-about-refs.ko-KR.md
  14. 44
      docs/09-tooling-integration.ko-KR.md
  15. 26
      docs/10-addons.ko-KR.md
  16. 185
      docs/10.1-animation.ko-KR.md
  17. 114
      docs/10.2-form-input-binding-sugar.ko-KR.md
  18. 62
      docs/10.3-class-name-manipulation.ko-KR.md
  19. 181
      docs/10.4-test-utils.ko-KR.md
  20. 23
      docs/10.5-clone-with-props.ko-KR.md
  21. 73
      docs/10.6-create-fragment.ko-KR.md
  22. 101
      docs/10.7-update.ko-KR.md
  23. 30
      docs/10.8-pure-render-mixin.ko-KR.md
  24. 72
      docs/10.9-perf.ko-KR.md
  25. 205
      docs/11-advanced-performance.ko-KR.md
  26. 9
      docs/complementary-tools.ko-KR.md
  27. 19
      docs/conferences.ko-KR.md
  28. 8
      docs/examples.ko-KR.md
  29. 7
      docs/flux-overview.ko-KR.md
  30. 1
      docs/flux-overview.md
  31. 7
      docs/flux-todo-list.ko-KR.md
  32. 1
      docs/flux-todo-list.md
  33. 116
      docs/getting-started.ko-KR.md
  34. 191
      docs/ref-01-top-level-api.ko-KR.md
  35. 134
      docs/ref-02-component-api.ko-KR.md
  36. 208
      docs/ref-03-component-specs.ko-KR.md
  37. 84
      docs/ref-04-tags-and-attributes.ko-KR.md
  38. 197
      docs/ref-05-events.ko-KR.md
  39. 17
      docs/ref-06-dom-differences.ko-KR.md
  40. 13
      docs/ref-07-special-non-dom-attributes.ko-KR.md
  41. 132
      docs/ref-08-reconciliation.ko-KR.md
  42. 193
      docs/ref-09-glossary.ko-KR.md
  43. 147
      docs/thinking-in-react.ko-KR.md
  44. 704
      docs/tutorial.ko-KR.md
  45. 147
      docs/videos.ko-KR.md

1
_config.yml

@ -29,6 +29,7 @@ markdown: redcarpet
redcarpet: redcarpet:
extensions: extensions:
- fenced_code_blocks - fenced_code_blocks
- footnotes
sass: sass:
style: :compressed style: :compressed
sass_dir: _css sass_dir: _css

30
docs/01-why-react.ko-KR.md

@ -0,0 +1,30 @@
---
id: why-react-ko-KR
title: 왜 React인가?
permalink: why-react-ko-KR.html
next: displaying-data-ko-KR.html
---
React는 페이스북과 인스타그램에서 사용자 인터페이스를 구성하기 위해 만들어진 라이브러리입니다. 많은 사람들은 React를 **[MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)** 에서의 **V** 로 생각하는 경향이 있습니다.
우리는 단 하나의 문제를 해결하기 위해 React를 만들었습니다: **지속해서 데이터가 변화하는 대규모 애플리케이션을 구축하기.** 이 문제를 해결하기 위해, React는 두가지 컨셉을 도입했습니다.
### 단순함
당신의 애플리케이션이 특정 시점에 어떻게 보여야 할지를 단순히 표현하는 것만으로, 데이터가 변할 때 React는 자동으로 모든 UI 업데이트를 관리해줍니다.
### 선언적 문법
데이터가 변할 때 React는 "새로 고침" 버튼을 누르듯이 작동하며, 데이터의 바뀐 부분만을 업데이트할 수 있습니다.
## 구성적인 컴포넌트를 만드세요
React는 재사용 가능한 컴포넌트들을 만드는 데에 도움이 됩니다. 사실, React를 사용하면 *단지* 컴포넌트를 만드는 일만 하게 됩니다. 컴포넌트들은 잘 캡슐화되어 되어 있기 때문에, 컴포넌트들은 코드의 재사용성을 높이고, 테스트를 쉽게 해 주며, 관심 분리의 원칙(separation of concerns)을 지키게 해 줍니다.
## 5분만 투자하세요
React는 많은 관습적인 사고에 도전하며, 첫눈에 볼 때는 이상한 아이디어들의 모음이라고 생각할 수도 있습니다. 이 가이드를 읽기 위해 [5분만 투자하세요](http://37signals.com/svn/posts/3124-give-it-five-minutes); 그 이상한 아이디어들은 페이스북과 인스타그램 안팎의 수천 개의 컴포넌트들을 만드는 데에 사용되었기 때문입니다.
## 더 알아보기
[이 블로그 포스트](http://facebook.github.io/react/blog/2013/06/05/why-react.html)에서 React를 만든 우리의 동기에 대해 알아볼 수 있습니다.

126
docs/02-displaying-data.ko-KR.md

@ -0,0 +1,126 @@
---
id: displaying-data-ko-KR
title: 데이터를 표시하기
permalink: displaying-data-ko-KR.html
prev: why-react-ko-KR.html
next: jsx-in-depth-ko-KR.html
---
UI를 가지고 할 수 있는 가장 기초적인 것은 데이터를 표시하는 것입니다. React는 데이터를 표시하고 데이터가 변할 때마다 인터페이스를 최신의 상태로 자동으로 유지하기 쉽게 해 줍니다.
## 시작하기
정말 간단한 예제를 보도록 하죠. 다음과 같은 코드의 `hello-react.html` 파일을 만듭시다.
```html
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
// ** 코드는 여기에 작성하면 됩니다! **
</script>
</body>
</html>
```
문서의 나머지에서, 코드가 위와 같은 HTML 템플릿에 들어갔다고 가정하고 JavaScript 코드에만 집중할 것입니다. 위의 주석 부분을 다음과 같은 JavaScript 코드로 바꿔 보세요:
```javascript
var HelloWorld = React.createClass({
render: function() {
return (
<p>
안녕, <input type="text" placeholder="이름을 여기에 작성하세요" />!
지금 시간은 {this.props.date.toTimeString()} 입니다.
</p>
);
}
});
setInterval(function() {
React.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
```
## 반응 적(Reactive) 업데이트
`hello-react.html` 파일을 웹 브라우저에서 열어 당신의 이름을 텍스트 필드에 써 보세요. React는 단지 시간을 표시하는 부분만을 바꿉니다 — 텍스트 필드 안에 입력한 것은 그대로 남아 있구요, 당신이 이 동작을 관리하는 그 어떤 코드도 쓰지 않았음에도 불구하고 말이죠. React는 그걸 올바른 방법으로 알아서 해줍니다.
우리가 이걸 할 수 있었던 건, React는 필요한 경우에만 DOM을 조작하기 때문입니다. **React는 빠른 React 내부의 DOM 모형을 이용하여 변경된 부분을 측정하고, 가장 효율적인 DOM 조작 방법을 계산해 줍니다.**
이 컴포넌트에 대한 입력은 `props` 라고 불립니다 — "properties" 를 줄인 것이죠. 그들은 JSX 문법에서는 어트리뷰트로서 전달됩니다. 당신은 `props` 를 컴포넌트 안에서 불변의(immutable) 엘리먼트로서 생각해야 하고, `this.props` 를 덮어씌우려고 해서는 안됩니다.
## 컴포넌트들은 함수와 같습니다
React 컴포넌트들은 매우 단순합니다. 당신은 그것들을 `props``state` (이것들은 나중에 언급할 것입니다) 를 받고 HTML을 렌더링하는 단순한 함수들로 생각해도 됩니다. 그것들은 너무 단순하기 때문에, 그것들의 작동을 이해하는 것 또한 쉽게 만듭니다.
> 주의:
>
> **한가지 제약이 있습니다**: React 컴포넌트들은 단 하나의 루트 노드(root node)만을 렌더할 수 있습니다. 만약 여러개의 노드들을 리턴하고 싶다면, 그것들은 단 하나의 루트 노드로 싸여져 있어야만 합니다.
## JSX 문법
우리는 컴포넌트를 사용하는 것이 "템플릿"과 "디스플레이 로직(display logic)"을 이용하는 것보다 관심을 분리(separate concerns)하는 데에 올바른 방법이라고 강하게 믿고 있습니다. 우리는 마크업과 그것을 만들어내는 코드는 친밀하게 함께 결합되어있다고 생각합니다. 또한, 디스플레이 로직은 종종 매우 복잡하고, 그것을 템플릿 언어를 이용해 표현하는 것은 점점 사용하기 어렵게 됩니다.
우리는 이 문제를 해결하는 최고의 해결책은, UI를 만드는 진짜 프로그래밍 언어의 표현력을 모두 사용할 수 있는 JavaScript 코드로부터 HTML과 컴포넌트 트리들을 생성하는 것임을 발견했습니다.
이것을 더 쉽게 하기 위해서, 우리는 매우 간단하고, **선택적인** HTML과 비슷한 문법을 추가하여 이 React 트리 노드들을 만들 수 있게 했습니다.
**JSX는 당신으로 하여금 HTML 문법을 이용해 JavaScript 객체를 만들게 해줍니다.** React를 이용해 순수한 JavaScript 문법으로 링크를 만드려고 한다면, 코드는 다음과 같습니다:
`React.createElement('a', {href: 'http://facebook.github.io/react/'}, '안녕하세요!')`
JSX를 이용하면:
`<a href="http://facebook.github.io/react/">안녕하세요!</a>`
우리는 이것이 React 앱들을 만들기 쉽게 하고, 디자이너들이 이 문법을 더 선호하는 것을 발견했습니다, 하지만 모든 사람은 그들만의 선호하는 워크플로우가 있기 마련이므로, **JSX는 React를 사용하기 위해 필수적이지는 않습니다.**
JSX는 매우 작은 언어입니다. 그것을 배우고 싶다면, [JSX 깊게 살펴보기](/react/docs/jsx-in-depth-ko-KR.html). 를 살펴 보시기 바랍니다. 또는, [우리의 온라인 JSX 컴파일러](/react/jsx-compiler.html)를 통해 문법이 변환되는 것을 살펴 보시기 바랍니다.
JSX는 HTML과 비슷하지만, 완전히 똑같지는 않습니다. [JSX의 실수하기 쉬운 부분들](/react/docs/jsx-gotchas-ko-KR.html)에 중요한 차이점들에 대해 설명되어 있습니다.
JSX를 사용하기 시작하기 위한 가장 쉬운 방법은 브라우저에서 작동하는 `JSXTransformer`를 사용하는 것입니다. 우리는 이것을 프로덕션에서는 사용하지 않기를 강하게 권장하는 바입니다. 당신은 우리의 커맨드 라인 [react-tools](http://npmjs.org/package/react-tools) 패키지를 이용하여 미리 컴파일(precompile)해 사용할 수 있습니다.
## JSX 없이 React 사용하기
JSX는 완전히 선택적입니다. 당신은 React와 JSX를 함께 사용하지 않아도 상관없습니다. 그냥 JavaScript에서 React 엘리먼트를 `React.createElement`로 만들 수 있습니다. 여기에 태그 이름이나 컴포넌트, 속성 객체, 자식 엘리먼트들을 전달하면 됩니다.
```javascript
var child1 = React.createElement('li', null, 'First Text Content');
var child2 = React.createElement('li', null, 'Second Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
React.render(root, document.body);
```
편의를 위하여, 당신은 팩토리 함수 헬퍼들을 이용해 커스텀 컴포넌트로부터 엘리먼트들을 만들 수 있습니다.
```javascript
var Factory = React.createFactory(ComponentClass);
...
var root = Factory({ custom: 'prop' });
React.render(root, document.body);
```
React는 이미 일반적인 HTML 태그에 대한 빌트인 팩토리를 가지고 있습니다.
```javascript
var root = React.DOM.ul({ className: 'my-list' },
React.DOM.li(null, '텍스트')
);
```

210
docs/02.1-jsx-in-depth.ko-KR.md

@ -0,0 +1,210 @@
---
id: jsx-in-depth-ko-KR
title: JSX 깊이보기
permalink: jsx-in-depth-ko-KR.html
prev: displaying-data-ko-KR.html
next: jsx-spread-ko-KR.html
---
[JSX](http://facebook.github.io/jsx/)는 XML과 비슷한 JavaScript문법 확장입니다. React에서 변환되는 간단한 JSX 구문을 사용하실 수 있습니다.
## 왜 JSX인가?
React를 위해 꼭 JSX를 사용할 필요는 없고, 그냥 일반 JS를 사용할 수도 있습니만 JSX를 사용하기를 추천합니다. 왜냐하면, 어트리뷰트를 가진 트리 구조로 정의할 수 있는 간결하고 익숙한 문법이기 때문입니다.
이것은 디자이너 같은 케쥬얼 개발자에게 더 익숙합니다.
XML에는 여닫는 태그의 장점이 있습니다. 태그는 큰 트리일 때 함수 호출이나 객체 리터럴보다 읽기 쉬워 집니다.
JSX는 JavaScript의 시맨틱을 변경하지 않습니다.
## HTML 태그 vs. React 컴포넌트
React는 렌더 HTML 태그(문자열)이나 React 컴포넌트(클래스)일 수 있습니다.
HTML 태그를 렌더하려면, 그냥 JSX에 소문자 태그를 사용하세요.
```javascript
var myDivElement = <div className="foo" />;
React.render(myDivElement, document.body);
```
React 컴포넌트를 렌더하려면, 대문자로 시작하는 로컬 변수를 만드세요.
```javascript
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.body);
```
React JSX는 대소문자를 로컬 컴포넌트 클래스와 HTML 태그를 구별하는 컨벤션으로 사용합니다.
> 주의:
>
> JSX가 JavaScript기 때문에, `class`, `for`같은 식별자는 XML 어트리뷰트 이름으로
> 권장하지 않습니다. 대신, React DOM 컴포넌트는 각각 `className`, `htmlFor`같은
> DOM 프로퍼티 이름을 기대합니다.
<a name="the-transform"></a>
## 변환
React JSX는 XML같은 문법에서 네이티브 JavaScript로 변환됩니다. XML 엘리먼트, 어트리뷰트, 자식은 `React.createElement`에 넘겨지는 인자로 변환됩니다.
```javascript
var Nav;
// 입력 (JSX):
var app = <Nav color="blue" />;
// 출력 (JS):
var app = React.createElement(Nav, {color:"blue"});
```
`<Nav />`를 사용하려면, `Nav`변수는 스코프에 있어야 합니다.
JSX에서는 XML 구문으로 자식을 지정할 수도 있습니다.
```javascript
var Nav, Profile;
// 입력 (JSX):
var app = <Nav color="blue"><Profile>click</Profile></Nav>;
// 출력 (JS):
var app = React.createElement(
Nav,
{color:"blue"},
React.createElement(Profile, null, "click")
);
```
클래스에 [displayName](/react/docs/component-specs-ko-KR.html#displayName)이 정의되어 있지 않으면 JSX는 변수명을 displayName으로 간주할 것입니다:
```javascript
// 입력 (JSX):
var Nav = React.createClass({ });
// 출력 (JS):
var Nav = React.createClass({displayName: "Nav", });
```
[JSX 컴파일러](/react/jsx-compiler.html)를 보면 JSX에서 어떻게 네이티브 JavaScript로 변환(desugars)하는지 볼 수 있고, [HTML-JSX 변환기](/react/html-jsx.html)는 이미 있는 HTML을 JSX로 변환해 줍니다.
JSX를 사용 하시려면, [시작하기](/react/docs/getting-started-ko-KR.html) 가이드에서 어떻게 컴파일을 하기 위해 설정하는지 보실 수 있습니다.
> 주의:
>
> JSX 표현식은 언제나 ReactElement로 평가됩니다. 실제 구현의 세부사항은 많이
> 다를 수 있습니다. 최적화 모드는ReactElement를 `React.createElement`에서 검증
> 코드를 우회하는 객체 리터럴로 ReactElement를 인라인으로 만들 수 있습니다.
## 네임스페이스를 사용한 컴포넌트
폼같은 자식을 많이 가지는 컴포넌트를 만든다면, 많은 변수 선언을 하게 될 것입니다.
```javascript
// 변수 선언의 어색한 블록
var Form = MyFormComponent;
var FormRow = Form.Row;
var FormLabel = Form.Label;
var FormInput = Form.Input;
var App = (
<Form>
<FormRow>
<FormLabel />
<FormInput />
</FormRow>
</Form>
);
```
더 간단하고 쉽게 *네임스페이스를 사용한 컴포넌트*를 사용해서, 다른 컴포넌트를 어트리뷰트로 가지는 하나의 컴포넌트만 쓸 수 있습니다.
```javascript
var Form = MyFormComponent;
var App = (
<Form>
<Form.Row>
<Form.Label />
<Form.Input />
</Form.Row>
</Form>
);
```
이렇게 하려면, *"sub-components"*를 메인 컴포넌트의 어트리뷰트로 만들 필요가 있습니다.
```javascript
var MyFormComponent = React.createClass({ ... });
MyFormComponent.Row = React.createClass({ ... });
MyFormComponent.Label = React.createClass({ ... });
MyFormComponent.Input = React.createClass({ ... });
```
코드를 컴파일할 때 JSX는 이것을 제대로 처리해 줍니다.
```javascript
var App = (
React.createElement(Form, null,
React.createElement(Form.Row, null,
React.createElement(Form.Label, null),
React.createElement(Form.Input, null)
)
)
);
```
> 주의:
>
> 이 기능은 [v0.11](http://facebook.github.io/react/blog/2014/07/17/react-v0.11.html#jsx) 이상에만 있습니다.
## JavaScript 표현식
### 어트리뷰트 표현식
JavaScript 표현식을 어트리뷰트 값으로 사용하려면, 표현식을 쌍따옴표(`""`)대신 중괄호(`{}`)로 감싸야 합니다.
```javascript
// 입력 (JSX):
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
// 출력 (JS):
var person = React.createElement(
Person,
{name: window.isLoggedIn ? window.name : ''}
);
```
### 자식 표현식
비슷하게, JavaScript 표현식을 자식을 표현하는 데 사용할 수 있습니다.
```javascript
// 입력 (JSX):
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
// 출력 (JS):
var content = React.createElement(
Container,
null,
window.isLoggedIn ? React.createElement(Nav) : React.createElement(Login)
);
```
### 주석
JSX에 주석을 넣기는 쉽습니다. 그냥 JS 표현식과 같습니다. 그냥 태그의 자식 섹션에서만 조심하시면 됩니다. 이럴 땐 주석 주변에 `{}`를 감싸야 합니다.
```javascript
var content = (
<Nav>
{/* 자식 주석, {}로 감싼다 */}
<Person
/* 여러
주석 */
name={window.isLoggedIn ? window.name : ''} // 줄 끝부분 주석
/>
</Nav>
);
```
> 주의:
>
> JSX 는 HTML과 비슷하지만 완전히 같지는 않습니다. 중요한 차이점을 보시려면 [JSX gotchas](/react/docs/jsx-gotchas-ko-KR.html)를 보세요.

56
docs/02.2-jsx-spread.ko-KR.md

@ -0,0 +1,56 @@
---
id: jsx-spread-ko-KR
title: JSX 스프레드 어트리뷰트
permalink: jsx-spread-ko-KR.html
prev: jsx-in-depth-ko-KR.html
next: jsx-gotchas-ko-KR.html
---
미리 컴포넌트에 넣을 모든 프로퍼티를 알게 된다면, JSX를 사용하기 쉬워집니다.
```javascript
var component = <Component foo={x} bar={y} />;
```
## Props의 변경은 나빠요.[^1]
하지만 어떤 프로퍼티를 설정하고 싶은지 모른다면, 객체 레이어에 넣고 싶어질 수도 있습니다.
```javascript
var component = <Component />;
component.props.foo = x; // 나쁨
component.props.bar = y; // 역시 나쁨
```
이것은 안티 패턴입니다. 왜냐하면 한참 뒤까지 정확한 propTypes을 체크할 수 없다는 뜻이기 때문입니다. 이것은 propTypes 에러는 알기 힘든 스택 트레이스로 끝난다는 의미입니다.
이 시점에서 props는 불변성인 것을 고려해야 합니다. props 객체를 변경하는 것은 다른 곳에서 예기치 못한 결과가 생길 수 있기 때문에 이상적으로는 이 시점에서 frozen 객체가 되어야 합니다.
## 스프레드 어트리뷰트
이제 JSX의 새로운 기능인 스프레드 어트리뷰트를 사용하실 수 있습니다.
```javascript
var props = {};
props.foo = x;
props.bar = y;
var component = <Component {...props} />;
```
전달한 객체의 프로퍼티가 컴포넌트의 props에 복사됩니다.
이렇게 여러 번 사용하거나 다른 어트리뷰트와 조합해서 사용할 수 있습니다. 명세의 순서는 중요합니다. 나중의 어트리뷰트가 이전 것보다 우선되기 때문입니다.
```javascript
var props = { foo: 'default' };
var component = <Component {...props} foo={'override'} />;
console.log(component.props.foo); // 'override'
```
## 이상한 `...` 표기법은 무엇인가요?
`...` 연산자(스프레드 연산자)는 이미 [ES6의 배열](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)에서 지원합니다. [객체 rest와 스프레드 프로퍼티](https://github.com/sebmarkbage/ecmascript-rest-spread)에 대한 ES7의 제안도 있습니다. JSX의 구문을 더 깔끔하게 하기 위해 지원되고 개발중인 표준을 활용하고 있습니다.
[^1]: 아무래도 좋지만, 이 제목의 원문 "Mutating Props is Bad, mkay"는 사우스 파크에
나온 대사 "[Drug is bad, mkay](https://www.youtube.com/watch?v=Uh7l8dx-h8M)"의
패러디입니다.

68
docs/02.3-jsx-gotchas.ko-KR.md

@ -0,0 +1,68 @@
---
id: jsx-gotchas-ko-KR
title: JSX Gotchas
permalink: jsx-gotchas-ko-KR.html
prev: jsx-spread-ko-KR.html
next: interactivity-and-dynamic-uis-ko-KR.html
---
JSX는 HTML처럼 보이지만, 작업하다 보면 마주치게 될 몇 가지 중요한 차이점이 있습니다.
> 주의:
>
> 인라인 `style` 어트리뷰트 같은 DOM과의 차이점은 [여기](/react/docs/dom-differences-ko-KR.html)를 보세요.
## HTML 엔티티
JSX의 리터럴 텍스트에 HTML 엔티티를 넣을 수 있습니다.
```javascript
<div>First &middot; Second</div>
```
동적 콘텐츠 안에 HTML 엔티티를 표시하려 할 때, React에서는 XSS 공격을 광범위하게 막기 위해서 기본적으로 모든 표시하는 문자열을 이스케이프 하기 때문에 더블 이스케이프 문제에 부딪히게 됩니다.
```javascript
// 나쁨: "First &middot; Second"를 표시
<div>{'First &middot; Second'}</div>
```
이 이슈를 피해 갈 방법은 여럿 있지만, 가장 쉬운 방법은 유니코드 문자를 JavaScript에 직접 쓰는 것입니다. 브라우저가 올바르게 표시하도록 파일이 UTF-8으로 저장되어 있고 올바른 UTF-8 지시자를 사용하고 있는지 확인해야 합니다.
```javascript
<div>{'First · Second'}</div>
```
더 안전한 대안으로 [엔티티에 대응하는 유니코드 숫자](http://www.fileformat.info/info/unicode/char/b7/index.htm)를 찾아 JavaScript 문자열 안에서 사용하는 방법도 있습니다.
```javascript
<div>{'First \u00b7 Second'}</div>
<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>
```
문자열과 JSX 엘리먼트를 혼합한 배열을 사용할 수도 있습니다.
```javascript
<div>{['First ', <span>&middot;</span>, ' Second']}</div>
```
최후의 수단으로, 항상 [생 HTML을 삽입](/react/docs/dom-differences-ko-KR.html)할 수 있습니다.
```javascript
<div dangerouslySetInnerHTML={{'{{'}}__html: 'First &middot; Second'}} />
```
## 커스텀 HTML 어트리뷰트
프로퍼티를 HTML 사양에는 없는 네이티브 HTML 엘리먼트에 넘기면, React는 그 프로퍼티를 렌더하지 않습니다. 커스텀 어트리뷰트를 사용하고 싶다면, 접두사로 `data-`를 붙이셔야 합니다.
```javascript
<div data-custom-attribute="foo" />
```
`aria-`로 시작하는 [Web 접근성](http://www.w3.org/WAI/intro/aria) 어트리뷰트는 제대로 렌더될 것입니다.
```javascript
<div aria-hidden={true} />
```

86
docs/03-interactivity-and-dynamic-uis.ko-KR.md

@ -0,0 +1,86 @@
---
id: interactivity-and-dynamic-uis-ko-KR
title: 상호 작용 및 동적 UI
permalink: interactivity-and-dynamic-uis-ko-KR.html
prev: jsx-gotchas-ko-KR.html
next: multiple-components-ko-KR.html
---
이미 React에서 [어떻게 데이터를 표시](/react/docs/displaying-data-ko-KR.html)하는지를 배웠습니다. 이제 UI와의 상호작용을 어떻게 만드는지 살펴보죠.
## 간단한 예제
```javascript
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
React.render(
<LikeButton />,
document.getElementById('example')
);
```
## 이벤트 핸들링과 통합적인(Synthetic) 이벤트
React에서의 이벤트 핸들러는 HTML에서 그러던 것처럼 간단히 카멜케이스 프로퍼티(camelCased prop)로 넘기면 됩니다. React의 모든 이벤트는 통합적인 이벤트 시스템의 구현으로 IE8 이상에서는 같은 행동이 보장됩니다. 즉, React는 사양에 따라 어떻게 이벤트를 일으키고(bubble) 잡는지 알고 있고, 당신이 사용하는 브라우저와 관계없이 이벤트 핸들러에 전달되는 이벤트는 [W3C 사양](http://www.w3.org/TR/DOM-Level-3-Events/)과 같도록 보장됩니다.
React를 폰이나 테블릿같은 터치 디바이스에서 사용하려 한다면, 간단히 `React.initializeTouchEvents(true);`로 터치 이벤트 핸들링을 켜면 됩니다.
## 기본 구현: 오토바인딩과 이벤트 델리게이션
코드를 고성능으로 유지하고 이해하기 쉽게 하기 위해, React는 보이지 않는 곳에서 몇 가지 일을 수행합니다.
**오토바인딩:** JavaScript에서 콜백을 만들 때, 보통은 `this`의 값이 정확하도록 명시적으로 메소드를 인스턴스에 바인드해야 합니다. React에서는 모든 메소드가 자동으로 React의 컴포넌트 인스턴스에 바인드됩니다. React가 바인드 메소드를 캐시하기 때문에 매우 CPU와 메모리에 효율적입니다. 타이핑해야 할 것도 줄어들죠!
**이벤트 델리게이션:** React는 실제로는 노드자신에게 이벤트 핸들러를 붙이지 않습니다. React가 시작되면 React는 탑 레벨의 단일 이벤트 리스너로 모든 이벤트를 리스닝하기 시작합니다. 컴포넌트가 마운트되거나 언마운트 될 때, 이벤트 핸들러는 그냥 내부 매핑에서 넣거나 뺄 뿐입니다. 이벤트가 발생하면, React는 이 매핑을 사용해서 어떻게 디스패치할 지를 알게 됩니다. 매핑에 이벤트 핸들러가 남아있지 않으면, React의 이벤트 핸들러는 그냥 아무것도 하지 않습니다. 왜 이 방식이 빠른지 더 알고 싶으시면, [David Walsh의 멋진 블로그 글](http://davidwalsh.name/event-delegate)을 읽어 보세요.
## 컴포넌트는 그냥 state 머신일 뿐
React는 UI를 간단한 state 머신이라 생각합니다. UI를 다양한 state와 그 state의 렌더링으로 생각함으로써 UI를 일관성 있게 관리하기 쉬워집니다.
React에서는, 간단히 컴포넌트의 state를 업데이트하고, 이 새로운 state의 UI를 렌더링합니다. React는 DOM의 변경을 가장 효율적인 방법으로 관리해줍니다.
## state의 동작 원리
React에게 데이터의 변경을 알리는 일반적인 방법은 `setState(data, callback)`을 호출하는 것입니다. 이 메소드는 `this.state``data`를 머지하고 컴포넌트를 다시 렌더링 합니다. 컴포넌트의 재-렌더링이 끝나면, 생략가능한 `callback`이 호출됩니다. 대부분의 경우 React가 UI를 최신상태로 유지해주기 때문에 `callback`을 사용할 필요가 없습니다.
## 어떤 컴포넌트가 state를 가져야 할까요?
대부분의 컴포넌트는 `props`로부터 데이터를 받아 렌더할 뿐입니다만, 가끔 유저 인풋, 서버 요청, 시간의 경과에 반응해야 할 필요가 있습니다. 이럴 때 state를 사용합니다.
**가능한 한 컴포넌트가 상태를 가지지 않도록(stateless) 하세요.** 이렇게 함으로써 가장 논리적인 장소로 state를 격리하게 되고 쉽게 애플리케이션을 추론할 수 있도록 중복을 최소화할 수 있습니다.
일반적인 패턴은 데이터만 렌더하는 여러 상태를 가지지 않은 컴포넌트를 만들고, 그 위에 상태기반(stateful) 컴포넌트를 만들어 계층 안의 자식 컴포넌트에게 `props`를 통해 state를 전달하는 것입니다. state를 가지지 않은 컴포넌트가 선언적인 방법으로 데이터를 렌더링 하는 동안, 상태기반 컴포넌트는 모든 상호작용 로직을 캡슐화합니다.
## state를 어떻게 *써야* 할까요?
**state는 컴포넌트의 이벤트 핸들러에 의해 UI 업데이트를 트리거할때 변경될 가능성이 있어, 그때 사용할 데이터를 가져야 합니다.** 실제 앱에서는 이 데이터는 매우 작고 JSON 직렬화 가능한 경향이 있습니다. 상태기반 컴포넌트를 만들때, 가능한 작게 state를 서술하고 `this.state`에만 저장하도록 해보세요. 그냥 `render()` 안에서 이 state를 기반으로 다른 모든 정보를 계산합니다. 이 방식으로 애플리케이션을 작성하고 생각하면 가장 최적의 애플리케이션으로 발전해가는 경향이 있다는 것을 발견하게 될 것입니다. 꼭 필요하지 않은 값이나 계산된 값을 state에 추가하는 것은 render가 그것을 계산하는 대신에 명시적으로 그것들을 맞춰줘야 하는 것을 의미하기 때문이죠.
## state를 어떻게 *쓰지 말아야* 할까요?
`this.state`는 UI의 state를 표현할 최소한의 데이터만을 가져야 합니다. 그래서 이런 것들을 가지지 않게끔 해야 합니다.
* **계산된 데이터:** state에 따라 값을 미리 계산하는 것에 대해 염려하지 마세요. 계산은 모두 `render()`에서 하는 것이 UI의 일관성을 유지하기 쉽습니다. 예를 들어, state에서 list items 배열을 가지고 있고 문자열으로 카운트를 렌더링 할 경우, state에 저장하기보다는 그냥 `render()` 메소드안에서 `this.state.listItems.length + ' list items'`를 렌더하세요.
* **React 컴포넌트:** 가지고 있는 props와 state로 `render()`안에서 만드세요.
* **props에서 복사한 데이터:** 가능한 한 원래의 소스로 props를 사용하도록 해보세요. props를 state에 저장하는 단 하나의 올바른 사용법은 이전 값을 알고 싶을 때입니다. props는 시간이 지나면 변경될 수도 있기 때문이죠.

190
docs/04-multiple-components.ko-KR.md

@ -0,0 +1,190 @@
---
id: multiple-components-ko-KR
title: 복합 컴포넌트
permalink: multiple-components-ko-KR.html
prev: interactivity-and-dynamic-uis-ko-KR.html
next: reusable-components-ko-KR.html
---
지금까지, 단일 컴포넌트에서 데이터를 표시하고 유저 입력을 다루는 것을 살펴보았습니다. 다음엔 React의 최고의 기능 중 하나인 조합가능성(composability)을 살펴봅시다.
## 동기: 관심의 분리
명확히 정의된 인터페이스와 다른 컴포넌트를 재사용해 모듈러 컴포넌트를 구축하면, 함수와 클래스를 이용했을 때 얻을 수 있는 이점 대부분을 얻을 수 있습니다. 특히 앱에서 *다른 관심을 분리*할 수 있습니다.아무리 간단히 새 컴포넌트를 만들었다고 해도 말이죠. 당신의 애플리케이션에서 쓸 커스텀 컴포넌트 라이브러리를 만들어서, 당신의 도메인에 최적화된 방법으로 UI를 표현할 수 있게 됩니다.
## 조합(Composition) 예제
간단히 페이스북 그래프 API를 사용해 프로필 사진과 유저이름을 보여주는 아바타 컴포넌트를 만든다고 합시다.
```javascript
var Avatar = React.createClass({
render: function() {
return (
<div>
<ProfilePic username={this.props.username} />
<ProfileLink username={this.props.username} />
</div>
);
}
});
var ProfilePic = React.createClass({
render: function() {
return (
<img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />
);
}
});
var ProfileLink = React.createClass({
render: function() {
return (
<a href={'http://www.facebook.com/' + this.props.username}>
{this.props.username}
</a>
);
}
});
React.render(
<Avatar username="pwh" />,
document.getElementById('example')
);
```
## 소유권(Ownership)
위의 예제에서, `Avatar` 인스턴스는 `ProfilePic``ProfileLink`인스턴스를 *가지고* 있습니다. React에서 **소유자는 다른 컴포넌트의 `props`를 설정하는 컴포넌트입니다**. 더 정식으로 말하면, `X` 컴포넌트가 `Y` 컴포넌트의 `render()` 메소드 안에서 만들어졌다면, `Y``X`*소유하고* 있다고 합니다. 앞에서 설명한 바와 같이, 컴포넌트는 자신의 `props`를 변경할 수 없습니다. `props`는 언제나 소유자가 설정한 것과 일치합니다. 이와 같은 중요한 성질은 UI가 일관성 있도록 해줍니다.
소유(owner-ownee)관계와 부모·자식 관계를 구별하는 것은 중요합니다. 부모·자식 관계가 DOM에서부터 쓰던 익숙하고 이미 알고있던 단순한 것인 한편, 소유관계는 React 고유의 것입니다. 위의 예제에서, `Avatar``div`, `ProfilePic`, `ProfileLink`인스턴스를 소유하고, `div``ProfilePic``ProfileLink`인스턴스의 (소유자가 아닌) **부모**입니다.
## 자식
React 컴포넌트 인스턴스를 만들 때, 추가적인 React 컴포넌트나 JavaScript 표현식을 시작과 끝 태그 사이에 넣을 수 있습니다. 이렇게 말이죠.
```javascript
<Parent><Child /></Parent>
```
`Parent``this.props.children`라는 특수 prop으로 자식들을 읽을 수 있습니다. **`this.props.children` 는 불투명한 데이터 구조이며,** [React.Children 유틸리티](/react/docs/top-level-api-ko-KR.html#react.children)를 사용해 자식들을 관리합니다.
### 자식 Reconciliation (비교조정)
**Reconciliation은 React가 DOM을 각각 새로운 렌더 패스에 업데이트하는 과정입니다.** 일반적으로, 자식은 렌더하는 순서에 따라 비교조정됩니다. 예를 들어, 각각의 마크업을 생성하는 두 개의 랜더 패스가 있다고 해봅시다.
```html
// Render Pass 1
<Card>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
<p>Paragraph 2</p>
</Card>
```
직관적으로 보면, `<p>Paragraph 1</p>`가 없어졌습니다만 그러는 대신에, React는 첫 번째 자식의 텍스트를 비교조정하고 마지막 자식을 파괴하도록 DOM을 비교조정할 것입니다. React는 자식들의 *순서*에 따라 비교조정합니다.
### 상태기반(Stateful) 자식
대부분의 컴포넌트에서는, 이것은 큰 문제가 아닙니다. 하지만 렌더 패스 간에 `this.state`를 유지하는 상태기반의 컴포넌트에서는 매우 문제가 될 수 있습니다.
대부분의 경우, 이 문제는 엘리먼트를 파괴하지 않고 숨김으로써 피해갈 수 있습니다.
```html
// Render Pass 1
<Card>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
<p style={{'{{'}}display: 'none'}}>Paragraph 1</p>
<p>Paragraph 2</p>
</Card>
```
<a name="dynamic-children"></a>
### 동적 자식
자식들이 섞이거나(검색의 결과같은 경우) 새로운 컴포넌트가 목록의 앞에 추가(스트림같은 경우)된다면 상황은 점점 더 까다로워집니다. 이런 때에의 동일성과 각 자식의 상태는 반드시 랜더 패스 간에 유지돼야 합니다. 각 자식에 `key`를 할당 함으로써 독자적으로 식별할 수 있습니다.
```javascript
render: function() {
var results = this.props.results;
return (
<ol>
{results.map(function(result) {
return <li key={result.id}>{result.text}</li>;
})}
</ol>
);
}
```
React가 키가 있는 자식들을 비교조정할 때, React는 `key`가 있는 자식이 (오염(clobbered)되는 대신) 재배치되고 (재사용되는 대신) 파괴되도록 보장할 것입니다.
`key`*항상* 배열 안의 각 컴포넌트의 컨테이너 HTML 자식이 아닌 컴포넌트에게 직접 주어져야 합니다.
```javascript
// 틀림!
var ListItemWrapper = React.createClass({
render: function() {
return <li key={this.props.data.id}>{this.props.data.text}</li>;
}
});
var MyComponent = React.createClass({
render: function() {
return (
<ul>
{this.props.results.map(function(result) {
return <ListItemWrapper data={result}/>;
})}
</ul>
);
}
});
// 맞음 :)
var ListItemWrapper = React.createClass({
render: function() {
return <li>{this.props.data.text}</li>;
}
});
var MyComponent = React.createClass({
render: function() {
return (
<ul>
{this.props.results.map(function(result) {
return <ListItemWrapper key={result.id} data={result}/>;
})}
</ul>
);
}
});
```
ReactFragment 객체를 넘기는 것으로 자식에 키를 할당할 수도 있습니다. 자세한 내용은 [키가 할당된 프래그먼트](create-fragment-ko-KR.html)를 참고하세요.
## 데이터 흐름
React에서 데이터는 위에서 말한 것처럼 `props`를 통해 소유자로부터 소유한 컴포넌트로 흐릅니다. 이것은 사실상 단방향 데이터 바인딩입니다. 소유자는 `props``state`를 기준으로 계산한 어떤 값으로 소유한 컴포넌트의 props를 바인드합니다. 이 과정은 재귀적으로 발생하므로, 데이터의 변경은 자동으로 모든 곳에 반영됩니다.
## 성능의 주의점
소유자가 가지고 있는 노드의 수가 많아지면 데이터의 변화에 반응하는 비용이 증가할 것으로 생각할 수도 있습니다. 좋은 소식은 JavaScript의 속도는 빠르고 `render()` 메소드는 꽤 간단한 경향이 있어, 대부분 애플리케이션에서 매우 빠르다는 점입니다. 덧붙여, 대부분의 병목 현상은 JS 실행이 아닌 DOM 변경에서 일어나고, React는 배치와 탐지 변경을 이용해 최적화해 줍니다.
하지만, 가끔 성능을 위해 정교하게 제어해야 할 때도 있습니다. 이런 경우, React가 서브트리의 처리를 건너 뛰도록 간단히 `shouldComponentUpdate()`를 오버라이드해 false를 리턴하게 할 수 있습니다. 좀 더 자세한 정보는 [React 참조 문서](/react/docs/component-specs-ko-KR.html)를 보세요.
> 주의:
>
> 데이터가 실제로는 변경되었지만 `shouldComponentUpdate()`가 false를 리턴한다면 React는 UI를 싱크시킬수 없습니다. 이 기능을 사용할 때에는 자신이 지금 무엇을 하고 있는지 알고 있고, 눈에 띄는 성능 문제가 있을 경우에만 사용하세요. JavaScript는 DOM에 비해 빠릅니다. 과소평가하지 마세요.

231
docs/05-reusable-components.ko-KR.md

@ -0,0 +1,231 @@
---
id: reusable-components-ko-KR
title: 재사용가능한 컴포넌트
permalink: reusable-components-ko-KR.html
prev: multiple-components-ko-KR.html
next: transferring-props-ko-KR.html
---
인터페이스를 설계할 때, 공통적으로 사용되는 디자인 요소들(버튼, 폼 필드, 레이아웃 컴포넌트 등)을 잘 정의된 인터페이스의 재사용 가능한 컴포넌트로 분해합니다. 이런 방법으로 다음에 UI를 구축할 때에는 훨씬 적은 코드로 만들 수 있습니다. 이 말은 더 빠른 개발 시간, 더 적은 버그, 더 적은 용량으로 할 수 있다는 뜻이죠.
## Prop 검증
앱의 규모가 커지면 컴포넌트들이 바르게 사용되었는지 확인하는게 도움이 됩니다. 확인은 `propTypes`를 명시해서 할 수 있습니다. `React.PropTypes`는 받은 데이터가 적절한지(valid) 확인하는데 사용할 수 있는 다양한 검증자(validator)를 제공합니다. prop에 부적절한 값을 명시한다면 JavaScript 콘솔에 경고가 보일 것입니다. 성능상의 문제로 `propTypes`는 개발 모드에서만 검사됩니다. 다음은 제공되는 검증자를 설명하는 예제입니다.
```javascript
React.createClass({
propTypes: {
// 특정 JavaScript 프리미티브 타입에 대한 prop을 명시할 수 있습니다.
// 기본적으로 이것들은 모두 선택적입니다.
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
// 렌더링될 수 있는 모든 것: 숫자, 문자열, 요소
// 이것들을 포함하는 배열이나 엘리먼트
optionalNode: React.PropTypes.node,
// React 엘리먼트
optionalElement: React.PropTypes.element,
// 클래스의 인스턴스 또한 prop으로 명시할 수 있습니다. JavaScript의 instanceof
// 연산자를 사용합니다.
optionalMessage: React.PropTypes.instanceOf(Message),
// 열거형처럼 특정 값들로만 prop을 제한해서 사용할 수 있습니다.
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 많은 타입들 중 하나로 사용할 수 있는 객체가 될 수도 있습니다.
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 특정 타입의 배열
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 특정 타입의 속성값을 갖는 객체
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 특정한 형태(shape)의 객체
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 위에 언급된 것들을 `isRequired`로 연결해서 prop이 제공되지 않을 때 경고를
// 띄우도록 할 수도 있습니다.
requiredFunc: React.PropTypes.func.isRequired,
// 어떤 데이터 타입도 가능
requiredAny: React.PropTypes.any.isRequired,
// 물론 사용자 정의 검증자도 지정할 수 있습니다. 이는 검증이 실패했을 때
// Error 객체를 리턴해야합니다. `console.warn`을 이나 throw를 하면 안됩니다.
// 그렇게하면 `oneOfType` 안에서 작동하지 않습니다.
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
},
/* ... */
});
```
## 기본 Prop 값
React는 매우 선언적(declarative)인 방법으로 `props`의 기본값을 정의할 수 있게 해줍니다.
```javascript
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
/* ... */
});
```
`getDefaultProps()`의 결과값은 캐시가 되며, 부모 컴포넌트에서 명시되지 않았을 때 `this.props.value`가 값을 가질 수 있도록 해주는데 사용됩니다.`getDefaultProps()`를 사용하면 반복적이고 깨지기 쉬운 코드를 짤 필요없이 그냥 안전하게 prop을 사용할 수 있습니다.
## Prop 전달하기: 단축
React 컴포넌트의 흔히 그냥 기본 HTML을 확장해서 씁니다. 타이핑을 아끼기 위해 기저의 HTML 엘리먼트에 HTML 속성들을 단순히 복사하는 컴포넌트가 필요할 수도 있습니다. JSX의 _spread_ 문법을 사용하면 이렇게 할 수 있습니다.
```javascript
var CheckLink = React.createClass({
render: function() {
// 모든 prop을 받아서 CheckLink에 넘기고 <a>에 복사합니다.
return <a {...this.props}>{'√ '}{this.props.children}</a>;
}
});
React.render(
<CheckLink href="/checked.html">
Click here!
</CheckLink>,
document.getElementById('example')
);
```
## 단일 자식
`React.PropTypes.element`을 통해 컴포넌트에 한 자식만 보내도록 명시할 수 있습니다.
```javascript
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
return (
<div>
{this.props.children} // 정확히 한 엘리먼트여야만 하며, 아니면 에러가 발생합니다.
</div>
);
}
});
```
## 믹스인
컴포넌트는 React에서 코드를 재사용할 수 있는 최고의 방법이지만, 가끔 아주 다른 컴포넌트에서 공통 기능이 필요한 때도 있습니다. 이런 상황을 [공통된 관심사(cross-cutting concerns)](http://en.wikipedia.org/wiki/Cross-cutting_concern)라 부르며, React에서는 `mixins`으로 이 문제를 해결합니다.
예를 들어, 컴포넌트가 주기적으로 업데이트되길 원할 경우가 있습니다. `setInterval()`을 사용하면 쉽지만, 필요 없어지면 메모리를 아끼기 위해 주기를 꼭 취소해야 합니다. React는 컴포넌트가 막 생성거나 없어질 때를 [생명주기 메소드](/react/docs/working-with-the-browser-ko-KR.html#component-lifecycle)를 통해 알려줍니다. 이런 메소드들을 사용해서 컴포넌트가 사라질 때 자동으로 정리해주는 `setInterval()`를 제공해주는 간단한 믹스인을 만들어보겠습니다.
```javascript
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);
}
};
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // 믹스인 사용
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // 믹스인에 있는 메소드를 호출
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
React.render(
<TickTock />,
document.getElementById('example')
);
```
믹스인의 괜찮은 점은 컴포넌트가 여러 믹스인을 사용하고 여러 믹스인에서 같은 생명주기 메소드를 사용할 때(예를 들어, 여러 믹스인에서 컴포넌트가 사라질 때 뭔가 정리하려 한다면) 모든 생명주기 메소드들의 실행은 보장됩니다. 믹스인에 정의된 메소드은 컴포넌트의 메소드가 호출됨에 따라 믹스인이 나열된 순서대로 실행됩니다.
## ES6 클래스
React 클래스를 일반적인 JavaScript 클래스로 선언할 수도 있습니다. 다음의 예제는 ES6 클래스 문법을 사용합니다:
```javascript
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
React.render(<HelloMessage name="Sebastian" />, mountNode);
```
API는 `getInitialState`를 제외하고 `React.createClass`와 유사합니다. 별도의 `getInitialState` 메소드 대신에, 필요한 `state` 프로퍼티를 생성자에서 설정할 수 있습니다.
또다른 차이점은 `propTypes``defaultProps`가 클래스의 내부가 아니라 생성자의 프로퍼티로 정의되어 있다는 것입니다.
```javascript
export class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: props.initialCount};
}
tick() {
this.setState({count: this.state.count + 1});
}
render() {
return (
<div onClick={this.tick.bind(this)}>
Clicks: {this.state.count}
</div>
);
}
}
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };
```
### 자동 바인딩 안됨
메소드는 일반 ES6 클래스와 동일한 시멘틱을 따릅니다. `this`를 인스턴스에 자동으로 바인딩하지 않는다는 이야기입니다. 명시적으로 `.bind(this)`나 화살표 함수(arrow function)을 사용하세요.
### 믹스인 안됨
불행하게도 ES6는 믹스인에 대한 지원이 없이 출시되었기 때문에, React에서 ES6 클래스를 사용한다면 믹스인을 사용할 방법이 없습니다. 대신, 우리는 믹스인에 의존하지 않고도 동작하도록 만들기 위해 열심히 노력하고 있습니다.

164
docs/06-transferring-props.ko-KR.md

@ -0,0 +1,164 @@
---
id: transferring-props-ko-KR
title: Props 전달
permalink: transferring-props-ko-KR.html
prev: reusable-components-ko-KR.html
next: forms-ko-KR.html
---
React에서는 컴포넌트를 감싸서 추상화하는 것이 일반적인 패턴입니다. 외부 컴포넌트에서는 간단한 프로퍼티만을 노출하여 복잡한 세부 구현을 감출 수 있습니다.
[JSX 스프레드 어트리뷰트](/react/docs/jsx-spread-ko-KR.html)를 통해 props에 추가적인 값을 병합할 수 있습니다.
```javascript
return <Component {...this.props} more="values" />;
```
만약 JSX를 사용하지 않는다면 ES6의 `Object.assign`나 Underscore의 `_.extend` 같은 객체 헬퍼를 사용할 수 있습니다:
```javascript
return Component(Object.assign({}, this.props, { more: 'values' }));
```
이 튜토리얼의 나머지 부분은 모범 답안을 소개할 것입니다. JSX와 실험적인 ES7 구문을 사용합니다.
## 수동적인 전달
대부분의 경우 명시적으로 프로퍼티를 아래로 전달해야 합니다. 이는 동작을 확신하는 내부 API의 일부만 공개하도록 합니다.
```javascript
var FancyCheckbox = React.createClass({
render: function() {
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
return (
<div className={fancyClass} onClick={this.props.onClick}>
{this.props.children}
</div>
);
}
});
React.render(
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
세상아 안녕!
</FancyCheckbox>,
document.body
);
```
하지만 `name`이나 `title`, `onMouseOver` 같은 prop들이 더 추가된다면 어떨까요?
## JSX에서 `...`를 사용해 전달하기
> 주의:
>
> 아래의 예제에서는 실험적인 ES7 문법이 사용되었기 때문에 `--harmony ` 플래그가 필요합니다. 브라우저에서 JSX 변환기를 사용 중이라면, `<script type="text/jsx;harmony=true">`를 사용해 스크립트를 작성하세요. 자세히 알아보려면 아래의 [잔여 프로퍼티와 스프레드 프로퍼티 ...](http://facebook.github.io/react/docs/transferring-props-ko-KR.html#rest-and-spread-properties-...)를 확인하세요.
때로는 모든 프로퍼티를 일일이 전달 하는것은 지루하고 덧없는 작업입니다. 이 경우 [구조 해체 할당(destructuring assignment)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)을 다른 프로퍼티를 함께 사용해 미상의 프로퍼티를 추출할 수 있습니다.
소비할 프로퍼티들을 나열하고, 그 뒤에 `...other`를 넣습니다.
```javascript
var { checked, ...other } = this.props;
```
이는 지금 소비한 props를 *제외한* 나머지를 아래로 전달합니다.
```javascript
var FancyCheckbox = React.createClass({
render: function() {
var { checked, ...other } = this.props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
// `other`에는 { onClick: console.log }가 포함되지만 checked 프로퍼티는 제외됩니다
return (
<div {...other} className={fancyClass} />
);
}
});
React.render(
<FancyCheckbox checked={true} onClick={console.log.bind(console)}>
세상아 안녕!
</FancyCheckbox>,
document.body
);
```
> 주의:
>
> 위의 예제에서는 `checked` prop 또한 마찬가지로 유효한 DOM 어트리뷰트입니다. 이런 식으로 구조의 해체(destructuring)를 하지 않으면 의도하지 않게 함께 전달될 수 있습니다.
미상의 `other` props을 전달할 때는 항상 구조 해체 패턴을 사용하세요.
```javascript
var FancyCheckbox = React.createClass({
render: function() {
var fancyClass = this.props.checked ? 'FancyChecked' : 'FancyUnchecked';
// 반례: `checked` 또한 내부 컴포넌트로 전달될 것입니다
return (
<div {...this.props} className={fancyClass} />
);
}
});
```
## 같은 Prop을 소비하고 전달하기
컴포넌트가 프로퍼티를 사용하지만 계속 넘겨야한다면, `checked={checked}`처럼 명시적으로 다시 넘길 수 있습니다. 리팩토링과 린트(lint)하기가 더 쉬우므로 이 방식이 `this.props` 객체 전부를 넘기는 것보다 낫습니다.
```javascript
var FancyCheckbox = React.createClass({
render: function() {
var { checked, title, ...other } = this.props;
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
var fancyTitle = checked ? 'X ' + title : 'O ' + title;
return (
<label>
<input {...other}
checked={checked}
className={fancyClass}
type="checkbox"
/>
{fancyTitle}
</label>
);
}
});
```
> 주의:
>
> 순서는 중요합니다. `{...other}`를 JSX props 이전에 넣는 것으로 컴포넌트의 사용자가 확실히 그것들을 오버라이드 할 수 없게 합니다. 위의 예제에서는 input이 `"checkbox"` 타입인 것을 보장합니다.
<a name="rest-and-spread-properties-..."></a>
## 잔여 프로퍼티와 스프레드 프로퍼티 `...`
잔여(Rest, `...`) 프로퍼티는 객체에서 소비되지 않은 나머지 프로퍼티를 추출해 새로운 객체로 만들 수 있게 해 줍니다. 구조 해체 패턴에서 열거된 다른 프로퍼티들은 모두 제외됩니다.
이는 [ES7 제안](https://github.com/sebmarkbage/ecmascript-rest-spread)의 실험적인 구현체입니다.
```javascript
var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
```
> 주의:
>
> 실험적인 ES7 구문을 활성화하려면 [JSX 커맨드라인 도구](http://npmjs.org/package/react-tools)를 `--harmony` 플래그와 함께 사용하세요.
## Underscore로 전달 다루기
JSX를 사용하지 않는다면 라이브러리를 사용해 같은 패턴을 쓸 수 있습니다. Underscore에서는 `_.omit`을 사용해 특정 프로퍼티를 제외하거나 `_.extend`를 사용해 새로운 객체로 프로퍼티를 복사할 수 있습니다.
```javascript
var FancyCheckbox = React.createClass({
render: function() {
var checked = this.props.checked;
var other = _.omit(this.props, 'checked');
var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
return (
React.DOM.div(_.extend({}, other, { className: fancyClass }))
);
}
});
```

151
docs/07-forms.ko-KR.md

@ -0,0 +1,151 @@
---
id: forms-ko-KR
title: 폼
permalink: forms-ko-KR.html
prev: transferring-props-ko-KR.html
next: working-with-the-browser-ko-KR.html
---
`<input>`, `<textarea>`, `<option>` 같은 폼 컴포넌트는 다른 네이티브 컴포넌트와 다릅니다. 왜냐하면, 사용자의 상호작용에 의해 변경될 수 있기 때문이죠. 이런 컴포넌트들은 사용자의 상호작용에 반응하여 폼을 더 쉽게 관리할 수 있도록 인터페이스를 제공합니다.
`<form>` 이벤트에 관한 정보는 [폼 이벤트](/react/docs/events-ko-KR.html#form-events)를 보세요.
## Props의 상호작용
폼 컴포넌트는 사용자 상호작용을 통해 영향을 받는 몇 가지 props를 지원합니다.
* `value`: `<input>`, `<textarea>` 컴포넌트에서 사용가능.
* `checked`: `checkbox`, `radio`타입의 `<input>` 컴포넌트에서 사용가능.
* `selected`: `<option>` 컴포넌트에서 사용가능.
HTML에서는 `<textarea>` 태그의 값을 설정할 때 `<textarea>` 태그의 자식이 사용되지만, React에서는 `value` 를 사용해야 합니다.
폼 컴포넌트는 `onChange` prop의 콜백을 설정하여 변경을 감시(listening)할 수 있습니다. `onChange` prop는 브라우저에 관계없이 다음과 같은 사용자 상호작용에 반응합니다.
* `<input>`, `<textarea>``value` 변경.
* `<input>``checked` state 변경.
* `<option>``selected` state 변경.
모든 DOM 이벤트처럼 `onChange` prop은 모든 네이티브 컴포넌트에서 지원되며 일어난(bubbled) 변경 이벤트를 감시하는데 사용할 수 있습니다.
## 제어되는(controlled) 컴포넌트
`value`가 설정된 `<input>`*제어되는* 컴포넌트입니다. 제어되는 `<input>`에서, 렌더 엘리먼트의 값은 항상 `value` prop을 반영합니다. 예를 들어,
```javascript
render: function() {
return <input type="text" value="Hello!" />;
}
```
이것은 항상 `Hello!`의 값을 가지는 input을 렌더합니다. 어떤 사용자 입력도 렌더된 엘리먼트에는 영향을 주지 않는데, 왜냐하면 React가 값을 `Hello!`로 설정했기 때문입니다. 사용자 입력에 따라 값을 업데이트하길 원한다면, `onChange` 이벤트를 사용할 수 있습니다.
```javascript
getInitialState: function() {
return {value: 'Hello!'};
},
handleChange: function(event) {
this.setState({value: event.target.value});
},
render: function() {
var value = this.state.value;
return <input type="text" value={value} onChange={this.handleChange} />;
}
```
이 예제에서는, 단순히 사용자가 주는 최신값을 받고 `<input>` 컴포넌트의 `value` prop을 업데이트하고 있습니다. 이 패턴은 사용자의 상호작용에 반응하거나 검증하는 인터페이스를 쉽게 구현하게 합니다. 예를 들어,
```javascript
handleChange: function(event) {
this.setState({value: event.target.value.substr(0, 140)});
}
```
이것은 사용자 입력을 받아들이지만, 시작에서부터 140자로 값을 자릅니다.
## 제어되지 않는(Uncontrolled) 컴포넌트
`value` 가 없(거나 `null`로 설정되어 있)는 `<input>`*제어되지 않는* 컴포넌트입니다. 제어되지 않는 `<input>`에서 렌더된 엘리먼트의 value값은 사용자의 입력을 반영합니다. 예를 들어,
```javascript
render: function() {
return <input type="text" />;
}
```
이것은 빈 값으로 시작되는 input을 랜더합니다. 임의의 사용자 입력은 즉시 렌더된 엘리먼트에 반영됩니다. 값의 업데이트를 감시하길 원한다면, 제어되는 컴포넌트처럼 `onChange` 이벤트를 사용할 수 있습니다.
비어 있지 않은 값으로 초기화하길 원한다면, `defaultValue` prop로 할 수 있습니다. 예를 들어,
```javascript
render: function() {
return <input type="text" defaultValue="Hello!" />;
}
```
이 예제는 위에있는 **제어되는 컴포넌트**에 더 가깝게 동작할 것입니다.
마찬가지로, `<input>``defaultChecked`를 지원하고 `<select>``defaultValue`를 지원합니다.
## 심화 주제
### 왜 제어되는 컴포넌트인가요?
React에서 `<input>`같은 폼 컴포넌트를 사용하면, 전통적인 폼 HTML을 쓸 때에는 없던 어려운 문제가 있습니다. 예를 들어 HTML에서
```html
<input type="text" name="title" value="Untitled" />
```
이렇게 하면 input은 `Untitled` 값으로 *초기화* 됩니다. 사용자가 input을 업데이트할 때, 노드의 value *프로퍼티*가 변경될 것입니다. 하지만, `node.getAttribute('value')`은 여전히 초기화 때 사용했던 값인 `Untitled`를 리턴합니다.
HTML과 다르게, React 컴포넌트는 초기화 시점 뿐만 아니라, 어떤 시점이라도 반드시 뷰의 state를 나타내야 합니다. 예를 들어 React에서
```javascript
render: function() {
return <input type="text" name="title" value="Untitled" />;
}
```
이 메소드가 어떤 시점에도 뷰를 기술하기 때문에, 텍스트 input의 값은 *언제나* `Untitled`입니다.
### 왜 Textarea에 value를 사용하나요?
HTML에서, `<textarea>`의 값은 보통 그것의 자식들로 설정됩니다.
```html
<!-- 반례: 이렇게 하지 마세요! -->
<textarea name="description">이것은 설명입니다.</textarea>
```
HTML에서는 이렇게 하면 여러 줄의 값을 쉽게 개발자가 넣을 수 있게 합니다. 하지만, React는 JavaScript기 때문에, 우리는 문자열 제한이 없고 개행이 필요하면 `\n`을 사용할 수 있습니다. 이 곳에서는 `value``defaultValue`가 있고, 그것이 자식들의 역할을 모호하게 합니다. 이런 이유로, `<textarea>`의 값을 설정할 때에는 자식들을 사용하지 않아야 합니다.
```javascript
<textarea name="description" value="이것은 설명입니다." />
```
자식들을 사용하기로 *했다면*, 자식들은 `defaultValue`처럼 동작할 것입니다.
### 왜 Select에 value를 사용하나요?
HTML `<select>`에서 선택된 `<option>`은 보통 option의 `selected` 어트리뷰트로 기술됩니다. React에서는 컴포넌트를 관리하기 쉽게 하기 위해, 다음 형식이 대신 채용됐습니다.
```javascript
<select value="B">
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
```
제어되지 않는 컴포넌트로 만드려면, 대신 `defaultValue`를 사용하세요.
> 주의:
>
> `select` 태그에 여러 옵션을 선택할 수 있도록, `value` 어트리뷰트에 배열을 넘길 수도 있습니다. `<select multiple={true} value={['B', 'C']}>`

147
docs/08-working-with-the-browser.ko-KR.md

@ -0,0 +1,147 @@
---
id: working-with-the-browser-ko-KR
title: 브라우저에서의 동작
permalink: working-with-the-browser-ko-KR.html
prev: forms-ko-KR.html
next: more-about-refs-ko-KR.html
---
React는 대부분의 경우 직접 DOM을 다루지 않아도 될만큼 강력한 추상화를 제공합니다. 하지만 서드파티 라이브러리나 기존의 코드들을 다루다 보면 간혹 기저(underlying)의 API에 접근해야 할 때도 있습니다.
## 가상의 DOM
React는 DOM을 직접 다루지 않기 때문에 굉장히 빠릅니다. React는 메모리에(in-memory) DOM의 표상(representation)을 관리합니다. `render()` 메소드는 DOM의 *서술*를 반환하고, React는 이를 메모리에 있는 DOM의 표상과 비교(diff)해 가장 빠른 방식으로 계산해서 브라우저를 업데이트해 줍니다.
게다가 React는 브라우저의 괴악함(quirks)에도 불구하고 모든 이벤트 객체가 W3C 명세를 보장하도록 통합적인 이벤트 시스템을 구현했습니다. 모든 것이 일관된 방식으로 일어나고(bubbles) 효율적인 방식으로 크로스 브라우징을 수행합니다. 심지어 IE8에서도 HTML5 이벤트를 사용할 수 있습니다!
더 효율적이고 쉬우므로 대개의 경우 React의 "가짜 브라우저"를 이용해 작업을 하게 될 것입니다. 하지만 간혹 jQuery 플러그인 같은 서드파티 라이브러리를 다루다 보면 기저(underlying)의 API에 접근할 필요가 있을지도 모릅니다. React는 기저의 DOM API를 직접 다루는 회피방법을 제공합니다.
## Refs와 findDOMNode()
브라우저와 상호 작용하려면 DOM 노드에 대한 참조가 필요합니다. React는 `React.findDOMNode(component)` 함수를 갖고 있으며, 이를 통해서 컴포넌트의 DOM 노드의 참조를 얻을 수 있습니다.
> 주의:
>
> `findDOMNode()`는 마운트 된 컴포넌트에서만 동작합니다 (DOM에 배치된 컴포넌트를 말합니다). 아직 마운트 되지 않은 컴포넌트에서 이를 호출하려고 하면 (컴포넌트가 아직 생성되기 이전인 `render()` 시점에 `findDOMNode()`를 호출한다든가) 예외가 발생합니다.
React 컴포넌트에 대한 참조는 현재의 React 컴포넌트를 위해 `this`를, 소유한 컴포넌트의 참조를 얻기 위해 refs를 사용해 얻을 수 있습니다. 다음과 같이 동작합니다:
```javascript
var MyComponent = React.createClass({
handleClick: function() {
// raw DOM API를 사용해 명시적으로 텍스트 인풋을 포커스 합니다.
React.findDOMNode(this.refs.myTextInput).focus();
},
render: function() {
// ref 어트리뷰트는 컴포넌트가 마운트되면 그에 대한 참조를 this.refs에 추가합니다.
return (
<div>
<input type="text" ref="myTextInput" />
<input
type="button"
value="Focus the text input"
onClick={this.handleClick}
/>
</div>
);
}
});
React.render(
<MyComponent />,
document.getElementById('example')
);
```
## Refs 심화
[refs 심화](/react/docs/more-about-refs-ko-KR.html) 문서에서 refs를 효율적으로 사용하는 법을 포함해 더 많은 내용을 익혀보세요.
<a name="component-lifecycle"></a>
## 컴포넌트 생명주기
컴포넌트의 생명주기에는 세 가지 주요 부분이 있습니다:
* **Mounting:** 컴포넌트가 DOM에 삽입되고 있습니다.
* **Updating:** 컴포넌트가 DOM의 업데이트 여부를 결정하기 위해 다시 렌더링되고 있습니다.
* **Unmounting:** 컴포넌트가 DOM에서 제거되고 있습니다.
React는 이 프로세스에 훅을 지정할 수 있는 생명주기 메소드를 제공합니다. 발생 직전 시점을 위한 **will** 메소드, 발생 직후 시점을 위한 **did** 메소드가 있습니다.
### Mounting
* `getInitialState(): object`는 컴포넌트가 마운트되기 전에 호출됩니다. 상태기반 컴포넌트는 이를 구현하고 초기 상태 데이터를 리턴합니다.
* `componentWillMount()`는 마운팅되기 직전에 호출됩니다.
* `componentDidMount()`는 마운팅 직후 호출됩니다. 초기화에 필요한 DOM 노드는 이곳에 있어야 합니다.
### Updating
* `componentWillReceiveProps(object nextProps)`는 마운트된 컴포넌트가 새로운 props을 받을 때 호출됩니다. 이 메소드는 `this.props``nextProps`을 비교하여 `this.setState()`를 사용해 상태 변환을 수행하는데 사용되야 합니다.
* `shouldComponentUpdate(object nextProps, object nextState): boolean`는 컴포넌트가 어떤 변경이 DOM의 업데이트를 보증하는지 결정해야 할 때 호출됩니다. 최적화하려면, React가 업데이트를 무시해야할 때 `this.props``nextProps`를, `this.state``nextState`를 비교해 false를 리턴하면 됩니다.
* `componentWillUpdate(object nextProps, object nextState)`는 업데이트가 발생하기 직전에 호출됩니다. 이 시점에는 `this.setState()`를 호출할 수 없습니다.
* `componentDidUpdate(object prevProps, object prevState)`는 업데이트가 발생한 후 즉시 호출됩니다.
### Unmounting
* `componentWillUnmount()`는 컴포넌트가 언마운트되어 파괴되기 직전에 호출됩니다. 정리(Cleanup)는 여기서 처리해야 합니다.
### Mounted 메소드
_마운트된_ 합성 컴포넌트들은 다음과 같은 메소드를 지원합니다:
* `findDOMNode(): DOMElement`는 렌더링 된 DOM 노드에 대한 참조를 얻기 위해 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
* `forceUpdate()``this.setState`를 사용하지 않고 컴포넌트 state의 더 깊은 측면(deeper aspect)의 변경된 것을 알고 있을 때 모든 마운트된 컴포넌트에서 호출할 수 있습니다.
## 브라우저 지원과 Polyfill
페이스북에서 우리는 IE8을 포함한 구식 브라우저를 지원합니다. 미래지향적인 JS를 작성할 수 있도록 우리는 polyfill을 오랫동안 써왔습니다. 이는 우리의 코드베이스에 구식 브라우저를 위한 코드뭉치를 흩뿌려 놓을 필요가 없으며 그럼에도 우리의 코드가 "잘 작동"할 것이라 예상할 수 있음을 의미합니다. 예를 들어, `+new Date()` 대신에 그냥 `Date.now()`를 사용할 수 있습니다. 오픈소스 React는 우리가 내부에서 사용하는것과 동일하기 때문에, 우리는 이를 통해 미래지향적인 JS를 사용하는 철학을 전달했습니다.
그 철학에 더하여, 우리는 또한 JS 라이브러리의 저자로서 polyfill을 라이브러리에 포함해서 배포하지 않습니다. 만약 모든 라이브러리가 이런 짓을 하면, 같은 polyfill을 여러 번 내리게 되어 쓸모없이 크기만 차지하는 죽은 코드들을 만들 것 입니다. 당신의 제품이 구식 브라우저를 지원해야한다면, [es5-shim](https://github.com/kriskowal/es5-shim) 같은 녀석을 사용할 기회가 있었을 겁니다.
### Polyfill은 구식 브라우저를 지원하기 위해 필요하다
[kriskowal's es5-shim](https://github.com/kriskowal/es5-shim)의 `es5-shim.js`는 React에 필요한 다음의 기능을 제공합니다:
* `Array.isArray`
* `Array.prototype.every`
* `Array.prototype.forEach`
* `Array.prototype.indexOf`
* `Array.prototype.map`
* `Date.now`
* `Function.prototype.bind`
* `Object.keys`
* `String.prototype.split`
* `String.prototype.trim`
[kriskowal's es5-shim](https://github.com/kriskowal/es5-shim)의 `es5-sham.js`는, React에 필요한 다음의 기능도 제공합니다:
* `Object.create`
* `Object.freeze`
압축되지 않은 React 빌드는 [paulmillr의 console-polyfill](https://github.com/paulmillr/console-polyfill)에서 다음의 기능이 필요합니다.
* `console.*`
`<section>`, `<article>`, `<nav>`, `<header>`, `<footer>`등 HTML5 엘리먼트를 IE8에서 이용하려면 [html5shiv](https://github.com/aFarkas/html5shiv)같은 스크립트가 추가로 필요합니다.
### 크로스 브라우징 이슈
React가 브라우저별 차이점을 썩 잘 추상화하긴 했지만 일부는 한정적이거나 우리가 발견하지 못한 이상한(quirky) 동작을 보여주기도 합니다.
#### IE8에서의 onScroll 이벤트
IE8에서는 `onScroll` 이벤트가 일어나지(bubble) 않으며, IE8은 이벤트의 캡쳐링 단계를 위한 핸들러를 정의하는 API를 갖고 있지 않습니다. 이는 React가 이 이벤트를 이해(listen) 할 방법이 없음을 뜻합니다. 현재 이 이벤트 핸들러는 IE8에서 무시됩니다.
더 많은 정보는 [onScroll doesn't work in IE8](https://github.com/facebook/react/issues/631) GitHub 이슈를 살펴보세요.

150
docs/08.1-more-about-refs.ko-KR.md

@ -0,0 +1,150 @@
---
id: more-about-refs-ko-KR
title: refs 심화
permalink: more-about-refs-ko-KR.html
prev: working-with-the-browser-ko-KR.html
next: tooling-integration-ko-KR.html
---
render 메소드를 통해 UI 구조를 얻은 다음, 반환된 컴포넌트 인스턴스에 접근하거나 메소드를 호출할 방법이 필요할 수도 있습니다. 반응적 데이터 플로우가 `render()`의 결과물에서 최신의 `props`가 각각의 자식으로 보내진 것을 항상 보장하기 때문에 애플리케이션의 데이터 플로우를 만드는데 대체로 이런 작업은 필요가 없지만, 여전히 이런 작업이 필요하거나 유리한 경우가 있긴 합니다.
인스턴스의 하위 계층구조에 존재하는 `<input />` 엘리먼트의 value를 빈 문자열(`''`)로 업데이트한 후 포커스 하는 경우를 생각해 봅시다.
```javascript
var App = React.createClass({
getInitialState: function() {
return {userInput: ''};
},
handleChange: function(e) {
this.setState({userInput: e.target.value});
},
clearAndFocusInput: function() {
this.setState({userInput: ''}); // 입력내용을 지워줍니다
// 이제 <input />에 포커스를 주길 원합니다!
},
render: function() {
return (
<div>
<div onClick={this.clearAndFocusInput}>
클릭해서 초기화하고 포커스주기
</div>
<input
value={this.state.userInput}
onChange={this.handleChange}
/>
</div>
);
}
});
```
한번 살펴보죠. 이 예제에서 우리는 시간이 지남에 따라 props에서 추론할 수 없는 무언가를 입력하도록 "알려주길" 원했습니다. 이 사례에서 우리는 이제 포커스 되도록 "알려주길" 원합니다. 그러나 몇 가지 문제가 있습니다. `render()`에서 반환된 것은 "자식" 컴포넌트의 실제 구성이 아니고, 단지 특정 시점의 인스턴스의 자식에 대한 *서술*일 뿐입니다. - 말하자면 스냅샷인 것이지요.
> 주의:
>
> 기억하세요, `render()`에서 반환된 것은 *실제* 자식 인스턴스가 아닙니다. 단지 특정 시점의 컴포넌트의 하위 계층구조에 있는 자식 인스턴스의 *서술*일 뿐입니다.
이는 `render()`에서 반환된 무언가를 "계속 유지할 수" 없으며 아무런 의미도 없을 것이라는 뜻입니다.
```javascript
// 반례: 이렇게 하면 안됩니다!
render: function() {
var myInput = <input />; // 여기서 메소드를 호출할 겁니다.
this.rememberThisInput = myInput; // 언젠가 미래의 특정 시점에 입력할 거에요! YAY!
return (
<div>
<div>...</div>
{myInput}
</div>
);
}
```
이 반례에서 `<input />`은 단지 `<input />`의 *서술*일 뿐입니다. 이 서술은 `<input />`에 대한 *진짜* **지원 인스턴스(backing instance)**를 생성하는 데 사용됩니다.
자 그럼 어떻게 *진짜* input의 지원 인스턴스를 다룰까요?
## ref 문자열 어트리뷰트
React는 `render()`로 출력된 컴포넌트에 추가할 수 있는 아주 특별한 프로퍼티를 지원합니다. 이 특별한 프로퍼티는 `render()`에서 반환한 모든 것들에 대해 각각에 대응하는 **지원 인스턴스**를 참조할 수 있습니다. 이는 항상 어떤 시점에서든 올바른 인스턴스를 보장합니다.
간단합니다:
1. `render`에서 반환된 값을 `ref` 어트리뷰트에 할당합니다:
```html
<input ref="myInput" />
```
2. 다른 코드(일반적으로는 이벤트 핸들러 코드)에서 `this.refs`를 통해 **지원 인스턴스**에 접근 합니다:
```javascript
this.refs.myInput
```
`React.findDOMNode(this.refs.myInput)`를 호출해 컴포넌트의 DOM 노드에 접근할 수 있습니다.
## ref 콜백 어트리뷰트
`ref` 어트리뷰트는 이름 대신 콜백 함수가 될 수도 있습니다. 이 콜백은 컴포넌트가 마운트 된 뒤 즉시 실행될 것입니다. 참조된 컴포넌트는 매개 변수로 전달되며 콜백은 이를 즉시 사용하거나, 앞으로 사용하기 위해 참조를 저장해 놓거나, 혹은 둘 다 할 것입니다.
`render`에서 반환한 모든 것에 간단하게 `ref` 어트리뷰트를 할당할 수 있습니다:
```html
<input ref={ function(component){ React.findDOMNode(component).focus();} } />
```
## 예제 완성하기
```javascript
var App = React.createClass({
getInitialState: function() {
return {userInput: ''};
},
handleChange: function(e) {
this.setState({userInput: e.target.value});
},
clearAndFocusInput: function() {
// input을 비워준다
this.setState({userInput: ''}, function() {
// 이 코드는 컴포넌트가 다시 렌더 된 다음 실행됩니다
React.findDOMNode(this.refs.theInput).focus(); // 짠! 포커스 됨!
});
},
render: function() {
return (
<div>
<div onClick={this.clearAndFocusInput}>
클릭해서 초기화하고 포커스주기
</div>
<input
ref="theInput"
value={this.state.userInput}
onChange={this.handleChange}
/>
</div>
);
}
});
```
이 예제에서 render 함수는 `<input />` 인스턴스의 서술을 반환했지만, 진짜 인스턴스는 `this.refs.theInput`을 통해 접근할 수 있었습니다. render에서 `ref="theInput"`을 가진 컴포넌트가 반환된 동안, `this.refs.theInput`은 적절한 인스턴스에 접근합니다. 이는 `<Typeahead ref="myTypeahead" />`처럼 DOM이 아닌 고수준의 컴포넌트에서도 동작합니다.
## 요약
Refs는 반응적인 `props``state` 스트리밍을 통해서는 불편했던 특정한 자식 인스턴스에 메시지 보내기를 수행하는 좋은 방법입니다. 하지만 애플리케이션의 데이터 플로우 전반에 사용해도 되는 go-to 같은 개념은 아닙니다. 기본적으로는 반응적인 데이터 플로우를 사용하고, `ref`는 근본적으로 반응적이지 않은 경우에만 사용하세요.
### 이점:
- 컴포넌트 클래스에 public 메소드(ex. Typeahead의 reset)를 선언할 수 있으며 refs를 통해 그를 호출할 수 있습니다. (ex. `this.refs.myTypeahead.reset()`)
- DOM을 측정하기 위해서는 거의 항상 `<input />` 같은 "기본" 컴포넌트를 다루고 `React.findDOMNode(this.refs.myInput)`를 통해 그 기저의 DOM 노드에 접근해야 합니다. Refs는 이 일을 확실하게 수행하는 몇 안 되는 실용적인 방법의 하나입니다.
- Refs는 자동으로 기록을 관리합니다! 자식이 파괴되면, 그의 ref도 마찬가지로 파괴됩니다. 참조를 유지하기 위해 뭔가 미친 짓을 하지 않는 한, 메모리 걱정은 하지 않아도 됩니다.
### 주의:
- 컴포넌트의 렌더 메소드에서는, 혹은 컴포넌트의 렌더 메소드가 콜스택 어디에서든 실행되는 동안에는 절대 접근하지 마세요.
- Google Closure Compiler에서의 분쇄 복원력 유지(to preserve Crushing resilience)를 위해서는 문자열로 정의한 것을 절대 프로퍼티로 접근하지 마세요. ref가 ref="myRefString"으로 정의되어 있다면 this.refs['myRefString']으로만 접근해야 한다는 이야기 입니다.
- React로 앱을 여럿 만들어 본 경험이 없다면, 보통은 처음엔 앱에서 "무언가 일어나도록" 하는데 refs를 사용하게 될 것입니다. 이 경우, 잠시 시간을 내어 `state`가 컴포넌트 계층구조의 어느 부분에서 관리되어야 할지 비판적으로 생각해 봅시다. 대개는 state가 계층구조의 더 높은 레벨에서 "소유"하는 것이 타당함이 명확해집니다. 그렇게 함으로써 `ref`를 사용해 "무언가 일어나도록" 하려는 욕망이 대부분 제거됩니다. - 대신에 데이터 플로우를 통해 대개 원하는 바를 달성하게 될 것입니다.

44
docs/09-tooling-integration.ko-KR.md

@ -0,0 +1,44 @@
---
id: tooling-integration-ko-KR
title: 툴 통합
permalink: tooling-integration-ko-KR.html
prev: more-about-refs-ko-KR.html
next: addons-ko-KR.html
---
모든 프로젝트는 JavaScript를 빌드, 배포할 때 다른 시스템을 사용합니다. 우리는 가능한 한 React를 환경에 구속받지 않도록 하려 노력했습니다.
## React
### CDN-호스트 React
[다운로드 페이지](/react/downloads.html)에서 React의 CDN 호스트 버전을 제공합니다. 이 미리 빌드된 파일들은 UMD 모듈 포맷을 사용합니다. 간단한 `<script>` 태그로 넣어보면 `React` 글로벌이 환경으로 주입(inject)될 것입니다. CommonJS와 AMD환경에서 별도의 작업 없이도 동작해야 합니다.
### master 사용하기
[GitHub 저장소](https://github.com/facebook/react)의 `master`에 빌드 방법이 있습니다. 이는 `build/modules`에 CommonJS 모듈 트리를 빌드합니다. 이는 CommonJS를 지원하는 어떤 환경이나 패키징 툴에도 넣을 수 있습니다.
## JSX
### 브라우저에서 JSX 변환
JSX를 사용하신다면, [다운로드 페이지](/react/downloads.html)에서 브라우저 JSX 변환기를 제공합니다. 간단히 `<script type="text/jsx">`를 넣으면 JSX 변환기가 작동합니다.
> 주의:
>
> 브라우저 JSX 변환기는 꽤 크고 안 할 수도 있는 클라이언트 측 연산을 하게 됩니다. 프로덕션 환경에서 사용하지 마시고, 다음 단락을 보세요.
### 상용화하기: 미리 컴파일된 JSX
[npm](http://npmjs.org/) 모듈을 가지고 있다면, 간단히 `npm install -g react-tools`를 실행해 커맨드 라인 `jsx` 툴을 설치할 수 있습니다. 이 툴은 JSX 구문을 일반적인 JavaScript파일로 변환해 브라우져에서 바로 실행할 수 있도록 합니다. 디렉터리를 감시해 파일이 변경되었을 때 자동으로 변환하도록 할 수도 있습니다. 예를 들면 `jsx --watch src/ build/` 이렇게요.
기본적으로는 JSX 파일들은 `.js` 확장자로 변환됩니다. `jsx --extension jsx src/ build/`를 사용해 `.jsx` 확장자로 파일들을 변환할 수 있습니다.
이 툴을 어떻게 사용하는지 더 자세하게 알고싶으시면 `jsx --help`를 실행해 보세요.
### 도움되는 오픈소스 프로젝트들
오픈 소스 커뮤니티는 JSX와 연동하는 여러 에디터와 빌드 시스템을 만들었습니다. 전 목록은 [JSX 연동](https://github.com/facebook/react/wiki/Complementary-Tools#jsx-integrations)에서 보세요.

26
docs/10-addons.ko-KR.md

@ -0,0 +1,26 @@
---
id: addons-ko-KR
title: 애드온
permalink: addons-ko-KR.html
prev: tooling-integration-ko-KR.html
next: animation-ko-KR.html
---
`React.addons`은 React 앱을 만드는 데 유용한 유틸리티를 두는 곳입니다. **실험적인 기능으로 취급해야 하지만** 결국 코어나 유틸리티 라이브러리에 포함될 예정입니다.
- [`TransitionGroup` 과 `CSSTransitionGroup`](animation-ko-KR.html)은 예를 들면 컴포넌트 삭제 직전의 트랜지션 처럼, 구현하기 까다로운 애니메이션과 트랜지션을 다룹니다.
- [`LinkedStateMixin`](two-way-binding-helpers-ko-KR.html)는 사용자 입력과 컴포넌트의 state사이의 조정(coordination)을 단순화 합니다.
- [`cloneWithProps`](clone-with-props-ko-KR.html)는 React 컴포넌트를 얕은 복사를 하고 props를 변경합니다.
- [`createFragment`](create-fragment-ko-KR.html)는 외부에서 키가 할당된 자식들의 모음을 만듭니다.
- [`update`](update-ko-KR.html)는 JavaScript안에서 불변 데이터를 다루기 쉽게하는 헬퍼 함수입니다.
- [`PureRenderMixin`](pure-render-mixin-ko-KR.html)는 특정 상황에서 성능을 향상시켜 줍니다.
- (비 추천) [`classSet`](class-name-manipulation-ko-KR.html)는 좀 더 알기 쉽게 DOM `class` 문자열을 다룹니다.
밑에 있는 애드온은 React 개발 (압축되지 않은) 버전에서만 사용가능 합니다.
- [`TestUtils`](test-utils-ko-KR.html)는 테스트 케이스를 적기 위한 간단한 헬퍼입니다. (압축되지 않은 빌드에서만 사용가능)
- [`Perf`](perf-ko-KR.html)는 성능을 측정하고, 최적화를 위한 힌트를 제공합니다.
애드온을 쓰려면, 보통 `react.js` 대신 `react-with-addons.js`(혹은 압축판)을 사용해야 합니다.
npm을 이용해 React 패키지를 설치해 사용한다면, 그냥 `require('react')` 대신 `require('react/addons')`을 사용해 모든 애드온을 쓸 수 있습니다.

185
docs/10.1-animation.ko-KR.md

@ -0,0 +1,185 @@
---
id: animation-ko-KR
title: 애니메이션
permalink: animation-ko-KR.html
prev: addons-ko-KR.html
next: two-way-binding-helpers-ko-KR.html
---
React에는 애니메이션을 위한 저 수준 API로 `ReactTransitionGroup` 애드온 컴포넌트가 있고 간단히 기초 CSS 애니메이션과 트랜지션을 구현할 수 있는 `ReactCSSTransitionGroup`가 있습니다.
## 고 레벨 API: `ReactCSSTransitionGroup`
`ReactCSSTransitionGroup``ReactTransitionGroup`를 기반으로 React 컴포넌트가 DOM에 들어가거나 나올때의 CSS의 트랜지션과 애니메이션을 구현하기 쉽게합니다. 이는 [ng-animate](http://www.nganimate.org/) 라이브러리에 영향을 받았습니다.
<a name="getting-stared"></a>
### 시작하기
`ReactCSSTransitionGroup``ReactTransitions`을 위한 인터페이스입니다. 이는 애니메이션을 제어할 모든 컴포넌트를 감싸는 하나의 엘리먼트 입니다. 아래는 목록의 아이템을 페이드 인/아웃하는 간단한 예제입니다.
```javascript{28-30}
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var TodoList = React.createClass({
getInitialState: function() {
return {items: ['hello', 'world', 'click', 'me']};
},
handleAdd: function() {
var newItems =
this.state.items.concat([prompt('Enter some text')]);
this.setState({items: newItems});
},
handleRemove: function(i) {
var newItems = this.state.items;
newItems.splice(i, 1);
this.setState({items: newItems});
},
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
{item}
</div>
);
}.bind(this));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup transitionName="example">
{items}
</ReactCSSTransitionGroup>
</div>
);
}
});
```
> 주의:
>
> `ReactCSSTransitionGroup`의 모든 자식은 [`key` 어트리뷰트](/react/docs/multiple-components-ko-KR.html#dynamic-children)를 반드시 만들어야 합니다. 한 아이템을 렌더한다 해도 예외는 아닙니다. 키는 React가 어떤 자식이 들어오고, 나가고, 머무르는지 파악할 때 사용합니다.
이 컴포넌트에서 새로운 아이템이 `ReactCSSTransitionGroup`에 추가되면 `example-enter` 아이템은 CSS 클래스를 가지게 되고 다음 순간에 `example-enter-active` CSS 클래스가 추가됩니다. 이는 `transitionName` prop을 기반으로 한 관례입니다.
이 클래스들은 CSS 애니메이션이나 트랜지션을 일으키는데 사용할 수 있습니다. 예를 들어, 이 CSS를 넣은 후 아이템을 추가해 보세요.
```css
.example-enter {
opacity: 0.01;
transition: opacity .5s ease-in;
}
.example-enter.example-enter-active {
opacity: 1;
}
```
`ReactCSSTransitionGroup`에서 아이템을 제거하려해도 DOM에는 남게 됩니다. 만약 애드온을 React의 최소화하지 않은 빌드와 사용한다면, 애니메이션이나 트랜지션이 일어나는 것을 예상하고 있었다는 React의 경고를 보게 될 것입니다. 그게 바로 `ReactCSSTransitionGroup`가 DOM 엘리먼트를 애니메이션이 끝날 때까지 페이지에 남겨두는 이유입니다. 이 CSS를 넣어보세요.
```css
.example-leave {
opacity: 1;
transition: opacity .5s ease-in;
}
.example-leave.example-leave-active {
opacity: 0.01;
}
```
### 애니메이션 그룹이 작동하려면 마운트가 필요
자식들에게 트랜지션을 적용하려면 `ReactCSSTransitionGroup`은 이미 DOM에 마운트되어 있어야 합니다. 예를 들어, 밑의 코드는 동작하지 않을 것입니다. 왜냐하면 `ReactCSSTransitionGroup` 안에서 새 아이템을 마운트하는 대신 새 아이템과 같이 `ReactCSSTransitionGroup`를 마운트했기 때문입니다. 이 것을 위에 있는 [시작하기](#getting-stared) 항목과 비교해보세요.
```javascript{12-15}
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
);
}, this);
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
{items}
</div>
);
}
```
### 아이템 하나이거나 없을 때의 애니메이션
위의 에제에서 `ReactCSSTransitionGroup`에 아이템 목록을 렌더했지만, `ReactCSSTransitionGroup`의 자식은 하나이거나 없을 수도 있습니다. 이는 한 엘리먼트가 들어오고 나가는 것의 애니메이션을 가능하게 합니다. 비슷하게, 현재 엘리먼트가 나가는 동안 새 앨리먼트의 애니메이션을 하면, 새 엘리먼트가 현재 엘리먼트를 교체하는 애니메이션을 만들 수 있습니다. 예를 들어 이렇게 간단한 이미지 회전 베너(carousel)를 구현할 수 있습니다.
```javascript{10-12}
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var ImageCarousel = React.createClass({
propTypes: {
imageSrc: React.PropTypes.string.isRequired
},
render: function() {
return (
<div>
<ReactCSSTransitionGroup transitionName="carousel">
<img src={this.props.imageSrc} key={this.props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
});
```
### 애니메이션 비활성화
원한다면 `enter``leave` 애니메이션을 비활성화 할 수 있습니다. 예를 들어, `enter` 애니메이션만 필요하고 `leave` 애니메이션은 필요없지만, `ReactCSSTransitionGroup`이 DOM 노드를 없애기 전 애니메이션이 완료되길 기다리고 있는 경우에 사용할 수 있습니다. `ReactCSSTransitionGroup``transitionEnter={false}``transitionLeave={false}` props를 추가하면 그 애니메이션을 비활성화 할 수 있습니다.
> 주의:
>
> `ReactCSSTransitionGroup`를 사용할 때는, 트랜지션이 종료되었을 때나 애니메이션 근처에서 더 복잡한 로직을 실행할 때 컴포넌트에 통지할 방법이 없습니다. 보다 세밀하게 제어하고 싶다면, 커스텀 트랜지션에 필요한 훅을 제공하는 저수준 `ReactTransitionGroup` API를 이용할 수 있습니다.
## 저수준 API: `ReactTransitionGroup`
`ReactTransitionGroup`은 애니메이션의 기초입니다. 이는 `React.addons.TransitionGroup`으로 접근할 수 있습니다. 위에 있는 예제처럼 자식들이 선언적으로 여기에 추가되거나 삭제되는 경우, 특별한 훅이 이 생명주기에서 호출됩니다.
### `componentWillEnter(callback)`
이는 이미 있는 `TransitionGroup`에 컴포넌트를 추가할 때 호출되는 `componentDidMount()`와 같이 호출됩니다. 이는 `callback`이 호출될 때까지 다른 애니메이션을 막습니다. `TransitionGroup`의 최조 렌더에서는 불려지지 않습니다.
### `componentDidEnter()`
이는 `componentWillEnter`에 넘겨주었던 `callback` 함수가 호출된 다음에 호출됩니다.
### `componentWillLeave(callback)`
이는 `ReactTransitionGroup`에서 자식이 제거되었을 때 호출됩니다. 자식이 제거되었다고 해도 `ReactTransitionGroup``callback`이 호출될 때까지 DOM에 자식을 남겨둡니다.
### `componentDidLeave()`
이는 `willLeave` `callback`이 호출될 때 호출됩니다. (`componentWillUnmount`와 같은 타이밍)
### 다른 컴포넌트 렌더하기
기본적으로 `ReactTransitionGroup``span`으로 렌더합니다. `component` prop으로 이 행동을 바꿀 수 있습니다. 예를 들어, `<ul>`을 렌더하고 싶다면 이렇게 하면 됩니다.
```javascript{1}
<ReactTransitionGroup component="ul">
...
</ReactTransitionGroup>
```
모든 React가 렌더할 수 있는 DOM 컴포넌트는 사용할 수 있습니다. 하지만 `component`가 DOM 컴포넌트일 필요는 없습니다. React 컴포넌트라면 무엇이든 넣을 수 있습니다. 직접 구현한 컴포넌트여도 됩니다!
> 주의:
>
> v0.12이전에는, DOM 컴포넌트를 사용할 때, `component` prop은 `React.DOM.*`로 참조할 필요가 있었습니다. 이제 컴포넌트가 단순히 `React.createElement`로 전달되기 때문에, `component` prop은 스트링이어야 합니다. 복합 컴포넌트는 팩토리를 넘겨야 합니다.
사용자 정의를 포함한 어떤 프로퍼티도 렌더된 컴포넌트의 프로퍼티가 됩니다. 예를 들어, `<ul>`에 CSS 클래스를 넣어서 렌더하려면 이렇게 하면 됩니다.
```javascript{1}
<ReactTransitionGroup component="ul" className="animated-list">
...
</ReactTransitionGroup>
```

114
docs/10.2-form-input-binding-sugar.ko-KR.md

@ -0,0 +1,114 @@
---
id: two-way-binding-helpers-ko-KR
title: 양방향 바인딩 핼퍼
permalink: two-way-binding-helpers-ko-KR.html
prev: animation-ko-KR.html
next: class-name-manipulation-ko-KR.html
---
`ReactLink`는 React에서 양방향 바인딩을 표현하는 쉬운 방법입니다.
> 주의:
>
> 프레임워크를 새로 접하신다면, 대부분의 애플리케이션에서 `ReactLink`는 필요없고 신중히 사용하셔야 함을 알려드립니다.
React에서 데이터 흐름은 소유주에서 자식으로의 단방향입니다. 이는 [폰 노이만 컴퓨팅 모델](http://ko.wikipedia.org/wiki/%ED%8F%B0_%EB%85%B8%EC%9D%B4%EB%A7%8C_%EA%B5%AC%EC%A1%B0)의 데이터가 단방향으로 흐르기 때문입니다. 이것을 "단방향 데이터 바인딩"으로 생각하셔도 됩니다.
하지만 많은 애플리케이션에서 데이터를 요청해서 프로그램으로 돌려줍니다. 예를 들어, 폼을 개발한다면, 사용자 입력을 받았을 때 `state`를 바꾸거나, JavaScript안에서 레이아웃을 바꾸고 그에 따라 어떤 DOM 엘리먼트의 크기를 바꾸게 하고 싶을 수도 있습니다.
React에서 이는 "change" 이벤트를 감시하고 데이터 소스(보통 DOM)에서 읽어 컴포넌트에서 `setState()`를 호출하는 식으로 할 수 있습니다. "데이터 흐름 반복을 제한"하면 더 이해하기 편하고, 쉽게 유지보수할 수 있는 프로그램이 만들어지는 것은 명확합니다. 더 자세한 내용은 [폼 문서](/react/docs/forms-ko-KR.html)를 확인하세요.
양방향 바인딩(묵시적으로 DOM의 어떤 값은 React `state`와 일치하도록 강제하는 것)은 간결하기도 하고 다양한 애플리케이션을 지원 할 수 있습니다. React는 `ReactLink`를 제공합니다. 이는 위에서 설명한 일반적인 데이터 흐름 반복 패턴을 설정하거나, 어떤 데이터 소스를 React `state`로 "링크하는" 편의 문법입니다.
> 주의:
>
> ReactLink는 얇은 레퍼고 `onChange`/`setState()`패턴 부분의 관례일 뿐입니다. React 애플리케이션에서의 데이터 흐름을 근본적으로 바꾸지는 않습니다.
## ReactLink: 적용 전후
`ReactLink`를 사용하지 않는 간단한 폼 예제입니다.
```javascript
var NoLink = React.createClass({
getInitialState: function() {
return {message: '안녕!'};
},
handleChange: function(event) {
this.setState({message: event.target.value});
},
render: function() {
var message = this.state.message;
return <input type="text" value={message} onChange={this.handleChange} />;
}
});
```
이것은 정말 잘 동작하고, 데이터가 어떻게 흐르는지 매우 명확하게 보여지지만, 폼필드가 많을 경우 약간 장황해 질 수 있습니다. 타이핑을 줄이기 위해 `ReactLink`를 사용해 보겠습니다.
```javascript{2,7}
var WithLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
return <input type="text" valueLink={this.linkState('message')} />;
}
});
```
`LinkedStateMixin`는 React 컴포넌트에 `linkState()`라는 메서드를 추가합니다. `linkState()`는 React state의 현재 값과 그것을 변경할 때의 콜백을 가지는 `ReactLink` 객체를 리턴합니다.
`ReactLink` 객체는 props로 트리의 위나 아래로 넘길 수 있어서, 쉽고 명확하게 계층구조에서 깊이 있는 컴포넌트와 높이 있는 state 사이의 양방향 바인딩을 설정할 수 있습니다.
checkbox의 `value` 어트리뷰트는 다른 것과 다르게 checkbox가 체크되었을 때 폼 submit에 값이 전달되는 것에 주의하세요.(기본값 `on`) 그래서 `value` 어트리뷰트는 checkbox가 체크되거나 해제될 때 업데이트되지 않습니다. checkbox에서는 `valueLink`대신 `checkedLink`를 사용하셔야 합니다.
```
<input type="checkbox" checkedLink={this.linkState('booleanValue')} />
```
## 내부 구조
`ReactLink`에는 크게 인스턴스를 생성하는 면과 사용하는 면이 있습니다. `ReactLink`가 얼마나 간단한지 확인하기 위해, 이 부분들을 보다 명시적으로 고쳐 봅시다.
### LinkedStateMixin 없이 ReactLink 쓰기
```javascript{5-7,9-12}
var WithoutMixin = React.createClass({
getInitialState: function() {
return {message: 'Hello!'};
},
handleChange: function(newValue) {
this.setState({message: newValue});
},
render: function() {
var valueLink = {
value: this.state.message,
requestChange: this.handleChange
};
return <input type="text" valueLink={valueLink} />;
}
});
```
보시다시피, `ReactLink` 객체는 `value``requestChange` prop만 가지는 매우 간단한 객체입니다. `LinkedStateMixin`도 간단합니다. 그냥 `this.state`의 값과 `this.setState()`에서 호출되는 콜백을 필드로 가질 뿐입니다.
### valueLink 없이 ReactLink 쓰기
```javascript
var WithoutLink = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function() {
var valueLink = this.linkState('message');
var handleChange = function(e) {
valueLink.requestChange(e.target.value);
};
return <input type="text" value={valueLink.value} onChange={handleChange} />;
}
});
```
`valueLink` prop도 간단합니다. 단순히 `onChange` 이벤트를 처리하고 `this.props.valueLink.requestChange()`를 호출하고 `this.props.value`대신 `this.props.valueLink.value`를 사용합니다. 그게 다에요!

62
docs/10.3-class-name-manipulation.ko-KR.md

@ -0,0 +1,62 @@
---
id: class-name-manipulation-ko-KR
title: 클래스 이름 조작
permalink: class-name-manipulation-ko-KR.html
prev: two-way-binding-helpers-ko-KR.html
next: test-utils-ko-KR.html
---
> 주의:
>
> 이 모듈은 이제 [JedWatson/classnames](https://github.com/JedWatson/classnames)에 독립적으로 있고 React와 관련없습니다. 그러므로 이 애드온은 제거될 예정입니다.
`classSet()`은 간단히 DOM `class` 문자열을 조작하는 편리한 도구입니다.
일반적으로 있을법한 경우와 `classSet()`을 사용하지 않았을 때의 처리법을 보시죠.
```javascript
// 어떤 `<Message />` React 컴포넌트의 안쪽
render: function() {
var classString = 'message';
if (this.props.isImportant) {
classString += ' message-important';
}
if (this.props.isRead) {
classString += ' message-read';
}
// 'message message-important message-read'
return <div className={classString}>좋아요, 거기서 봅시다.</div>;
}
```
이것은 순식간에 장황해질 수 있습니다. 클래스 이름 문자열은 읽기 어렵고 에러가 발생하기도 쉽죠. `classSet()`가 이 문제를 해결할 수 있습니다.
```javascript
render: function() {
var cx = React.addons.classSet;
var classes = cx({
'message': true,
'message-important': this.props.isImportant,
'message-read': this.props.isRead
});
// 최종 문자열은 동일하지만, 훨씬 깔끔함
return <div className={classes}>좋아요, 거기서 봅시다.</div>;
}
```
`classSet()`을 사용할 때 사용할지 안할지 잘 모르는 CSS 클래스 이름 키와 함께 객체를 전달합니다. true로 간주되는(Truthy) 값은 키를 결과 문자열의 일부로 만듭니다.
`classSet()`은 클래스 이름을 인자로 넘겨 연결되게 할 수도 있습니다.
```javascript
render: function() {
var cx = React.addons.classSet;
var importantModifier = 'message-important';
var readModifier = 'message-read';
var classes = cx('message', importantModifier, readModifier);
// 최종 문자열은 'message message-important message-read'
return <div className={classes}>좋아요, 거기서 봅시다.</div>;
}
```
복잡한 문자열 연결은 이제 안하셔도 됩니다!

181
docs/10.4-test-utils.ko-KR.md

@ -0,0 +1,181 @@
---
id: test-utils-ko-KR
title: 테스트 유틸리티
permalink: test-utils-ko-KR.html
prev: class-name-manipulation-ko-KR.html
next: clone-with-props-ko-KR.html
---
`React.addons.TestUtils`는 선택한 테스트 프레임워크(React는 [Jest](http://facebook.github.io/jest/)를 사용)에서 React 컴포넌트를 테스트하기 쉽게 합니다.
### Simulate
```javascript
Simulate.{eventName}(DOMElement element, object eventData)
```
DOM 노드에 이벤트 디스패치하는 것을 시뮬레이트합니다. 선택적으로 `eventData`를 통해 이벤트 데이터도 처리할 수 있습니다. **아마 `ReactTestUtils`에서 가장 유용한 유틸리티일 것 입니다.**
사용 예:
```javascript
var node = React.findDOMNode(this.refs.input);
React.addons.TestUtils.Simulate.click(node);
React.addons.TestUtils.Simulate.change(node, {target: {value: 'Hello, world'}});
React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter"});
```
`Simulate`에는 React가 이해하는 모든 이벤트에 대해 메소드가 있습니다.
### renderIntoDocument
```javascript
ReactComponent renderIntoDocument(ReactComponent instance)
```
문서의 detach된 DOM 노드에 컴포넌트를 렌더합니다. **이 기능은 DOM을 필요로 합니다.**
### mockComponent
```javascript
object mockComponent(function componentClass, string? mockTagName)
```
목 컴포넌트 모듈을 이 메소드에 넘겨 더미 React 컴포넌트로 사용할 수 있도록 합니다. 이 더미는 유용한 메소드와 함께 사용해 기능을 보강할 수 있습니다. 일반적인 렌더링과는 다르게, 컴포넌트는 제공된 자식을 포함하는 평범한 `<div>`가 됩니다. (`mockTagName`을 통해 div가 아닌 다른 태그를 지정해 줄 수도 있습니다.)
### isElement
```javascript
boolean isElement(ReactElement element)
```
`element`가 ReactElement면 true를 리턴합니다.
### isElementOfType
```javascript
boolean isElementOfType(ReactElement element, function componentClass)
```
`element`가 React `componentClass` 타입인 ReactElement면 true를 리턴합니다.
### isDOMComponent
```javascript
boolean isDOMComponent(ReactComponent instance)
```
`instance`가 (`<div>`나 `<span>`같은) DOM 컴포넌트면 true를 리턴합니다.
### isCompositeComponent
```javascript
boolean isCompositeComponent(ReactComponent instance)`
```
`instance`가 (`React.createClass()`로 생성된) 복합 컴포넌트면 true를 리턴합니다.
### isCompositeComponentWithType
```javascript
boolean isCompositeComponentWithType(ReactComponent instance, function componentClass)
```
`instance`가 (`React.createClass()`로 생성된) 복합 컴포넌트고 React `componentClass` 타입이면 true를 리턴합니다.
### findAllInRenderedTree
```javascript
array findAllInRenderedTree(ReactComponent tree, function test)
```
`tree`안의 모든 컴포넌트에서 `test(component)`가 true인 모든 컴포넌트를 모읍니다. 이것만으로는 그렇게 유용하지 않습니다만, 다른 테스트 유틸와 같이 사용합니다.
### scryRenderedDOMComponentsWithClass
```javascript
array scryRenderedDOMComponentsWithClass(ReactComponent tree, string className)
```
렌더된 트리의 모든 컴포넌트 인스턴스 중에서 클래스 이름이 `className`인 DOM 컴포넌트들을 찾습니다.
### findRenderedDOMComponentWithClass
```javascript
ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string className)
```
`scryRenderedDOMComponentsWithClass()`와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.
### scryRenderedDOMComponentsWithTag
```javascript
array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
```
렌더된 트리의 모든 컴포넌트 인스턴스중에서 태그 이름이 `tagName`인 DOM 컴포넌트들을 찾습니다.
### findRenderedDOMComponentWithTag
```javascript
ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagName)
```
`scryRenderedDOMComponentsWithTag()`와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.
### scryRenderedComponentsWithType
```javascript
array scryRenderedComponentsWithType(ReactComponent tree, function componentClass)
```
타입이 `componentClass`인 모든 컴포넌트 인스턴스를 찾습니다.
### findRenderedComponentWithType
```javascript
ReactComponent findRenderedComponentWithType(ReactComponent tree, function componentClass)
```
`scryRenderedComponentsWithType()`와 비슷하지만 하나의 결과만 기대될 때 사용합니다. 하나의 결과를 리턴하거나 한개 이상의 결과가 나온 경우에는 예외를 던집니다.
## 얕은 렌더링
얕은 렌더링은 "한 단계 깊이의" 컴포넌트를 렌더할 수 있는 실험적인 기능입니다. 자식 컴포넌트가 인스턴스화 되거나 렌더되는 등의 동작에 대한 걱정 없이 렌더 메소드가 반환하는 것만 검증합니다. 이 기능은 DOM이 필요하지 않습니다.
```javascript
ReactShallowRenderer createRenderer()
```
테스트에서 얕은 렌더러를 생성하고자 할때 호출합니다. 이를 이벤트와 업데이트에 스스로 반응하는 컴포넌트를 렌더하기 위한 "장소"라고 생각할 수 있습니다.
```javascript
shallowRenderer.render(ReactElement element)
```
`React.render`와 유사합니다.
```javascript
ReactComponent shallowRenderer.getRenderOutput()
```
렌더가 호출 된 후, 얕게 렌더된 결과물을 반환합니다. 그 후엔 결과물에 대한 검증을 시작할 수 있습니다. 예를 들어 컴포넌트의 렌더 메소드가 다음을 반환한다면:
```javascript
<div>
<span className="heading">Title</span>
<Subcomponent foo="bar" />
</div>
```
그 후에는 검증할 수 있습니다:
```javascript
result = renderer.getRenderOutput();
expect(result.type).toBe('div');
expect(result.props.children).toEqual([
<span className="heading">Title</span>
<Subcomponent foo="bar" />
]);
```
현재 얕은 테스트는 refs를 지원하지 않는 등 몇가지 제약사항이 있습니다. 우리는 이 기능을 빠르게 먼저 배포하고 React 커뮤니티의 피드백을 받아 나아갈 방향을 찾고자 합니다.

23
docs/10.5-clone-with-props.ko-KR.md

@ -0,0 +1,23 @@
---
id: clone-with-props-ko-KR
title: ReactElement 클론하기
permalink: clone-with-props-ko-KR.html
prev: test-utils-ko-KR.html
next: create-fragment-ko-KR.html
---
드문 경우긴 하지만 엘리먼트에서 소유하지 않은 엘리먼트의 props를 변경하고 싶을 때가 있습니다 (`this.props.children`로 전달된 엘리먼트의 `className` 변경 같은 경우). 아니면 전달된 엘리먼트의 복사본 여러 개를 만들고 싶을 수도 있습니다. 이는 `cloneWithProps()`로 할 수 있습니다.
#### `ReactElement React.addons.cloneWithProps(ReactElement element, object? extraProps)`
`element`를 얕게 복사하고 `extraProps`로 넘긴 props를 머지합니다. `className``style` props는 지능적인 방법으로 머지됩니다.
> 주의:
>
> `cloneWithProps``key`를 클론된 엘리먼트에 전달하지 않습니다. 키를 보존하고 싶으시면, `extraProps` 객체에 넣으세요.
>
> ```js
> var clonedElement = cloneWithProps(originalElement, { key : originalElement.key });
> ```
>
> 비슷하게 `ref`도 유지되지 않습니다.

73
docs/10.6-create-fragment.ko-KR.md

@ -0,0 +1,73 @@
---
id: create-fragment-ko-KR
title: 키가 할당된 프래그먼트
permalink: create-fragment-ko-KR.html
prev: clone-with-props-ko-KR.html
next: update-ko-KR.html
---
대부분의 경우는 `key` prop으로 `render`에서 반환된 엘리먼트에 키를 명시할 수 있습니다. 하지만 말썽을 부리는 경우가 한가지 있습니다: 재정렬을 할 두개의 자식 집합을 가지고 있는 경우, 감싸는 엘리먼트 없이 각각의 집합에 키를 부여하는 것은 불가능 합니다.
이 말은, 만약 다음과 같은 컴포넌트가 있다면:
```js
var Swapper = React.createClass({
propTypes: {
// `leftChildren``rightChildren`은 문자열, 엘리먼트, 배열 혹은 다른 무언가 일 수 있음.
leftChildren: React.PropTypes.node,
rightChildren: React.PropTypes.node,
swapped: React.PropTypes.bool
}
render: function() {
var children;
if (this.props.swapped) {
children = [this.props.rightChildren, this.props.leftChildren];
} else {
children = [this.props.leftChildren, this.props.rightChildren];
}
return <div>{children}</div>;
}
});
```
`swapped` prop을 변경할 경우 자식은 마운트 해제되거나 다시 마운트 될 수 있습니다. 두 자식 집합에 키가 할당되지 않았기 때문입니다.
이 문제를 해결하기 위해서 `React.addons.createFragment`를 사용해 자식 집합에 키를 부여할 수 있습니다.
#### `ReactFragment React.addons.createFragment(object children)`
배열을 만드는 대신에 다음과 같이 해볼 수 있습니다:
```js
if (this.props.swapped) {
children = React.addons.createFragment({
right: this.props.rightChildren,
left: this.props.leftChildren
});
} else {
children = React.addons.createFragment({
left: this.props.leftChildren,
right: this.props.rightChildren
});
}
```
전달된 객체의 키(`left`, `right`)는 모든 자식 집합의 키로 사용됩니다. 그리고 객체에서 키들의 순서는 렌더된 자식들의 순서를 결정하는데 사용됩니다. 이러한 변경으로 두 자식 집합은 언마운팅하지 않고도 DOM에서 적절하게 재정렬 됩니다.
`createFragment`의 반환값은 불명확한 객체로 취급되어야 합니다; `React.Children` 헬퍼를 사용해 프래그먼트를 순환할 수 있지만 직접 접근해서는 안됩니다. 명세에는 없지만 모든 주요 브라우저와 VM들에서 JavaScript 엔진이 숫자가 아닌 키에 대해서도 객체 목록 순서를 보존한다는 점을 주의하세요.
> **주의:**
>
> 미래에 `createFragment`는 대략 다음과 같은 API로 교체될 것입니다
>
> ```js
> return (
> <div>
> <x:frag key="right">{this.props.rightChildren}</x:frag>,
> <x:frag key="left">{this.props.leftChildren}</x:frag>
> </div>
> );
> ```
>
> JSX에서 엘리먼트로 감싸지 않고도 key를 바로 선언할 수 있게 될 것입니다.

101
docs/10.7-update.ko-KR.md

@ -0,0 +1,101 @@
---
id: update-ko-KR
title: 불변성 헬퍼들
permalink: update-ko-KR.html
prev: create-fragment-ko-KR.html
next: pure-render-mixin-ko-KR.html
---
React에서는 mutation을 포함해 어떤 데이터 관리 방식도 사용하실 수 있습니다. 하지만 애플리케이션의 성능이 중요한 부분에서 불변의(immutable) 데이터를 사용할 수 있다면, 쉽게 빠른 `shouldComponentUpdate()` 메소드를 구현해 애플리케이션의 속도를 크게 향상시킬 수 있습니다.
JavaScript에서 불변성의 데이터를 다루는 것은 [Clojure](http://clojure.org/)같이 그것을 위해 디자인된 언어로 다루는 것보다는 어렵습니다. 하지만, React는 간단한 불변성 헬퍼를 제공합니다. `update()`는 이런 종류의 데이터를 근본적인 변화 *없이* 쉽게 다루도록 해줍니다.
## 주요 아이디어
만약 데이터를 이렇게 변화시킨다면:
```js
myData.x.y.z = 7;
// or...
myData.a.b.push(9);
```
이전의 카피가 덮어씌워진다면 어떤 자료가 바뀌었는지 알 방도가 없습니다. 대신에, `myData`의 새로운 카피를 만들고 오직 변화가 필요한 부분만 바꿀 필요가 있습니다. 그 다음 `shouldComponentUpdate()` 에서 `myData`의 이전 카피와 새로운 카피를 `===` 연산자를 사용하여 비교할 수 있습니다.
```js
var newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);
```
하지만 깊은 복사는 비싸고, 가끔은 불가능하기도 합니다. 변화가 필요한 객체만 복제하고, 변화가 없는 객체는 다시 사용하는 방법으로만 비용을 줄일 수 있습니다. 안타깝지만 오늘날의 JavaScript에서는 그 방법이 성가실 수 있습니다:
```js
var newData = extend(myData, {
x: extend(myData.x, {
y: extend(myData.x.y, {z: 7}),
}),
a: extend(myData.a, {b: myData.a.b.concat(9)})
});
```
이것은 꽤 성능이 좋긴 하지만 (`log n`개의 객체만 얕은 복사하고, 나머지는 재사용하기 때문에), 일일히 쓰기엔 큰 고통이 따릅니다. 이 반복들을 보세요! 이건 짜증날 뿐만 아니라 버그들을 야기할수도 있습니다.
`update()`는 이런 패턴 속에서 코드를 더 쉽게 쓸 수 있도록 편의 문법을 제공합니다. 코드는 이렇습니다:
```js
var newData = React.addons.update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});
```
([MongoDB 쿼리 언어](http://docs.mongodb.org/manual/core/crud-introduction/#query)에서 영감을 받은) 이 문법에 익숙해지기에는 시간이 조금 걸리긴 하지만, 쓸모 없는 반복이 없고 정적분석이 가능할 뿐더러 변할 수 있는(mutative) 버전보다 더 많은 타이핑이 필요하지도 않습니다.
`$`가 앞에 붙어있는 키들은 *커맨드* 라고 불립니다. "변하는" 자료 구조는 *타겟* 이라고 불립니다.
## 사용가능한 커맨드들
* `{$push: array}` 모든 아이템들을 타겟에 있는 `array``push()`합니다.
* `{$unshift: array}` 타겟속 `array`에 있는 모든 아이템들을 `unshift()`합니다.
* `{$splice: array of arrays}` `arrays` 안의 각 아이템들이 `splice()`를 주어진 인자들을 사용해 호출하게 합니다.
* `{$set: any}` 타겟 전체를 대체합니다.
* `{$merge: object}` 타겟과 `object`의 키들을 병합합니다.
* `{$apply: function}` 는 지금 값을 함수에 전달하고 새로운 리턴 값으로 업데이트합니다.
## 예제
### 간단한 push
```js
var initialArray = [1, 2, 3];
var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
```
`initialArray` 은 여전히 `[1, 2, 3]` 입니다.
### 중첩된 컬렉션
```js
var collection = [1, 2, {a: [12, 17, 15]}];
var newCollection = update(collection, {2: {a: {$splice: [[1, 1, 13, 14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
```
이것은 `collection`의 인덱스 `2`의 키 `a`에 접근해, 인덱스 `1`에 있는 한 아이템을 접합(splice)해서(`17`를 제거하고) `13`, `14`를 추가합니다.
### 현재 상태에 의거해 값을 업데이트
```js
var obj = {a: 5, b: 3};
var newObj = update(obj, {b: {$apply: function(x) {return x * 2;}}});
// => {a: 5, b: 6}
// 위의 것과 같은 동작을 합니다만, 깊게 중첩된 컬렉션들에서는 더 장황해 집니다.
var newObj2 = update(obj, {b: {$set: obj.b * 2}});
```
### (얕은) 합병
```js
var obj = {a: 5, b: 3};
var newObj = update(obj, {$merge: {b: 6, c: 7}}); // => {a: 5, b: 6, c: 7}
```

30
docs/10.8-pure-render-mixin.ko-KR.md

@ -0,0 +1,30 @@
---
id: pure-render-mixin-ko-KR
title: PureRenderMixin
permalink: pure-render-mixin-ko-KR.html
prev: update-ko-KR.html
next: perf-ko-KR.html
---
React 컴포넌트의 렌더 함수가 "pure"하다면 (다른 말로, props나 state에 같은 값이 주어질 때 같은 결과를 렌더한다면) 몇몇 경우엔 이 믹스인을 사용하여 성능을 향상시킬 수 있습니다.
예제:
```js
var PureRenderMixin = require('react/addons').addons.PureRenderMixin;
React.createClass({
mixins: [PureRenderMixin],
render: function() {
return <div className={this.props.className}>foo</div>;
}
});
```
내부적으로 믹스인은 현재의 props와 state를 다음 값과 비교하여 같다면 `false`를 반환하도록 [shouldComponentUpdate](/react/docs/component-specs-ko-KR.html#updating-shouldcomponentupdate)를 구현합니다.
> 주의:
>
> 여기서는 객체에 대한 얕은(shallow) 비교만 합니다. 복잡한 데이터 구조를 가진 경우에는 깊은 부분의 차이에 대해 잘못된 false를 반환 할 수도 있습니다. 간단한 props와 state를 사용하는 컴포넌트에만 적용하거나 깊은 데이터 구조가 변경 되었을때는 `forceUpdate()`를 사용하세요. 아니면 중첩 데이터의 비교를 빠르고 용이하게 하기 위해 [immutable 객체](http://facebook.github.io/immutable-js/)의 도입을 고려해보세요.
>
> 또, `shouldComponentUpdate`는 컴포넌트 서브트리의 업데이트를 건너뜁니다. 모든 자식 컴포넌트들도 "pure"한지 확인하세요.

72
docs/10.9-perf.ko-KR.md

@ -0,0 +1,72 @@
---
id: perf-ko-KR
title: 성능 도구
permalink: perf-ko-KR.html
prev: pure-render-mixin-ko-KR.html
next: advanced-performance-ko-KR.html
---
React는 보통 처음에는 꽤 빠릅니다. 하지만 모든 성능을 짜내야 하는 상황일 때를 위해, React는 [shouldComponentUpdate](/react/docs/component-specs.html#updating-shouldcomponentupdate) 훅을 제공해 React의 diff 알고리즘을 위한 최적화 힌트를 추가할 수 있습니다.
덧붙여 앱의 전반적인 성능의 개요도 제공합니다. ReactPerf는 프로파일링 도구로 정확히 어디에 훅이 필요한지 알려줍니다.
> 주의:
>
> React의 개발 빌드는 제공되는 추가 기능으로 인해 프로덕션 빌드보다 느립니다. 추가 기능에는 React의 친절한 콘솔 경고같은 것이 있습니다.(이는 프로덕션 빌드에서는 제거 됩니다) 따라서, 프로파일러는 앱의 _상대적으로_ 비싼 부분만 표시하도록 합니다.
## 일반 API
여기에서 설명하는 `Perf` 객체는 `react-with-addons.js`를 사용해 개발 모드에서 빌드될 때 `React.addons.Perf`로 노출됩니다.
### `Perf.start()``Perf.stop()`
측정을 시작/정지합니다. 그 사이의 React 연산은 밑에 있는 분석을 하기위해 기록됩니다. 미미한 양의 연산은 무시됩니다.
### `Perf.printInclusive(measurements)`
전 수행 시간을 출력합니다. 인자가 넘겨지지 않으면, 기본값은 지난 기록부터의 모든 측정이 됩니다. 이 출력은 밑에 있는 것처럼 콘솔에서 깔끔한 테이블로 그려집니다.
![](/react/img/docs/perf-inclusive.png)
### `Perf.printExclusive(measurements)`
컴포넌트를 마운트하는 시간을 포함하지 않은 "exclusive" 시간입니다. 여기에는 props 연산, `getInitialState`, `componentWillMount` 호출, `componentDidMount`등이 포함됩니다.
![](/react/img/docs/perf-exclusive.png)
### `Perf.printWasted(measurements)`
**프로파일러에서 가장 유용한 부분입니다**.
렌더가 같아서, DOM을 변경(touch)하지 않는 경우같은 실제로는 아무것도 렌더하지 않는 컴포넌트가 사용하는 "낭비되는" 시간을 출력합니다.
![](/react/img/docs/perf-wasted.png)
### `Perf.printDOM(measurements)`
"set innerHTML"이나 "remove"같은 기저의 DOM 조작을 출력합니다.
![](/react/img/docs/perf-dom.png)
## 고급 API
위의 출력 메소드에 `Perf.getLastMeasurements()`를 사용해 결과를 이쁘게 출력합니다.
### `Perf.getLastMeasurements()`
마지막 start-stop 세션에서 측정들의 배열을 가져옵니다. 이 배열은 이런 객체들을 가지고 있습니다.
```js
{
// 용어 "inclusive"와 "exclusive"는 위에서 설명했음
"exclusive": {},
// '.0.0'는 노드의 React ID
"inclusive": {".0.0": 0.0670000008540228, ".0": 0.3259999939473346},
"render": {".0": 0.036999990697950125, ".0.0": 0.010000003385357559},
// 인스턴스의 수
"counts": {".0": 1, ".0.0": 1},
// DOM 변경(touch)
"writes": {},
// 추가 디버깅 정보
"displayNames": {
".0": {"current": "App", "owner": "<root>"},
".0.0": {"current": "Box", "owner": "App"}
},
"totalTime": 0.48499999684281647
}
```

205
docs/11-advanced-performance.ko-KR.md

@ -0,0 +1,205 @@
---
id: advanced-performance-ko-KR
title: 성능 심화
permalink: advanced-performance-ko-KR.html
prev: perf-ko-KR.html
---
React를 도입하려 할 때 많은 사람이 묻는 첫 번째 질문은 React를 사용하지 않을 때처럼 애플리케이션이 빠르고 반응성도 좋을 것이냐는 것입니다. 모든 상태변화에 대해 컴포넌트의 하위 트리를 전부 다시 렌더링하는 아이디어에 대해 사람들은 이 프로세스가 성능에 부정적인 영향을 줄 것으로 생각하지만, React는 여러 가지 영리한 방법을 통해 UI를 업데이트하는데 필요한 비싼 DOM 조작을 최소화합니다.
## DOM 조정 회피
React는 브라우저에서 렌더된 DOM 하위 트리의 서술자 개념인 *가상의 DOM*을 사용합니다. 이 병렬적인 서술체는 React가 DOM 노드를 생성하거나 이미 존재하는 DOM 노드에 접근하는 것(JavaScript 객체를 조작하는 것보다 느리죠)을 피하게 해 줍니다. 컴포넌트의 props나 state가 변경되면 React는 새로운 가상의 DOM을 구성해 이전의 것과 비교해서 실제 DOM 업데이트가 필요한지 결정합니다. 가능한 적게 변화를 적용하기 위해, React는 둘이 다를 경우에만 DOM을 [조정](/react/docs/reconciliation-ko-KR.html)할 것입니다.
이에 더해, React는 컴포넌트 생명주기 함수인 `shouldComponentUpdate`를 제공합니다. 이는 다시 렌더링하는 프로세스가 일어나기 직전에 일어나며 개발자가 프로세스를 중단할 수 있게 합니다. 이 함수의 기본구현은 `true`를 반환해 React가 업데이트를 수행하도록 합니다.
```javascript
shouldComponentUpdate: function(nextProps, nextState) {
return true;
}
```
React가 이 함수를 자주 호출한다는 것을 명심하십시오. 따라서 구현체는 빨라야 합니다.
대화 스레드가 여럿 돌고 있는 메시지처리 애플리케이션을 생각해 봅시다. 오직 하나의 스레드만이 변경되었다고 가정해 보죠. `ChatThread``shouldComponentUpdate`를 구현했다면 React는 다른 스레드의 렌더링 프로세스를 건너뛸 수 있습니다.
```javascript
shouldComponentUpdate: function(nextProps, nextState) {
// TODO: 현재의 대화 스레드가 이전의 것과 다른지 아닌지를 반환한다
}
```
정리하자면, React는 사용자가 `shouldComponentUpdate`를 사용해 렌더링 프로세스를 중단하고 가상의 DOM과 비교해 업데이트 여부를 결정해서 DOM의 하위 트리를 조정하는 비싼 DOM 조작을 피하도록 합니다.
## shouldComponentUpdate 실전
다음은 컴포넌트의 하위 트리입니다. 각각은 `shouldComponentUpdate`의 반환값(SCU)과 가상의 DOM과의 동일성(vDOMEq)을 표시합니다. 마지막으로, 원의 색은 컴포넌트가 조정되었는지를 표시합니다.
<figure><img src="/react/img/docs/should-component-update.png" /></figure>
위의 예시에서, C2를 루트로 하는 하위 트리에 대해 `shouldComponentUpdate``false`를 반환했기 때문에 React는 새로운 가상의 DOM을 만들 필요가 없습니다. 따라서 DOM을 조정할 필요도 없습니다. React가 C4와 C5에는 `shouldComponentUpdate`를 요청하지도 않은 것을 확인하세요.
C1과 C3의 `shouldComponentUpdate``true`를 반환했기 때문에 React는 하위 노드로 내려가 그들을 확인합니다. C6는 `true`를 반환했네요; 이는 가상의 DOM과 같지 않기 때문에 DOM의 조정이 일어났습니다. 마지막으로 흥미로운 사례는 C8입니다. React가 이 노드를 위해 가상의 DOM을 작동했지만, 노드가 이전의 것과 일치했기 때문에 DOM의 조정을 일어나지 않았습니다.
React가 C6에만 DOM 변경을 수행한 것을 확인하세요. 이는 필연적이었습니다. C8의 경우는 가상의 DOM과 비교를 해 제외되었고, C2의 하위 트리와 C7은 `shouldComponentUpdate` 단계에서 제외되어 가상의 DOM은 구동조차 되지 않았습니다.
자 그럼, 어떻게 `shouldComponentUpdate`를 구현해야 할까요? 문자열 값을 렌더하는 컴포넌트를 생각해보죠.
```javascript
React.createClass({
propsTypes: {
value: React.PropTypes.string.isRequired
},
render: function() {
return <div>this.props.value</div>;
}
});
```
다음과 같이 간단히 `shouldComponentUpdate`를 구현해 볼 수 있습니다:
```javascript
shouldComponentUpdate: function(nextProps, nextState) {
return this.props.value !== nextProps.value;
}
```
여기까지는 좋습니다. 간단한 props/state 구조를 다루기는 쉽습니다. 단순한 등식비교 구현을 일반화하고 이를 컴포넌트에 혼합할 수도 있습니다. 사실, React는 이미 그런 구현을 제공합니다: [PureRenderMixin](/react/docs/pure-render-mixin-ko-KR.html).
하지만 만약 컴포넌트의 props나 state가 가변적인 데이터 구조로 되어 있다면 어떨까요? 컴포넌트의 prop으로 `'bar'`같은 문자열 대신에 `{ foo: 'bar' }`처럼 문자열을 포함한 JavaScript 객체를 전달받는다고 해봅시다.
```javascript
React.createClass({
propsTypes: {
value: React.PropTypes.object.isRequired
},
render: function() {
return <div>this.props.value.foo</div>;
}
});
```
전에 구현했던 `shouldComponentUpdate`는 언제나 예상대로 작동하지 않을 것입니다:
```javascript
// this.props.value가 { foo: 'bar' }라고 가정합니다
// nextProps.value도 { foo: 'bar' }라고 가정하지만,
// 이 참조는 this.props.value와 다른 것입니다
this.props.value !== nextProps.value; // true
```
문제는 prop이 실제로 변경되지 않았을 때도 `shouldComponentUpdate``true`를 반환할 거라는 겁니다. 이를 해결하기 위한 대안으로 아래와 같이 구현해 볼 수 있습니다:
```javascript
shouldComponentUpdate: function(nextProps, nextState) {
return this.props.value.foo !== nextProps.value.foo;
}
```
기본적으로, 우리는 변경을 정확히 추적하기 위해서 깊은 비교를 해야 했습니다. 이 방법은 성능 면에서 제법 비싸고 각각의 모델마다 다른 깊은 등식 코드를 작성해야 하므로 확장이 힘들어 집니다. 심지어 객체 참조를 신중히 관리하지 않는다면 작동하지도 않을 수 있습니다. 컴포넌트가 부모에 의해 다뤄지는 경우를 살펴보죠:
```javascript
React.createClass({
getInitialState: function() {
return { value: { foo: 'bar' } };
},
onClick: function() {
var value = this.state.value;
value.foo += 'bar'; // 안티패턴 입니다!
this.setState({ value: value });
},
render: function() {
return (
<div>
<InnerComponent value={this.state.value} />
<a onClick={this.onClick}>클릭하세요</a>
</div>
);
}
});
```
처음엔 내부 컴포넌트(`<InnerComponent />`)가 `{ foo: 'bar' }`를 value prop으로 가진 채 렌더될 것입니다. 사용자가 앵커(`<a>`)를 클릭한다면 부모 컴포넌트의 state는 `{ value: { foo: 'barbar' } }`로 업데이트되고, 내부 컴포넌트 또한 `{ foo: 'barbar' }`를 새로운 value prop으로 전달받아 다시 렌더링 되는 프로세스가 일어날 것입니다.
이 문제는 부모와 내부 컴포넌트가 같은 객체에 대한 참조를 공유하기 때문에 발생합니다. `onClick` 함수의 두 번째 줄에서 객체에 대한 변경이 일어날 때, 내부 컴포넌트의 prop도 변경될 것입니다. 따라서 다시 렌더링 되는 프로세스가 시작될 때 `shouldComponentUpdate`가 호출되고 `this.props.value.foo``nextProps.value.foo`와 같게 됩니다. 실제로 `this.props.value``nextProps.value`와 같은 객체이기 때문입니다.
그에따라 prop의 변경을 놓치게 되어 다시 렌더링하는 프로세스가 중단되고, UI는 `'bar'`에서 `'barbar'`로 업데이트되지 않습니다.
## 구원자 Immutable-js
[Immutable-js](https://github.com/facebook/immutable-js)는 Lee Byron이 만들고 Facebook이 오픈소스화 한 Javascript 컬렉션 라이브러리입니다. 이는 *구조의 공유(structural sharing)*를 통해 *불변의 영속적인(immutable persistent)* 컬렉션을 제공합니다. 이러한 속성이 무엇을 의미하는지 살펴보죠:
* *불변성(Immutable)*: 컬렉션이 한번 생성되면, 이 후 다른 시점에 변경될 수 없습니다.
* *영속성(Persistent)*: 새로운 컬렉션이 이전의 컬렉션이나 셋(set) 같은 뮤테이션(mutation)에서 생성될 수 있습니다. 기존의 컬렉션은 새로운 컬렉션이 생성된 후에도 여전히 유효합니다.
* *구조의 공유(Structural Sharing)*: 새로운 컬렉션은 가능한 한 원래의 컬렉션과 같은 구조를 사용해 생성됩니다. 공간 효율성과 적절한 성능을 위해 복사를 최소화합니다.
불변성은 변경의 추적을 비용을 줄여줍니다; 변경은 항상 새로운 객체에만 발생하기 때문에 객체에 대한 참조가 변경될 때만 확인하면 됩니다. 예를 들어 일반적인 JavaScript 코드에서는:
```javascript
var x = { foo: "bar" };
var y = x;
y.foo = "baz";
x === y; // true
```
`y`가 수정되더라도 여전히 같은 객체인 `x`를 참조하고 있기 때문에, 이 비교는 `true`를 반환합니다. 하지만 이 코드를 immutable-js를 사용해 다음과 같이 작성할 수 있습니다:
```javascript
var SomeRecord = Immutable.Record({ foo: null });
var x = new SomeRecord({ foo: 'bar' });
var y = x.set('foo', 'baz');
x === y; // false
```
이 경우, `x`가 변경되면 새로운 참조가 반환되기 때문에, 우리는 안전하게 `x`가 변경되었을 것으로 추정할 수 있습니다.
변경을 탐지할 수 있는 또 다른 방법은 세터(setter)에 의해 설정된 플래그를 더티 체킹(dirty checking)하는 것입니다. 이 방식의 문제는 당신이 세터를 사용할 뿐만 아니라 수많은 추가 코드를 작성하거나 어떻게든 클래스들을 인스트루먼트(instrument) 하도록 강요한다는 것입니다. 혹은 변경(mutations) 직전에 객체를 깊은 복사(deep copy) 한 뒤 깊은 비교(deep compare)를 수행해 변경 여부를 판단할 수 있습니다. 이 방식의 문제점은 deepCopy와 deepCompare 둘 다 비용이 많이 드는 연산이라는 것입니다.
그래서 Immutable 자료구조는 `shouldComponentUpdate`의 구현에 필요한 객체의 변경사항을 추적할 수 있는 덜 자세하지만 저렴한 방법을 제공합니다. 그에 따라 immutable-js가 제공하는 추상화를 사용해 props와 state 어트리뷰트를 모델링한다면, `PureRenderMixin`을 사용해 성능을 향상할 수 있습니다.
## Immutable-js와 Flux
[Flux](http://facebook.github.io/flux/)를 사용한다면 immutable-js를 사용해 stores를 작성해야 합니다. [전체 API](http://facebook.github.io/immutable-js/docs/#/)를 살펴보세요.
Immutable 자료구조를 이용해 스레드를 모델링하는 예제를 살펴봅시다. 먼저 모델링하려는 엔티티마다 `Record`를 정의해야 합니다. Record는 특정 필드들의 값을 유지하기 위한 불변의 컨테이너입니다:
```javascript
var User = Immutable.Record({
id: undefined,
name: undefined,
email: undefined
});
var Message = Immutable.Record({
timestamp: new Date(),
sender: undefined,
text: ''
});
```
`Record` 함수는 필드별로 기본값이 선언된 객체에 대한 정의를 넘겨받습니다.
메시지 store는 두 개의 List를 통해 users와 messages를 추적할 수 있습니다:
```javascript
this.users = Immutable.List();
this.messages = Immutable.List();
```
각각의 *페이로드* 타입을 처리하는 기능을 구현하는 것은 꽤 간단합니다. 예를 들면, store가 새 메시지를 나타내는 페이로드를 확인할 때 레코드를 새로 생성하고 메시지 리스트에 추가할 수 있습니다.
```javascript
this.messages = this.messages.push(new Message({
timestamp: payload.timestamp,
sender: payload.sender,
text: payload.text
});
```
자료구조가 불변이기 때문에 push 함수의 결과를 this.messages에 할당할 필요가 있으니 주의하세요.
React 측에서는, 컴포넌트의 state를 보존하기 위해 immutable-js 자료구조를 사용한다면, 모든 컴포넌트에 `PureRenderMixin`을 혼합해 다시 렌더링하는 프로세스를 중단할 수 있습니다.

9
docs/complementary-tools.ko-KR.md

@ -0,0 +1,9 @@
---
id: complementary-tools-ko-KR
title: 상호 보완적인 도구들
permalink: complementary-tools-ko-KR.html
prev: videos-ko-KR.html
next: examples-ko-KR.html
---
이 페이지는 이동되었습니다. [GitHub wiki](https://github.com/facebook/react/wiki/Complementary-Tools).

19
docs/conferences.ko-KR.md

@ -0,0 +1,19 @@
---
id: conferences-ko-KR
title: 컨퍼런스들
permalink: conferences-ko-KR.html
prev: thinking-in-react-ko-KR.html
next: videos-ko-KR.html
---
### React.js Conf 2015
1월 28일 & 29일
[웹사이트](http://conf.reactjs.com/) - [스케줄](http://conf.reactjs.com/schedule.html) - [비디오들](https://www.youtube.com/playlist?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr)
<iframe width="650" height="315" src="//www.youtube.com/embed/KVZ-P-ZI6W4?list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr" frameborder="0" allowfullscreen></iframe>
### ReactEurope 2015
7월 2일 & 3일
[웹사이트](http://www.react-europe.org/) - [스케줄](http://www.react-europe.org/#schedule)

8
docs/examples.ko-KR.md

@ -0,0 +1,8 @@
---
id: examples-ko-KR
title: 예제들
permalink: examples-ko-KR.html
prev: complementary-tools-ko-KR.html
---
이 페이지는 이동되었습니다. [GitHub wiki](https://github.com/facebook/react/wiki/Examples).

7
docs/flux-overview.ko-KR.md

@ -0,0 +1,7 @@
---
id: flux-overview-ko-KR
title: Flux 애플리케이션 아키텍쳐
permalink: flux-overview-ko-KR.html
---
이 페이지는 Flux 웹사이트로 이동되었습니다. [거기서 보세요](http://facebook.github.io/flux/docs/overview.html).

1
docs/flux-overview.md

@ -1,6 +1,7 @@
--- ---
id: flux-overview id: flux-overview
title: Flux Application Architecture title: Flux Application Architecture
permalink: flux-overview.html
--- ---
This page has been moved to the Flux website. [View it there](http://facebook.github.io/flux/docs/overview.html). This page has been moved to the Flux website. [View it there](http://facebook.github.io/flux/docs/overview.html).

7
docs/flux-todo-list.ko-KR.md

@ -0,0 +1,7 @@
---
id: flux-todo-list-ko-KR
title: Flux TodoMVC 튜토리얼
permalink: flux-todo-list-ko-KR.html
---
이 페이지는 Flux 웹사이트로 이동되었습니다. [거기서 보세요](http://facebook.github.io/flux/docs/todo-list.html).

1
docs/flux-todo-list.md

@ -1,6 +1,7 @@
--- ---
id: flux-todo-list id: flux-todo-list
title: Flux TodoMVC Tutorial title: Flux TodoMVC Tutorial
permalink: flux-todo-list.html
--- ---
This page has been moved to the Flux website. [View it there](http://facebook.github.io/flux/docs/todo-list.html). This page has been moved to the Flux website. [View it there](http://facebook.github.io/flux/docs/todo-list.html).

116
docs/getting-started.ko-KR.md

@ -0,0 +1,116 @@
---
id: getting-started-ko-KR
title: 시작해보기
permalink: getting-started-ko-KR.html
next: tutorial-ko-KR.html
redirect_from: "docs/index-ko-KR.html"
---
## JSFiddle
React를 시작하는 가장 빠른 방법은 다음의 Hello World JSFiddle 예제를 따라 해 보는 것입니다.
* **[React JSFiddle](http://jsfiddle.net/reactjs/69z2wepo/)**
* [React JSFiddle without JSX](http://jsfiddle.net/reactjs/5vjqabv3/)
## 초심자용 키트
초심자용 키트를 내려받아 시작합니다.
<div class="buttons-unit downloads">
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
초심자용 키트 내려받기 {{site.react_version}}
</a>
</div>
초심자용 키트의 최상위 디렉터리에 아래의 내용대로 `helloworld.html` 파일을 생성합니다.
```html
<!DOCTYPE html>
<html>
<head>
<script src="build/react.js"></script>
<script src="build/JSXTransformer.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
React.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
```
JavaScript 안에 보이는 XML 구문은 JSX라고 합니다; 더 자세한 내용은 [JSX syntax](/react/docs/jsx-in-depth-ko-KR.html)을 확인하세요. 일반적인 JavaScript로 번역하기 위해 `<script type="text/jsx">`를 사용하고 `JSXTransformer.js`를 포함하는 것으로 실제로 브라우저에서 변환작업을 수행합니다.
### 파일의 분리
React JSX 코드는 분리된 파일로 존재할 수 있습니다. 다음 내용으로 `src/helloworld.js`를 생성해보세요.
```javascript
React.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
```
그다음 `helloworld.html`에서 참조합니다:
```html{10}
<script type="text/jsx" src="src/helloworld.js"></script>
```
### 오프라인 변환
먼저 커맨드라인 도구를 설치합니다. ([npm](http://npmjs.org/) 필요):
```
npm install -g react-tools
```
그다음, `src/helloworld.js` 파일을 일반 JavaScript 파일로 변환합니다:
```
jsx --watch src/ build/
```
수정할 때마다 `build/helloworld.js` 파일이 자동생성됩니다.
```javascript{2}
React.render(
React.createElement('h1', null, 'Hello, world!'),
document.getElementById('example')
);
```
아래의 내용대로 HTML 파일을 업데이트합니다:
```html{6,10}
<!DOCTYPE html>
<html>
<head>
<title>Hello React!</title>
<script src="build/react.js"></script>
<!-- JSXTransformer는 이제 불필요합니다! -->
</head>
<body>
<div id="example"></div>
<script src="build/helloworld.js"></script>
</body>
</html>
```
## CommonJS를 원하시나요?
만약 React를 [browserify](http://browserify.org/), [webpack](http://webpack.github.io/)이나 기타 CommonJS와 호환되는 모듈시스템과 함께 사용하고 싶다면, [`react` npm 패키지](https://www.npmjs.org/package/react)를 사용하세요. 그 외에도 `jsx` 빌드툴은 아주 쉽게 CommonJS 외에도 대부분의 패키징 시스템에 통합될 수 있습니다.
## 다음 단계로
더 알아보려면 [튜토리얼](/react/docs/tutorial-ko-KR.html)과 초심자용 키트의 `examples` 디렉터리에서 다른 예제들을 확인해 보세요.
커뮤니티의 기여로 운영되는 Wiki도 있습니다: [워크플로우, UI 컴포넌트, 라우팅, 데이터 관리 등](https://github.com/facebook/react/wiki/Complementary-Tools)
React의 세계에 오신 것을 환영합니다. 행운을 빌어요!

191
docs/ref-01-top-level-api.ko-KR.md

@ -0,0 +1,191 @@
---
id: top-level-api-ko-KR
title: 최상위 API
permalink: top-level-api-ko-KR.html
next: component-api-ko-KR.html
redirect_from: "/docs/reference-ko-KR.html"
---
## React
`React`는 React 라이브러리의 진입점입니다. 미리 빌드된 패키지를 사용하는 경우 전역 변수로 접근할 수 있습니다. CommonJS 모듈을 사용하는 경우에는 `require()`로 불러올 수 있습니다.
### React.Component
```javascript
class Component
```
ES6 클래스 구문을 사용해 React 컴포넌트를 정의했을 때 기본 클래스가 되는 부분입니다. 어떻게 ES6 클래스 구문을 사용해 React를 다루는지는 [재사용가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html#es6-classes)를 확인하세요. 기본 클래스에서 실제 제공되는 메소드들에는 어떤것이 있는지 알아보려면 [컴포넌트 API](/react/docs/component-api-ko-KR.html)를 확인하세요.
### React.createClass
```javascript
ReactClass createClass(object specification)
```
주어진 명세에 따라 컴포넌트 클래스를 만듭니다. 컴포넌트는 단 하나의 자식만을 리턴하는 `render` 메소드를 구현합니다. 그 자식은 임의 깊이의 자식 구조를 가질 수 있습니다. 컴포넌트가 일반적인 프로토타입 기반의 클래스와 다른 점은 생성할 때 `new` 연산자를 사용하지 않아도 된다는 것입니다. 컴포넌트는 (`new` 연산자를 통해) 내부 인스턴스를 만들어 주는 편의 래퍼(wrapper)입니다.
명세 객체에 대한 자세한 정보는 [컴포넌트 명세와 생명주기](/react/docs/component-specs-ko-KR.html)를 참고하세요.
### React.createElement
```javascript
ReactElement createElement(
string/ReactClass type,
[object props],
[children ...]
)
```
주어진 타입의 새 `ReactElement`를 만들고 리턴합니다. `type` 인자는 HTML 태그명 문자열 (예: 'div', 'span' 등) 또는 (`React.createClass`로 만든) `ReactClass`입니다.
### React.cloneElement
```
ReactElement cloneElement(
ReactElement element,
[object props],
[children ...]
)
```
`element`를 시작점으로 새로운 `ReactElement`를 클론해 반환합니다. 반환된 엘리먼트에는 원본의 props와 새로운 props가 얕게 병합됩니다. 새 자식은 존재하는 자식을 교체할 것입니다. `React.addons.cloneWithProps`와는 다르게, 원본 엘리먼트의 `key``ref`는 보존될 것입니다. `cloneWithProps`와는 달리 props이 병합되는데는 어떠한 특별한 동작도 없습니다. [v0.13 RC2 블로그 포스트](/react/blog/2015/03/03/react-v0.13-rc2.html)에서 추가적인 내용을 확인하세요.
### React.createFactory
```javascript
factoryFunction createFactory(
string/ReactClass type
)
```
주어진 타입의 ReactElement를 만들어주는 함수를 리턴합니다. `React.createElement`와 마찬가지로 `type` 인자는 HTML 태그명 문자열 (예: 'div', 'span' 등) 또는 `ReactClass`입니다.
### React.render
```javascript
ReactComponent render(
ReactElement element,
DOMElement container,
[function callback]
)
```
주어진 ReactElement를 `container` 인자에 넘어온 DOM 안에 렌더링하고 컴포넌트의 레퍼런스를 리턴합니다.
어떤 ReactElement가 이미 `container`에 렌더링 된 적이 있다면, 그것을 업데이트한 뒤 React 컴포넌트의 최신 상태를 반영하기 위해 꼭 필요한 만큼만 DOM을 변경합니다.
콜백 인자를 넘기면 컴포넌트가 렌더링되거나 업데이트 된 다음 호출됩니다.
> 주의:
>
> `React.render()`는 넘어온 컨테이너 노드의 내용을 교체합니다.
> 추후에 기존 자식들을 덮어쓰지 않고 이미 있는 DOM 노드에 컴포넌트를 삽입하는 것도 지원할 가능성이 있습니다.
### React.unmountComponentAtNode
```javascript
boolean unmountComponentAtNode(DOMElement container)
```
DOM에 마운트된 React 컴포넌트를 제거하고 이벤트 핸들러 및 state를 정리합니다. 컨테이너에 마운트된 컴포넌트가 없는 경우에는 호출해도 아무 동작을 하지 않습니다. 컴포넌트가 마운트 해제된 경우 `true`를, 마운트 해제할 컴포넌트가 없으면 `false`를 리턴합니다.
### React.renderToString
```javascript
string renderToString(ReactElement element)
```
주어진 ReactElement의 최초 HTML을 렌더링합니다. 이 함수는 서버에서만 사용해야 합니다. React가 HTML 문자열을 리턴합니다. HTML을 서버에서 생성하고 마크업을 최초 요청에 내려보내서, 페이지 로딩을 빠르게 하거나 검색 엔진이 크롤링할 수 있도록 하는 SEO 목적으로 이 메소드를 사용할 수 있습니다.
또한 이 메소드로 서버에서 렌더링한 마크업을 포함한 노드에 `React.render()`를 호출하면, React는 마크업을 보존하고 이벤트 핸들러만 붙이므로 최초 로딩을 매우 빠르게 느껴지게 할 수 있습니다.
### React.renderToStaticMarkup
```javascript
string renderToStaticMarkup(ReactElement element)
```
`renderToString`와 비슷하지만 `data-react-id`처럼 React에서 내부적으로 사용하는 추가적인 DOM 어트리뷰트를 만들지 않습니다. 추가적인 어트리뷰트를 제거하면 생성되는 마크업의 용량을 줄일 수 있기 때문에 React를 단순한 정적 페이지 생성기로 사용할 때 유용합니다.
### React.isValidElement
```javascript
boolean isValidElement(* object)
```
주어진 객체가 ReactElement인지 확인합니다.
### React.findDOMNode
```javascript
DOMElement findDOMNode(ReactComponent component)
```
이 컴포넌트가 DOM에 마운트된 경우 해당하는 네이티브 브라우저 DOM 엘리먼트를 리턴합니다. 이 메소드는 폼 필드의 값이나 DOM의 크기/위치 등 DOM에서 정보를 읽을 때 유용합니다. `render``null`이나 `false`를 리턴할 때 `React.findDOMNode()``null`을 리턴합니다.
### React.DOM
`React.DOM`은 DOM 컴포넌트에 대해 `React.createElement`의 편의 래퍼(wrapper)를 제공합니다. JSX를 사용하지 않는 경우에만 사용하십시오. 예를 들어, `React.DOM.div(null, 'Hello World!')`와 같이 사용할 수 있습니다.
### React.PropTypes
`React.PropTypes`는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있는 컴포넌트의 `propTypes` 객체에 들어가는 타입을 가집니다. `propTypes`에 대한 자세한 정보는 [재사용 가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html)를 참고하세요.
### React.initializeTouchEvents
```javascript
initializeTouchEvents(boolean shouldUseTouch)
```
React의 이벤트 시스템이 모바일 기기의 터치 이벤트를 처리하도록 설정합니다.
### React.Children
`React.Children`은 불투명한 자료 구조인 `this.props.children`를 다룰 수 있는 유틸리티를 제공합니다.
#### React.Children.map
```javascript
object React.Children.map(object children, function fn [, object context])
```
`children`의 바로 밑에 있는 모든 자식에 `fn`을 호출합니다. 이 때 `this``context`로 설정됩니다. `children`이 중첩된 객체나 배열일 경우 그 안의 값을 순회합니다. 따라서 `fn`에 컨테이너 객체가 넘어가는 일은 일어나지 않습니다. `children``null`이거나 `undefined`면 빈 객체 대신 `null` 또는 `undefined`를 리턴합니다.
#### React.Children.forEach
```javascript
React.Children.forEach(object children, function fn [, object context])
```
`React.Children.map()`과 비슷하지만 객체를 리턴하지 않습니다.
#### React.Children.count
```javascript
number React.Children.count(object children)
```
`children`에 들어있는 컴포넌트의 총 갯수를 리턴합니다. 이 갯수는 `map`이나 `forEach`에 넘긴 콜백이 호출되는 횟수와 동일합니다.
#### React.Children.only
```javascript
object React.Children.only(object children)
```
`children`에 단 하나의 자식이 있을 때 그 자식을 리턴합니다. 그 밖의 경우에는 예외를 발생시킵니다.

134
docs/ref-02-component-api.ko-KR.md

@ -0,0 +1,134 @@
---
id: component-api-ko-KR
title: 컴포넌트 API
permalink: component-api-ko-KR.html
prev: top-level-api-ko-KR.html
next: component-specs-ko-KR.html
---
## React.Component
React 컴포넌트의 인스턴스는 React가 렌더링 시에 내부적으로 만듭니다. 이때 만들어진 인스턴스는 이후의 렌더링에서 다시 사용되고 컴포넌트의 메소드들에서 `this` 변수로 접근할 수 있습니다. React 외부에서 React 컴포넌트의 핸들을 얻는 방법은 `React.render`의 리턴값을 저장하는 것이 유일합니다. 다른 컴포넌트 안에서 비슷한 결과를 얻으려면 [refs](/react/docs/more-about-refs-ko-KR.html)를 사용해야 합니다.
### setState
```javascript
setState(function|object nextState[, function callback])
```
`nextState`를 현재 state에 합칩니다. 이벤트 핸들러와 서버 요청 콜백에서 UI 업데이트를 발생시키기 위해 이 메소드를 주로 사용합니다.
첫번째 인자는 업데이트를 위한 키를 0개 이상 가진 객체이거나 업데이트를 위한 키들을 포함한 객체를 반환하는 함수(의 state나 props)일 수 있습니다.
객체를 사용하는 간단한 예제입니다...
```javascript
setState({mykey: '새로운 값'});
```
`function(state, props)`처럼 인자를 포함한 함수를 넘겨주는 것도 가능합니다. 어떤 값이든 state와 props의 이전 값을 참고해서 원자적인 업데이트를 큐에 추가(enqueue)하려는 경우 이는 유용합니다. 예를 들어 state의 값을 증가 시키려는 경우 같이 처리 가능합니다:
```javascript
setState(function(previousState, currentProps) {
return {myInteger: previousState.myInteger + 1};
});`
```
두번째 인자는 선택적이며, `setState`가 한번 완료되고 컴포넌트가 다시 렌더 되었을때 실행되는 콜백 함수입니다.
> 주의:
>
> *절대로* `this.state`를 직접 변경하지 마세요. 그 뒤에 `setState()`를 호출하면 그동안 변경했던 것이 교체될 수 있습니다. `this.state`는 변경 불가능한 것으로 생각하시는 것이 좋습니다.
>
> `setState()`를 호출해도 `this.state`가 곧바로 변경되지 않고 대기 중인 state transition이 만들어집니다. 이 메소드를 호출한 직후 `this.state`에 접근하면 바뀌기 전의 값을 리턴할 가능성이 있습니다.
>
> `setState`에 대한 호출이 동기적으로 처리된다는 보장이 없으며, 성능 향상을 위해 배치 처리될 수 있습니다.
>
> `setState()``shouldComponentUpdate()`에 조건부 렌더링 로직이 구현되어 있지 않다면 항상 재렌더링을 발생시킵니다. 변경 가능한 객체를 사용하고 있고 조건부 렌더링 로직을 `shouldComponentUpdate()`에 구현할 수 없는 경우라면 새로운 state가 이전 state와 달라지는 경우에만 `setState()`를 호출하여 불필요한 재렌더링을 피할 수 있습니다.
### replaceState
```javascript
replaceState(object nextState[, function callback])
```
`setState()`와 비슷하지만 기존에 존재하는 state 중 nextState에 없는 키는 모두 삭제됩니다.
> 주의:
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.
### forceUpdate
```javascript
forceUpdate([function callback])
```
`render()` 메소드가 `this.props``this.state`가 아닌 다른 곳에서 데이터를 읽어오는 경우 `forceUpdate()`를 호출하여 React가 `render()`를 다시 실행하도록 만들 수 있습니다. `this.state`를 직접 변경하는 경우에도 `forceUpdate()`를 호출해야 합니다.
`forceUpdate()`를 호출하면 `shouldComponentUpdate()`를 생략하고 해당 컴포넌트 `render()` 함수가 호출됩니다. 각 자식 컴포넌트에 대해서는 `shouldComponentUpdate()`를 포함해 보통 라이프 사이클 메서드를 호출합니다. React는 마크업이 변경된 경우에만 DOM을 업데이트합니다.
특별한 경우가 아니면 `forceUpdate()`는 되도록 피하시고 `render()`에서는 `this.props``this.state`에서만 읽어오세요. 그렇게 하는 것이 애플리케이션을 훨씬 단순하고 효율적으로 만들어줍니다.
### getDOMNode
```javascript
DOMElement getDOMNode()
```
이 컴포넌트가 DOM에 마운트된 경우 해당하는 네이티브 브라우저 DOM 엘리먼트를 리턴합니다. 이 메소드는 폼 필드의 값이나 DOM의 크기/위치 등 DOM에서 정보를 읽을 때 유용합니다. `render``null`이나 `false`를 리턴하였다면 `this.getDOMNode()``null`을 리턴합니다.
> 주의:
>
> getDOMNode는 [React.findDOMNode()](/react/docs/top-level-api.html#react.finddomnode)로 교체되었습니다.
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.
### isMounted
```javascript
bool isMounted()
```
`isMounted()`는 컴포넌트가 DOM에 렌더링되었으면 true를, 아니면 false를 리턴합니다. 비동기적으로 `setState()``forceUpdate()`를 호출할 때 이 메소드를 사용하여 오류를 방지할 수 있습니다.
> 주의:
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.
### setProps
```javascript
setProps(object nextProps[, function callback])
```
외부 JavaScript 애플리케이션과 연동하는 경우 `React.render()`로 렌더링된 React 컴포넌트에 변경을 알리고 싶을 때가 있습니다.
최상위 컴포넌트를 업데이트할 때 `React.render()`를 같은 노드에 다시 호출하는 것이 바람직한 방법이지만, `setProps()`를 호출해서 props를 바꾸고 재렌더링을 발생시킬 수 있습니다. 콜백 함수를 추가로 넘기면 `setProps`가 완료되고 컴포넌트가 다시 렌더링된 다음에 한번 호출됩니다.
> 주의:
>
> 가능하다면 `React.render()`를 다시 호출하는 선언적인 방법이 더 바람직합니다. 그렇게 하는 편이 업데이트에 대해 생각하는 것을 쉽게 만듭니다. (두가지 방식에 눈에 띄는 성능 차이는 없습니다.)
>
> 이 메소드는 최상위 컴포넌트에만 호출 가능합니다. 다시 말해, `React.render()`에 바로 넘긴 컴포넌트에서만 사용할 수 있고 자식에서는 불가능합니다. 자식 컴포넌트에 `setProps()`를 사용하고 싶다면, 그 대신 반응적인 업데이트의 장점을 활용하여 `render()` 안에서 자식 컴포넌트를 만들 때 새로운 prop을 넘기세요.
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.
### replaceProps
```javascript
replaceProps(object nextProps[, function callback])
```
`setProps()`와 비슷하지만 두 객체를 합치는 대신 이전에 존재하던 props를 삭제합니다.
> 주의:
>
> 이 메소드는 `React.Component`를 확장한 ES6 `class` 컴포넌트에서는 사용할 수 없습니다. React의 미래 버전에서 이는 완전히 사라지게 될 것입니다.

208
docs/ref-03-component-specs.ko-KR.md

@ -0,0 +1,208 @@
---
id: component-specs-ko-KR
title: 컴포넌트 명세와 생명주기
permalink: component-specs-ko-KR.html
prev: component-api-ko-KR.html
next: tags-and-attributes-ko-KR.html
---
## 컴포넌트 명세
`React.createClass()`를 호출하여 컴포넌트 클래스를 생성할 때, `render` 메소드를 포함한 명세 객체를 제공해야 합니다. 또한 필요한 경우 여기에서 설명하는 다른 생명주기 메소드를 명세 객체에 추가로 제공할 수 있습니다.
### render
```javascript
ReactComponent render()
```
`render()` 메소드는 필수 항목입니다.
호출되면 `this.props``this.state`를 토대로 하나의 자식 컴포넌트를 리턴합니다. 이 자식 컴포넌트는 네이티브 DOM 컴포넌트의 가상 표현 (`<div />`나 `React.DOM.div()` 등) 또는 직접 정의한 조합(composite) 컴포넌트가 될 수 있습니다.
아무 것도 렌더링되지 않도록 하려면 `null`이나 `false`를 리턴합니다. React는 지금의 차이 비교 알고리즘이 작동할 수 있도록 내부적으로는 `<noscript>` 태그를 렌더링합니다. `null`이나 `false`를 리턴한 경우, `React.findDOMNode(this)``null`을 리턴합니다.
`render()` 함수는 순수 함수여야 합니다. 즉, 컴포넌트의 상태를 변경하지 않고, 여러번 호출해도 같은 결과를 리턴하며, DOM을 읽고 쓰거나 브라우저와 상호작용(예를 들어 `setTimeout`를 사용)하지 않아야 합니다. 브라우저와 상호작용해야 한다면 `componentDidMount()`나 다른 생명주기 메소드에서 수행해야 합니다. `render()` 함수를 순수 함수로 유지하면 서버 렌더링이 훨씬 쓸만해지고 컴포넌트에 대해 생각하기 쉬워집니다.
### getInitialState
```javascript
object getInitialState()
```
컴포넌트가 마운트되기 전에 한번 호출됩니다. 리턴값은 `this.state`의 초기값으로 사용됩니다.
### getDefaultProps
```javascript
object getDefaultProps()
```
클래스가 생성될 때 한번 호출되고 캐시됩니다. 부모 컴포넌트에서 prop이 넘어오지 않은 경우 (`in` 연산자로 확인) 매핑의 값이 `this.props`에 설정됩니다.
이 메소드는 인스턴스가 만들어지기 전에 호출되므로 `this.props`에 의존할 수 없습니다. 그리고 `getDefaultProps()`의 리턴값에 포함된 복잡한 객체는 복사되지 않고 인스턴스 간에 공유됩니다.
### propTypes
```javascript
object propTypes
```
`propTypes` 객체는 컴포넌트에 넘어오는 props가 올바른지 검사할 수 있게 해줍니다. `propTypes`에 대한 자세한 정보는 [재사용 가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html)를 참고하세요.
### mixins
```javascript
array mixins
```
`mixins` 배열은 여러 컴포넌트 사이에 동작을 공유하는 믹스인을 사용할 수 있게 해줍니다. 믹스인에 대한 자세한 정보는 [재사용 가능한 컴포넌트](/react/docs/reusable-components-ko-KR.html)를 참고하세요.
### statics
```javascript
object statics
```
`statics` 객체는 컴포넌트 클래스의 스태틱 메소드를 정의할 수 있게 해줍니다. 에를 들어:
```javascript
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
```
이 블럭 안에서 정의된 메소드는 인스턴스를 하나도 만들지 않은 시점에도 호출할 수 있고, 컴포넌트의 props나 state에 접근할 수 없습니다. 스태틱 메소드에서 props의 값을 확인하려면 호출자가 스태틱 메소드에 props를 인자로 넘기도록 해야합니다.
### displayName
```javascript
string displayName
```
`displayName` 문자열은 디버그 메시지에 사용됩니다. JSX는 이 값을 자동으로 설정합니다. [JSX 깊이 알기](/react/docs/jsx-in-depth-ko-KR.html#the-transform)를 참고하세요.
## 생명주기 메소드
컴포넌트의 생명주기에서 특정 시점마다 실행되는 메소드들입니다.
### 마운트 시: componentWillMount
```javascript
componentWillMount()
```
최초 렌더링이 일어나기 직전에 클라이언트 및 서버에서 한번 호출됩니다. 이 메소드 안에서 `setState`를 호출하면, `render()`에서 업데이트된 state를 확인할 수 있고 state가 변함에도 불구하고 `render()`가 한번만 실행됩니다.
### 마운트 시: componentDidMount
```javascript
componentDidMount()
```
최초 렌더링이 일어난 다음 클라이언트에서만 한번 호출됩니다. (서버에서는 호출되지 않습니다.) 이 시점에 컴포넌트는 `React.findDOMNode(this)`로 접근 가능한 DOM 표현을 가집니다.
다른 JavaScript 프레임워크를 연동하거나, `setTimeout`/`setInterval`로 타이머를 설정하고 AJAX 요청을 보내는 등의 작업을 이 메소드에서 합니다.
### 업데이트 시: componentWillReceiveProps
```javascript
componentWillReceiveProps(object nextProps)
```
컴포넌트가 새로운 props를 받을 때 호출됩니다. 이 메소드는 최초 렌더링 시에는 호출되지 않습니다.
`render()`가 호출되기 전에 prop의 변화를 감지하여 `this.setState()`를 호출해서 state를 업데이트할 수 있습니다. 이전 props는 `this.props`로 접근할 수 있습니다. 이 함수 안에서 `this.setState()`를 호출해도 추가 렌더링이 발생하지 않습니다.
```javascript
componentWillReceiveProps: function(nextProps) {
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}
```
> 주의:
>
> `componentWillReceiveState`에 해당하는 메소드는 없습니다. prop이 변할 때 state가 바뀔 수는 있지만, 그 역은 불가능합니다. state의 변화에 따라 작업을 실행해야 하면 `componentWillUpdate`를 사용하세요.
<a name="updating-shouldcomponentupdate"></a>
### 업데이트 시: shouldComponentUpdate
```javascript
boolean shouldComponentUpdate(object nextProps, object nextState)
```
새로운 props 또는 state를 받아 렌더링을 하기 전에 호출됩니다. 최초 렌더링 시나 `forceUpdate`를 사용하는 경우에는 호출되지 않습니다.
새로운 props와 state가 컴포넌트 업데이트를 필요로 하지 않는 것이 확실하다면
`false`를 리턴하세요.
```javascript
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.id !== this.props.id;
}
```
`shouldComponentUpdate`가 false를 리턴하면, 다음에 state가 바뀌기 전까지 `render()`가 완전히 호출되지 않고 넘어갑니다. (그리고 `componentWillUpdate``componentDidUpdate` 또한 호출되지 않습니다.)
기본적으로 `shouldComponentUpdate`는 항상 true를 리턴합니다. `state`가 제자리에서(in place) 바뀐 경우에 발생하는 파악하기 힘든 버그를 막기 위함입니다. 하지만 `state`가 항상 변경 불가능하도록 주의하고 `render()`에서 `props``state`를 읽기만 하면 이전 props 및 state와 바뀌는 값을 비교하는 `shouldComponentUpdate`를 직접 구현할 수 있습니다.
성능에 병목이 있다면, 특히 컴포넌트가 매우 많은 경우 `shouldComponentUpdate`를 사용하여 앱을 빠르게 만들 수 있습니다.
### 업데이트 시: componentWillUpdate
```javascript
componentWillUpdate(object nextProps, object nextState)
```
새로운 props나 state를 받았을 때 렌더링 직전에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.
업데이트가 일어나기 전에 준비하기 위해 사용할 수 있습니다.
> 주의:
>
> 이 메소드에서는 `this.setState()`를 호출할 수 없습니다. prop 변화에 반응하여 state를 업데이트해야 할 경우, `componentWillReceiveProps`를 대신 사용하세요.
### 업데이트 시: componentDidUpdate
```javascript
componentDidUpdate(object prevProps, object prevState)
```
컴포넌트의 업데이트가 DOM에 반영된 직후에 호출됩니다. 최초 렌더링 시에는 호출되지 않습니다.
컴포넌트가 업데이트된 뒤 DOM을 조작해야 하는 경우 사용할 수 있습니다.
### 마운트 해제 시: componentWillUnmount
```javascript
componentWillUnmount()
```
컴포넌트가 DOM에서 마운트 해제 되기 직전에 호출됩니다.
이 메소드에서 타이머를 무효화하거나 `componentDidMount`에서 만들어진 DOM 엘리먼트를 정리하는 등 필요한 정리 작업을 수행할 수 있습니다.

84
docs/ref-04-tags-and-attributes.ko-KR.md

@ -0,0 +1,84 @@
---
id: tags-and-attributes-ko-KR
title: 태그와 어트리뷰트
permalink: tags-and-attributes-ko-KR.html
prev: component-specs-ko-KR.html
next: events-ko-KR.html
---
## 지원되는 태그
React는 모든 공통 엘리먼트를 지원하려 합니다. 필요한 엘리먼트가 목록에 없다면, 이슈로 등록해 주세요.
### HTML 엘리먼트
다음의 HTML 엘리먼트가 지원됩니다.
```
a abbr address area article aside audio b base bdi bdo big blockquote body br
button canvas caption cite code col colgroup data datalist dd del details dfn
dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5
h6 head header hr html i iframe img input ins kbd keygen label legend li link
main map mark menu menuitem meta meter nav noscript object ol optgroup option
output p param picture pre progress q rp rt ruby s samp script section select
small source span strong style sub summary sup table tbody td textarea tfoot th
thead time title tr track u ul var video wbr
```
### SVG 엘리먼트
다음의 SVG 엘리먼트가 지원됩니다.
```
circle defs ellipse g line linearGradient mask path pattern polygon polyline
radialGradient rect stop svg text tspan
```
아마 Canvas, SVG, VML(IE8 전용)에 렌더할 때 쓰는 React의 드로잉 라이브러리인 [react-art](https://github.com/facebook/react-art)도 흥미 있으실 수 있습니다.
## 지원되는 어트리뷰트
React는 모든 `data-*`, `aria-*` 어트리뷰트와 밑에 있는 모든 어트리뷰트를 지원합니다.
> 주의:
>
> 모든 어트리뷰트는 카멜케이스이고, `class` `for` 어트리뷰트는 각각 DOM API의 사양에 맞춰서 `className` `htmlFor` 가 됩니다.
이벤트의 목록을 보시려면 [지원되는 이벤트](/react/docs/events-ko-KR.html)를 확인하세요.
### HTML 어트리뷰트
이런 표준 어트리뷰트가 지원됩니다.
```
accept acceptCharset accessKey action allowFullScreen allowTransparency alt
async autoComplete autoFocus autoPlay cellPadding cellSpacing charSet checked classID
className cols colSpan content contentEditable contextMenu controls coords
crossOrigin data dateTime defer dir disabled download draggable encType form
formAction formEncType formMethod formNoValidate formTarget frameBorder height
hidden href hrefLang htmlFor httpEquiv icon id label lang list loop manifest
marginHeight marginWidth max maxLength media mediaGroup method min multiple
muted name noValidate open pattern placeholder poster preload radioGroup
readOnly rel required role rows rowSpan sandbox scope scrolling seamless
selected shape size sizes span spellCheck src srcDoc srcSet start step style
tabIndex target title type useMap value width wmode
```
덧붙여, 이런 비표준 어트리뷰트도 지원됩니다.
- 모바일 사파리를 위한 `autoCapitalize autoCorrect`.
- [오픈 그래프](http://ogp.me/) 메타 태그를 위한 `property`.
- [HTML5 마이크로데이터](http://schema.org/docs/gs.html)를 위한 `itemProp itemScope itemType itemRef itemId`.
컴포넌트에 직접 HTML 문자열을 넣을 때 사용하는, React 전용 어트리뷰트 `dangerouslySetInnerHTML`([자세한 정보는 여기](/react/docs/special-non-dom-attributes-ko-KR.html))도 있습니다.
### SVG 어트리뷰트
```
cx cy d dx dy fill fillOpacity fontFamily fontSize fx fy gradientTransform
gradientUnits markerEnd markerMid markerStart offset opacity
patternContentUnits patternUnits points preserveAspectRatio r rx ry
spreadMethod stopColor stopOpacity stroke strokeDasharray strokeLinecap
strokeOpacity strokeWidth textAnchor transform version viewBox x1 x2 x y1 y2 y
```

197
docs/ref-05-events.ko-KR.md

@ -0,0 +1,197 @@
---
id: events-ko-KR
title: 이벤트 시스템
permalink: events-ko-KR.html
prev: tags-and-attributes-ko-KR.html
next: dom-differences-ko-KR.html
---
## 통합적인(Synthetic) 이벤트
이벤트 핸들러는 브라우저의 네이티브 이벤트의 크로스 브라우저 래퍼(wrapper)인`SyntheticEvent`의 인스턴스에 전달됩니다. 모든 브라우저에서 동작한다는 점을 제외하면, `SyntheticEvent``stopPropagation()``preventDefault()`를 포함해, 브라우저의 네이티브 이벤트와 같은 인터페이스를 가지고 있습니다.
어떤 이유로 기본 브라우저 이벤트가 필요하다면, 그냥 `nativeEvent`를 사용해 할 수 있습니다. 모든 `SyntheticEvent` 객체는 이런 어트리뷰트를 가집니다.
```javascript
boolean bubbles
boolean cancelable
DOMEventTarget currentTarget
boolean defaultPrevented
number eventPhase
boolean isTrusted
DOMEvent nativeEvent
void preventDefault()
void stopPropagation()
DOMEventTarget target
number timeStamp
string type
```
> 주의:
>
> v0.12 시점에서, 이벤트 핸들러에서 `false` 를 리턴하는 것은 더 이상 이벤트의 전달(propagation)을 멈추지 않습니다. 대신, `e.stopPropagation()``e.preventDefault()`로 적절히 수동으로 트리거해야 합니다.
## 지원되는 이벤트
React는 다른 브라우저에서 일관된 특성을 가지도록 이벤트를 일반화합니다.
밑에 있는 이벤트 핸들러들은 일으키는(bubbling) 단계에서 이벤트를 트리거합니다. 이벤트 핸들러를 캡처 단계로 등록하려면, 이벤트 이름에 `Capture`를 붙이면 됩니다. 예를 들어, 캡처 단계의 클릭 이벤트를 다루려면 `onClick`를 사용하는 대신에 `onClickCapture`를 사용해야 합니다.
### 클립보드 이벤트
이벤트 이름:
```
onCopy onCut onPaste
```
프로퍼티:
```javascript
DOMDataTransfer clipboardData
```
### 키보드 이벤트
이벤트 이름:
```
onKeyDown onKeyPress onKeyUp
```
프로퍼티:
```javascript
boolean altKey
Number charCode
boolean ctrlKey
function getModifierState(key)
String key
Number keyCode
String locale
Number location
boolean metaKey
boolean repeat
boolean shiftKey
Number which
```
### 포커스 이벤트
이벤트 이름:
```
onFocus onBlur
```
프로퍼티:
```javascript
DOMEventTarget relatedTarget
```
<a name="form-events"></a>
### 폼 이벤트
이벤트 이름:
```
onChange onInput onSubmit
```
onChange 이벤트에 대한 더 자세한 정보는 [](/react/docs/forms-ko-KR.html)에서 확인하세요.
### 마우스 이벤트
이벤트 이름:
```
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
```
`onMouseEnter``onMouseLeave` 이벤트는 평범하게 일어나는(bubbling) 대신 입력된 컴포넌트에 남겨지도록 컴포넌트에서 전달되고 캡쳐 단계가 없습니다.
프로퍼티:
```javascript
boolean altKey
Number button
Number buttons
Number clientX
Number clientY
boolean ctrlKey
function getModifierState(key)
boolean metaKey
Number pageX
Number pageY
DOMEventTarget relatedTarget
Number screenX
Number screenY
boolean shiftKey
```
### 터치 이벤트
터치 이벤트를 활성화 하려면, 컴포넌트를 렌더하기 전에
`React.initializeTouchEvents(true)`를 호출하세요.
이벤트 이름:
```
onTouchCancel onTouchEnd onTouchMove onTouchStart
```
프로퍼티:
```javascript
boolean altKey
DOMTouchList changedTouches
boolean ctrlKey
function getModifierState(key)
boolean metaKey
boolean shiftKey
DOMTouchList targetTouches
DOMTouchList touches
```
### UI 이벤트
이벤트 이름:
```
onScroll
```
프로퍼티:
```javascript
Number detail
DOMAbstractView view
```
### 휠 이벤트
이벤트 이름:
```
onWheel
```
프로퍼티:
```javascript
Number deltaMode
Number deltaX
Number deltaY
Number deltaZ
```

17
docs/ref-06-dom-differences.ko-KR.md

@ -0,0 +1,17 @@
---
id: dom-differences-ko-KR
title: DOM과의 차이점
permalink: dom-differences-ko-KR.html
prev: events-ko-KR.html
next: special-non-dom-attributes-ko-KR.html
---
React는 성능과 크로스 브라우저 호환성을 이유로 브라우저에 독립적인 이벤트와 DOM 시스템으로 구현되었습니다. 브라우저 DOM 구현의 일관성없는 부분들을 정리할 기회를 가졌습니다.
* 모든 DOM 프로퍼티와 어트리뷰트는 (이벤트 핸들러를 포함해) 표준 JavaScript 스타일과 일치하도록 카멜케이스를 사용해야 합니다. **하지만**, `data-*``aria-*` 어트리뷰트는 [사양을 준수해](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#data-*) 소문자만 사용해야 합니다.
* `style` 어트리뷰트는 CSS 문자열 대신에 카멜케이스로 된 프로퍼티를 가지는 JavaScript 객체를 받습니다. 이는 DOM `style` JavaScript 프로퍼티와 일치하면서도 좀 더 효율적이며, XSS 보안 취약점을 예방할 수 있습니다.
* 모든 이벤트 객체는 W3C 사양을 준수하고, 모든 이벤트(submit을 포함해)는 W3C 사양에 따라 일으킵(bubble)니다. 좀 더 자세한 정보는 [이벤트 시스템](/react/docs/events-ko-KR.html)을 보세요.
* `onChange` 이벤트는 기대대로 동작합니다. 이 이벤트는 일관성없이 blur시점에서 발생하지 않고 폼 필드가 변경될 때만 발생합니다.[^1] 우리는 의도적으로 기존 브라우저 동작을 차단했습니다. `onChange`는 이름과 실제 동작이 다르고, React는 실시간으로 사용자 입력에 반응할 때 이 이벤트에 의존하기 때문입니다. 더 자세한 정보는 [](/react/docs/forms-ko-KR.html)을 보세요.
* `value``checked` 폼 input 어트리뷰트, `textarea`. [자세히 보기](/react/docs/forms-ko-KR.html).
[^1]: **역주**: 일관성 없다는 표현에 대해 부연 설명하자면, 네이티브의 onChange는 변경뿐만 아니라 blur에서도 반응합니다.

13
docs/ref-07-special-non-dom-attributes.ko-KR.md

@ -0,0 +1,13 @@
---
id: special-non-dom-attributes-ko-KR
title: DOM이 아닌 특별한 어트리뷰트
permalink: special-non-dom-attributes-ko-KR.html
prev: dom-differences-ko-KR.html
next: reconciliation-ko-KR.html
---
[DOM 차이점](/react/docs/dom-differences-ko-KR.html)처럼, React는 DOM에는 존재하지 않는 몇몇 어트리뷰트도 제공합니다.
- `key`: 선택적인 고유 식별자. 컴포넌트가 `render` 과정에서 섞일 때, diff 알고리즘에 의해 파괴되고, 다시 생성될 수 있습니다. 컴포넌트에 영속적인(persists) 키를 할당하면 컴포넌트가 확실히 유지되게 할 수 있습니다. 더 자세한 것은 [여기](/react/docs/multiple-components-ko-KR.html#dynamic-children)에서 보세요.
- `ref`: [여기](/react/docs/more-about-refs-ko-KR.html)를 보세요.
- `dangerouslySetInnerHTML`: 생(raw) HTML을 넣을 수 있게 합니다. 주로 DOM 문자열 관리 라이브러리와의 협력하기 위해 사용합니다. 더 자세한 것은 [여기](/react/tips/dangerously-set-inner-html.html)를 보세요.

132
docs/ref-08-reconciliation.ko-KR.md

@ -0,0 +1,132 @@
---
id: reconciliation-ko-KR
title: 비교조정(Reconciliation)
permalink: reconciliation-ko-KR.html
prev: special-non-dom-attributes-ko-KR.html
next: glossary-ko-KR.html
---
React의 주요 설계 철학은 업데이트할 때마다 전체 앱을 다시 렌더하는 것처럼 보이게 API를 만드는 것입니다. 이렇게 하면 애플리케이션 작성이 훨씬 쉬워지지만 한편으로는 어려운 도전 과제이기도 합니다. 이 글에서는 강력한 휴리스틱으로 어떻게 O(n<sup>3</sup>) 복잡도의 문제를 O(n)짜리로 바꿀 수 있었는지 설명합니다.
## 동기
최소한의 연산으로 어떤 트리를 다른 트리로 바꾸는 것은 복잡하고 많이 연구된 문제입니다. n을 트리에 있는 노드 수라고 할 때 [최신 알고리즘](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf)은 O(n<sup>3</sup>) 복잡도를 가집니다.
다시 말해 1000개의 노드를 표시하려면 10억 번 수준의 비교를 해야 한다는 뜻입니다. 이는 우리가 필요한 용도로는 너무 비쌉니다. 이 수치를 좀 더 알기 쉽게 설명하면, 요즘 CPU는 1초에 대략 30억 번의 연산을 하므로 가장 빠른 구현으로도 1초 안에 이러한 비교는 계산해낼 수 없다는 것입니다.
최적의 알고리즘을 사용할 수 없기 때문에, 완전하진 않지만 다음의 두 가지 가정에 기반한 휴리스틱을 사용한 O(n) 알고리즘으로 구현했습니다.
1. 같은 클래스의 두 컴포넌트는 비슷한 트리를 생성하고, 서로 다른 클래스를 가진 두 컴포넌트는 서로 다른 트리를 생성할 것이다.
2. 각 렌더 과정들 사이에 유지되는 엘리먼트에 고유한 키를 제공할 수 있다.
실제로 이러한 가정은 거의 모든 실용적인 상황에서 굉장히 빠릅니다.
## 일대일 비교
트리 비교를 하기 위해서는 먼저 두 노드를 비교할 수 있어야 합니다. 세 가지 경우를 다룹니다.
### 서로 다른 노드 타입
두 노드의 타입이 서로 다르다면, React는 이를 두 개의 서로 다른 서브트리로 간주해 처음 것을 버리고 두번째 것을 만들어 삽입합니다.
```xml
renderA: <div />
renderB: <span />
=> [removeNode <div />], [insertNode <span />]
```
동일한 로직이 커스텀 컴포넌트에 대해서도 적용됩니다. 타입이 다르다면 React는 그 컴포넌트들이 무엇을 렌더하는지 조차도 비교하지 않습니다. 그저 처음 것을 DOM에서 제거하고 두번째 것을 삽입합니다.
```xml
renderA: <Header />
renderB: <Content />
=> [removeNode <Header />], [insertNode <Content />]
```
이러한 고수준의 사실을 알 수 있다는 것이 React의 비교 알고리즘이 빠르면서 정확할 수 있는 비결입니다. 트리의 커다란 부분을 일찌감치 탐색 대상에서 제외하고 비슷할 가능성이 높은 부분에 집중할 수 있는 좋은 휴리스틱을 제공합니다.
`<Header>` 엘리먼트가 생성하는 DOM이 `<Content>`가 생성하는 것과 비슷하게 생길 확률은 매우 낮습니다. 이 두 구조를 비교하는데 시간을 낭비하지 않고 React는 그냥 트리를 처음부터 새로 만듭니다.
한편 두 번의 연속적인 렌더에서 같은 위치에 `<Header>` 엘리먼트가 있다면 비슷한 구조일 것이므로 탐색할만 합니다.
### DOM 노드
두 DOM 노드를 비교할 때는 어트리뷰트를 보고 무엇이 바뀌었는지 선형 시간 안에 결정할 수 있습니다.
```xml
renderA: <div id="before" />
renderB: <div id="after" />
=> [replaceAttribute id "after"]
```
스타일을 불명확한 문자열로 다루지 않고 키-값 객체를 사용합니다. 이는 변경된 프로퍼티만 업데이트 하도록 해줍니다.
```xml
renderA: <div style={{'{{'}}color: 'red'}} />
renderB: <div style={{'{{'}}fontWeight: 'bold'}} />
=> [removeStyle color], [addStyle font-weight 'bold']
```
어트리뷰트가 업데이트된 다음에는, 모든 자식도 재귀적으로 업데이트합니다.
### 커스텀 컴포넌트
우리는 두 커스텀 컴포넌트를 같은 것으로 취급하기로 했습니다. 컴포넌트는 상태를 가지기 때문에 새 컴포넌트를 그냥 사용할 수는 없습니다. React는 새 컴포넌트의 모든 어트리뷰트를 취해 이전 컴포넌트의 `component[Will/Did]ReceiveProps()`를 호출해 줍니다.
이제 이전 컴포넌트가 작동합니다. 거기 있는 `render()` 메소드가 호출되고 비교 알고리즘이 다시 새로운 결과와 이전 결과를 비교합니다.
## 목록끼리 비교
### 문제가 되는 경우
React는 매우 단순한 방식으로 자식 비교조정(children reconciliation)을 합니다. 자식 목록을 동시에 서로 비교하다가 차이를 발견하면 변경 사항을 적용합니다.
예를 들어 맨 끝에 엘리먼트를 추가한 경우에는:
```xml
renderA: <div><span>first</span></div>
renderB: <div><span>first</span><span>second</span></div>
=> [insertNode <span>second</span>]
```
맨 앞에 엘리먼트를 삽입하는 경우가 문제입니다. React는 두 노드가 모두 span인지 확인하고 변경 모드로 작동합니다.
```xml
renderA: <div><span>first</span></div>
renderB: <div><span>second</span><span>first</span></div>
=> [replaceAttribute textContent 'second'], [insertNode <span>first</span>]
```
원소의 목록을 변환하기 위한 최소 연산 집합을 찾는 알고리즘이 여럿 있습니다. [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance)를 사용하면 O(n<sup>2</sup>) 복잡도로 원소 한 개의 삽입, 삭제, 교체를 위해 필요한 최솟값을 찾을 수 있습니다. Levenshtein 알고리즘을 사용해도 노드가 다른 위치로 이동한 경우는 알아낼 수 없고, 그것을 알아내는 알고리즘은 더욱 높은 복잡도를 가집니다.
### 키(keys)
해결할 수 없어보이는 이 문제를 풀기 위해 선택적인 어트리뷰트를 도입했습니다. 각 자식에 키(key)를 할당해 이를 비교하는 데에 사용합니다. 키를 명시하면 React가 해시 테이블을 사용하여 삽입, 삭제, 교체 및 이동을 O(n) 복잡도로 찾아낼 수 있습니다.
```xml
renderA: <div><span key="first">first</span></div>
renderB: <div><span key="second">second</span><span key="first">first</span></div>
=> [insertNode <span>second</span>]
```
실제 상황에서 키를 찾는 것은 별로 어렵지 않습니다. 대부분의 경우, 표시하려는 엘리먼트는 이미 고유한 식별자를 가지고 있습니다. 그렇지 않은 경우에도 모델에 새로운 ID 프로퍼티를 추가하거나 내용의 일부분을 해시하여 키를 생성할 수 있습니다. 키는 형제 노드 사이에서만 고유하면 됩니다. 전역적으로 고유할 필요는 없습니다.
## 트레이드오프
비교조정 알고리즘이 구현 세부사항이라는 것을 기억하는 것은 중요합니다. React가 전체 앱을 모든 동작마다 새로 렌더해도 결과는 같을 것입니다. 일반적인 사용 패턴을 빠르게 만들 수 있도록 저희는 계속 휴리스틱을 다듬고 있습니다.
현재 구현에서 서브트리가 형제 노드 사이에서 이동하는 경우는 표현할 수 있지만, 그 외의 곳으로 이동했는지는 알 수 없습니다. 알고리즘에 따라 전체 서브트리가 다시 렌더됩니다.
두 가지 휴리스틱에 의존하기 때문에 그에 대한 가정이 만족되지 않으면 성능이 좋지 않을 것입니다.
1. 서로 다른 컴포넌트 클래스의 서브트리는 비교하려고 시도하지 않습니다. 만약 매우 비슷한 출력 결과의 두 컴포넌트를 왔다갔다 하는 경우 같은 클래스로 만들 수 있습니다. 실제 상황에서는 큰 문제가 없습니다.
2. 안정적인 키를 붙이지 않을 경우 (예를 들어 Math.random()을 사용한다거나) 모든 서브트리가 매번 다시 렌더될 것입니다. 사용자에게 키를 선택하도록 하는 대신 실수할 수 있는 여지가 있습니다.

193
docs/ref-09-glossary.ko-KR.md

@ -0,0 +1,193 @@
---
id: glossary-ko-KR
title: React (가상) DOM 용어
permalink: glossary-ko-KR.html
prev: reconciliation-ko-KR.html
---
다음은 React에서 사용되는 용어들로, 이 다섯 가지의 타입을 구별하는 것은 중요합니다.
- [ReactElement / ReactElement 팩토리](#react-elements)
- [ReactNode](#react-nodes)
- [ReactComponent / ReactComponent 클래스](#react-components)
## React 엘리먼트
`ReactElement`는 React의 주요 타입입니다. `type`, `props`, `key`, `ref`의 네 가지 프로퍼티를 가집니다. 메소드는 가지지 않으며 프로토타입에는 아무 것도 들어있지 않습니다.
이러한 객체는 `React.createElement`를 통해 만들 수 있습니다.
```javascript
var root = React.createElement('div');
```
DOM에 새로운 트리를 렌더링하기 위해서는 `ReactElement`를 만들고 일반적인 DOM `Element` (`HTMLElement` 또는 `SVGElement`)와 함께 `React.render`에 넘깁니다. `ReactElement`를 DOM `Element`와 혼동해서는 안됩니다. `ReactElement`는 가볍고, 상태를 갖지 않으며, 변경 불가능한, DOM `Element`의 가상 표현입니다. 즉 가상 DOM입니다.
```javascript
React.render(root, document.body);
```
DOM 엘리먼트에 프로퍼티를 추가하려면 두번째 인자로 프로퍼티 객체를, 세번째 인자로 자식을 넘깁니다.
```javascript
var child = React.createElement('li', null, 'Text Content');
var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);
```
React JSX를 사용하면 `ReactElement`가 알아서 만들어집니다. 따라서 다음 코드는 앞의 코드와 같습니다:
```javascript
var root = <ul className="my-list">
<li>Text Content</li>
</ul>;
React.render(root, document.body);
```
__팩토리__
`ReactElement` 팩토리는 그저 특정한 `type` 프로퍼티를 가지는 `ReactElement`를 만들어주는 함수입니다. React에는 팩토리를 만드는 헬퍼가 내장되어 있습니다. 그 함수는 사실상 다음과 같습니다:
```javascript
function createFactory(type){
return React.createElement.bind(null, type);
}
```
이를 이용하면 편리한 단축 함수를 만들 수 있어 항상 `React.createElement('div')`를 입력하지 않아도 됩니다.
```javascript
var div = React.createFactory('div');
var root = div({ className: 'my-div' });
React.render(root, document.body);
```
React에는 이미 보통의 HTML 태그를 위한 팩토리가 내장되어 있습니다:
```javascript
var root = React.DOM.ul({ className: 'my-list' },
React.DOM.li(null, 'Text Content')
);
```
JSX를 사용하면 팩토리가 필요하지 않습니다. 이미 JSX가 `ReactElement`를 만드는 편리한 단축 문법을 제공합니다.
## React 노드
`ReactNode`는 다음 중 하나가 될 수 있습니다:
- `ReactElement`
- `string` (`ReactText`로 부르기도 함)
- `number` (`ReactText`로 부르기도 함)
- `ReactNode`의 배열 (`ReactFragment`로 부르기도 함)
이들은 자식을 표현하기 위해 다른 `ReactElement`의 프로퍼티에 사용됩니다. 사실상 이들이 `ReactElement`의 트리를 형성합니다.
## React 컴포넌트
`ReactElement`만 가지고도 React를 사용할 수는 있지만, React의 장점을 제대로 활용하려면 `ReactComponent`를 사용하여 상태를 가진 캡슐화된 객체를 만들기를 원할 것입니다.
`ReactComponent` 클래스는 그냥 JavaScript 클래스 (또는 "생성자 함수")입니다.
```javascript
var MyComponent = React.createClass({
render: function() {
...
}
});
```
이 생성자가 호출될 때 최소한 `render` 메소드를 가진 객체를 리턴해야 합니다. 이 리턴된 객체를 `ReactComponent`라고 부릅니다.
```javascript
var component = new MyComponent(props); // 절대 하지 마세요.
```
테스트 목적이 아니라면 __절대__ 이 생성자를 직접 호출하지 마십시오. React가 알아서 호출해줍니다.
대신 `ReactComponent` 클래스를 `createElement`에 넘겨 `ReactElement`를 받을 수 있습니다.
```javascript
var element = React.createElement(MyComponent);
```
또는 JSX를 사용하면:
```javascript
var element = <MyComponent />;
```
이것이 `React.render`에 넘겨지면 React가 알아서 생성자를 호출하여 `ReactComponent`를 만들고 리턴합니다.
```javascript
var component = React.render(element, document.body);
```
같은 타입의 `ReactElement`와 같은 컨테이너 DOM `Element`를 가지고 `React.render`를 계속 호출하면 항상 같은 인스턴스를 리턴합니다. 이 인스턴스는 상태를 가집니다.
```javascript
var componentA = React.render(<MyComponent />, document.body);
var componentB = React.render(<MyComponent />, document.body);
componentA === componentB; // true
```
그렇기 때문에 직접 인스턴스를 만들어서는 안됩니다. `ReactComponent`가 생성되기 전에 `ReactElement`가 대신 가상의 `ReactComponent` 역할을 합니다. 이전 `ReactElement`와 새 `ReactElement`를 비교하여 새로운 `ReactComponent`를 만들지, 아니면 기존 것을 재사용할지 결정합니다.
`ReactComponent``render` 메소드는 또다른 `ReactElement`를 리턴해야 합니다. 이렇게 해서 컴포넌트들이 조합됩니다. 결과적으로 렌더링 과정은 다음과 같습니다. `string` 타입의 태그를 가진 `ReactElement`를 통해 DOM `Element` 인스턴스가 생성되며 문서에 삽입됩니다.
## 형식 타입 정의
__진입점__
```
React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;
```
__노드와 엘리먼트__
```
type ReactNode = ReactElement | ReactFragment | ReactText;
type ReactElement = ReactComponentElement | ReactDOMElement;
type ReactDOMElement = {
type : string,
props : {
children : ReactNodeList,
className : string,
etc.
},
key : string | boolean | number | null,
ref : string | null
};
type ReactComponentElement<TProps> = {
type : ReactClass<TProps>,
props : TProps,
key : string | boolean | number | null,
ref : string | null
};
type ReactFragment = Array<ReactNode | ReactEmpty>;
type ReactNodeList = ReactNode | ReactEmpty;
type ReactText = string | number;
type ReactEmpty = null | undefined | boolean;
```
__클래스와 컴포넌트__
```
type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;
type ReactComponent<TProps> = {
props : TProps,
render : () => ReactElement
};
```

147
docs/thinking-in-react.ko-KR.md

@ -0,0 +1,147 @@
---
id: thinking-in-react-ko-KR
title: 리액트로 생각해보기
permalink: thinking-in-react-ko-KR.html
prev: tutorial-ko-KR.html
next: videos-ko-KR.html
---
이 문서의 원본은 [공식 블로그](/react/blog)의 [포스팅](/react/blog/2013/11/05/thinking-in-react.html) 입니다.
제가 생각하기에, React는 JavaScript로 크고 빠른 웹 애플리케이션을 만드는데 최고입니다. 페이스북과 인스타그램에서 우리에게 잘 맞도록 조정되어 왔습니다.
React의 많은 뛰어난 점들 중 하나는 생각을 하면서 애플리케이션을 만들게 한다는 겁니다. 이 포스트에서 React를 이용해 검색이 가능한 상품자료 테이블을 만드는 생각 과정을 이해할 수 있게 차근차근 설명할 겁니다.
## 모형으로 시작해보기
우리가 이미 JSON API와 디자이너로부터 넘겨받은 모형을 이미 가지고 있다고 생각해봅시다. 보시다시피 우리 디자이너는 별로 좋지 않습니다:
![Mockup](/react/img/blog/thinking-in-react-mock.png)
우리의 JSON API는 아래와 같은 데이터를 리턴합니다:
```
[
{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"},
{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"},
{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"},
{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"},
{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"},
{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"}
];
```
## 1단계: UI를 계층 구조의 컴포넌트로 분쇄하세요.
당신이 하고싶은 첫번째는 모형에 있는 모든 컴포넌트 (그리고 자식엘리먼트) 주위에 상자를 그리고, 이름을 부여하는 것입니다. 만약 당신이 디자이너와 같이 작업중이라면, 그들은 이미 이 작업을 해놨을지도 모릅니다. 당장 가서 이야기해보세요. 그들의 포토샵 레이어 이름이 결국 당신의 React 컴포넌트들의 이름이 될 것입니다.
그런데 무엇이 컴포넌트가 되어야 할까요? 당신이 새로운 함수나 객체를 만들어야만 한다면, 똑같이 적용하세요. 한가지 방법은 [단일 책임의 원칙](http://ko.wikipedia.org/wiki/%EB%8B%A8%EC%9D%BC_%EC%B1%85%EC%9E%84_%EC%9B%90%EC%B9%99) 입니다. 즉 하나의 컴포넌트는 이상적으로 한가지 작업만 수행해야 합니다. 컴포넌트가 결국 커진다면 작은 자식 컴포넌트로 쪼개져야 합니다.
주로 JSON 데이터 모델을 사용자에게 보여주기 때문에, 자료 모델이 잘 설계 되었다면 UI(혹은 컴포넌트 구조)가 잘 맞아 떨어진다는 것을 알게 될 겁니다. UI와 자료 모델은 같은 *정보 설계구조*로 따라가는 경향이 있기 때문입니다. 즉, UI를 컴포넌트들로 쪼개는 작업은 크게 어렵지 않습니다. 확실하게 각각 하나의 부분이 되도록 쪼개세요.
![Component diagram](/react/img/blog/thinking-in-react-components.png)
이 간단한 애플리케이션에는 다섯개의 컴포넌트가 있습니다. 각 컴포넌트들이 대표하는 자료를 기울여 표기했습니다.
1. **`FilterableProductTable` (오렌지):** 예제 전부를 포함합니다.
2. **`SearchBar` (파랑):** 모든 *사용자 입력* 을 받습니다.
3. **`ProductTable` (초록):** *자료 모음*을 *사용자 입력*에 맞게 거르고 보여줍니다.
4. **`ProductCategoryRow` (청록):** 각 *카테고리*의 제목을 보여줍니다.
5. **`ProductRow` (빨강):** 각 *프로덕트*를 보여줍니다.
`ProductTable`을 보면 테이블 제목("Name", "Price" 라벨들을 포함한)은 컴포넌트가 아닌것을 알 수 있습니다. 이건 기호의 문제이고, 어느쪽으로 만들던 논쟁거리입니다. 예를 들어 저는 *자료 모음*을 그리는 `ProductTable`의 의무라고 생각했기 때문에 남겨 두었습니다. 하지만 이 제목이 복잡해진다면 (예를 들어 정렬을 추가할 여유가 있다거나 하는), 이건 확실히 `ProductTableHeader` 컴포넌트로 만드는 것이 맞을 겁니다.
이제 모형에 들어있는 컴포넌트들에 대해 알아보았으니, 계층 구조로 만들어 봅시다. 이건 쉽습니다. 다른 컴포넌트 속에 들어있는 컴포넌트를 자식으로 나타내기만 하면 됩니다.
* `FilterableProductTable`
* `SearchBar`
* `ProductTable`
* `ProductCategoryRow`
* `ProductRow`
## 2단계: 정적 버전을 만드세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/yun1vgqb/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
계층구조의 컴포넌트들을 가지고 있으니, 이젠 애플리케이션을 구현할 시간입니다. 가장 쉬운 방법은 상호작용을 하지 않는 채로 자료 모델을 이용해 UI를 그리는 것입니다. 정적 버전을 만드는 데에는 적은 생각과 많은 노동이 필요하고, 상호작용을 추가하는 데에는 많은 생각과 적은 노동이 필요하기 때문에 둘을 분리하는 것은 쉽습니다. 왜 그런지 봅시다.
자료 모델을 그리는 애플리케이션의 정적버전을 만들기 위해서, 다른 컴포넌트에 재사용할 컴포넌트를 만들고 자료 전달을 위해 *props*를 사용하고 싶을 것입니다. 만약 *상태*라는 개념에 익숙하다면, 정적 버전을 만들때 **절대 상태를 사용하지 마세요**. 상태는 오직 상호작용, 즉 가변적인 자료를 위해서만 준비되어 있습니다. 정적 버전을 만들 때는 필요가 없습니다.
껍데기부터 혹은 속알맹이부터 만들 수 있습니다. 즉 계층구조상 위에서부터 (`FilterableProductTable` 부터) 혹은 아래에서부터 (`ProductRow`), 어느 방향에서든 시작해도 됩니다. 통상 큰 프로젝트에서는 계층구조상 위에서부터 시작하는 것이 쉽고, 테스트를 작성할때는 아래에서부터 시작하는 것이 쉽습니다.
이 단계의 결과, 자료 모델을 그리는 재활용 가능한 컴포넌트의 라이브러리를 갖게 되었습니다. 정적버전 이후로 컴포넌트들은 오직 `render()` 메소드만 갖고 있습니다. 계층구조상 가장 위의 컴포넌트 (`FilterableProductTable`)은 자료 모델을 prop으로 취할 것입니다. 자료 모델이 변했을 때, `React.render()`를 다시 부르면 업데이트 됩니다. 어떻게 UI가 업데이트 되는지 참 알기 쉽습니다. 자료가 바뀌어도 처리해야 할 복잡한 일이 아무것도 없습니다. React의 **단일 방향 자료 흐름** (혹은 *단일방향 바인딩*)이 모든것을 모듈식으로, 추론하기 쉽게, 그리고 빠르게 유지해줍니다.
이 단계를 진행하는 데에 도움이 필요하시다면, [React 문서](/react/docs/getting-started-ko-KR.html)를 참조하세요.
### 잠시만: props vs state
React 에는 두가지 타입의 자료 "모델"이 있습니다: props 와 state. 두가지의 구분점을 이해하는데 매우 중요합니다; 혹시 차이점을 확신하지 못한다면 걷어내세요 [공식 문서](/react/docs/interactivity-and-dynamic-uis-ko-KR.html).
## 3단계: UI state 의 표현을 작지만 완전하도록 확인하세요.
상호적인 UI를 만들기 위해서는 자료 모델 변화에 반응할 수 있어야 합니다. React는 **state**로 이걸 쉽게 만들어주죠.
올바르게 애플리케이션을 만들기 위해서는 첫째로 애플리케이션에 필요한 변할 수 있는 state 들의 최소한의 집합에 대해서 생각해볼 필요가 있습니다. 여기 방법이 있습니다: *스스로 반복하지 마세요* (DRY). 애플리케이션의 상태를 나타낼 수 있는 가장 최소한의 표현 방식을 찾고, 그 밖의 것은 필요할 때 계산합니다. 예를들어 TODO 목록를 만든다고 칩시다. TODO 아이템들의 배열만 유지하세요; 갯수를 표현하기 위한 state 변수를 분리하지 마세요. 대신 TODO 아이템들 배열의 길이를 이용하세요.
예제 애플리케이션에서의 모든 자료유형에 대해 생각해 봅시다:
* product 들의 원본 목록
* 사용자가 입력한 검색어
* 체크박스의 값
* product 들의 필터된 목록
어느것이 state 가 될지 따져봅시다. 간단하게 각 자료에 대해 세가지만 생각해 보세요.
1. 만약 부모로부터 props 를 이용해 전달됩니까? 그렇다면 이건 state가 아닙니다.
2. 종종 바뀝니까? 아니라면 이것 역시 state가 아닙니다.
3. 컴포넌트에 있는 다른 state나 props를 통해서 계산되어질 수 있습니까? 역시 state가 아닙니다.
product 들의 원본 목록은 props를 통해서 전달되기 때문에, state가 아닙니다. 검색어와 체크박스의 값은 다른것에 의해 계산될 수 있는 값이 아니고, 시시각각 변하기때문에 state가 맞습니다. 마지막으로 product 들의 걸러진 목록 역시 state가 아닙니다. 원본 목록과 검색어, 체크박스의 값 등에 의해 연산되어지는 값이기 때문이죠.
결국, state는 다음과 같습니다:
* 사용자가 입력한 검색어
* 체크박스의 값
## 4단계: 어디서 state가 유지되어야 하는지 확인하세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/zafjbw1e/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
이제 최소한의 state가 무엇인지 알아냈습니다. 다음은 어떤 컴포넌트가 이 state를 변형하거나 만들어낼지 알아내야 합니다.
기억하세요: React는 계층적 아래 컴포넌트로만 향하는 단일방향성 자료 흐름을 가집니다. 지금당장은 어떤 컴포넌트가 자기 자신의 state를 가져야 할지 명확하지 않을 것입니다. **이것이 초심자가 가장 이해하기 어려운 부분입니다**. 이제 개념을 명확히 하기 위해 다음으로 따라가 봅시다:
애플리케이션에서 state의 경우:
* 모든 컴포넌트가 state를 통해 무언가를 그려냅니다.
* 대표 컴포넌트가 뭔지 찾으세요 (계층적으로 다른 컴포넌트들의 단일 상위 컴포넌트는 state를 가질 필요가 있습니다).
* 대표 컴포넌트 혹은 또다른 컴포넌트는 가능한 상위의 컴포넌트가 state를 소유해야 합니다.
* 만약 state를 가져야할 컴포넌트가 어느 것인지 모르겠으면, 새로운 컴포넌트를 만들어 state를 부여하고 기존의 대표 컴포넌트 위에 추가하세요.
이 전략을 우리 애플리케이션에 적용해 봅시다.
* `ProductTable`은 state에 대해 걸러질 필요가 있고, `SearchBar` 역시 검색어 state와 체크박스 state를 보여줄 필요가 있습니다.
* 대표 컴포넌트는 `FilterableProductTable` 입니다.
* 개념적으로 검색어와 체크박스 값은 `FilterableProductTable`에 있어야 한다는 것이 명확합니다.
좋습니다. state를 `FilterableProductTable`에서 관리하도록 결정했습니다. 먼저 `getInitialState()` 메소드를 `FilterableProductTable`에 추가하세요. 이 메소드는 애플리케이션의 초기 state를 갖도록 `{filterText: '', inStockOnly: false}`를 리턴하면 됩니다. 그리고 `filterText``inStockOnly``ProductTable``SearchBar`에 prop으로 전달하세요. 마지막으로 이 prop들을 `ProductTable`을 걸러내는 데, 그리고 `SearchBar` form fields의 값을 세팅하는데 사용하세요.
이제 어떻게 애플리케이션이 동작하는지 볼 수 있습니다: `filterText``"ball"`로 설정하고 업데이트합니다. 자료 테이블이 제대로 업데이트 되는 것을 볼 수 있을 겁니다.
## 5단계: 반대방향 자료 흐름을 추가하세요.
<iframe width="100%" height="300" src="https://jsfiddle.net/reactjs/n47gckhr/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
앞서 우리는 계층적으로 아랫방향 흐름의 props, state전달로 잘 동작하는 애플리케이션을 만들었습니다. 이제 다른방향의 자료 흐름을 지원할 시간입니다: form 컴포넌트들은 `FilterableProductTable`의 state를 업데이트할 필요성이 있죠.
React는 어떻게 이 프로그램이 동작하는지 이해하기 쉽게 이 자료의 흐름을 명시적으로 만들어주지만 전통적인 두 방향의 자료 바인딩보다 다소 입력할 것이 많습니다. React는 이러한 패턴을 양방향 바인딩처럼 편하게 사용할 수 있도록 ReactLink를 제공하지만, 이 글의 목적상 명시적인 방식만 사용했습니다.
지금 예제에 문자열을 입력하거나 체크박스를 체크하더라도 React가 입력을 무시하는것을 볼 수 있습니다. 의도적으로 `input`의 prop에 `value`를 세팅하면 항상 `state``FilterableProductTable`로부터 전달되어야 합니다.
우리가 원하는 것이 무엇인지 생각해 봅시다. 사용자가 form을 바꿀때마다 사용자 입력을 반영하기 위해 업데이트 하기를 원하죠. 컴포넌트들이 오직 자기 자신의 state만 업데이트 하더라도 `FilterableProductTable`은 state가 변할때마다 반영되어야할 `SearchBar`에 콜백을 전달할 것입니다. 이 알림을 위해서 `onChange`이벤트를 사용할 수 있습니다. 그리고 `FilterableProductTable`으로부터 전달된 콜백은 `setState()`를 호출할 것이고, 애플리케이션은 업데이트될 것입니다.
많은 코드가 필요한 것 같이 들릴 수 있지만 실제로는 몇 줄 되지 않습니다. 그리고 애플리케이션의 구석구석에서 데이터가 어떻게 흐르는지 매우 명확해집니다.
## 그리고
이 글이 컴포넌트와 React로 애플리케이션을 어떻게 만들지에 대한 아이디어가 되길 바랍니다. 원래 하던 방식보다 조금 타이핑을 더 해야할지도 모르지만, 코드는 쓰는 경우보다 읽히는 경우가 많다는 점, 매우 읽기 편하고 명시적인 코드를 썼다는 점을 기억하세요. 컴포넌트로 큰 라이브러리를 만들기 시작할 때, 이 명시성과 모듈성에 감사하게 될 것이며 재사용함에 따라 코드의 양도 줄어들 것입니다. :)

704
docs/tutorial.ko-KR.md

@ -0,0 +1,704 @@
---
id: tutorial-ko-KR
title: 튜토리얼
permalink: tutorial-ko-KR.html
prev: getting-started-ko-KR.html
next: thinking-in-react-ko-KR.html
---
블로그에 붙일만한 간단하지만 실용적인 댓글상자를 만들어 볼 것입니다. Disqus, LiveFyre, Facebook에서 제공하는 것 같은 실시간 댓글의 간단한 버전이죠.
이런 기능을 넣겠습니다:
* 댓글목록
* 댓글작성폼
* 커스텀 백엔드를 위한 Hooks
멋진 기능도 조금 넣어보겠습니다:
* **낙관적 댓글 달기:** 댓글은 서버에 저장되기도 전에 목록에 나타납니다. 그래서 빠르게 느껴집니다.
* **실시간 업데이트:** 다른 사용자가 남기는 댓글이 실시간으로 나타납니다.
* **Markdown 지원:** 사용자는 글을 꾸미기 위해 Markdown 형식을 사용할 수 있습니다.
### 그냥 다 생략하고 소스만 보고 싶나요?
[GitHub에 전부 있습니다.](https://github.com/reactjs/react-tutorial)
### 서버 구동하기
이 튜토리얼을 시작할 때 필요한 건 아니지만, 나중에 실행 중인 서버에 `POST` 요청을 하는 기능을 추가하게 될 것입니다. 서버를 구성하는 것이 익숙하다면, 본인이 편한 방식대로 서버를 구성해 주세요. 서버사이드에 대한 고민없이 React의 학습 그 자체에 집중하고 싶은 분들을 위해서, 몇 가지 언어로 간단한 서버코드를 작성해 놓았습니다 - JavaScript (Node.js), Python, Ruby, Go, PHP 버전이 있고, GitHub에서 찾아보실 수 있습니다. [소스를 확인](https://github.com/reactjs/react-tutorial/)하거나 [zip 파일을 다운로드](https://github.com/reactjs/react-tutorial/archive/master.zip)하고 시작하세요.
튜토리얼을 시작하려면, `public/index.html`을 열고 바로 시작하세요.
### 시작하기
이 튜토리얼에서는 CDN에 있는 미리 빌드된 JavaScript 파일들을 사용합니다. 선호하는 에디터를 열어, 새로운 HTML 문서를 만드세요:
```html
<!-- index.html -->
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/jsx">
// 여기에 코드를 작성합니다
</script>
</body>
</html>
```
다음 진행을 위해, 위의 스크립트 태그안에 JavaScript 코드를 작성합니다.
> 주의:
>
> 여기서는 ajax 요청 코드를 단순화 하기 위해 jQuery를 넣었지만, 이는 React의 동작에 필수적인 것은 **아닙니다**.
### 첫 번째 컴포넌트
모듈화 된, 조합가능한 컴포넌트가 React의 전부입니다. 댓글상자 예제에서 우리는 다음과 같은 컴포넌트 구조를 가질 것입니다:
```
- CommentBox
- CommentList
- Comment
- CommentForm
```
자, 이제 `CommentBox` 컴포넌트를 만들어 봅시다. `<div>` 하나로 구성되어 있습니다.
```javascript
// tutorial1.js
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
Hello, world! I am a CommentBox.
</div>
);
}
});
React.render(
<CommentBox />,
document.getElementById('content')
);
```
#### JSX 문법
JavsScript 안의 유사 XML 구문이 먼저 눈에 띌 것입니다. 우리에겐 이를 JavaScript로 변환해주는 간단한 프리컴파일러(precompiler)가 있습니다.
```javascript
// tutorial1-raw.js
var CommentBox = React.createClass({displayName: 'CommentBox',
render: function() {
return (
React.createElement('div', {className: "commentBox"},
"Hello, world! I am a CommentBox."
)
);
}
});
React.render(
React.createElement(CommentBox, null),
document.getElementById('content')
);
```
JSX의 사용은 선택적이지만 JSX 문법이 일반 JavsScript보다 사용하기 쉽습니다. [JSX 문법 문서](/react/docs/jsx-in-depth.html)에서 더 알아보세요.
#### 무슨 일이 일어나고 있는가
우리는 새로운 React 컴포넌트를 만들기 위해 `React.createClass()`로 JavaScript 객체에 몇 개의 메소드를 담아 넘겼습니다. 이 중 가장 중요한것은 `render` 메소드인데, 이는 React 컴포넌트 트리를 리턴해서 최종적으로 실제 HTML을 그려주게 됩니다.
`<div>` 태그들은 실제 DOM 노드가 아니라 React `div` 컴포넌트의 인스턴스입니다. 이것은 React가 다룰 수 있는 데이터의 표시자(markers)나 조각이라 생각하셔도 됩니다. React는 **안전합니다**. 생(raw) HTML 문자열을 생성하는 것이 아니기 때문에 XSS을 기본적으로 방지합니다.
일반적인 HTML만 리턴할 수 있는 것은 아닙니다. 여러분이 직접 만든 (또는 다른 사람들이 만들어 놓은) 컴포넌트의 트리를 리턴할 수도 있습니다. 이것이 React를 **조합가능(composable)하게 만듭니다**: 유지보수 가능한 프론트엔드를 위한 핵심 교리(key tenet)지요.
`React.render()`는 최상위 컴포넌트의 인스턴스를 만들고, 두 번째 인수로 전달받은 DOM 엘리먼트에 마크업을 삽입해 프레임워크를 시작합니다.
## 컴포넌트 조합하기
이제 `CommentList``CommentForm`을 위한 뼈대를 구축해 봅시다. 이전과 마찬가지로 단순히 `<div>` 태그 하나 입니다.
```javascript
// tutorial2.js
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
안녕! 난 댓글목록이야.
</div>
);
}
});
var CommentForm = React.createClass({
render: function() {
return (
<div className="commentForm">
안녕! 난 댓글 폼이야.
</div>
);
}
});
```
다음은 `CommentBox` 컴포넌트가 새로 만든 컴포넌트들을 사용하도록 수정합니다.
```javascript{6-8}
// tutorial3.js
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList />
<CommentForm />
</div>
);
}
});
```
방금 만든 컴포넌트들을 어떻게 HTML 태그들과 섞어 사용하는지 살펴보세요. HTML 컴포넌트들도 한가지 차이만 제외한다면 우리가 정의한 것과 같은 표준적인 React 컴포넌트입니다. JSX 컴파일러가 자동으로 HTML 태그들을 `React.createElement(tagName)` 표현식으로 재작성하고 나머지는 그대로 둘 것입니다. 이는 전역 네임스페이스가 오염되는 것을 막아줍니다.
### props 사용하기
부모로 부터 받은 데이터에 의존하는 `Comment` 컴포넌트를 만들어 봅시다. 부모 컴포넌트로 부터 받은 데이터는 자식 컴포넌트에서 '프로퍼티'로 사용가능 합니다. 이 '프로퍼티들'은 `this.props`를 통해 접근합니다. props를 사용해 `CommentList`에서 전달받은 데이터를 읽어들이고, 마크업을 렌더할 수 있을 것입니다.
```javascript
// tutorial4.js
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
{this.props.children}
</div>
);
}
});
```
JSX 내부의 중괄호로 둘러싸인 JavaScript 표현식(어트리뷰트나 엘리먼트의 자식으로 사용된)을 통해 텍스트나 React 컴포넌트를 트리에 더할 수 있습니다. `this.props`를 통해 컴포넌트에 전달된 특정한 어트리뷰트들에, `this.props.children`을 통해 중첩된 엘리먼트들에 접근할 수 있습니다.
### 컴포넌트 프로퍼티 (Component Properties)
`Comment` 컴포넌트를 만들었으니, 여기에 글쓴이와 내용을 넘겨보도록 합시다. 이렇게 함으로써 각 고유한 comment에서 같은 코드를 재사용할 수 있습니다. 먼저 댓글 몇 개를 `CommentList`에 추가해 봅시다:
```javascript{6-7}
// tutorial5.js
var CommentList = React.createClass({
render: function() {
return (
<div className="commentList">
<Comment author="Pete Hunt">댓글입니다</Comment>
<Comment author="Jordan Walke">*또 다른* 댓글입니다</Comment>
</div>
);
}
});
```
부모 컴포넌트인 `CommentList`에서 자식 컴포넌트인 `Comment`에 데이터들을 전달하고 있는것을 확인할 수 있습니다. 예를 들어, 우리는 어트리뷰트로 *Pete Hunt*를, XML 형식의 자식 노드로 *댓글입니다*를 첫 번째 `Comment`로 넘겼습니다. 위에서 언급했듯이 `Comment` 컴포넌트는 그들의 '프로퍼티'를 `this.props.author`, `this.props.children`를 통해 접근합니다.
### Markdown 추가하기
Markdown은 텍스트를 포맷팅하는 간단한 방식입니다. 예를 들어, 별표(`*`)로 텍스트를 둘러싸는 것은 강조의 의미입니다.
먼저 서드파티 라이브러리인 **Showdown**을 애플리케이션에 추가합니다. 이 JavaScript 라이브러리는 Markdown 텍스트를 HTML 문법으로 변환해줍니다. head 태그안에 스크립트 태그를 추가해 주세요. (React playground에는 이미 포함되어 있습니다):
```html{7}
<!-- index.html -->
<head>
<title>Hello React</title>
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>
</head>
```
다음은, 댓글 텍스트를 Markdown으로 전환하고 출력해 봅시다.
```javascript{2,10}
// tutorial6.js
var converter = new Showdown.converter();
var Comment = React.createClass({
render: function() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
{converter.makeHtml(this.props.children.toString())}
</div>
);
}
});
```
우리가 한 일이라고는 Showdown 라이브러리를 호출한 것 뿐입니다. Showdown이 `this.props.children`에서 텍스트를 읽어들여 처리할 수 있도록 React 형식의 텍스트(React's wrapped text)를 단순 텍스트(raw string)으로 전환하기 위해 명시적으로 `toString()`을 호출했습니다.
하지만 여기엔 문제가 있습니다! 우리는 HTML 태그들이 정상적으로 렌더되길 원하지만 브라우저에 출력된 결과물은 "`<p>``<em>`또 다른`</em>` 댓글입니다`</p>`"처럼 태그가 그대로 보일것입니다.
React는 이런 식으로 XSS 공격을 예방합니다. 우회할 방법이 있긴 하지만 프레임워크는 사용하지 않도록 경고하고 있습니다:
```javascript{5,11}
// tutorial7.js
var converter = new Showdown.converter();
var Comment = React.createClass({
render: function() {
var rawMarkup = converter.makeHtml(this.props.children.toString());
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
<span dangerouslySetInnerHTML={{"{{"}}__html: rawMarkup}} />
</div>
);
}
});
```
이는 의도적으로 생(raw) HTML을 넣기 힘들게 하려고 만든 특별한 API지만 Showdown을 사용하기 위해 이 백도어를 활용합시다.
**잊지 마세요:** 이 기능은 Showdown이 안전한 것으로 믿고 사용하는 것입니다.
### 데이터 모델 연결하기
지금까지는 소스코드에 직접 댓글을 넣었습니다. 이제부터는 JSON 데이터 덩어리를 댓글 목록에 렌더해보겠습니다. 최종적으로는 서버에서 데이터가 내려오겠지만, 지금은 소스에 직접 데이터를 넣어봅시다:
```javascript
// tutorial8.js
var data = [
{author: "Pete Hunt", text: "댓글입니다"},
{author: "Jordan Walke", text: "*또 다른* 댓글입니다"}
];
```
이 데이터를 모듈화된 방식으로 `CommentList`에 넣어야 합니다. props을 이용해 데이터를 넘기도록 `CommentBox``React.render()` 호출 코드를 수정합시다.
```javascript{7,15}
// tutorial9.js
var CommentBox = React.createClass({
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.props.data} />
<CommentForm />
</div>
);
}
});
React.render(
<CommentBox data={data} />,
document.getElementById('content')
);
```
이제 `CommentList`에서 데이터를 다룰 수 있습니다. 댓글을 동적으로 렌더해봅시다:
```javascript{4-10,13}
// tutorial10.js
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function (comment) {
return (
<Comment author={comment.author}>
{comment.text}
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
});
```
이게 전부입니다!
### 서버에서 가져오기(Fetching)
이제 데이터를 소스에 직접 넣는 방식에서 서버에서 동적으로 받아서 처리하는 방식으로 바꿔봅시다. 데이터 prop을 삭제하고 처리할 URL로 변경해 줍시다.
```javascript{3}
// tutorial11.js
React.render(
<CommentBox url="comments.json" />,
document.getElementById('content')
);
```
이 컴포넌트는 이전 것과 다르게, 스스로 다시 렌더링해야 합니다. 컴포넌트는 서버에서 요청이 들어올때까지는 아무 데이터도 가지고 있지 않다가, 특정한 시점에서 새로운 댓글을 렌더할 필요가 있을 것입니다.
### 반응적 state
지금까지, 각각의 컴포넌트는 props를 기반으로 한번 렌더되었습니다. `props`는 불변성을 갖습니다: 그것들은 부모에서 전달되어 부모에게 "소유" 되어 있습니다. 컴포넌트에 상호작용을 구현하기 위해서, 가변성을 갖는 **state**를 소개합니다. `this.state`는 컴포넌트에 한정(private)되며 `this.setState()`를 통해 변경할 수 있습니다. state가 업데이트 되면, 컴포넌트는 자신을 스스로 다시 렌더링합니다.
`render()` 메소드는 `this.props``this.state`를 위한 함수로 선언적으로 작성됩니다. 프레임워크에서 입력값에 따른 UI가 항상 일관성 있음을 보장해줍니다.
서버가 데이터를 가져오면 댓글 데이터가 변경될 것입니다. 댓글 데이터의 배열을 `CommentBox`의 state로 추가해봅시다:
```javascript{3-5,10}
// tutorial12.js
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
```
`getInitialState()` 는 컴포넌트의 생명주기동안 한 번만 실행되며 컴포넌트의 초기 state를 설정합니다.
### state 업데이트하기
컴포넌트의 최초 생성 시에, 서버에서 GET 방식으로 JSON을 넘겨받아 최신의 데이터가 state에 반영되길 원했습니다. 실제 애플리케이션에선 이것이 동적인 엔드포인트이지만, 이 예제에서는 정적 JSON 파일을 사용해서 간단하게 만들어보겠습니다.
```javascript
// tutorial13.json
[
{"author": "Pete Hunt", "text": "댓글입니다"},
{"author": "Jordan Walke", "text": "*또 다른* 댓글입니다"}
]
```
서버에 비동기 요청을 위해 jQuery를 사용합니다.
주의: 우리의 앱이 AJAX 애플리케이션으로 변화하고 있기 때문에, 이제 파일 시스템의 파일을 참조하는 대신 웹서버를 사용하도록 앱을 개발해야 합니다. [위에서 언급한 바와 같이](#running-a-server), 우리는 튜토리얼의 나머지 부분에 필요한 기능을 제공하는 서버를 몇 가지 준비해 놓았습니다. [GitHub에 올려놓았으니](https://github.com/reactjs/react-tutorial) 확인해 보세요.
```javascript{6-17}
// tutorial13.js
var CommentBox = React.createClass({
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
```
여기서 `componentDidMount`는 컴포넌트가 렌더링 된 다음 React에 의해 자동으로 호출되는 메소드입니다. 동적 업데이트의 핵심은 `this.setState()`의 호출입니다. 우리가 이전의 댓글 목록을 서버에서 넘어온 새로운 목록으로 변경하면 자동으로 UI가 업데이트 될 것입니다. 이 반응성 덕분에 실시간 업데이트에 아주 작은 수정만 가해집니다. 우리는 여기선 간단한 폴링을 사용할 것이지만 웹소켓등의 다른 기술도 쉽게 사용할 수 있습니다.
```javascript{3,14,19-20,34}
// tutorial14.js
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
});
React.render(
<CommentBox url="comments.json" pollInterval={2000} />,
document.getElementById('content')
);
```
우리가 여기서 한것은 AJAX 호출을 별도의 메소드로 분리하고 컴포넌트가 처음 로드된 시점부터 2초 간격으로 계속 호출되도록 한 것입니다. 브라우저에서 직접 돌려보고 `comments.json`파일을 수정해보세요; 2초 간격으로 변화되는 모습이 보일 것입니다!
### 새로운 댓글 추가하기
이제 폼을 만들어볼 시간입니다. 우리의 `CommentForm` 컴포넌트는 사용자에게 이름과 내용을 입력받고 댓글을 저장하기 위해 서버에 요청을 전송해야 합니다.
```javascript{5-9}
// tutorial15.js
var CommentForm = React.createClass({
render: function() {
return (
<form className="commentForm">
<input type="text" placeholder="이름" />
<input type="text" placeholder="내용을 입력하세요..." />
<input type="submit" value="올리기" />
</form>
);
}
});
```
이제 폼의 상호작용을 만들어 보겠습니다. 사용자가 폼을 전송하는 시점에 우리는 폼을 초기화하고 서버에 요청을 전송하고 댓글목록을 업데이트해야 합니다. 폼의 submit 이벤트를 감시하고 초기화 해주는 부분부터 시작해 보죠.
```javascript{3-13,16-19}
// tutorial16.js
var CommentForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!text || !author) {
return;
}
// TODO: 서버에 요청을 전송합니다
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="이름" ref="author" />
<input type="text" placeholder="내용을 입력하세요..." ref="text" />
<input type="submit" value="올리기" />
</form>
);
}
});
```
##### 이벤트
React는 카멜케이스 네이밍 컨벤션으로 컴포넌트에 이벤트 핸들러를 등록합니다. 폼이 유효한 값으로 submit되었을 때 폼필드들을 초기화하도록 `onSubmit` 핸들러를 등록합니다.
폼 submit에 대한 브라우저의 기본동작을 막기 위해 이벤트시점에 `preventDefault()`를 호출합니다.
##### Refs
우리는 자식 컴포넌트의 이름을 지정하기 위해 `ref` 어트리뷰트를, 컴포넌트를 참조하기 위해 `this.refs`를 사용합니다. 고유한(native) 브라우저 DOM 엘리먼트를 얻기 위해 `React.findDOMNode(component)`를 호출할 수 있습니다.
##### props으로 콜백 처리하기
사용자가 댓글을 등록할 때, 새로운 댓글을 추가하기 위해 댓글목록을 업데이트해주어야 합니다. `CommentBox`가 댓글목록의 state를 소유하고 있기 때문에 이 로직 또한 `CommentBox`에 있는것이 타당합니다.
자식 컴포넌트가 그의 부모에게 데이터를 넘겨줄 필요가 있습니다. 부모의 `render` 메소드에서 새로운 콜백(`handleCommentSubmit`)을 자식에게 넘겨주고, 자식의 `onCommentSubmit` 이벤트에 그것을 바인딩해주는 식으로 구현합니다. 이벤트가 작동될때(triggered)마다, 콜백이 호출됩니다:
```javascript{15-17,30}
// tutorial17.js
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment) {
// TODO: 서버에 요청을 수행하고 목록을 업데이트한다
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
```
사용자가 폼을 전송할 때, `CommentForm`에서 콜백을 호출해 봅시다:
```javascript{10}
// tutorial18.js
var CommentForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({author: author, text: text});
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},
render: function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="이름" ref="author" />
<input type="text" placeholder="이름을 입력하세요..." ref="text" />
<input type="submit" value="올리기" />
</form>
);
}
});
```
이제 콜백이 제자리를 찾았습니다. 우리가 할 일은 서버에 요청을 날리고 목록을 업데이트하는 것 뿐입니다:
```javascript{16-27}
// tutorial19.js
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment) {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
```
### 최적화: 낙관적 업데이트
우리의 애플리케이션은 이제 모든 기능을 갖추었습니다. 하지만 댓글이 목록에 업데이트되기 전에 완료요청을 기다리는 게 조금 느린듯한 느낌이 드네요. 우리는 낙관적 업데이트를 통해 댓글이 목록에 추가되도록 함으로써 앱이 좀 더 빨라진 것처럼 느껴지도록 할 수 있습니다.
```javascript{16-18}
// tutorial20.js
var CommentBox = React.createClass({
loadCommentsFromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
handleCommentSubmit: function(comment) {
var comments = this.state.data;
var newComments = comments.concat([comment]);
this.setState({data: newComments});
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
getInitialState: function() {
return {data: []};
},
componentDidMount: function() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return (
<div className="commentBox">
<h1>댓글</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
});
```
### 축하합니다!
몇 단계를 거쳐 간단하게 댓글창을 만들어 보았습니다. [왜 React인가](/react/docs/why-react-ko-KR.html)에서 더 알아보거나, 혹은 [API 레퍼런스](/react/docs/top-level-api-ko-KR.html)에 뛰어들어 해킹을 시작하세요! 행운을 빕니다!

147
docs/videos.ko-KR.md

@ -0,0 +1,147 @@
---
id: videos-ko-KR
title: 비디오들
permalink: videos-ko-KR.html
prev: conferences-ko-KR.html
next: complementary-tools-ko-KR.html
---
### Rethinking best practices - JSConf.eu
<iframe width="650" height="315" src="//www.youtube.com/embed/x7cQ3mrcKaY" frameborder="0" allowfullscreen></iframe>
"페이스북과 인스타그램에서, 우리는 React 를 이용해 웹에서 벌어질 수 있는 한계를 뛰어넘으려 노력하고 있습니다. 저는 프레임워크에 대한 짤막한 소개로 시작해서, 논쟁이 벌어질 수 있는 다음의 세가지 주제로 넘어갈겁니다. 템플릿의 개념을 버리고 Javascript 를 이용해 View 를 구축하기, 자료가 변할때 전체 어플리케이션을 다시 그리기(“re-rendering”), 그리고 DOM과 events의 경량화된 구현 입니다." -- [Pete Hunt](http://www.petehunt.net/)
### Thinking in react - tagtree.tv
[tagtree.tv](http://tagtree.tv/)의 비디오는 간단한 어플리케이션을 구성하면서 [Thinking in React](/react/docs/thinking-in-react-ko-KR.html)의 원리들을 전달합니다.
<figure>[![](/react/img/docs/thinking-in-react-tagtree.png)](http://tagtree.tv/thinking-in-react)</figure>
### Secrets of the Virtual DOM - MtnWest JS
<iframe width="560" height="315" src="//www.youtube.com/embed/h3KksH8gfcQ" frameborder="0" allowfullscreen></iframe>
"이번에는 왜 우리가 virtual DOM을 만들었는지, 이것이 다른 시스템들과는 어떻게 다른지, 그리고 브라우져 기술들의 미래와 어떻게 관련이 있는지에 대해서 이야기 해 볼 겁니다." -- [Pete Hunt](http://www.petehunt.net/)
### Going big with React
"이 발표에서, 이 모든 JS 프레임워크가 다음을 약속하는것처럼 보입니다: 꺠끗한 구현들, 빠른 코드 디자인, 완전한 수행. 그런데 당신이 Javascript 스트레스 테스트를 할때, 어떤 일이 발생합니까? 혹은 6MB의 코드를 던지면 무슨일이 발생합니까? 이번에는 높은 스트레스 환경에서 React가 어떻게 작동하는지, 그리고 이것이 우리 팀이 방대한 크기의 코드를 안전하게 구성하는데 어떻게 도움이 되어줄지를 조사해 볼겁니다."
[![](https://i.vimeocdn.com/video/481670116_650.jpg)](https://skillsmatter.com/skillscasts/5429-going-big-with-react#video)
### CodeWinds
CodeWinds Episode 4 에서 [Pete Hunt](http://www.petehunt.net/)와 [Jeff Barczewski](http://jeff.barczewski.com/)가 React에 대해서 이야기 합니다.
<figure>[![](/react/img/docs/codewinds-004.png)](http://codewinds.com/4)</figure>
<table width="100%"><tr><td>
02:08 - What is React and why use it?<br />
03:08 - The symbiotic relationship of ClojureScript and React<br />
04:54 - The history of React and why it was created<br />
09:43 - Updating web page with React without using data binding<br />
13:11 - Using the virtual DOM to change the browser DOM<br />
13:57 - Programming with React, render targets HTML, canvas, other<br />
16:45 - Working with designers. Contrasted with Ember and AngularJS<br />
21:45 - JSX Compiler bridging HTML and React javascript<br />
23:50 - Autobuilding JSX and in browser tools for React<br />
24:50 - Tips and tricks to working with React, getting started<br />
</td><td>
27:17 - Rendering HTML on the server with Node.js. Rendering backends<br />
29:20 - React evolved through survival of the fittest at Facebook<br />
30:15 - Ideas for having state on server and client, using web sockets.<br />
32:05 - React-multiuser - distributed shared mutable state using Firebase<br />
33:03 - Better debugging with React using the state transitions, replaying events<br />
34:08 - Differences from Web Components<br />
34:25 - Notable companies using React<br />
35:16 - Could a React backend plugin be created to target PDF?<br />
36:30 - Future of React, what's next?<br />
39:38 - Contributing and getting help<br />
</td></tr></table>
[방송 자료 읽어보기](http://codewinds.com/4)
### JavaScript Jabber
Javascript Jabber 73에서 [Pete Hunt](http://www.petehunt.net/)와 [Jordan Walke](https://github.com/jordwalke)가 React에 대해서 이야기했습니다.
<figure>[![](/react/img/docs/javascript-jabber.png)](http://javascriptjabber.com/073-jsj-react-with-pete-hunt-and-jordan-walke/#content)</figure>
<table width="100%"><tr><td>
01:34 – Pete Hunt Introduction<br />
02:45 – Jordan Walke Introduction<br />
04:15 – React<br />
06:38 – 60 Frames Per Second<br />
09:34 – Data Binding<br />
12:31 – Performance<br />
17:39 – Diffing Algorithm<br />
19:36 – DOM Manipulation
</td><td>
23:06 – Supporting node.js<br />
24:03 – rendr<br />
26:02 – JSX<br />
30:31 – requestAnimationFrame<br />
34:15 – React and Applications<br />
38:12 – React Users Khan Academy<br />
39:53 – Making it work
</td></tr></table>
[전체 기록 읽어보기](http://javascriptjabber.com/073-jsj-react-with-pete-hunt-and-jordan-walke/)
### Introduction to React.js - Facebook Seattle
<iframe width="650" height="315" src="//www.youtube.com/embed/XxVg_s8xAms" frameborder="0" allowfullscreen></iframe>
By [Tom Occhino](http://tomocchino.com/), [Jordan Walke](https://github.com/jordwalke)
### Backbone + React + Middleman Screencast
<iframe width="650" height="315" src="//www.youtube.com/embed/iul1fWHVU6A" frameborder="0" allowfullscreen></iframe>
Backbone은 React로 REST API를 제공하기 위한 아주 좋은 방법입니다. 이 화면중개는 [Backbone-React-Component](https://github.com/magalhas/backbone-react-component)을 이용해서 어떻게 이 두가지를 병합하는지 보여줍니다. Middleman은 이 예제에서 사용되는 프레임워크이지만, 쉽게 다른 프레임워크로 대체하실 수 있습니다. 지원되는 템플릿은 [이곳](https://github.com/jbhatab/middleman-backbone-react-template)에서 찾으실 수 있습니다. -- [열린 마음의 혁명들](http://www.openmindedinnovations.com/)
### Developing User Interfaces With React - Super VanJS
<iframe width="650" height="315" src="//www.youtube.com/embed/1OeXsL5mr4g" frameborder="0" allowfullscreen></iframe>
By [Steven Luscher](https://github.com/steveluscher)
### Introduction to React - LAWebSpeed meetup
<iframe width="650" height="315" src="//www.youtube.com/embed/SMMRJif5QW0" frameborder="0" allowfullscreen></iframe>
by [Stoyan Stefanov](http://www.phpied.com/)
### React, or how to make life simpler - FrontEnd Dev Conf '14
<iframe width="560" height="315" src="//www.youtube.com/embed/YJNUK0EA_Jo" frameborder="0" allowfullscreen></iframe>
**러시아어** by [Alexander Solovyov](http://solovyov.net/)
### "Functional DOM programming" - Meteor DevShop 11
<iframe width="650" height="315" src="//www.youtube.com/embed/qqVbr_LaCIo" frameborder="0" allowfullscreen></iframe>
### "Rethinking Web App Development at Facebook" - Facebook F8 Conference 2014
<iframe width="650" height="315" src="//www.youtube.com/embed/nYkdrAPrdcw" frameborder="0" allowfullscreen></iframe>
### React and Flux: Building Applications with a Unidirectional Data Flow - Forward JS 2014
<iframe width="650" height="315" src="//www.youtube.com/embed/i__969noyAM" frameborder="0" allowfullscreen></iframe>
Facebook 개발자 [Bill Fisher](http://twitter.com/fisherwebdev)와 [Jing Chen](http://twitter.com/jingc)가 Flux 와 React 에 대해서 이야기합니다. 그리고 어떻게 단일 방향의 자료흐름을 사용하는 어플리케이션 구조가 방대한 코드를 정리하는지에 대해서 이야기합니다."
### Server-Side Rendering of Isomorphic Apps at SoundCloud
<iframe src="//player.vimeo.com/video/108488724" width="500" height="281" frameborder="0" allowfullscreen></iframe>
Server-side rendering을 위해 [SoundCloud](https://developers.soundcloud.com/blog/)가 React 와 Flux를 사용하는지 by [Andres Suarez](https://github.com/zertosh)
[발표 자료와 예제 코드](https://github.com/zertosh/ssr-demo-kit)
### Introducing React Native (+Playlist) - React.js Conf 2015
<iframe width="650" height="315" src="//www.youtube.com/watch?v=KVZ-P-ZI6W4&index=1&list=PLb0IAmt7-GS1cbw4qonlQztYV1TAW0sCr" frameborder="0" allowfullscreen></iframe>
2015년에 [Tom Occhino](https://twitter.com/tomocchino)님이 React의 과거와 현재를 리뷰하고 나아갈 방향을 제시했습니다.
Loading…
Cancel
Save