์กฐ์ฉํ ๋น์ด๋ฒ๋ฆฐ ๊ฐ ํ๋์์ ์์ํ ORM ๋ฉ์ด์ ์ ๊ทธ๋ ์ด๋ ๊ฒ์ฆ ์ ๋ตNew
๐ Overview
์ต๊ทผ ์ฌ๋ด ํจํค์ง ์ ๋ฐ์ดํธ์ ๋๋ถ์ด NestJS 12+ / MikroORM v7+ ๋ก ๋ฒ์ ์ ๋ฐ์ดํธ๋ฅผ ์งํํ๋ค.
๋๋ถ๋ถ์ ํ์ ์๋ฌ๋ฅผ ์ง์ฐ๊ณ ๋ณ๊ฒฝ๋ API๋ฅผ ๋ฐ๋ผ๊ฐ๋, ์์ ๋ฒ์ ์์ ์์ ์ด์๋ค.
๊ทธ ๊ณผ์ ์์ ์ ๋ ์ค๋ ๋ถ์ก๊ณ ์์๋ ๋ฌธ์ ๊ฐ ํ๋ ์์๋ค. MikroORM ์ ๋ฐ์ดํธ ์ค, ์๋ฒ ๋๋ ๊ฐ ๊ฐ์ฒด(Value Object)๋ก ๋งคํํ ํ๋๊ฐ ํน์ ์กฐํ ๊ฒฝ๋ก์์๋ง ์กฐ์ฉํ ๋น์ด๋ฒ๋ฆฌ๋ ํ์์ด์๋ค.
์๋ฌ๋ ๋ถ๋ถ๋ช ํ๊ณ , ํ์ ์๋ฌ์กฐ์ฐจ ๋์ง ์์๋ค. ์ปดํ์ผ์ ํต๊ณผํ๊ณ ๋ฐํ์์์๋ง ๊ฐ์ด ์ฌ๋ผ์ง๋ ํํ๋ผ, e2e ์๋๋ฆฌ์ค๊ฐ ์๋์๋ค๋ฉด ์๋ง ์กฐ์ฉํ ๋ฐฐํฌ๋์ด ์ด์์์ ๋ง์ฃผ์ณค์ ๋ฌธ์ ์๋ค.
์ด์ ๋๋ถ์ด ์์ฐ์ค๋ฝ๊ฒ ๋ฐ๋ผ์จ ์ง๋ฌธ์ด ์์๋ค. ๋ค๋ฅธ ์ง์ ์์๋ ๊ฐ์ ์ฑ๊ฒฉ์ ์ด์๊ฐ ๋ ์์ง ์์๊น?
๊ทธ๋์ e2e ์๋๋ฆฌ์ค์ ๊ฒ์ฆ ์ถ์ ์ฎ๊ฒผ๋ค. ๋จ์ํ โ์๋ต์ด ๊ฐ์๊ฐโ๋ฅผ ํ์ธํ๋ ๊ฒ์ ๋๋ถ์ด, โ๋ฐํ๋๋ ์ฟผ๋ฆฌ๊ฐ ๊ฐ์๊ฐโ ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถ๋ ๋ฐฉํฅ์ผ๋ก.
์ด๋ฒ ํฌ์คํ ์ ๊ทธ ํ๋จ์ ๊ณผ์ ๊ณผ, ๊ทธ๋์ ๋ง๋ค๊ฒ ๋ ์ฟผ๋ฆฌ ํฌํผยท๋ง์ด๊ทธ๋ ์ด์ ์ ์ฉ ํ ์คํธยทCI ์ค๊ณ๋ฅผ ๊ธฐ๋ก์ผ๋ก ๋จ๊ธฐ๊ณ ์ ํ๋ค.
1. ์กฐ์ฉํ ๋น๋ ๊ฐ โ ์๋ฒ ๋๋ VO์ ์ปฌ๋ผ ์ด๋ฆ ์ถฉ๋
๋ฌธ์ ๊ฐ ๋ ๊ตฌ์กฐ๋ ์ด๋ ๋ค. ์ฌ์ฉ์ ์ํฐํฐ๊ฐ ๋น๋ฐ๋ฒํธ๋ฅผ ๊ฐ ๊ฐ์ฒด๋ก ๊ฐ์ธ ์๋ฒ ๋๋๋ก ๋งคํํ๊ณ ์์๋ค.
๊ฐ ๊ฐ์ฒด๋ ํ์ ๊ฒ์ฆ๊ณผ ํด์ฑ ์ฑ ์์ ๊ฐ๊ณ , ์ค์ ์ ์ฅ์ ์ปฌ๋ผ ํ๋๋ก ๋จ์ด์ง๋ค.
// ๊ฐ ๊ฐ์ฒด ์ชฝ โ ์์ ์์ฑ value ๊ฐ ์ค์ ์ปฌ๋ผ password ๋ก ์ ์ฅ๋๋ค
export const PasswordSchema = new EntitySchema<Password>({
class: Password,
embeddable: true,
properties: {
value: {
fieldName: 'password',
type: 'string',
},
},
});
// ์ฌ์ฉ์ ์ํฐํฐ ์ชฝ โ prefix ๋ฅผ ๋น์ ์์ ์ปฌ๋ผ์ ๊ทธ๋๋ก ์ด๋ค
export const UserSchema = new EntitySchema<User>({
class: User,
properties: {
// ...
password: {
kind: ReferenceKind.EMBEDDED,
entity: () => Password,
prefix: '',
},
},
});User ์ํฐํฐ์ ์ ์ธํ ์๋ฒ ๋๋ ํ๋กํผํฐ ์ด๋ฆ(password)๊ณผ, ๊ทธ ์์ value ๊ฐ ์ค์ ๋ก ์ ์ฅ๋๋ ์ปฌ๋ผ ์ด๋ฆ(password)์ด ๊ฐ๋ค๋ ์ ์ด ํต์ฌ์ด๋ค.
v6์์๋ ์ด ๊ตฌ์ฑ์ด ๋ฌธ์ ์์ด ๋์ํ๋ค. ๊ทธ๋์ ์ค๋ซ๋์ ์๋ฌด๋ ์์ฌํ์ง ์์๋ค.
v7๋ก ์ฌ๋ฆฐ ๋ค, ์ฌ์ฉ์์ ๊ด๊ณ๋ฅผ ํจ๊ป ์กฐํํ๋ ๊ฒฝ๋ก์์๋ง ์คํจ๊ฐ ๋ํ๋๊ธฐ ์์ํ๋ค.
๊ด๊ณ๋ฅผ JOIN์ผ๋ก ๋ถ์ฌ ํ ๋ฒ์ ๊ฐ์ ธ์ค๋ ์ ๋ต์์๋ ์๋์ฒ๋ผ ์ปฌ๋ผ๋ง๋ค ๋ณ์นญ์ด ๋ถ๋๋ค.
select `e0`.*,
`u1`.`user_id` as `u1__user_id`,
`u1`.`password` as `u1__password` -- ์ด ๋ณ์นญ์ด ๋ฌธ์ ์ ์ถ๋ฐ์
from `exchange_requests` as `e0`
inner join `users` as `u1` on `e0`.`user_id` = `u1`.`user_id`๋ณ์นญ์ ๋ค์ ํ๋กํผํฐ๋ก ๋๋๋ฆฌ๋ ๋จ๊ณ์์, ORM์ password๋ผ๋ ์ด๋ฆ์ ์ปฌ๋ผ๋ณด๋ค ํ๋กํผํฐ ๋ฉํ๋ฐ์ดํฐ์์ ๋จผ์ ์ฐพ๋๋ค.
๊ทธ๋ฐ๋ฐ ๊ทธ ์ด๋ฆ์ผ๋ก ๊ฐ์ฅ ๋จผ์ ๋งค์นญ๋๋ ๊ฒ์ ์ค์ ๊ฐ์ ๋ด๋ ์์ ์ปฌ๋ผ์ด ์๋๋ผ, Password ์๋ฒ ๋๋ธ์ ๊ฐ๋ฆฌํค๋ ํ๋กํผํฐ ์์ฒด๋ค.
์ด ํ๋กํผํฐ๋ ํ๋์ ์ด๋ฆ์ด ์ฌ๋ฌ ์ปฌ๋ผ์ผ๋ก ํผ์ณ์ง๋ ๋ณตํฉ ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ์, ๋จ์ผ ์ปฌ๋ผ์ ๊ฐ์ ๋ฐ์์ผ ํ๋ ์๋ฆฌ์ ๋์ด๋ ์๊ฐ ๋งคํ์ด ์ฑ๋ฆฝํ์ง ์๋๋ค.
์์ธ์ ์ฐพ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฐ ์ด์ ๋ ์ธ ๊ฐ์ง์๋ค.
- ํ์ ๊ฒ์ฌ๋ก๋ ์ ํ ๋ณด์ด์ง ์๋๋ค. ์คํค๋ง๋ ์ํฐํฐ๋ ์ ์์ ์ธ ํ์ ์ด๋ค.
User์ํฐํฐ๋ง ๋จ๋ ์ผ๋ก ์กฐํํ ๋๋ ์ ์์ด๋ค. ๋ค๋ฅธ ์ํฐํฐ์์User๋ฅผ ํจ๊ป ๋ถ๋ฌ์ค๋ ๊ฒฝ๋ก์์๋ง ๊นจ์ง๋ค.- ์คํจ ์ง์ ์ด ๋๋ฉ์ธ๊ณผ ๋ฉ๋ค. ์ฟผ๋ฆฌ ์กฐ๋ฆฝ ๋ด๋ถ์์ ํฐ์ง๋ฏ๋ก, ๋ก๊ทธ๋ง ๋ณด๋ฉด ๋น๋ฐ๋ฒํธ ๋งคํ์ด ์์ธ์ด๋ผ๋ ๋จ์๊ฐ ์๋ค.
์ ๋ฆฌํ๋ฉด โ์ ๊ทธ๋ ์ด๋๋ก ์ธํด ๋ฐํ์ ๊ท์น์ด ๋ฐ๋์๋๋ฐ, ๊ทธ ๋ณํ๊ฐ ๊ฒ์ฆ๋์ง ์์ ์ฑ ํน์ ๊ฒฝ๋ก์์๋ง ์กฐ์ฉํ ๋๋ฌ๋๋โ ํํ์๋ค.
์ต์ข ์ ์ผ๋ก ํํ ํด๋ฒ์ ์ด๋ฆ ์ถฉ๋ ์์ฒด๋ฅผ ์์ ๋ ๊ฒ์ด์๋ค.
// ์๋ฒ ๋๋ ํ๋กํผํฐ ์ด๋ฆ์ ์ปฌ๋ผ ์ด๋ฆ๊ณผ ๋ถ๋ฆฌํ๊ณ , ํ๋กํผํฐ๊ฐ ์ ์ ํ ํค ์ด๋ฆ๋ fieldName ์ผ๋ก ๋ฐ๋ก ์ง์ ํ๋ค
hashedPassword: {
kind: ReferenceKind.EMBEDDED,
entity: () => Password,
prefix: '',
fieldName: '_password',
},์ด ๋ฐฉ๋ฒ์ ๊ณ ๋ฅธ ์ด์ ๋ DB ์คํค๋ง๋ฅผ ์ ํ ๊ฑด๋๋ฆฌ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ปฌ๋ผ ์ด๋ฆ์ ๊ทธ๋๋ก password์ด๋ฏ๋ก ๋ง์ด๊ทธ๋ ์ด์
์ด ํ์ ์๊ณ , ๊ตฌ๋ฒ์ ์ ํ๋ฆฌ์ผ์ด์
๊ณผ์ ๊ณต์กด๋ ๊ทธ๋๋ก ์ ์ง๋๋ค.
์ด ์ง์ ์ด ์ค์ํ๋ ๊ฑด, ๋กค๋ง ๋ฐฐํฌ ๊ณผ์ ์์ ์คํค๋ง ๋ง์ด๊ทธ๋ ์ด์ ์ ํจ๊ป ์งํํ๋ ๊ฒ์ด ๋ถ๋ด์ค๋ฌ์ ๊ธฐ ๋๋ฌธ์ด๋ค.
์ปฌ๋ผ ์ด๋ฆ์ ๋ฐ๊พธ๋ ์ ํ์ ํ๋ค๋ฉด ์ ๊ท ํ๋ ์ถ๊ฐ โ ๋ง์ด๊ทธ๋ ์ด์ โ ๊ตฌ/์ ํ๋ ๋ณํ ์กฐํ(ํ์ ํธํ) โ deprecated ํ๋ ์ ๊ฑฐ ๋ผ๋ ๋จ๊ณ๋ฅผ ๋ฐ์์ผ ํ๋ค.
๋ฐฐํฌ ์ค ๋ ๋ฒ์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ฐ์ ํ ์ด๋ธ์ ๋์์ ๋ฐ๋ผ๋ณด๋ ๊ตฌ๊ฐ์ด ์๊ธฐ๊ณ , ๊ฐ ๋จ๊ณ๋ง๋ค ๋ณ๋์ ๋ฐฐํฌ์ ๊ฒ์ฆ์ด ๋ฐ๋ผ๋ถ๋๋ค. ์ด๋ฒ ๋ฌธ์ ์ ํฌ๊ธฐ์ ๋นํด ์ง๋ถํด์ผ ํ ๋น์ฉ์ด ์ง๋์น๊ฒ ๋น์ธ๋ค๊ณ ํ๋จํ๋ค.
๋ฐ๋ฉด ํ๋กํผํฐ ์ด๋ฆ๋ง ๋ฐ๊พธ๋ ์ ํ์ ๋ณ๊ฒฝ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋ ์์์ ๋๋๋ค. ๋ฐฐํฌ ์์์ ์ ์ฝ์ด ์๊ณ , ๋๋๋ฆฌ๋ ๊ฒ๋ ์ฝ๋ ๋๋๋ฆฌ๊ธฐ ํ ๋ฒ์ด๋ฉด ๋๋ค.
๊ฒํ ํ๋ค๊ฐ ์ ์ ๋์๋ ๋จ๊ฒจ๋๋ค.
- ์ปค์คํ ๋งคํ ํ์ ์ผ๋ก ๊ต์ฒด: ๋ฉ์ธํ ์ด๋๊ฐ ๋จ์ผ ์์ฑ ์๋ฒ ๋๋ธ ๋์ ๊ถ๊ณ ํ๋ ๋ฐฉํฅ์ด๋ค(discussion #3685). ๊ตฌ์กฐ์ ์ผ๋ก๋ ๊ฐ์ฅ ๊นจ๋ํ์ง๋ง, ๊ฐ ๊ฐ์ฒด๊ฐ ๊ฐ์ง ๊ฒ์ฆยทํด์ฑ ์ฑ ์์ ํ์ ๋ณํ ๊ณ์ธต์ผ๋ก ์ฎ๊ฒจ์ผ ํด์ ๋ณ๊ฒฝ ๋ฒ์๊ฐ ์ปธ๋ค.
- ์ ์ญ ๋ก๋ฉ ์ ๋ต์ ๋ณ๋ ์ฟผ๋ฆฌ ๋ฐฉ์์ผ๋ก ๊ณ ์ : JOIN ๋ณ์นญ์ ๋ง๋ค์ง ์๊ฒ ํ๋ ์ฐํ๋ค. ๊ทธ๋ฌ๋ ์ฟผ๋ฆฌ ๋น๋์์ ๋ช ์์ ์ผ๋ก ์กฐ์ธํด ํจ๊ป selectํ๋ ์ฝ๋๊ฐ ๋จ์ ์์ผ๋ฉด ๊ทธ๋๋ก ์คํจํ๋ค. ๋ฌด์๋ณด๋ค ๋ฌธ์ ๋ฅผ ๋ฎ๋ ์ ํ์ด์๋ค.
- ์ ๋์ฌ ์ค์ ์ ๋๊ณ ๊ฐ ๊ฐ์ฒด ์ชฝ์ ํ๋๋ช ์ ์ฃผ๋ ๋ฐฉ์: ๊ณผ๊ฑฐ์ ๋น์ทํ ํํผ๋ฅผ ์๋ํ ์ ๋ก๊ฐ ์์์ง๋ง, ๊ฐ ๊ฐ์ฒด์ ์บก์ํ๋ฅผ ๊นจ๋จ๋ฆฌ๋ ๋๊ฐ๊ฐ ๋ฐ๋ผ์๋ค.
2. ์๋ต ๋น๊ต๋ง์ผ๋ก๋ ์กํ์ง ์๋ ๋ณํ โ ๋ฐํ ์ฟผ๋ฆฌ ์๋ฅผ ๊ณ์ฝ์ผ๋ก ๋ง๋ค๊ธฐ
์ด ์ด์๋ฅผ ๋๊ธฐ๊ณ ๋๋ ๋ ์ ๊ฒฝ ์ฐ์ด๋ ๊ฒ์ ๊ฐ์ ์ฑ๊ฒฉ์ ๋ฌธ์ ๊ฐ ๋ ์๋๋ฐ ์์ง ์ ๋ณด์ด๋ ๊ฒ ์๋๊น ํ๋ ์ ์ด์๋ค.
๋ฉ์ด์ ์ ๊ทธ๋ ์ด๋์์ ์ํํ ๋ณํ๋ ๋์ฒด๋ก ์ด๋ฐ ๋ชจ์์ ํ๋ค.
- ์๋ต JSON์ ์์ ํ ๋์ผํ๋ค.
- ๊ทธ๋ฐ๋ฐ ๋ด๋ถ์์ ๋ฐํ๋๋ SQL์ ๋ฌ๋ผ์ก๋ค.
- ๊ทธ ์ฐจ์ด๊ฐ ์คํ ๊ณํ์ ๋ฐ๊พธ๊ฑฐ๋, ํน์ ์กฐ๊ฑด์์๋ง ๊ฐ์ด ๋น๊ฒ ๋ง๋ ๋ค.
e2e ํ ์คํธ๋ ์๋ต์ ๊ฒ์ฆํ๋ฏ๋ก ์ด ๋ณํ๋ฅผ ๊ตฌ์กฐ์ ์ผ๋ก ํต๊ณผ์ํจ๋ค. ์ค์ ๋ก ์ด๋ฒ ์ ๊ทธ๋ ์ด๋์์๋ CI๋ ์ ๋ถ ์ด๋ก์ด์๋ค.
๊ทธ๋์ ๋ฐํ ์ฟผ๋ฆฌ ์์ฒด๋ฅผ ๊ด์ธก ๋์์ผ๋ก ๋์ด์ฌ๋ฆฌ๋ ํฌํผ๋ฅผ ๋ง๋ค์๋ค. ์ปค๋ฅ์ ์ด SQL์ ์คํํ๋ ๋จ์ผ ์ง์ ์ ๊ฐ์ธ ํธ์ถ ํ์๋ฅผ ์ผ๋ค.
export function installQueryCounter(orm: MikroORM): QueryCounter {
const connection = orm.em.getConnection();
const original = connection.execute;
let executed = 0;
// ์๋ณธ์ ๋ฐํ๊ฐ๊ณผ ์์ธ๋ฅผ ๊ทธ๋๋ก ํต๊ณผ์ํจ๋ค โ ๋์์ ๋ฐ๊พธ๋ฉด ์ ๋๋ค
connection.execute = (...args) => {
executed += 1;
return original.apply(connection, args);
};
return {
count: () => executed,
reset: () => {
executed = 0;
},
restore: () => {
connection.execute = original;
},
};
}์ฌ๊ธฐ์ ํ ๊ฐ์ง ๊ฒฐ์ ์ ํ๋ค. SQL ๋ฌธ์์ด์ ๊ทธ๋๋ก ๋จ์ธํ์ง ์๋๋ค.
๊ธฐ๋๊ฐ์ผ๋ก SQL์ ๋ฐ์๋๋ฉด ํ ์คํธ๋ ๊ฐ๋ ฅํด์ง์ง๋ง, ๋์์ ๊ตฌํ์ ๊ณ ์ ํด๋ฒ๋ ค ์ฌ์์ฑ ์์ฒด๋ฅผ ๋ง๋๋ค. ์ ๊ทธ๋ ์ด๋ ๊ณผ์ ์์๋ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ๊พธ๋ ๊ฒ์ด ๋ชฉ์ ์ธ๋ฐ, ๊ทธ ๋ชฉ์ ๊ณผ ์ ๋ฉด์ผ๋ก ์ถฉ๋ํ๋ค.
๋์ ๊ณ์ฝ์ ๋ ๊ฐ์ง๋ก ์ก์๋ค.
- ์ ๋ ฅ๊ณผ ์ถ๋ ฅ โ ๊ฐ์ ์กฐ๊ฑด์ ๊ฐ์ ๊ฒฐ๊ณผ, ๊ฐ์ ์ด ๊ฑด์.
- ๋ฐํ ์ฟผ๋ฆฌ ์์ ์ํ๊ณผ ํํ.
/**
* ์๋๋ฆฌ์ค๋ณ ๋ฐํ ์ฟผ๋ฆฌ ์ ์ํ.
* ์
๊ทธ๋ ์ด๋ ์ด์ ๋ฒ์ ์์ ์ค์ ๋ก ์ธก์ ํ ๊ฐ์ ๊ทธ๋๋ก ๊ธฐ๋๊ฐ์ผ๋ก ์ผ๋๋ค.
* ์ฌ์์ฑ ๊ฒฐ๊ณผ๊ฐ ์ด ๊ฐ์ ๋์ผ๋ฉด N+1 ์ด ์๊ฒผ๊ฑฐ๋ ๋ก๋ฉ ์ ๋ต์ด ๋ฐ๋ ๊ฒ์ด๋ค.
*/
const QueryCountLimits = {
// find ์ต์
์ populate ๋ฅผ ํจ๊ป ๋๊ฒจ ์ฐ๊ด์ ํ ๋ฒ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ๋ก
inlinePopulate: 4,
// ๋ฃจํธ๋ฅผ ๋จผ์ ์กฐํํ ๋ค em.populate() ๋ก ์ฐ๊ด์ ๋์ค์ ์ฑ์ฐ๋ ๊ฒฝ๋ก
populateAfterFind: 4,
// to-one ๊ด๊ณ๋ง ๋ ๋จ๊ณ๋ก ํ๊ณ ๋ค์ด๊ฐ๋ ์ค์ฒฉ ์กฐํ ๊ฒฝ๋ก
nestedToOneOnly: 3,
// to-one ๊ด๊ณ ํ๋๋ง ํจ๊ป ๊ฐ์ ธ์ค๋ ๊ฐ์ฅ ๋จ์ํ ๊ฒฝ๋ก
toOneOnly: 2,
} as const;
/**
* ์๋๋ฆฌ์ค๋ณ ๋ฐํ ์ฟผ๋ฆฌ ์ ํํ.
* ๋ฃจํธ ์กฐํ 1ํ + populate ๊ฐ ํ๊ณ ๋ค์ด๊ฐ๋ ๊ณ์ธต๋ง๋ค ์ต์ 1ํ๊ฐ ํ์ํ๋ฏ๋ก,
* ์ด๋ค ์ ๋ต์ ์ฐ๋๋ผ๋ ์ด๋ณด๋ค ์ ๊ฒ ๋์ฌ ์๋ ์๋ ๊ฐ์ด๋ค.
* (์: toOneOnly ๋ JOIN ์ผ๋ก ํฉ์ณ๋ ์ต์ 1ํ, ๋ณ๋ ์ฟผ๋ฆฌ๋ผ๋ฉด 2ํ)
*
* ์ด ๊ฐ์ด ํ์ํ ์ด์ ๋ ์ํ ๋จ์ธ๋ง์ผ๋ก๋ "์ฟผ๋ฆฌ๊ฐ ๋๋ฌด ์ ๊ฒ ๋์จ ๊ฒฝ์ฐ"๋ฅผ ์ก์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
* ์นด์ดํฐ๊ฐ SQL ๋ฐํ ์ง์ ์ ๋์ณ 0 ์ ์ธ๋๋ผ๋ ์ํ์ ๋ง์กฑํ๋ฏ๋ก ํ
์คํธ๊ฐ ํต๊ณผํด๋ฒ๋ฆฐ๋ค.
*/
const QueryCountFloors = {
/* ... */
} as const;ํํ์ ํจ๊ป ๋ ์ด์ ๊ฐ ๊ฝค ์ค์ํ๋ค. ๋ํผ๊ฐ ์ด๋ค ์คํ ๊ฒฝ๋ก๋ฅผ ๋์ณ ์นด์ดํธ๊ฐ 0์ด ๋์ด๋, ์ํ ๋จ์ธ๋ง ์์ผ๋ฉด ํ ์คํธ๋ ๊ทธ๋๋ก ํต๊ณผํ๋ค. ์ด ๊ฒฝ์ฐ ํ ์คํธ๋ ์๋ฌด๊ฒ๋ ๊ฒ์ฆํ์ง ๋ชปํ๋ฉด์ ํต๊ณผ ์ ํธ๋ง ๋ณด๋ด๊ฒ ๋๋ค.
์ด ์ถ์ ์ก๊ณ ๋๋ v7์ ๊ธฐ๋ณธ ๋ก๋ฉ ์ ๋ต ๋ณ๊ฒฝ(balanced)์ฒ๋ผ ์ฟผ๋ฆฌ ๊ฐ์ ์์ฒด๊ฐ ๋ฌ๋ผ์ง๋ ๋ณํ๋ ํ
์คํธ๊ฐ ๋งํด์ฃผ๊ฒ ๋์๋ค.
3. ๋ง์ด๊ทธ๋ ์ด์ ์ ์ฉ ํ ์คํธ์, ๋ผ์ด๋ด๊ธฐ ์ฌ์ด CI ๊ตฌ์ฑ
๋ค์ ๋ฌธ์ ๋ โ์ด ํ ์คํธ๋ค์ ์ด๋์ ๋ ๊ฒ์ธ๊ฐโ์๋ค.
์ด๋ฒ์ ์ถ๊ฐํ ํ ์คํธ๋ค์ ์ฒ์๋ถํฐ ํ์์ ์ธ ์ฑ๊ฒฉ์ด์๋ค.
v6 ์์ knex API ๋ฅผ ์ง์ ์ฐ๊ณ ์๋ ์ผ๋ถ ์ฟผ๋ฆฌ๋ฅผ ์ฟผ๋ฆฌ ๋น๋ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์์ฑํด์ผ ํ๊ณ , ์ด ํ ์คํธ๋ค์ ๊ทธ ์ฌ์์ฑ์ด ๊ธฐ์กด ๋์์ ๊ทธ๋๋ก ์ ์งํ๋์ง ํ์ธํ๊ธฐ ์ํ ์ฅ์น์๋ค.
๋ฐ๊ฟ ๋งํ๋ฉด, ์ฌ์์ฑ์ด ๋๋๊ณ ๊ฒ์ฆ๊น์ง ๋ง์น๋ฉด ์ญํ ๋ ํจ๊ป ๋๋๋ค. ๊ทธ ์ดํ๋ก๋ CI ์ปจํ ์ด๋ ์คํ ์๊ฐ๋ง ๋๋ฆด ๋ฟ์ด๋ค.
๊ทธ๋์ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ฉ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด ๊ทธ ์๋์๋ง ๋ชจ์๋ค. ๋๋ ํฐ๋ฆฌ์งธ ์ง์ฐ๋ฉด ํ ์คํธ๋, CI ์ค์ ๋ ํจ๊ป ์ ๋ฆฌ๋๋ ๊ตฌ์กฐ๋ฅผ ์ํ๋ค.
๊ณ์ฝ์ ์ถ์ด HTTP ์๋ต์ด ์๋๋ผ ์ ์ถ๋ ฅ๊ณผ ๋ฐํ ์ฟผ๋ฆฌ ์์๊ธฐ ๋๋ฌธ์, ์ปจํธ๋กค๋ฌ๋ฅผ ๊ฑฐ์น์ง ์๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ปจํ ์คํธ์์ ์ฟผ๋ฆฌ๋ฅผ ์ง์ ๋์คํจ์นํ๋๋ก ํ๋ค.
/**
* ์ฟผ๋ฆฌ ์ฌ์์ฑ ์ ๋์์ ๊ณ์ฝ์ผ๋ก ๊ณ ์ ํ๋ ์ฟผ๋ฆฌ ์ ์ฉ ํ
์คํธ์ฉ ํฌํผ.
* ๊ณ์ฝ ์ถ์ด SQL ๋ฌธ์์ด์ด ์๋๋ผ ์
์ถ๋ ฅ๊ณผ ๋ฐํ ์ฟผ๋ฆฌ ์๋ผ, HTTP ๋์ ๋ฒ์ค๋ก ์ง์ ๋์คํจ์นํ๋ค.
*/
export async function createQueryTestContext(): Promise<QueryTestContext> {
const app = await createE2eApp();
return { ...app, queryBus: app.get(QueryBus) };
}CI์์๋ e2e ๋ฅผ ๋๋ฉ์ธ ๋จ์๋ก ๋๋ ๋ณ๋ ฌ ์คํํ๊ณ ์์๋๋ฐ, ์ด ๋๋ ํฐ๋ฆฌ๋ ๋๋ฉ์ธ ๊ตฌ์กฐ ๋ฐ์ ์์ด ์๋ ํ์์ ๊ฑธ๋ฆฌ์ง ์์๋ค.
๊ทธ๋์ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์กฐ๊ธ ์๋ดค๋ค. ๋ง์ด๊ทธ๋ ์ด์ ๋๋ ํฐ๋ฆฌ๊ฐ ์์ ๋๋ง ์คํ ๊ทธ๋ฃน์ ํ๋ ๋ง๋ถ์ด๊ณ , ๋๋ ํฐ๋ฆฌ๋ฅผ ์ง์ฐ๋ฉด ๊ทธ ๊ทธ๋ฃน๋ ๊ฐ์ด ์ฌ๋ผ์ง๊ฒ ํ๋ค.
์ฌ๊ธฐ์ ๊ฒ์ฌ๋ฅผ ํ๋ ๋ ๋ฃ์๋ค. ์ด๋ ์คํ ๊ทธ๋ฃน์๋ ์กํ์ง ์๋ e2e ํ์ผ์ด ์์ผ๋ฉด CI ๋ฅผ ์คํจ์ํค๋ ๊ฒ์ด๋ค. ๋ก์ปฌ jest ๋ ํ์ผ ์์น์ ๋ฌด๊ดํ๊ฒ ๊ธ์ด๊ฐ๊ธฐ ๋๋ฌธ์, ์์น๋ฅผ ์๋ชป ๋๋ฉด ๋ก์ปฌ์์๋ ๋ฉ์ฉกํ ๋๊ณ CI ์์๋ ๊ทธ ํ์ผ์ ์กด์ฌ์กฐ์ฐจ ๋ชจ๋ฅธ ์ฑ ์กฐ์ฉํ ์ฑ๊ณตํ๋ค. ์์น๋ฅผ ์ฌ๋์ด ๋งค๋ฒ ๊ธฐ์ตํ๋ ๊ฒ๋ณด๋ค๋ ์คํฌ๋ฆฝํธ๊ฐ ๊ฑธ๋ฌ์ฃผ๋ ํธ์ด ๋ซ๋ค๊ณ ๋ดค๋ค.
ํ ์คํธ๋ฅผ ๋ค ์ง๊ณ ๋๋ ํ ๊ฐ์ง๊ฐ ๋ ๊ถ๊ธํด์ก๋ค. ์ง๊ธ ์ด ํ ์คํธ๊ฐ ๋ณด์ฅํ๋ ๊ฑด ๊ฒฐ๊ตญ ๋ด๊ฐ ์์ฑํ ์๋๋ฆฌ์ค ์์์ ์ฟผ๋ฆฌ๊ฐ ๊ฐ๋ค๋ ๊ฒ๋ฟ์ธ๋ฐ, ์ด์์์ ์ค์ ๋ก ๋๊ฐ๋ ์ฟผ๋ฆฌ์ ๋น๊ตํ๋ฉด ์ด๋จ๊น?
๋ง์นจ ์ด์ APM ์ด DB ์คํฌ์ SQL ๋ณธ๋ฌธ์ ๊ทธ๋๋ก ๋จ๊ธฐ๊ณ ์์๋ค. ๋๋ถ์ ๋ฐฐํฌํ์ง ์๊ณ ๋ ์ด์์ด ๋ฐํํ ์ฟผ๋ฆฌ๋ฅผ ๊บผ๋ด๋ณผ ์ ์์๋ค.
๊ฐ์ API ๊ฒฝ๋ก๋ฅผ ๋ก์ปฌ์์ ์ ๋ฒ์ ์ผ๋ก ์คํํด SQL ์ ๋ชจ์ผ๊ณ , ์์ชฝ์ ์ ๊ทํ(๊ณต๋ฐฑ ์ถ์ฝ, ๋ฆฌํฐ๋ด์ ์๋ฆฌํ์์๋ก ์นํ)ํด์ ๋น๊ตํ๋ค.
- ๊ฐ์ฅ ํฌ๊ฒ ์ฌ์์ฑํ ์ง๊ณ ์ฟผ๋ฆฌ: ์ ๊ทํ ํ 959์๊ฐ ์ ๋ถ ์ผ์น
- UNION ํ์ ํ ์ด๋ธ์ ์ฐ๋ ๊ฒ์ ์ฟผ๋ฆฌ: ๊ตฌ์กฐ๋ ๊ฐ๊ณ ๊ฐ ๊ฐ๋๋ฅผ ๊ดํธ๋ก ๊ฐ์ธ๋ ํ๊ธฐ๋ง ์ฐจ์ด
- ๊ฐ ๊ฐ์ฒด ๋ฌธ์ ๋ฅผ ๊ณ ์น ๋ค์ JOIN ๋ณ์นญ: ์ด์๊ณผ ์์ ํ ๋์ผ
๐ค Understanding
์ด๋ฒ ์ ๊ทธ๋ ์ด๋์์ ์ป์ ๊ตํ์, ๋ฉ์ด์ ๋ฒ์ ๋ณ๊ฒฝ์ด ํ์ ์ผ๋ก ๋๋ฌ๋์ง ์๋ ๋ฐํ์ ๊ท์น๊น์ง ํจ๊ป ๋ฐ๊พผ๋ค๋ ์ ์ด๋ค.
๊ณต์ ์ ๊ทธ๋ ์ด๋ ๊ฐ์ด๋์๋ ์กฐ์ฉํ ๋์์ด ๋ฌ๋ผ์ง๋ ํญ๋ชฉ๋ค์ด ๋ถ๋ช ํ ์ ํ ์๋ค.
Change detection is no longer automatic on scalar properties, an explicit
em.persistcall is required now
Both are now enabled by default, and the auto-fixing mechanism is removed.
Default loading strategy is
balanced
์ธ ์ค ๋ชจ๋ ์ปดํ์ผ๋ฌ๊ฐ ์๋ ค์ฃผ์ง ์๊ณ , ์๋ต๋ง ๋ณด๋ ํ ์คํธ๋ ์๋ ค์ฃผ์ง ์๋๋ค. ๊ฒ์ฆ์ ์ถ์ ๊ฒฐ๊ณผ์์ ์ฟผ๋ฆฌ๋ก ์ฎ๊ธด ๊ฒ์ด ์ด๋ฒ ์์ ์์ ๊ฐ์ฅ ๊ฐ์ด์น ์๋ ๊ฒฐ์ ์ด์๋ค๊ณ ์๊ฐํ๋ ์ด์ ๋ค.
์๋ฒ ๋๋ ๊ฐ ๊ฐ์ฒด ์ด์ผ๊ธฐ๋ก ๋์๊ฐ๋ฉด, ํ๋กํผํฐ ์ด๋ฆ๊ณผ ์ปฌ๋ผ ์ด๋ฆ์ ๋ง์ถ๋ ๋ฐฉ์์ ์ค๋์ ๋ถํฐ ์ด์ด์จ ํ ์ปจ๋ฒค์ ์ด์๋ค. v6 ์์๋ ๋ฌธ์ ์์ด ๋์ํ์ผ๋ ๋๊ตฌ๋ ์์ฌํ ์ด์ ๊ฐ ์์๊ณ , ๊ทธ ์ปจ๋ฒค์ ์ด v7 ์์ ์ด๊ธ๋ ๊ฒ ์์ฒด๋ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋นํ ๋ชซ์ด๋ผ๊ณ ์๊ฐํ๋ค.
๋ค๋ง ํ๋์ ํ๋กํผํฐ ์ด๋ฆ์ด ์ฌ๋ฌ ์ปฌ๋ผ์ผ๋ก ํผ์ณ์ง๋ ๊ตฌ์กฐ๊ฐ ๋จ์ผ ์ปฌ๋ผ ์๋ฆฌ์ ๋์๋ค๋ฉด, ORM ์ด ์ง๋จ ๊ฐ๋ฅํ ๋ฉ์์ง๋ฅผ ์ฃผ๋ ํธ์ด ๋ง๋ค๊ณ ๋ณธ๋ค. ์ง๊ธ์ ์กฐํ ๊ฒฝ๋ก์ ๋ฐ๋ผ ๊ฐ์ด ๋น๋ ํํ๋ก๋ง ๋๋ฌ๋์ ์์ธ๊น์ง ๋๋ฌํ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋๋ฌด ๋ฉ์๋ค.
๊ฐ์ ์ฌ๋ก์ ์ ์คํธ๋ฆผ ์ด์๋ ์ฐพ์ง ๋ชปํ๋ค. ์ฌํ ์กฐ๊ฑด์ ์ขํ๊ณ โ๋ฒ๊ทธโ๋ก ๋ณผ์ง โ์ง๋จ ๋ฉ์์ง ๊ฐ์ ์์ฒญโ์ผ๋ก ๋ณผ์ง ์ค์ค๋ก ๋จผ์ ๊ฒฐ๋ก ์ ๋ธ ๋ค, ์ต์ ์ฌํ ์ ์ฅ์์ ํจ๊ป ์ ๋ณดํด๋ณผ ์๊ฐ์ด๋ค. ๋ฉ์ธํ ์ด๋๊ฐ ์ด๋ฏธ ๋จ์ผ ์์ฑ ์๋ฒ ๋๋ธ๋ณด๋ค ์ปค์คํ ํ์ ์ ๊ถ๊ณ ํ๊ณ ์์ผ๋, ์ค๊ณ๋ฅผ ๊ทธ๋๋ก ๋ ์ฑ ๋์๋ง ๋ฐ๊ฟ๋ฌ๋ผ๋ ์๊ตฌ๊ฐ ๋์ง ์๋๋ก ๋ค๋ฌ๋ ์ผ์ด ๋จผ์ ๋ค.
์ฐธ๊ณ ์๋ฃ