본문 바로가기
프로그래밍/Angular

앵귤러 기초(Angular basic) 21. 서비스 만들기

by 신나요 2022. 1. 30.

서비스를 만들고 이용해 보겠습니다.

 

이번 포스트에서는 아래의 내용을 다루고 있습니다.

  1. 앵귤러 서비스를 만드는 과정
  2. 인젝터에 서비스 등록하는 방법
  3. 루트 인젝터, 컴포넌트 인젝터
  4. 서비스를 위존성 주입(Dependency Injection)하는 방법

 

현재 앵귤러 기초 포스트에서 만들고 있는 영화 목록 화면을 잠시 살펴보겠습니다.

 

영화 목록 화면에서 테이블에 표시하고 있는 영화 데이터는 현재 컴포넌트 클래스의 프로퍼티로 하드코딩되어있는 상태입니다.

지금부터 영화 목록 데이터를 서비스를 통해 얻어오도록 개선해 보겠습니다.

앵귤러 서비스 만들기

서비스 만드는 단계를 간단히 정리해 보면 아래와 같습니다.

1. 서비스 클래스 만들기

2. 데코레이터를 이용해서 메타데이터 정의하기

3. 필요한 것 Import하기

4. 서비스의 로직 작성하기

 

먼저 파일을 만들겠습니다.

지금 만들 서비스는 영화 데이터만 제공하므로 영화 폴더에 추가하겠습니다.

새 파일을 movie.service.ts 명명 규칙을 따라 만들도록 하겠습니다.

Movie.servie.ts의 내용은 아래와 같습니다.

이 서비스는 Movie객체를 제공할 예정이므로 MovieService라고 만들었습니다.

다음으로 Injectable 데코레이터로 클래스를 데코레이트하고, 해당 데코레이터에 대해 Import를 추가하였습니다.

 

이제 구조가 갖춰졌으므로 메소드를 추가하겠습니다.

MovieService는 영화 리스트를 반환하는 역할을 해야 하므로 getMovies메서드를 작성하였습니다.

메서드의 리턴 타입을movie []로 주고 리턴은 하드 코딩된 데이터를 돌려주었습니다.

후속 포스터에서 http를 사용해서 영화 리스트를 가져오는 방법으로 개선할 예정입니다.

 

서비스를 이용하여 영화 리스트를 제공함으로써 서비스는 컴포넌트에서 벗어나 데이터를 관리할 책임을 가지게 됩니다.

이로써 컴포넌트와는 독립적으로 서비스 로직을 더 쉽게 수정하거나 재사용이 가능해집니다.

 

서비스는 Angular 인젝터에 등록할 때까지는 평범한 클래스입니다.

만든 서비스를 등록해 보겠습니다.


인젝터에 서비스 등록하는 방법

위 그림처럼 앵귤러 인젝터에 서비스를 등록하면 인젝터는 생성자를 이용하여 서비스를 삽입하는 모든 컴포넌트들에게 서비스 인스턴스를 제공해 줍니다.

그림에 표시된 인젝터의 예는 루트 애플리케이션 인젝터를 나타낸 것입니다.

루트 인젝터는 최상위 인젝터를 의미합니다.

 

루트 애플리케이션 인젝터 외에도 앵귤러에는 컴포넌트 트리를 미러링 하는 각 컴포넌트에 대한 인젝터가 있습니다.

루트 애플리케이션 인젝터에 등록된 서비스는 애플리케이션의 모든 구성 요소 또는 다른 서비스에서 사용할 수 있습니다.

특정 컴포넌트에 등록된 서비스는 해당  컴포넌트와 해당 하위 컴포넌트에서만 사용할 수 있습니다.

 

예를 들어 서비스가 MovieListComponent의 인젝터에 등록된 경우 MovieListComponent와 그 하위 컴포넌트StarScoreComponent에서만 서비스를 주입할 수 있습니다.

 

컴포넌트를 앵귤러 모듈에 정의했던 것처럼Angular 모듈에서 서비스를 정의할 필요는 없습니다.

그렇다면 언제 루트 인젝터와 컴포넌트 인젝터에 서비스를 등록해야 할까요?

 

루트 인젝터에 서비스를 등록하면 애플리케이션 전체에서 서비스를 사용할 수 있습니다.

대부분의 경우 루트 인젝터에 서비스를 등록해 이용합니다.

 

서비스의 인젝터 등록은 어떤 인젝터를 사용하느냐에 따라 달라집니다.

1. 루트 인젝터

먼저 루트 애플리케이션 인젝터에 서비스 등록을 알아보겠습니다.

