Angular 2에서 싱글 톤 서비스를 어떻게 만듭니 까?


142

부트 스트랩을 할 때 주입하면 모든 자식이 동일한 인스턴스를 공유해야하지만 내 기본 및 헤더 구성 요소 (주 응용 프로그램에는 헤더 구성 요소 및 라우터 콘센트가 포함됨)가 각각 별도의 서비스 인스턴스를 얻습니다.

페이스 북 자바 스크립트 API와 FacebookService를 사용하는 UserService를 호출하는 데 사용하는 FacebookService가 있습니다. 내 부트 스트랩은 다음과 같습니다.

bootstrap(MainAppComponent, [ROUTER_PROVIDERS, UserService, FacebookService]);

로깅에서 부트 스트랩 호출이 완료되는 것처럼 보이며 각 생성자의 코드가 실행되기 전에 FacebookService와 UserService가 생성되는 것을 볼 수 있습니다. MainAppComponent, HeaderComponent 및 DefaultComponent :

여기에 이미지 설명을 입력하십시오


8
당신은 확실히 당신은하고 있지 추가 UserServiceFacebookServiceproviders다른 곳?
Günter Zöchbauer

답변:


132

제이슨은 완전히 맞아요! 의존성 주입이 작동하는 방식으로 인해 발생합니다. 계층 적 인젝터를 기반으로합니다.

Angular2 애플리케이션에는 여러 인젝터가 있습니다.

  • 응용 프로그램을 부트 스트랩 할 때 구성하는 루트
  • 구성 요소 당 인젝터. 다른 구성 요소 안에 구성 요소를 사용하는 경우 구성 요소 인젝터는 상위 구성 요소의 하위입니다. 응용 프로그램 구성 요소 (응용 프로그램을 증폭시킬 때 지정하는 구성 요소)에는 루트 인젝터가 부모 인젝터가 있습니다.

Angular2가 컴포넌트 생성자에 무언가를 주입하려고 할 때 :

  • 구성 요소와 연관된 인젝터를 찾습니다. 일치하는 것이 있으면이를 사용하여 해당 인스턴스를 가져옵니다. 이 인스턴스는 느리게 생성되며이 인젝터의 싱글 톤입니다.
  • 이 수준에 공급자가 없으면 부모 인젝터 등을 살펴 봅니다.

따라서 전체 응용 프로그램에 대해 싱글 톤을 사용하려면 루트 인젝터 또는 응용 프로그램 구성 요소 인젝터 수준에서 공급자를 정의해야합니다.

그러나 Angular2는 인젝터 트리를 아래에서 볼 것입니다. 즉, 가장 낮은 수준의 공급자가 사용되며 연결된 인스턴스의 범위가이 수준이됩니다.

자세한 내용은이 질문을 참조하십시오.


1
고마워, 잘 설명해. 그것은 각도 2의 자체 포함 된 구성 요소 패러다임으로 인해 깨지기 때문에 반 직관적입니다. 페이스 북을위한 컴포넌트 라이브러리를 만들고 있다고하는데, 모두 싱글 톤 서비스를 사용하기를 원합니다. 로그인 한 사용자의 프로필 사진과 게시 할 다른 사용자의 프로필 사진을 표시하는 구성 요소가있을 수 있습니다. 이러한 구성 요소를 사용하는 앱은 서비스 자체를 사용하지 않더라도 Facebook 서비스를 공급자로 포함해야합니까? 실제 서비스의 싱글 톤을 관리하는 'getInstance ()'메소드를 사용하여 서비스를 반환 할 수 있습니다.
Jason Goemaat

@tThierryTemplier 반대로 어떻게해야합니까, 여러 구성 요소를 주입하고 매번 새 인스턴스를 인스턴스화하려는 공통 서비스 클래스가 있습니다 (제공자 / 지시자 옵션은 더 이상 사용되지 않고 다음 릴리스에서 제거되어야 함)
Boban Stojanovski

너무 멍청해서 미안하지만 싱글 톤 서비스를 어떻게 만드는지 잘 모르겠습니다. 더 자세히 설명해 주시겠습니까?
gyozo kudor

