프로젝트의 백엔드에서 타입스크립트를 사용하기로 했다. 기존 JS로 구현하는 express 서버의 많은 부분인 변경이 되었다. 그리고 특히 이전까지는 mysql에 쿼리문과 CRUD 명령을 할 때, Sequelize라는 ORM을 사용해왔었는데, 타입스크립트에서는 타입스크립트 지원 문제로 typeorm을 사용하게 되었다. 덕분에 이전엔 경험하지 못 했던 에러들을 목격하게 된다.
사실 이 에러는 정말 기본적인 typeorm 설정을 모르고 맹목적으로 코딩을 하면 내는 문제이다.
이 에러를 낸 경위를 먼저 살펴보겠다. mysql에 express 서버를 처음 연결하는 단계였다.
[data-source 코드]
import { DataSource } from "typeorm";
import User from "../entity/User";
require("dotenv").config();
export const AppDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
database: "OPENPOOL",
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
synchronize: true,
logging: true,
entities: [User],
})
default AppDataSource
[User Entity]
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export default class User {
@PrimaryGeneratedColumn()
id: number
@Column()
address: string
}
[Controller]
import AppDataSource from "../db/data-source";
import {Request, Response} from "express";
import User from "../entity/User";
export const addUser = async (req : Request, res: Response)=>{
const address : string = req.body.address;
await AppDataSource
.createQueryBuilder()
.insert()
.into(User)
.values([{
address: address
}]).execute();
return res.status(200).send("success db");
}
데이터베이스의 User 테이블에 address값만 갖는 레코드를 추가하는 아주 간단한 코드다. 하지만 이코드를 통해서 addUser를 실행시키면 아래와 같은 에러가 발생한다.
TypeError: this.subQuery is not a function appears
위와 같은 에러에 대한 질문에 많은 답변이 data-source
에서 데이터베이스 연결 설정을 해주는 부분의 entities
의 값을 제대로 설정하라고 조언한다.
이를테면 아래와 같이 말이다.
[조언 방식]
{
// 생략...
entities : ["src/entity/*.{ts,js}"]
// 생략...
}
하지만 필자의 경우에는 생성된 모델 데이터인 User.ts
를 모듈로 불러와 바로 입력했기 때문에 사실 형태만 다르지 충분히 작동 가능한 설정방식 이었다.
[필자 방식]
import User from "../entity/User";
{
// 생략...
entities : [User]
// 생략...
}
보통의 경우에는 이 설정을 제대로 안해줘서 생기는 문제라 발생하는 문제들인 듯하다. 하지만 필자의 경우는 달랐다.
필자의 경우는 User Entity 파일에 모델링 되어 있는 Scheme이 실제 Local DBMS에 반영이 안되어 있어서 문제였다. 더 쉽게 말하자면 User Table이 필자 Database에 없었던 것이다.
이 문제는 직접 mysql에서 테이블을 생성해줘도 되고, data-source
에서 데이터베이스 연결 설정을 할 때 ORM으로 데이터베이스를 초기화해도 해결을 할 수 있다.
필자는 후자의 방법을 선택하여 해결하였다.
import { DataSource } from "typeorm";
import User from "../entity/User";
require("dotenv").config();
const AppDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
database: "OPENPOOL",
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
synchronize: true,
logging: true,
entities: [User],
})
if (!AppDataSource.isInitialized){
AppDataSource.initialize()
.then(()=>{
console.log("db init success");
})
.catch((error)=> console.log(error));
}
export default AppDataSource