서비스에 Injectable데코레이터를 달아주고, providedIn설정을 'root'로 설정합니다.

이 설정을 하면 애플리케이션의 모든 컴포넌트 또는 다른 서비스에서 액세스가 가능해집니다..

 

2.컴포넌트 인젝터

다음은 특정 컴포넌트 인젝터에 서비스를 등록하는 방법에 대해 알아보겠습니다.

MovieListComponent와 같은 특정 컴포넌트에 대한 서비스를 등록하려면 해당 컴포넌트에 아래와 같이 서비스를 등록해야 합니다.

 

지금부터 작성하는 예제에서는 루트 인젝터를 이용하겠습니다.

인젝터에 관해선 아직 어려운 얘기들이 많이 남아있지만, 지금 단계에선 이정도 정보로도 훌륭히 애플리케이션을 작성할 수 있을 것입니다.

 

자 이제 서비스 등록까지 마쳤습니다.

이제 마지막 단계인 서비스 주입을 해보겠습니다.


서비스 의존성 주입하기

앵귤러에서 의존성 주입을 어떻게 해야 할까요?

이 질문은 타입스크립트에서 의존성 주입을 어떻게 해야 할까요 로 바꿀 수 있습니다.

답은 생성자에 있습니다.

모든 클래스에는 클래스 인스턴스가 생성될 때 실행되는 생성자가 있습니다.

클래에서 명시적으로 정의된 생성자가 없을 경우 암시적 생성자가 사용됩니다.

하지만 서비스 인스턴스와 같은 의존성 주입을 하려면 명시적 생성자가 필요합니다.

타입 스크립트에서 생성자는 생성자 함수로 정의됩니다.

일반적으로 생성자 함수에 들어가는 코드는 가능한 적게 써야 합니다.

생성자 함수는 컴포넌트가 생성될 때 실행되기 때문에 주로 초기화에 사용되며, 부작용이 있거나 실행시간이 오래 걸리는 코드는 쓰지 않는것이 좋습니다.

 

위와 같이 의존성을 생성자 함수에 대한 매개변수로 지정하여 의존성을 식별하게 됩니다.

또한 주입된 서비스 인스턴스를 보관할 private변수를 정의하였습니다.

이 클래스가 생성되면 Angular인젝터는 이 매개변수를 서비스의 인스턴스로 설정해 줍니다.

그런 다음 삽입된 서비스 인스턴스를 로컬 private 변수에 할당합니다.

할당까지 마치면 클래스의 어느 곳에서나 로컬 변수(_movieService)를 사용하여 서비스의 프로퍼티 혹은 메서드에 액세스 할 수 있습니다.

위와 같은 코드는 TypeScript의 일반적인 패턴입니다.

 

위 코드를 아래와 같이 바꿀 수 있습니다.

private와 같은 접근자 키워드를 생성자 매개변수에 추가하기만 하면 됩니다.

위와 같이 작성 함으로 변수를 선언하고, 매개변수를 정의하고, 변수를 매개변수로 할당까지 포함된 처리가 가능합니다.

앵귤러 코드를 작성할 때 대부분 이런 방식을 사용하는 걸 볼 수 있습니다.

 

작성 중인 코드를 마무리하겠습니다.

 

컴포넌트에서 가지고 있던 영화 데이터 들은 빈 배열 값으로 초기화해주었습니다.

컨스트럭터에서 의존성 주입을 하여,  movieService에 인스턴스를 할당했습니다.

ngOnInt라이프 사이클 훅에서,  서비스를 이용해 영화 데이터를 가져오고 그것을 다시 movies배열에 할당해 주었습니다.

초기 화면에 모든 영화가 보이길 원하기 때문에, filteredMovies에 가져온 모든 데이터를  초기화 해주었습니다.

 

이제 코드가 마무리되었으니 브라우저에서 확인해 보겠습니다.

 

데이터가 잘 표시되네요.

보이는 화면은 바뀐 게 없지만, 데이터를 가져오는 부분을 서비스로 만들어 화면에 출력하였습니다.

지금 서비스는 단순 하드 코딩된 데이터를 가져오지만, 차후에 http를 이용하여 데이터를 가져오도록 개선할 것입니다.

서비스 쪽으로 데이터 담당 역할을 분리했으니, 컴포넌트 쪽은 수정할 필요가 없겠군요.


여기까지 수고하셨습니다.

다음 포스트는  HTTP를 이용한 데이터를 가져오기를 알아보도록 하겠습니다.

 

댓글