따라서 서비스의 단일 인스턴스로 작업하려면 app.module.ts 또는 app.component.ts에서 공급자로 선언해야합니까?
user1767316

app.module.ts에서만 각 서비스를 선언하면 나에게 도움이되었습니다.
user1767316

142

업데이트 (Angular 6 +)

싱글 톤 서비스 를 만드는 권장 방법 이 변경되었습니다. 이제 @Injectable서비스 의 데코레이터에서 '루트'로 제공 되도록 지정하는 것이 좋습니다 . 이것은 나에게 의미가 있으며 더 이상 모듈에 제공된 서비스를 모두 나열 할 필요가 없습니다. 필요할 때 서비스를 가져 오면 적절한 장소에 등록됩니다. 모듈을 가져와야 만 제공되도록 모듈지정할 수도 있습니다.

@Injectable({
  providedIn: 'root',
})
export class ApiService {
}

업데이트 (각도 2)

NgModule을 사용하여 지금 할 수있는 방법은 서비스 클래스로 'CoreModule'을 만들고 모듈의 공급자에 서비스를 나열하는 것입니다. 그런 다음 기본 앱 모듈에서 핵심 모듈을 가져와 생성자에서 해당 클래스를 요청하는 모든 자식에게 하나의 인스턴스를 제공합니다.

CoreModule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ApiService } from './api.service';

@NgModule({
    imports: [
        CommonModule
    ],
    exports: [ // components that we want to make available
    ],
    declarations: [ // components for use in THIS module
    ],
    providers: [ // singleton services
        ApiService,
    ]
})
export class CoreModule { }

AppModule.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

@NgModule({
    declarations: [ AppComponent ],
    imports: [
        CommonModule,
        CoreModule // will provide ApiService
    ],
    providers: [],
    bootstrap: [ AppComponent ]
})
export class AppModule { }

원래 답변

에 제공자 bootstrap()를 나열하면 구성 요소 데코레이터에 제공자 를 나열하지 않아도됩니다.

import { ApiService } from '../core/api-service';

@Component({
    selector: 'main-app',
    templateUrl: '/views/main-app.html',
    // DO NOT LIST PROVIDERS HERE IF THEY ARE IN bootstrap()!
    // (unless you want a new instance)
    //providers: [ApiService]
})
export class MainAppComponent {
    constructor(private api: ApiService) {}
}

실제로 '제공자'에 클래스를 나열하면 새 인스턴스가 만들어지고 부모 구성 요소에 이미 나열되어 있으면 자식이 필요하지 않으며 새 인스턴스가 있으면 새 인스턴스가 생성됩니다.


1
현재 (2017 년 1 월) 서비스가 [providers]아닌 모듈 파일에 서비스 가 표시 bootstrap()됩니까?
Jason Swett

5
왜 넣지 ApiService에서 AppModuleproviders, 따라서의 필요성을 피하기 CoreModule? (이것이 @JasonSwett이 제안한 것인지 확실하지 않습니다.)
Jan Aagaard

1
@JasonGoemaat 컴포넌트에서 사용하는 예제를 추가 할 수 있습니까? 우리 ApiService는 상단을 가져올 수는 있지만 왜 CoreModule의 공급자 배열에 넣은 다음 app.module에서 가져 오려고 귀찮게합니까? 아직 클릭하지 않았습니다.
hogan

따라서 서비스를 모듈 공급자에게 제공하면 해당 모듈에 대한 싱글 톤이 제공됩니다. 그리고 컴포넌트 제공자에 서비스를 추가하면 컴포넌트의 각 인스턴스에 대해 새 인스턴스가 작성됩니까? 맞습니까?
BrunoLM

@BrunoLM 테스트 앱을 만들었습니다. 무슨 일이 일어나고 있는지 보여주는 을 . TestService코어 및 앱 모듈 모두에 지정되어 있지만 모듈에서 인스턴스가 생성되지 않기 때문에 각도가 인젝터 트리보다 높지 않습니다. 따라서 모듈에서 서비스를 제공하고 절대 사용하지 않으면 인스턴스가 생성되지 않는 것 같습니다.
Jason Goemaat

24

나는 각도가 티에리와 같은 계층 적 인젝터를 가지고 있다는 것을 안다.

