서비스는 앵귤러에서 의존성 주입을 위해 사용되는 요소입니다. 컴포넌트에서 비즈니스 로직을 분리할 수 있지요.
서비스를 사용함으로써 컴포넌트에서 new를 통해 객체를 생성하지 않고 Injectable class에서 데이터를 얻어올 수 있습니다.
Reference : https://angular.io/guide/dependency-injection
의존성 주입(DI, Dependency Injection)이란 각 객체간의 결합을 느슨하게 만들어 프로그램이 의존성 역전(Dependency inversion)과 단일 책임 법칙(Single responsibility principle)을 따르게 설계하는 디자인 패턴을 의미합니다.
각 구성요소(혹은 객체)간의 관계를 해당 객체 내부(혹은 소스코드)상에 정의하지 않고 외부에 정의하는 것 이라고 설명할 수 있습니다.
제어 역전(IoC)가 조금 더 일반적인 개념입니다. DI는 IoC의 부분집합이라 할 수 있겠습니다.
IoC가 제어에 대한 문제라면 DI는 객체간의 관계에 대한 이야기라고 할 수도 있겠지요.
Reference : https://en.wikipedia.org/wiki/Dependency_injection
Reference : https://en.wikipedia.org/wiki/Single_responsibility_principle
Reference : https://en.wikipedia.org/wiki/Dependency_inversion_principle
Reference : https://en.wikipedia.org/wiki/Inversion_of_control
의존성 주입 디자인 패턴을 적용함으로서 각 객체간 의존도를 낮추어 코드의 재사용성을 높이고 유지보수를 용이하게 합니다.
지난번에 작성한 employees 컴포넌트에 서비스를 추가해 보겠습니다.
터미널에서 다음 명령어를 입력합니다.
ng generate service employees |
생성된 service는 다음과 같이 구성되어 있습니다 :
//employees.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class EmployeesService {
constructor() { }
}
이 서비스는 hero 데이터를 미리 정의해준 mock data 뿐만 아니라 웹 서비스, 로컬 스토리지 등 어디서든지 가져올 수 있습니다.
지금 단계에서는 mock data만 가지고 있기 때문에 해당 데이터를 가져와 getEmployees() 함수를 통하여 반환하도록 작성하겠습니다.
//employees.service.ts
import { Injectable } from '@angular/core';
import { Employee } from './employees/employee';
import { EMPLOYEES } from './employees/employeeList';
@Injectable({
providedIn: 'root'
})
export class EmployeesService {
constructor() { }
getEmployees(): Employee[] {
return EMPLOYEES;
}
}
앵귤러 CLI 커맨드 ng generate 는 생성된 service를 root 모듈에 주입합니다.
root 모듈에 주입된 서비스는 어플리케이션 전역에서 싱글톤 객체로 사용됩니다.
Departments service도 작성해 줍니다.
ng generate service departments |
//departments.service.ts
import { Injectable } from '@angular/core';
import { Department } from './departments/department';
import { DEPARTMENTS } from './departments/departmentList';
@Injectable({
providedIn: 'root'
})
export class DepartmentsService {
constructor() { }
getDepartments(): Department[] {
return DEPARTMENTS;
}
}
이제 /employees/employees.component.ts 파일과 /departments/departments.component.ts 파일로 돌아가서 import EMPLOYEES, import DEPARTMENTS를 삭제하고, Employees와 Departments를 다음과 같은 단순 정의로 변경합니다.
//employees.component.ts
import { Component, OnInit } from '@angular/core';
import { Employee } from './employee';
import { Department } from '../departments/department';
@Component({
selector: 'app-employees',
templateUrl: './employees.component.html',
styleUrls: ['./employees.component.css']
})
export class EmployeesComponent implements OnInit {
employees: Employee[]; //EDITED!
rankList: string[] = ['Chairman', 'Vice Chairman', 'President', 'Senior Executive Vice President', 'Senior Managing Director',
'Managing Director', 'Department Manager', 'Deputy General Manager', 'General Manager', 'Manager', 'Assistant Manager',
'Chief', 'Assistant Manager', 'Staff', 'Intern'];
departments: Department[]; //EDITED!
selectedEmployee: Employee;
constructor() { }
ngOnInit() {
}
onSelect(employee: Employee): void {
this.selectedEmployee = employee;
}
updateEmployee(newDeptID: string, newRank: string): void {
this.selectedEmployee.departmentID = +newDeptID;
this.selectedEmployee.rank = newRank;
}
}
//departments.component.ts
import {Component, Input, OnInit} from '@angular/core';
import { Department } from './department';
@Component({
selector: 'app-departments',
templateUrl: './departments.component.html',
styleUrls: ['./departments.component.css']
})
export class DepartmentsComponent implements OnInit {
departments: Department[]; //EDITED!
selectedDepartment: Department;
constructor() { }
ngOnInit() {
}
onSelect(department: Department): void {
this.selectedDepartment = department;
}
}
그리고 각 service를 컴포넌트에 inject해 준 다음, 각 서비스의 getDepartments 혹은 getEmployees 함수를 통해 데이터를 받아오는 함수를 작성합니다.
또한 작성된 각 함수를 ngOnInit() 함수에서 call 합니다.
완성된 각 .ts 파일은 다음과 같습니다 :
//employees.component.ts
import { Component, OnInit } from '@angular/core';
import { Employee } from './employee';
import { Department } from '../departments/department';
import { EmployeesService } from '../employees.service'; //ADDED!
import { DepartmentsService } from '../departments.service'; //ADDED!
@Component({
selector: 'app-employees',
templateUrl: './employees.component.html',
styleUrls: ['./employees.component.css']
})
export class EmployeesComponent implements OnInit {
employees: Employee[];
rankList: string[] = ['Chairman', 'Vice Chairman', 'President', 'Senior Executive Vice President', 'Senior Managing Director',
'Managing Director', 'Department Manager', 'Deputy General Manager', 'General Manager', 'Manager', 'Assistant Manager',
'Chief', 'Assistant Manager', 'Staff', 'Intern'];
departments: Department[];
selectedEmployee: Employee;
constructor(private employeesService: EmployeesService, private departmentsService: DepartmentsService) { }
ngOnInit() {
this.getEmployees(); //ADDED!
this.getDepartments(); //ADDED!
}
getEmployees(): void { //ADDED!
this.employees = this.employeesService.getEmployees();
}
getDepartments(): void { //ADDED!
this.departments = this.departmentsService.getDepartments();
}
onSelect(employee: Employee): void {
this.selectedEmployee = employee;
}
updateEmployee(newDeptID: string, newRank: string): void {
this.selectedEmployee.departmentID = +newDeptID;
this.selectedEmployee.rank = newRank;
}
}
//departments.component.ts
import {Component, Input, OnInit} from '@angular/core';
import { Department } from './department';
import { DepartmentsService } from '../departments.service'; //ADDED!
@Component({
selector: 'app-departments',
templateUrl: './departments.component.html',
styleUrls: ['./departments.component.css']
})
export class DepartmentsComponent implements OnInit {
departments: Department[];
selectedDepartment: Department;
constructor(private departmentsService: DepartmentsService) { }
ngOnInit() {
this.getDepartments(); //ADDED!
}
getDepartments(): void { //ADDED!
this.departments = this.departmentsService.getDepartments();
}
onSelect(department: Department): void {
this.selectedDepartment = department;
}
}
프로젝트를 빌드하여 실행시키면 기존과 같이 동작하는 것을 확인할 수 있습니다.
'Tech > Angular' 카테고리의 다른 글
[Angular] 양방향 바인딩 (2-way binding) (0) | 2020.01.15 |
---|---|
[Angular] UI 작업, 라우팅 (routing-module) (0) | 2020.01.08 |
[Angular] 클릭 이벤트 핸들러, ngIf (0) | 2020.01.07 |
[Angular] 부트스트랩 적용하기 (ng-bootstrap 사용) (0) | 2020.01.06 |
[Angular] 리스트 생성, ngFor (0) | 2020.01.04 |