개요
TypeORM을 사용하면서 그냥 자동 생성되는 number타입의 id를 auto-increment로 사용하게 되면 실제 서비스 하는데 있어서는, 외부인에게 너무 많은 정보를 노출하게 된다.
그러면 TypeORM에서 PrimaryColumn을 string으로 자동 생성해주는 @PrimaryGeneratedColumn(’uuid’) 을 사용하게 될 것이다.
@PrimaryGeneratedColumn('uuid')
id: string;
JavaScript
복사
그러면 엔티티가 생성이 될때마다 각 테이블의 기본키인 id칼럼은 다음과 같은 형식을 가지게 된다.
1. 3f8f1e2b-9c1a-4d3b-8f1e-2b9c1a4d3b8f
2. 7e4b2c1d-5f6a-4e7b-9d8c-2a1b3c4d5e6f
3. 9a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d
4. 5d4c3b2a-1f0e-9d8c-7b6a-5e4f3d2c1b0a
5. 8f7e6d5c-4b3a-2c1d-0e9f-8d7c6b5a4e3f
JavaScript
복사
하지만 이는 무작위로 생성된 128비트길이의 문자열로, 서비스가 점점 확장되는 상황에 있다면은 uuid의 조회 성능을 고려하지 않을 수 없다. 그래서 여러가지 id타입이 나오게 된다.
1. nanoId
2. ulid
3. cuid
4. objectId (mongoDB)
등등..
JavaScript
복사
TypeORM의 제약조건
일단 다양한 아이디타입을 사용하고 싶어도 typeOrm에서 다 호환이 되지 않는다는 게 문제였다. primaryKey 자동생성해주는 데코레이터를 사용하게 되면 typeOrm에서 지원해주는 옵션은 다음과 같다.
- increment (정수 자동증가)
- uuid (128비트 길이의 고유 식별자)
- rowid (64비트 정수 식별자 - sqllite에서 사용)
- identity (정수 자동증가 - SQL server에서 사용)
- sequence (정수 자동증가 - postgresql에서 사용)
JavaScript
복사
아까도 언급했다시피, 필자는 정수자동증가방식은 실제 서비스에서는 사용하는게 취약하다고(물론 더 많은 이유가 있겠지만) 생각하기 때문에 uuid를 사용하려고 했으나.. 이 역시 조회 성능 문제가 있었다.
그래서 알아본것이 ulid 와 uuidv6이다.
두 방식의 공통점은 무작위 문자열이지만 시간순으로 정렬이 가능하다는 장점이였다. B-tree검색 성능을 최대로 활용할려면 전제조건은 정렬이 가능해야한다는 것이기 때문이다.
발생한 문제상황
필자는 문자열길이도 너무 긴것보다는 ULID의 길이가 적당하다고 판단해서 사용할려고 했지만, typeOrm에서 지정하는 방식이 아니라서 사용이 안되었다.
import { ulid } from 'ulidx';
@Entity()
export class UserInfo extends BaseTable {
@PrimaryGeneratedColumn('uuid')
id: string;
@BeforeInsert()
private beforeInsert() {
this.id = ulid();
}
JavaScript
복사
ulidx는 ulid라이브러리가 몇년전부터 업데이트가 되지 않아서 다른 개발자가 이어받아 새로운 라이브러리로 만들고 계속 관리중인것 같다.
위의 방식으로 아이디를 생성할려고 하면 필자가 사용하고 있는 postgresql에서 uuid타입이 아니라고 에러를 내뱉는다. 그래서 결국 uuidv6를 사용하게 된다. typeorm에서 기본 지원하는 uuid 방식은 v4이며 이는 시간순 정렬이 되지 않는다.
uuidv6 사용
uuidv6는 공식적으로 표준화 된 버전은 아니지만, 시간기반으로 생성되는 uuid타입이라고 생각하면된다.
설치
npm install uuid
JavaScript
복사
사용
import { v6 as uuidv6 } from 'uuid';
@Entity()
export class UserInfo extends BaseTable {
@PrimaryGeneratedColumn('uuid')
id: string;
@BeforeInsert()
private beforeInsert() {
this.id = uuidv6(); //시간 순 정렬이 가능한 uuidv6를 사용해서 자동삽입
}
JavaScript
복사
ulid를 사용할때는 uuid타입이 아니라고 에러를 내뱉었는데, uuidv6를 사용하면 엔티티 초기화에서는 typeorm 기본 uuid문법으로 초기화 되고, 실제 엔티티를 생성하기 바로 직전에 해당 아이디를 uuidv6로 치환해서 데이터를 생성하게 된다.
데이터 예시
{
"success": true,
"statusCode": 201,
"message": "요청이 성공적으로 처리되었습니다.",
"data": {
"id": "1ef9d918-dba7-62c0-97a6-89824a51dd28",
"email": "Orland22@gmail.com"
}
}
JavaScript
복사
너무 길어서 좀 신경이 쓰이긴 한데, typeOrm 환경에서는 어쩔수 없는 것 같다.