그러나 부모에게 실제로 주입하고 싶지 않은 유스 케이스를 찾으면 여기에 다른 옵션이 있습니다.

우리는 서비스의 인스턴스를 생성하여이를 달성 할 수 있으며, 항상이를 반환해야합니다.

import { provide, Injectable } from '@angular/core';
import { Http } from '@angular/core'; //Dummy example of dependencies

@Injectable()
export class YourService {
  private static instance: YourService = null;

  // Return the instance of the service
  public static getInstance(http: Http): YourService {
    if (YourService.instance === null) {
       YourService.instance = new YourService(http);
    }
    return YourService.instance;
  }

  constructor(private http: Http) {}
}

export const YOUR_SERVICE_PROVIDER = [
  provide(YourService, {
    deps: [Http],
    useFactory: (http: Http): YourService => {
      return YourService.getInstance(http);
    }
  })
];

그런 다음 구성 요소에서 사용자 정의 제공 방법을 사용합니다.

@Component({
  providers: [YOUR_SERVICE_PROVIDER]
})

그리고 계층 적 인젝터에 의존하지 않고 싱글 톤 서비스를 제공해야합니다.

나는 이것이 더 좋은 방법이라고 말하지 않고, 누군가 계층 적 인젝터가 불가능한 문제가있는 경우를 대비합니다.


1
가해야 SHARE_SERVICE_PROVIDERYOUR_SERVICE_PROVIDER구성 요소에? 또한 서비스 파일을 가져 오는 것이 정상과 같이 필요하고 생성자가 여전히 'YourService'유형의 매개 변수를 가질 것이라고 가정합니다. 나는 이것이 내가 생각하는 것을 좋아한다. 단일 톤을 보장하고 서비스가 계층 구조에 제공되도록 할 필요는 없다. 또한 단일 구성 요소 providers대신 서비스를 나열하여 개별 구성 요소가 자체 복사본을 얻을 수 있습니다 .
Jason Goemaat

@JasonGoemaat 당신이 맞아요. 편집했습니다. 정확히, 생성자와 추가 한 해당 구성 요소의 공급자에서 정확히 같은 방식으로 수행합니다 YOUR_SERVICE_PROVIDER. 예, 모든 구성 요소는 공급자에 추가하기 만하면 동일한 인스턴스를 얻게됩니다.
Joel Almeida

개발자가 이것을 사용하는 시점에서, 그들은 Angular가이 상황에서 제공하는 메커니즘을 사용하지 않을 경우 왜 Angular를 사용 하는가? 애플리케이션 수준에서 서비스를 제공하는 것은 Angular와 관련된 모든 상황에 충분해야합니다.
RyNo

1
+1 싱글 톤 서비스를 생성하는 방법이지만 , 속성을 키-값 인스턴스로 간단히 변경하여 멀티 톤 서비스 를 생성하는 방법으로 매우 instance
유용

1
@RyNo 모든 경로에 서비스가 필요하지 않은 응용 프로그램 또는 정적 인스턴스를 원하고 그것을 사용하는 다른 모듈과 동일한 인스턴스를 사용하려는 재사용 가능한 모듈을 상상할 수 있습니다. 서버에 대한 웹 소켓 연결을 생성하고 메시지를 처리하는 것입니다. 앱의 일부 경로 만 사용하고 싶을 수도 있으므로 필요하지 않은 경우 앱이 시작될 때 서비스 인스턴스와 웹 소켓 연결을 만들 필요가 없습니다. 사용되는 모든 곳에서 서비스가 '초기화'되도록 구성 요소를 프로그래밍 할 수 있지만 주문형 싱글 톤이 유용합니다.
Jason Goemaat

16

구문이 변경되었습니다. 이것을 확인하십시오 링크를

종속성은 인젝터 범위 내의 싱글 톤입니다. 아래 예제에서 단일 HeroService 인스턴스는 HeroesComponent 및 해당 HeroListComponent 하위에서 공유됩니다.

1 단계. @Injectable 데코레이터로 싱글 톤 클래스 만들기

@Injectable()
export class HeroService {
  getHeroes() { return HEROES;  }
}

2 단계. 생성자에 주입

