[ TypeORM ] bigQeury DB를 이용해서 트리거함수 만들기(typeORM subscribe기능)
in BackEnd
DB의 기능에는 트리거
와 프로시저
가 있는데,
트리거
는 ‘A가 끝나면 B를 실행해줘’ 라는 개념이라면
(Ex. 상품을 등록하면 상품로그가 생성되게 해줘)
프로시저
는 DB에서 함수를 만드는 것이다. (요즘은 보통 DBA(DB관리자)들이 DB관리할때 사용한다)
프로시저는 예전에 많이 사용했던 개념이고 요즘은 JS단에서 함수를 생성해서 사용한다.
그래서 지금은 트리거를 이용하는 방법에 대해서 설명
할거임 ദ്ദി◍•ᴗ•◍)
이제부터 상품을 등록하면(createProduct) 상품로그를 생성하는 트리거를 만들건데,
이 로그들을 mysql에 저장하게 되면 용량이 금방 다 차버리게 된다.
그래서 이럴때는 로그만 저장해주는 디비가 따로 있으면 좋겠다는 생각을 하게되는데,
이때 사용할수있는 디비가 GCP에서는 BigQuery
라는 디비가 있다
BigQuery란 용량의 제한이 없고, 넣으면 넣는대로 다 들어가는 db이다.
그래서 로그성 데이터들은 빅쿼리에 넣게 되면 용량걱정없이 저장할 수 있다.
조회하기도 빠르다. 데이터 양이 늘어나면 나중에 조회하는것도 시간이 오래 걸리는데
빅쿼리에서는 그런 문제를 해결해준다
그럼이제 상품을 등록할때 트리거가 발현되도록 GCP bigquery설정과 코드를 짜보도록 하쟈 ᧖(• ᦢ •)ᦣ
GCP BigQuery 설정
이제는 GCP에서 설정해주어야 할 차례
gcp에서 bigquery로 들어간다
그리고 새 쿼리 작성
버튼 클릭
그러면 데이터세트 만드는 창이 나오는데, 거기서 원하는 ID, 지역을 선택하고 데이터세트 만들기
버튼 클릭
데이터세트가 만들어지면 테이블만들기
버튼을 클릭한다
원하는 테이블 이름으로 테이블을 생성한다.
그러면 데이터세트 밑에 테이블이 새로 생성된것을 확인할 수 있다
생성된 테이블을 클릭하면 스키마 수정
이라는 버튼을 눌러서
빅쿼리에 저장할 내용들을 입력한다.
이제는 암호키를 발급받아야함. 암호키를 발급받는 방법은
IAM 및 관리자 > 서비스계정
에 들어간다
서비스계정 만들기
버튼 클릭하기
서비스계정ID
작성하고 완료 하기
엑세스권한부여
에서는 BigQuery > BigQuery 관리자
를 클릭한다
그리고 완료
로 서비스계정을 완성한다.
만들어진 키에서 키 관리
를 클릭한다
거기서 새 키 만들기
누르고
JSON으로 키를 만든다
키가 만들어졌다! (•̀ᴗ•́)و ̑̑
이제 createProduct api를 호출하면 bigquery에 로그가 잘 쌓이는지 확인하면 된다.
api 호출해서 잘 입력됐다고 가정하고, 잘 됐다면
gcp bigqeury에서 테이블로 들어간다. (데이터세트를 누르면 다른게 나오니까 테이블을 클릭해야함)
그리고 쿼리
를 누르면 새탭에서 열기
혹은 분할탭에서 열기
를 눌러 쿼리문을 확인한다
그러면 아래쪽에 쿼리결과
를 확인할 수 있다
VSCODE 에서 트리거 만들어보기
service.ts
에서 createProduct
의 비지니스로직이 구현되고 나면
이걸 바로 알아채고 다음 함수를 실행시켜달라는 트리거를 만들어야 하는데
createProduct 의 비지니스로직이 구현되는걸 typeorm에서 알아차리는 기능이 이미 있다.
그 기능이 바로 subscriber 기능이다.
자 그럼 한번 해봅시댜
entity 폴더 안에 product.subscriber.ts 라는 파일을 하나 만든다.
그리고 그 내용안에는 아래 코드를 넣는다.
import {
Connection,
EntitySubscriberInterface,
EventSubscriber,
InsertEvent,
} from "typeorm";
import { Product } from "./product.entity";
import { BigQuery } from "@google-cloud/bigquery";
@EventSubscriber() //이벤트가 발생되면 바로 실행
export class ProductSubscriber implements EntitySubscriberInterface<Product> {
constructor(connection: Connection) {
connection.subscribers.push(this);
}
listenTo() {
//누구를 주시하고 있을건데?
return Product;
}
afterInsert(event: InsertEvent<any>): void | Promise<any> {
console.log(event);
const id = event.entity.id;
const name = event.entity.name;
const description = event.entity.description;
const price = event.entity.price;
const isSoldout = event.entity.isSoldout;
console.log(`${id} ${name} ${description} ${price} ${isSoldout}`);
const bigQuery = new BigQuery({
keyFilename: "gcp-bigquery.json",
projectId: "프로젝트아이디",
});
bigQuery.dataset("빅쿼리데이터이름").table("빅쿼리테이블명").insert([
{
id,
name,
description,
price,
isSoldout,
},
]);
}
}
@EventSubscriber()
데코레이터를 통해 트리거 기능을 할거라는걸 nest.js에 알려주어야 한다.
export class ProductSubscriber
이렇게만 있으면 그냥 단순 클래스인데,
@EventSubscriber()
의 기능을 구현을 하기 위해서 특정기능들을 구현을 해야 작동을 하게 된다. 그래서
implemnets EntitySubscriberInterface
를 추가해줌
EntitySubscriberInterface
는 어떤 entity를 쓸건데? 라고 물어보는 기능이므로 <>
안에 사용할 엔티티를 넣어주어야 한다.
나는 상품 엔티티와 엮을거기때문에 최종적으로는
export class ProductSubscriber implements EntitySubscriberInterface<Product>
이렇게 클래스를 만들어줌
간단히 말하자면,
Product 엔티티에 이벤트가 감지되는지 구독👀(감시)하고 있을게요 라는 뜻이다.
constructor(connection: Connection){
connection.subscribers.push(this);
}
그리고 constructor
에다가는 typeORM
에서 제공해주는 Connection을 이용한다.
product테이블만 subscriber
기능을 구현하는게 아니기 때문에(다른테이블에서도 만들수있으니)
구독정보에다가 내 클래스(=this)를 push하는것이다. 내 클래스라 함은 ProductSubscriber
클래스를 의미한다.
listenTo() {
return Product
}
어떤 테이블을 주시하고있을건지 적어주면 된다.
afterInsert
말고도 굉장히 많은 옵션들이 있다.
그 옵션들은 공식문서 에 나와있으니까 본인들이 원하는걸로 작성하면 됨.
나는 db에 정보가 새로 생성되면 그 다음에 함수가 실행됐으면 하니까 afterInsert
로 작성했다.
console.log(event);
로 찍어보면 event
안에는 실제 db에 저장된 내용들이 찍힌다.
const id = event.entity.id;
const name = event.entity.name;
const description = event.entity.description;
...
...
이런식으로 본인이 적은 엔티티를 불러올 수 있다.
원하는것만 꺼내먹으면 됨 🍎
그리고 이렇게 gcp 빅쿼리와 이어주어야 한다.
const bigQuery = new BigQuery({
keyFilename: "gcp-bigquery.json",
projectId: "프로젝트아이디",
});
bigQuery.dataset("빅쿼리데이터이름").table("빅쿼리테이블명").insert([
//객체하나당 1줄입력
{
id,
name,
description,
price,
isSoldout,
},
]);
이렇게 만들어준 subscriber
파일을 모듈에서 providers
에 import해주어야한다.
product.module.ts
로 가서 ProductSubscriber
를 import 해주자
providers: [
ProductSubscriber,
ProductsResolver,
ProductsService,
],
끗! (งᐛ)ว (งᐖ )ว