Service 안에서는 데이터베이스 관련된 로직을 처리한다.
데이터베이스에서 데이터를 생성, 조회, 업데이트, 삭제하거나 데이터 유효성을 체크하는 등의 작업을 수행한다.
이 Service를 사용할 때는, @Injectable
로 감싸져서 모듈에 제공되며, 이 Service는 어플리케이션 전체에서 사용될 수 있다.
Injectable의 의미는 주입할 수 있다는 의미다.
그렇기 때문에, A controller, B controller, C controller ... 등에서 해당 service를 주입해서 사용할 수 있는 것이다.
@Injectable()
export class HiService{
getHi(): string {
return `Hello World!`;
}
}
위의 Service는 Controller에서 다음과 같이 사용할 수 있다.
@Get()
getHi(): string{
return this.hiService.getHi();
}
Controller에서 this.hiService.getHi()
를 사용함으로써 Service에 정희한 getHi메소드를 Controller에 주입하여 사용할 수 있다.
import {UsersService} from './users.service';
import {User} from './users.model';
@Controller('user')
export class UsersController {
constructor(private usersService: UsersService){}
@Get('/:id)
getUserById(@Param('id') id:string):User{
return this.usersService.getUserById(id);
}
}
위의 코드는 Controller와 Service 사이의 의존성 주입을 보여주고 있다.
UserController : NestJS에서 User Controller 클래스를 정의하고 있다.
이 Controller의 경우@Controller('user')
로 엔드포인트가 /user
와 관련된 요청일 경우 처리되는 컨트롤러다.
Constructor : UsersController 안에 생성자로 UsersService를 주입받는다.
이 Constructor를 통해 Controller가 해당 Service를 사용할 수 있게 되는 것이다.
@Get('/:id') :/user/:id
경로로 HTTP GET 요청이 들어올때 처리하게 된다.
파라미터로 id를 가져와 변수에 할당한다.
getUserById : getUserById 메서드가 usersService안에 있는 getUserById 메서드를 호출해서 id에 따른 특정 글을 가져온다.
NestJS에서 Service는 명령어로 생성한다.
nest g service 이름 --no-spec
ornest g service 이름
터미널에 위의 명령어를 입력하면 생성된다.
여기서 각각 의미하는 걸 알아보자면,
nest Cli를 이용해서
+ 만든다
+ service를
+ [이름] 이름으로 된
1️⃣ 명령어를 통해
2️⃣ 해당 폴더 안에 service가 생성되면
3️⃣ 자동적으로 해당 폴더.module.ts
안에 providers
에다가 자동으로 업데이트가 된다.
@Injectable
데코레이터가 있다. 이를 통해 다른 컴포넌트에서 해당 service를 주입할 수 있게 된다.
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {}
터미널에서 cli로 service를 생성하면 아래와 같이 module의 Providers 부분에 자동으로 해당 service가 추가된다.
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import {UsersService} from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
이 service에서는 Controller에서보다 조금 더 복잡한 것들을 처리하게 된다.
따라서 이 Service를 Controller에서 사용할 수 있도록 해줘야한다.
constructor
에서 의존성 주입이 이루어진다.
이를 통해 Controller에서 해당 Service를 이용할 수 있게 되는 것이다.
import {Controller} from '@nestjs/common';
import {UsersService} from './users.service';
@Controller('users')
export class UsersController {
constructor(private usersService: UserService){}
}
위의 코드는 typeScript
기능을 사용해서, userService파라미터에 userService객체를 타입으로 지정해준다.
@Controller('users')
export class UsersController{
usersService: UsersService;
constructor( usersService: UsersService){
this.usersService = usersService;
}
@Get()
getAllUsers(): User[]{
return this.usersService.getAllUsers();
}
}
this.usersService
에 usersService를 할당해준다.같은 프로퍼티의 경우 이 색으로 구분
같은 파라미터의 경우 이 색으로 구분
위의 코드를 간단하게 만들기 위해서는 접근 제한자(
public
,protected
,private
)을 생성자 파라미터에 선언한다.
이렇게하면, 해당 생성자 파라미터는 클래스 프로퍼티로 선언된다.
import {Controller} from '@nestjs/common';
import {UsersService} from './users.service';
@Controller('users')
export class UsersController {
constructor(private usersService: UserService){}
}
getAllUsers(){
this.usersService.getAllUsers();// 서비스 안의 메소드 사용
}
위의 코드를 보면 접근 제한자를 사용하여 코드를 간단하게 만들 수 있는 것을 확인할 수 있다.
여기서 private
을 선언했는데,
이렇게되면, userService 프로퍼티는 UsersController 클래스 내부에서만 사용 가능하게 된다.
Provider는 NestJS의 기본 개념 중 하나로 정보를 공유하거나 특정 기능을 수행할 때 사용된다.
예를 들어, DB 연결, API호출, 로깅 등을 수행하는 Service나 저장소인 Repository 모두Provider로 사용될 수 있는 것이다.
이외에도 Factories, Helpers 등 모두 Provider로 취급될 수 있다.
Provider의 주요 아이디어는 의존성을 주입할 수 있다는 것이다.
의존성 주입
객체 간 관계를 구축하고 어플리케이션의 유연성과 확장성을 향상시키는 패턴.
따라서 Provider를 통해 클래스나 객체를 생성하고, 필요한 부분을 주입하여 다른 곳에서도 사용될 수 있다.
이렇게되면 코드가 변경되거나 확장될 때, 기존의 코드를 최소한으로 수정하면서 새로운 기능을 추가하거나 변경할 수 있다.
Service가 DB와 연결해야할 때, 연결 객체를 생성하는 Factory를 Provider로 주입받아 사용할 수 있다.
나중에 DB를 변경하거나, 다른 DB로 바꿀 때, Service를 수정하지 않아도 되기 때문에 유지 보수성을 증가시킬 수 있다.
또 다른 예를 보자면, 하나의 Controller에 필요한 모든 기능들을 Controller에 구현할 수 없다.
따라서 Controller에 필요한 기능들을 Services, Factories, Repositories, Helpers들을 Controller에서 사용할 수 있도록 만드는 것이다.
Provider를 사용하기 위해서는 module에 등록해야한다.
module 파일 내부에서 providers 부분에서 해당 모듈에서 사용하려는 Provider들을 넣어주면 된다.
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
Provider에서 가장 중요한 것은 바로 의존성을 주입할 수 있다는 것이다.
Provider를 통해 필요한 기능들을 생성하고, 필요한 곳이 있다면 다른 곳에서 해당 기능을 주입해 사용할 수 있다.
이에 따라 코드의 재사용성과 유지보수성을 높여주며, 확장성을 강화시켜준다.
참고
NestJS 공식문서