From 7cc2da8b0e8b664045380e51627c18576c708c54 Mon Sep 17 00:00:00 2001 From: bluecri Date: Mon, 5 Jun 2017 11:23:59 +0900 Subject: [PATCH 1/2] Trans(hierarchical-dependency-injection.jade) --- .../hierarchical-dependency-injection.jade | 188 ++++++++++++++++-- 1 file changed, 169 insertions(+), 19 deletions(-) diff --git a/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade b/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade index 1b8a0df7..22d151d3 100644 --- a/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade +++ b/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade @@ -2,37 +2,67 @@ block includes include ../_util-fns :marked + 여러분은 Angular 의존성 주입을 [의존성 주입](./dependency-injection.html) 가이드에서 배웠습니다. + You learned the basics of Angular Dependency injection in the [Dependency Injection](./dependency-injection.html) guide. + Angular는 계층적인 의존성 주입 시스템을 가지고 있습니다. + 실제로 애플리케이션의 컴포넌트 트리와 평행한 주입기들의 트리가 존재합니다. + 여러분은 컴포넌트 트리의 레벨에 상관없이 모든 주입들을 재구성할 수 있습니다. + Angular has a _Hierarchical Dependency Injection_ system. There is actually a tree of injectors that parallel an application's component tree. You can reconfigure the injectors at any level of that component tree. + 이 가이드에서는 이와 같은 시스템을 어떻게 잘 활용할 수 있을지 알아보겠습니다. + This guide explores this system and how to use it to your advantage. + 이 파트의 시도해보세요. + Try the . .l-main-section :marked + ## 주입기 트리 + ## The injector tree + [의존성 주입](./dependency-injection.html) 가이드에서 + 여러분은 의존성 주입기를 구성하는 방법과 특정 의존성들이 필요할 때 그 의존성을 되찾아오는 방법을 배웠습니다. + In the [Dependency Injection](./dependency-injection.html) guide, you learned how to configure a dependency injector and how to retrieve dependencies where you need them. + 사실, ***주입기***와 같은 것들은 존재하지 않습니다. + 어플리케이션은 여러개의 주입기를 가지고 있을것입니다. + Angular 어플리케이션은 컴포넌트들의 트리입니다. 각각의 컴포넌트 인스턴스는 각 인스턴스만의 주입기를 가지고 있습니다. + 컴포넌트들의 트리는 주입기들의 트리와 평행합니다. + In fact, there is no such thing as ***the*** injector. An application may have multiple injectors. An Angular application is a tree of components. Each component instance has its own injector. The tree of components parallels the tree of injectors. .l-sub-section - :marked - The component's injector may be a _proxy_ for an ancestor injector higher in the component tree. - That's an implementation detail that improves efficiency. - You won't notice the difference and - your mental model should be that every component has its own injector. + :marked + 컴포넌트의 인젝터는 컴포넌트 트리에서 상위에 있는 상위 주입기의 프록시 일 수 있습니다. + 효율성을 향상시키는 구현 세부 사항입니다. + 여러분은 이 차이를 알아 채지 못할 것이고 당신의 정신 모델은 모든 컴포넌트가 자신의 주입기를 가져야한다는 것입니다. + + The component's injector may be a _proxy_ for an ancestor injector higher in the component tree. + That's an implementation detail that improves efficiency. + You won't notice the difference and + your mental model should be that every component has its own injector. :marked + Tour of Heroes application을 약간 변형시켜 만든 다음 가이드를 고려해봅시다. + 여러개의 하위 컴포넌트들을 갖는 AppComponent가 가장 상단에 있습니다. + 하위 컴포넌트 중 하나는 'HeroesListComponent'입니다. + 이 'HeroesListComponent'는 'HeroTaxReturnComponent'의 여러 인스턴스들을 갖고 있고 관리합니다. + 다음 모형도는 이 가이드에서 설명하고 있는 3-level 컴포넌트 트리와 3개의 'HeroTaxReturnComponent'가 동시에 열려있는 상태를 나타내고 있습니다. + Consider this guide's variation on the Tour of Heroes application. At the top is the `AppComponent` which has some sub-components. One of them is the `HeroesListComponent`. @@ -44,7 +74,15 @@ figure.image-display img(src="/resources/images/devguide/dependency-injection/component-hierarchy.png" alt="injector tree" width="600") :marked - ### Injector bubbling + ### 주입기 버블링 + + ### Injector bubbling + + 컴포넌트가 의존성을 요청할 떄, Angular는 해당 컴포넌트의 인젝터에 등록되어 있는 Provider와의 종속성을 충족하려고 시도합니다. + 만약 컴포넌트의 주입기에 Provider가 없다면 요청을 상위 컴포넌트의 주입기로 전달합니다. + 해당 주입기가 요청을 충족시키지 못하면 다시 그 상위 컴포넌트의 주입기로 요청을 전달합니다. + Angular가 요청을 처리할 수 있는 주입기를 찾거나 더 이상 상위 주입기가 없을 때 까지 요청은 계속 전달되며 이를 버블링이라고 합니다. + 더 이상 상위 주입기가 없다면 Angular는 오류를 던집니다. When a component requests a dependency, Angular tries to satisfy that dependency with a provider registered in that component's own injector. If the component's injector lacks the provider, it passes the request up to its parent component's injector. @@ -59,60 +97,114 @@ figure.image-display This a topic for another day. :marked + ### 다른 레벨에서 서비스의 재 제공 + 주입기 트리의 여러 레벨에서 특정 종속성 토큰에 대한 provider를 다시 등록할 수 있습니다. + 공급자를 새로 다시 등록할 필요는 없습니다. 타당한 이유가 없다면 이와같은 행동은 해선 안됩니다. + 하지만 *가능은 합니다*. + ### Re-providing a service at different levels You can re-register a provider for a particular dependency token at multiple levels of the injector tree. - You don't *have* to re-register providers. You shouldn't do so unless you have a good reason. + You don't *have* to re-register providers. You shouldn't do so unless you have a good reason. But you *can*. + 해결 로직이 위로 진행됨에 따라 중간에 등록된 첫번째 provider를 마주합니다. + 따라서 중간 주입기에 있는 provider가 트리의 하위 항목에 존재하는 서비스 요청을 가로 챕니다. + 트리에서 상위 레벨의 provider를 효과적으로 재구성하고 상위 레벨의 provider를 가리게 됩니다. + As the resolution logic works upwards, the first provider encountered wins. Thus, a provider in an intermediate injector intercepts a request for a service from something lower in the tree. It effectively "reconfigures" and "shadows" a provider at a higher level in the tree. - If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat. + 최상위 레벨 (일반적으로 루트인 'AppModule') 에서만 provider들을 지정하는 경우 주입기 트리가 평평한 형태를 나타냅니다. + 모든 요청은 당신이 `!{_bootstrapModule}` 메서드로 구성해놓은 NgModule 루트 주입기까지 도달합니다. + + If you only specify providers at the top level (typically the root `AppModule`), the tree of injectors appears to be flat. All requests bubble up to the root NgModule injector that you configured with the `!{_bootstrapModule}` method. .l-main-section :marked + ## 컴포넌트 주입기 + ## Component injectors + 다수의 레벨에서 1개 또는 다수의 provider를 구성하는 능력은 흥미롭고 유용한 가능성을 열어줍니다. + The ability to configure one or more providers at different levels opens up interesting and useful possibilities. :marked + ### 시나리오: 서비스 독립 + ### Scenario: service isolation + 구조적인 원인들로 인해 어플리케이션 도메인에 있는 서비스에 접근이 제한될 수 있습니다. + Architectural reasons may lead you to restrict access to a service to the application domain where it belongs. + 이 가이드는 범죄자들의 리스트를 보여주는 `VillainsListComponent`를 포함합니다. + 범죄자의 리스트 정보들은 `VillainsService`로부터 얻습니다. + The guide sample includes a `VillainsListComponent` that displays a list of villains. It gets those villains from a `VillainsService`. - While you could provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`), + 당신이 'AppModule' 루트 (이곳에서 'HeroesService'도 찾을 수 있습니다.) 안에 'VillainsService'를 제공한다면, + 이러한 작업은 _Hero_ 워크플로우 뿐만 아니라 어플리케이션 어디서든지 'VillainsService'를 사용할 수 있도록 만들어줍니다. + + While you could provide `VillainsService` in the root `AppModule` (that's where you'll find the `HeroesService`), that would make the `VillainsService` available everywhere in the application, including the _Hero_ workflows. + 만약 당신이 나중에 'VillainsService'를 수정한다면, hero 컴포넌트 어딘가에 있는 특정 부분을 망가뜨릴 수 있습니다. + 일어나서는 안되는 일이지만 당신이 서비스를 제공한 그 방식은 이러한 위험을 초래할 수 있습니다. + If you later modify the `VillainsService`, you could break something in a hero component somewhere. That's not supposed to happen but the way you've provided the service creates that risk. + 대신, 다음과 같이 'VillainsListComponent'의 `providers` 메타데이터로 'VillainsService'를 제공합니다. + Instead, provide the `VillainsService` in the `providers` metadata of the `VillainsListComponent` like this: +makeExample('hierarchical-dependency-injection/ts/src/app/villains-list.component.ts', 'metadata','src/app/villains-list.component.ts (metadata)')(format='.') :marked - By providing `VillainsService` in the `VillainsListComponent` metadata — and nowhere else —, + 'VillainsListComponent'의 메타데이터 안에 'VillainsService'를 제공하고 — 그 밖에 다른곳에서 —, + 이 서비스는`VillainsListComponent` 와 그것의 하위 컴포넌 트리에서만 사용할 수트 있게 됩니다. + 이는 여전히 싱글톤이지만 _villain_ 도메인에만 혼자 존재하는 싱글톤입니다. + + By providing `VillainsService` in the `VillainsListComponent` metadata — and nowhere else —, the service becomes available only in the `VillainsListComponent` and its sub-component tree. It's still a singleton, but it's a singleton that exist solely in the _villain_ domain. + 당신은 hero 컴포넌트가 이를 접근할 수 없다고 확신합니다. 이로써 당신은 에러에 노출될 위험을 줄였습니다. + You are confident that a hero component can't access it. You've reduced your exposure to error. + ### 시나리오 : 다수의 편집 세션 + ### Scenario: multiple edit sessions + 많은 어플리케이션들은 사용자가 다수의 작업들을 동시에 열 수 있도록 허용합니다. + 예를 들어 세금 준비 어플리케이션에서 작성자는 여러 세금 신고서를 작성할 수 있으며 + 하루종일 여러개의 신고서들중 하나를 선택하고 다시 다른 것으로 전환하여 작업할 수 있습니다. + Many applications allow users to work on several open tasks at the same time. For example, in a tax preparation application, the preparer could be working several tax returns, switching from one to the other throughout the day. + 이 가이드는 Tour of Heroes 테마의 예제를 통해 시나리오를 보여줍니다. + 슈퍼 히어로의 목록을 표시하는 바깥 쪽 'HeroListComponent'를 상상해보십시오. + This guide demonstrates that scenario with an example in the Tour of Heroes theme. Imagine an outer `HeroListComponent` that displays a list of super heroes. - To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return. + 영웅의 소득 신고서를 열려면, 작성자가 영웅 이름을 클릭하면 해당 신고서를 편집 할 수있는 구성 요소가 열립니다. + 선택된 각 영웅 소득 신고서는 자체 컴포넌트 에서 열리며 동시에 여러 개의 소득 신고가 가능합니다. + + To open a hero's tax return, the preparer clicks on a hero name, which opens a component for editing that return. Each selected hero tax return opens in its own component and multiple returns can be open at the same time. + 각각의 소득 신고서 컴포넌트는 + * 자체 소득 신고 편집 세션입니다. + * 다른 컴포넌트의 신고에 영향을주지 않고 소득 신고서를 변경할 수 있습니다. + * 소득 신고서에 변경 사항을 저장하거나 취소할 수 있습니다. + Each tax return component * is its own tax return editing session. * can change a tax return without affecting a return in another component. @@ -121,68 +213,123 @@ figure.image-display figure.image-display img(src="/resources/images/devguide/dependency-injection/hid-heroes-anim.gif" width="400" alt="Heroes in action") :marked - One might suppose that the `TaxReturnComponent` has logic to manage and restore changes. - That would be a pretty easy task for a simple hero tax return. + 'HeroTaxReturnComponent'에는 변경 사항을 관리하고 복원하는 논리가 있다고 가정 할 수 있습니다. + 그것은 단순한 영웅의 소득 신고를 위한 매우 쉬운 일이 될 것입니다. + 현실적으로 많은 양의 소득 신고 데이터 모델을 사용한다면 변경 관리가 까다로울 수 있습니다. + 다음 예와 같이 해당 관리를 도우미 서비스에 위임 할 수 있습니다. + + One might suppose that the `HeroTaxReturnComponent` has logic to manage and restore changes. + That would be a pretty easy task for a simple hero tax return. In the real world, with a rich tax return data model, the change management would be tricky. You might delegate that management to a helper service, as this example does. - Here is the `HeroTaxReturnService`. + 여기 'HeroTaxReturnService'가 있습니다. + 하나의 'HeroTaxReturn'을 캐싱하고, 해당 변경에 대한 변경 사항을 추적하며, 이를 저장하거나 복원 할 수 있습니다. + 또한 주입으로 획득한 어플리케이션 수준의 'HeroService' 싱글톤에 위임합니다. + + Here is the `HeroTaxReturnService`. It caches a single `HeroTaxReturn`, tracks changes to that return, and can save or restore it. It also delegates to the application-wide, singleton `HeroService`, which it gets by injection. +makeExample('hierarchical-dependency-injection/ts/src/app/hero-tax-return.service.ts', '', 'src/app/hero-tax-return.service.ts') :marked + 다음은 `HeroTaxReturnComponent`을 사용하는 예시입니다. + Here is the `HeroTaxReturnComponent` that makes use of it. +makeExample('hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts', null, 'src/app/hero-tax-return.component.ts') :marked + _tax-return-to-edit_는 getter 및 setter로 구현 된 input 속성을 통해 도착합니다. + setter는 들어오는 리턴 값으로 'HeroTaxReturnService'의 컴포넌트 인스턴스를 초기화합니다. + getter는 항상 서비스가 영웅의 현재 상태를 반환합니다. + 컴포넌트는 서비스에게 소득 신고서를 저장하고 복원하도록 요청합니다. + The _tax-return-to-edit_ arrives via the input property which is implemented with getters and setters. The setter initializes the component's own instance of the `HeroTaxReturnService` with the incoming return. The getter always returns what that service says is the current state of the hero. The component also asks the service to save and restore this tax return. + _this_ 서비스가 어플리케이션 수준의 싱글톤이라면 큰 문제가 될 것입니다. + 모든 컴포넌트는 동일한 서비스 인스턴스를 공유합니다. + 각 컴포넌트는 다른 영웅에게 속한 소득 신고서를 덮어 씁니다. + 정말 지저분하군요! + There'd be big trouble if _this_ service were an application-wide singleton. - Every component would share the same service instance. + Every component would share the same service instance. Each component would overwrite the tax return that belonged to another hero. What a mess! + 'HeroTaxReturnComponent'를 위한 메타데이터를 자세히 살펴보세요. 'providers' 속성도 확인하세요. + Look closely at the metadata for the `HeroTaxReturnComponent`. Notice the `providers` property. +makeExample('hierarchical-dependency-injection/ts/src/app/hero-tax-return.component.ts', 'providers') :marked - The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`. - Recall that every component _instance_ has its own injector. + `HeroTaxReturnComponent`는`HeroTaxReturnService`의 자체 공급자를 가지고 있습니다. + 모든 컴포넌트 _인스턴트_에는 자체 주입기가 있음을 잊지 마세요. + 컴포넌트 수준에서 서비스를 제공하면 컴포넌트의 _모든_ 인스턴스가 자체 서비스 인스턴스를 가져옵니다. + 소득 신고서에서 덮어 쓰기 문제가 없습니다. 엉망이 아닙니다. + + The `HeroTaxReturnComponent` has its own provider of the `HeroTaxReturnService`. + Recall that every component _instance_ has its own injector. Providing the service at the component level ensures that _every_ instance of the component gets its own, private instance of the service. No tax return overwriting. No mess. - + .l-sub-section :marked + 나머지 시나리오 코드는 문서의 다른 부분에서 배울 수 있는 다른 Angular 기능과 기술들에 의존합니다. + 이를 검토하고 에서 다운로드 할 수 있습니다. + The rest of the scenario code relies on other Angular features and techniques that you can learn about elsewhere in the documentation. You can review it and download it from the :marked + ### 시나리오: 특수한 공급자 + ### Scenario: specialized providers + 서비스를 다시 제공하는 또 다른 이유는 컴포넌트 트리의 더 깊은 레벨에서 해당 서비스를 _더 특수한_ 구현으로 대체하기 위함입니다. + Another reason to re-provide a service is to substitute a _more specialized_ implementation of that service, deeper in the component tree. + [Dependency Injection] (./ dependency-injection.html) 가이드의 Car 예제를 다시 생각해보세요. + `CarService`,`EngineService`,`TiresService`를 위한 _generic_ providers를 사용하여 루트 주입기 (A로 표시)를 설정하였습니다. + Consider again the Car example from the [Dependency Injection](./dependency-injection.html) guide. - Suppose you configured the root injector (marked as A) with _generic_ providers for + Suppose you configured the root injector (marked as A) with _generic_ providers for `CarService`, `EngineService` and `TiresService`. + 당신은 다음과 같이 세 가지 일반 서비스로 구성된 자동차를 표시하는 자동차 컴포넌트 (A)를 만들었습니다. + You create a car component (A) that displays a car constructed from these three generic services. + 그다음 당신은 `CarService` and `EngineService`를 위한 _특수한_ provider를 정의하는 자식 컴포넌트 (B)를 생성합니다. + _특수_ 공급자는 컴포넌트 B에서 진행되는 모든 것에 적합한 특수한 능력을 가지고 있습니다. + Then you create a child component (B) that defines its own, _specialized_ providers for `CarService` and `EngineService` that have special capabilites suitable for whatever is going on in component (B). + 컴포넌트 (C)는 `CarService`를 위한 _더 특수한_ provider임과 동시에 컴포넌트 B의 자식입니다. + Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`. figure.image-display img(src="/resources/images/devguide/dependency-injection/car-components.png" alt="car components" width="220") :marked + 뒤에서 각 컴포넌트는 해당 컴포넌트 자체에 대해 정의 된 provider를 자체 주입기로 설정합니다. 이 개수는 0개, 1개, 또는 그 이상이 될 수 있습니다. + Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself. + 가장 아래의 컴포넌트 (C)에서 'Car'의 인스턴스를 해결하면 + 그 컴포넌트의 주입기는 주입기 (B)에 의해 해석되는 "Engine"을 갖는 주입기 (C)에 의해 해결된 "Car"의 인스턴스를 생성하고, + `Tires'는 root 주입기 (A)가 해결합니다. + + 만약 여러분이 'Car 인스턴스를 컴포넌트 트리에서 가장 낮은 레벨인 컴포넌트 (C)에서 해결한다면, + 이것의 주입기는 root 주입기 (A)가 해결한 'Tires'와 주입기 (B)가 해결한 'Engine'로 + 주입기 (C)가 해결한 'Car' 인스턴스를 생성할 것입니다. + When you resolve an instance of `Car` at the deepest component (C), its injector produces an instance of `Car` resolved by injector (C) with an `Engine` resolved by injector (B) and `Tires` resolved by the root injector (A). @@ -192,6 +339,9 @@ figure.image-display .l-sub-section :marked + 이 _cars_ 시나리오의 코드는 `car.components.ts` 및`car.services.ts` 파일에 있으 + 파일을 검토하고 다운로드 할 수 있습니다. + The code for this _cars_ scenario is in the `car.components.ts` and `car.services.ts` files of the sample which you can review and download from the :marked From d435d3995853899e98373d65603c490d51106dbd Mon Sep 17 00:00:00 2001 From: bluecri Date: Mon, 5 Jun 2017 11:35:12 +0900 Subject: [PATCH 2/2] Trans(hierarchical-dependency-injection.jade) --- .../guide/hierarchical-dependency-injection.jade | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade b/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade index 22d151d3..91deaa1c 100644 --- a/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade +++ b/public/docs/ts/latest/guide/hierarchical-dependency-injection.jade @@ -47,14 +47,14 @@ block includes .l-sub-section :marked - 컴포넌트의 인젝터는 컴포넌트 트리에서 상위에 있는 상위 주입기의 프록시 일 수 있습니다. - 효율성을 향상시키는 구현 세부 사항입니다. - 여러분은 이 차이를 알아 채지 못할 것이고 당신의 정신 모델은 모든 컴포넌트가 자신의 주입기를 가져야한다는 것입니다. - - The component's injector may be a _proxy_ for an ancestor injector higher in the component tree. - That's an implementation detail that improves efficiency. - You won't notice the difference and - your mental model should be that every component has its own injector. + 컴포넌트의 인젝터는 컴포넌트 트리에서 상위에 있는 상위 주입기의 프록시 일 수 있습니다. + 효율성을 향상시키는 구현 세부 사항입니다. + 여러분은 이 차이를 알아 채지 못할 것이고 당신의 정신 모델은 모든 컴포넌트가 자신의 주입기를 가져야한다는 것입니다. + + The component's injector may be a _proxy_ for an ancestor injector higher in the component tree. + That's an implementation detail that improves efficiency. + You won't notice the difference and + your mental model should be that every component has its own injector. :marked Tour of Heroes application을 약간 변형시켜 만든 다음 가이드를 고려해봅시다.