export class HeroListComponent { 
  constructor(heroService: HeroService) {
    this.heroes = heroService.getHeroes();
  }

3 단계. 공급자 등록

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    routing,
    HttpModule,
    JsonpModule
  ],
  declarations: [
    AppComponent,
    HeroesComponent,
    routedComponents
  ],
  providers: [
    HeroService
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }

내 어떤 경우 Injectable클래스는 서비스를하지 않고 단지가 들어 static글로벌 사용하기 위해 문자열을?
Syed Ali Taqi

2
[{provide : 'API_URL', useValue : ' coolapi.com '}]
Whisher

7

추가 @Injectable서비스에 장식을, 그리고 그것을 싱글 것 루트 모듈의 공급 업체로 등록.


내가 이해하고 있다면 말 해주세요. 내가 말한대로하면 싱글 톤이됩니다. 그 외에도 서비스가 다른 모듈의 공급자 인 경우 더 이상 싱글 톤이되지 않습니까? 계층 구조로 인해.
heringer

1
그리고 페이지의 @Component 데코레이터에 공급자를 등록하지 마십시오.
Laura

@Laura. 실제로 서비스를 사용하는 구성 요소로 가져와도됩니까?
Mark

@Mark 예, 가져와야하며 다음 constructor과 같이 선언하면됩니다 . import { SomeService } from '../../services/some/some'; @Component({ selector: 'page-selector', templateUrl: 'page.html', }) export class SomePage { constructor( public someService: SomeService ) { }
Laura

6

이것은 나를 위해 잘 작동하는 것 같습니다

@Injectable()
export class MyStaticService {
  static instance: MyStaticService;

  constructor() {
    return MyStaticService.instance = MyStaticService.instance || this;
  }
}

8
이것을 Angular2 안티 패턴이라고 부릅니다. 서비스를 올바르게 제공하면 Angular2는 항상 동일한 인스턴스를 주입합니다. 또한 참조 stackoverflow.com/questions/12755539/...
귄터 Zöchbauer에게

3
@ Günter Zöchbauer는 "서비스를 올바르게 제공하고 Angular2는 항상 동일한 인스턴스를 주입합니다"에 대해 조언을 해줄 수 있습니다. ? 명확하지 않으며 인터넷 검색을 통해 유용한 정보를 찾을 수 없기 때문입니다.
nowiko

질문에 도움이 될만한이 답변을 방금 올렸습니다 stackoverflow.com/a/38781447/217408 (또한 링크 참조)
Günter Zöchbauer

2
이것은 완벽 해요. 당신은 해야 angulars 자신의 의존성 주입을 사용하지만, 당신이있을 것으로 예상 할 때 서비스가 싱글 절대적으로 확신이 패턴을 사용에 아무런 해가 없습니다. 두 곳에서 동일한 서비스를 제공하기 때문에 버그를 찾는 데 많은 시간을 절약 할 수 있습니다.
PaulMolloy

나는이 패턴을 사용하여 내가 직면 한 문제가 서비스가 싱글 톤이 아니기 때문이라는 것을 확인했다
hr-tis

5

다음은 Angular 버전 2.3의 실제 예제입니다. 이 생성자 (private _userService : UserService)와 같은 방식으로 서비스 생성자를 호출하십시오. 그리고 앱의 싱글 톤을 생성합니다.

user.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { Subject }    from 'rxjs/Subject';
import { User } from '../object/user';


@Injectable()
export class UserService {
    private userChangedSource;
    public observableEvents;
    loggedUser:User;

    constructor() {
       this.userChangedSource = new Subject<any>();
       this.observableEvents = this.userChangedSource.asObservable();
    }

    userLoggedIn(user:User) {
        this.loggedUser = user;
        this.userChangedSource.next(user);
    }

    ...
}

app.component.ts

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { UserService } from '../service/user.service';
import { User } from '../object/user';

@Component({
    selector: 'myApp',
    templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
    loggedUser:User;

    constructor(private _userService:UserService) { 
        this._userService.observableEvents.subscribe(user => {
                this.loggedUser = user;
                console.log("event triggered");
        });
    }
    ...
}

4

singleton service 는 앱에 하나의 인스턴스 만 존재하는 서비스입니다.

애플리케이션에 싱글 톤 서비스를 제공하는 방법2 가지 가 있습니다.

  1. providedIn속성을 사용 하거나

  2. AppModule응용 프로그램 에서 직접 모듈 제공

제공된 사용

Angular 6.0부터는 싱글 톤 서비스를 만드는 가장 좋은 방법 providedIn은 서비스 @Injectable()데코레이터 에서 루트 로 설정 하는 것 입니다. 이것은 Angular에게 응용 프로그램 루트에서 서비스를 제공하도록 지시합니다.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

NgModule 제공자 배열

6.0 이전의 Angular 버전으로 빌드 된 앱에서 서비스는 다음과 같이 NgModule 제공자 배열로 등록됩니다.

@NgModule({
  ...
  providers: [UserService],
  ...
})

이것이 NgModuleroot AppModule인 경우 UserService는 싱글 톤이며 앱 전체에서 사용할 수 있습니다. 이런 식으로 코딩 된 것을 볼 수도 있지만 서비스 자체 providedIn에서 @Injectable()데코레이터 의 속성을 사용하는 것이 Angular 6.0보다 바람직합니다.


3

useValue공급자에서 사용할 수 있습니다

import { MyService } from './my.service';

@NgModule({
...
  providers: [ { provide: MyService, useValue: new MyService() } ],
...
})

5
useValue싱글 톤과 관련이 없습니다. Usevalue는 DI가 호출 하거나 DI가 호출 할 때 값을 반환하는 함수가 전달되는 위치 Type( useClass) 대신 값을 전달하는 것입니다 . Angular DI는 공급자마다 단일 인스턴스를 자동으로 유지 관리합니다. 한 번만 제공하면 싱글 톤이됩니다. 그냥 잘못된 정보 때문에 미안 해요, downvote에있다 : - /newuseFactory
귄터 Zöchbauer

3

각도 @ 6에서, 당신은 할 수 있습니다 providedInInjectable.

@Injectable({
  providedIn: 'root'
})
export class UserService {

}

여기 에서 문서를 확인 하십시오.

Angular에서 서비스를 싱글 톤으로 만드는 두 가지 방법이 있습니다.

  1. 서비스가 응용 프로그램 루트에 제공되어야한다고 선언합니다.
  2. AppModule 또는 AppModule에서만 가져 오는 모듈에 서비스를 포함 시키십시오.

Angular 6.0부터는 싱글 톤 서비스를 생성하는 기본 방법은 서비스에서 애플리케이션 루트에 제공해야하는 서비스를 지정하는 것입니다. 이는 서비스의 @Injectable 데코레이터에서 providedIn을 루트로 설정하여 수행됩니다.


이것은 좋지만 일부 항목을 선언하여 해결할 수있는 변수가 없을 때 예기치 않은 문제가 발생할 수 있습니다 public static.
cjbarth

2

app.module.ts에서만 서비스를 공급자로 선언하십시오.

그것은 나를 위해 일을했다.

providers: [Topic1Service,Topic2Service,...,TopicNService],

그런 다음 생성자 private 매개 변수를 사용하여 인스턴스를 지정하십시오.

constructor(private topicService: TopicService) { }

또는 서비스가 html에서 사용되는 경우 -prod 옵션은 다음을 요구합니다.

Property 'topicService' is private and only accessible within class 'SomeComponent'.

서비스 멤버를 추가하고 생성자에서받은 인스턴스로 채 웁니다.

export class SomeComponent {
  topicService: TopicService;
  constructor(private topicService: TopicService) { 
    this.topicService= topicService;
  }
}

0
  1. 응용 프로그램 수준에서 서비스 싱글 톤을 만들려면 app.module.ts 에서 정의해야합니다.

    공급자 : [MyApplicationService] (자식 모듈에서 동일하게 정의하여 해당 모듈을 특정하게 만들 수 있음)

    • 싱글 톤 개념을 깨뜨리는 구성 요소에 대한 인스턴스를 작성하는 제공자에이 서비스를 추가하지 말고 생성자를 통해 삽입하십시오.
  2. 컴포넌트 레벨의 서비스 작성에서 싱글 톤 서비스를 정의하려면 app.module.ts에 해당 서비스를 추가하고 아래 스 니펫에 표시된대로 특정 컴포넌트 내에 제공자 배열을 추가하십시오.

    @Component ({선택자 : 'app-root', templateUrl : './test.component.html', styleUrls : [ './test.component.scss'], 제공 업체 : [TestMyService]})

  3. Angular 6은 응용 프로그램 수준에서 서비스를 추가 할 수있는 새로운 방법을 제공합니다. AppModule의 provider [] 배열에 서비스 클래스를 추가하는 대신 @Injectable ()에서 다음 구성을 설정할 수 있습니다.

    @Injectable ({providedIn : 'root'}) 내보내기 클래스 MyService {...}

"새로운 구문"은 한 가지 이점을 제공합니다. 서비스는 앵귤러 (씬 뒤에)에 의해 느리게로드 될 수 있으며 중복 코드는 자동으로 제거 될 수 있습니다. 이로 인해 성능 및 로딩 속도가 향상 될 수 있습니다. 그러나 이는 일반적으로 더 큰 서비스 및 앱에만 적용됩니다.


0

위의 훌륭한 답변 외에도 싱글 톤의 항목이 여전히 싱글 톤으로 작동하지 않으면 누락 된 것이있을 수 있습니다. 싱글 톤에서 공개 함수를 호출하고 잘못된 변수를 사용하고 있음을 발견했을 때 문제가 발생했습니다. 문제는 this싱글 톤의 모든 공용 기능에 대해 싱글 톤에 바인딩되는 것이 보장되지 않는다는 것이 밝혀졌습니다 . 다음과 같이 here 의 조언을 따르면이 문제를 해결할 수 있습니다 .

@Injectable({
  providedIn: 'root',
})
export class SubscriptableService {
  public serviceRequested: Subject<ServiceArgs>;
  public onServiceRequested$: Observable<ServiceArgs>;

  constructor() {
    this.serviceRequested = new Subject<ServiceArgs>();
    this.onServiceRequested$ = this.serviceRequested.asObservable();

    // save context so the singleton pattern is respected
    this.requestService = this.requestService.bind(this);
  }

  public requestService(arg: ServiceArgs) {
    this.serviceRequested.next(arg);
  }
}

또는 클래스 멤버를 public static대신 대신 선언하면 public컨텍스트가 중요하지 않지만 SubscriptableService.onServiceRequested$종속성 삽입을 사용하고을 통해 액세스하는 대신 액세스해야합니다 this.subscriptableService.onServiceRequested$.


0

부모와 자식 서비스

다른 서비스를 사용하는 부모 서비스와 자식 서비스에 문제가있었습니다. 하나의 인스턴스를 사용하려면 앱 모듈 공급자의 자식을 참조하여 부모의 별칭을 지정할 수 있습니다. 부모는 자녀의 속성에 액세스 할 수 없지만 두 서비스 모두에 동일한 인스턴스가 사용됩니다. https://angular.io/guide/dependency-injection-providers#aliased-class-providers

app.module.ts

providers: [
  ChildService,
  // Alias ParentService w/ reference to ChildService
  { provide: ParentService, useExisting: ChildService}
]

앱 모듈 범위 밖의 구성 요소에서 사용하는 서비스

구성 요소와 서비스로 구성된 라이브러리를 만들 때 두 개의 인스턴스가 생성되는 문제가 발생했습니다. 하나는 내 Angular 프로젝트와 하나는 내 라이브러리 내부의 구성 요소입니다. 수정 :

my-outside.component.ts

@Component({...})
export class MyOutsideComponent {
  @Input() serviceInstance: MyOutsideService;
  ...
}

my-inside.component.ts

  constructor(public myService: MyOutsideService) { }

my-inside.component.hmtl

<app-my-outside [serviceInstance]="myService"></app-my-outside>

자신의 질문에 대답 하시겠습니까? 그렇다면 질문을 게시 한 후 답변 필드에 잘라 내기 / 붙여 넣기하여 답변을 정식 답변으로 분리 할 수 ​​있습니다.
ryanwebjackson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.