Le dรฉveloppement de Knex.js โ un query builder SQL que j'affectionne beaucoup โ va reprendre plus activement.
Le dรฉveloppement de Knex.js โ un query builder SQL que j'affectionne beaucoup โ va reprendre plus activement.
์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์ธก๋ฉด์์ ๋ณธ Drizzle ORM ๋ Kysely ๋น๊ต
TypeScript๋ก ๋ฐฑ์๋ ์๋ฒ๋ฅผ ๊ฐ๋ฐํ๋ฉด์ ์ ์ ํ ORM ์ ํ์ ํญ์ ์ค์ํ ๊ฒฐ์ ์ค ํ๋์ ๋๋ค. ์ต๊ทผ ์ ํ๋ก์ ํธ์์ Drizzle ORM๊ณผ Kysely๋ฅผ ๋ชจ๋ ์ฌ์ฉํด ๋ณผ ๊ธฐํ๊ฐ ์์๋๋ฐ, ๊ฐ์ธ์ ์ผ๋ก๋ Drizzle ORM์ด ๋ ํธ๋ฆฌํ๊ณ ์์ฐ์ฑ์ด ๋์๋ ๊ฒฝํ์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค.๋ ORM์ ๋ํ ๊ฐ๋ตํ ์๊ฐ Drizzle ORM์ TypeScript์ฉ ORM์ผ๋ก, ํ์ ์์ ์ฑ๊ณผ ์ง๊ด์ ์ธ API๋ฅผ ๊ฐ์ ์ผ๋ก ๋ด์ธ์ฐ๊ณ ์์ต๋๋ค. ์คํค๋ง ์ ์๋ถํฐ ๋ง์ด๊ทธ๋ ์ด์ , ์ฟผ๋ฆฌ ๋น๋๊น์ง ํ์คํ ๊ฐ๋ฐ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค. Kysely๋ โํ์ ์์ ํ SQL ์ฟผ๋ฆฌ ๋น๋โ๋ก ์์ ์ ์๊ฐํ๋ฉฐ, ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ์์คํ ์ ํ์ฉํด ์ฟผ๋ฆฌ ์์ฑ ์ ํ์ ์์ ์ฑ์ ๋ณด์ฅํฉ๋๋ค. ๋ ๋๊ตฌ ๋ชจ๋ ํ๋ฅญํ์ง๋ง, ์ ๊ฐ๋ฐ ๊ฒฝํ์ ๋น์ถ์ด ๋ณผ ๋ Drizzle ORM์ด ๋ช ๊ฐ์ง ์ธก๋ฉด์์ ๋ ํธ๋ฆฌํ์ต๋๋ค.Drizzle ORM์ ์ ํธํ๊ฒ ๋ ์ด์ ์คํค๋ง ์ ์์ ์ง๊ด์ฑ Drizzle ORM์ ์คํค๋ง ์ ์ ๋ฐฉ์์ ๋งค์ฐ ์ง๊ด์ ์ด๊ณ ์ ์ธ์ ์ ๋๋ค:import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';export const users = pgTable('users', { id: serial('id').primaryKey(), name: text('name').notNull(), email: text('email').unique().notNull(), age: integer('age')});<Drizzle ORM์ ์ด ์คํค๋ง ์ ์๋ก๋ถํฐ ์๋์ผ๋ก CREATE TABLE SQL์ ์์ฑํ ์ ์์ด, ์คํค๋ง์ ์ฝ๋๊ฐ ํญ์ ๋๊ธฐํ๋์ด ์์ต๋๋ค. ๋ฐ๋ฉด Kysely๋ ํ์ ์ ์์ ๋ ์ค์ ์ ๋๊ณ ์์ด ์คํค๋ง์ ํ์ ์ ์๊ฐ ๋ถ๋ฆฌ๋๋ ๊ฒฝํฅ์ด ์์ต๋๋ค:interface Database { users: { id: Generated<number>; name: string; email: string; age: number | null; };}<์ด ํ์ ์ ์๋ TypeScript ์ฝ๋์์ ํ์ ์์ ์ฑ์ ์ ๊ณตํ์ง๋ง, ์ด ํ์ ์ ์๋ง์ผ๋ก๋ CREATE TABLE SQL์ ์์ฑํ ์ ์๋ค๋ ๊ฒ์ด ๊ฒฐ์ ์ ์ธ ๋จ์ ์ ๋๋ค. ์ค์ ๋ก ํ ์ด๋ธ์ ์์ฑํ๋ ค๋ฉด ๋ณ๋์ SQL ์คํฌ๋ฆฝํธ๋ ๋ง์ด๊ทธ๋ ์ด์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์ด๋ ํ์ ๊ณผ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง ๊ฐ์ ๋ถ์ผ์น ๊ฐ๋ฅ์ฑ์ ๋์ ๋๋ค. Drizzle์ ์ ๊ทผ ๋ฐฉ์์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง์ TypeScript ํ์ ์ ๋ ๊ธด๋ฐํ๊ฒ ์ฐ๊ฒฐํด์ฃผ์ด ๊ฐ๋ฐ ๊ณผ์ ์์ ํผ๋์ ์ค์ฌ์ฃผ์์ต๋๋ค.๋ง์ด๊ทธ๋ ์ด์ ๊ฒฝํ Drizzle ORM์ ๋ง์ด๊ทธ๋ ์ด์ ๋๊ตฌ(drizzle-kit)๋ ์ ๋ง ์ธ์์ ์ด์์ต๋๋ค. ์คํค๋ง ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ๊ฐ์งํ๊ณ SQL ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ์์ฑํด์ฃผ๋ ๊ธฐ๋ฅ์ด ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ฅผ ํฌ๊ฒ ๊ฐ์ ํ์ต๋๋ค:npx drizzle-kit generate:pg<์ด ๋ช ๋ น์ด ํ๋๋ก ์คํค๋ง ๋ณ๊ฒฝ์ฌํญ์ ๋ํ ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ด ์์ฑ๋๋ฉฐ, ์ด๋ฅผ ๊ฒํ ํ๊ณ ์ ์ฉํ๋ ๊ณผ์ ์ด ๋งค์ฐ ๊ฐ๋จํ์ต๋๋ค. ๋ฐ๋ฉด Kysely์ ๋ง์ด๊ทธ๋ ์ด์ ์ ๋ณธ์ง์ ์ผ๋ก ์๋์ ์ ๋๋ค. ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ์์ฑํด์ผ ํ๋ฉฐ, ์คํค๋ง ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ๊ฐ์งํ๊ฑฐ๋ SQL์ ์์ฑํด์ฃผ๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค:// Kysely์ ๋ง์ด๊ทธ๋ ์ด์ ์์async function up(db: Kysely<any>): Promise<void> { await db.schema .createTable('users') .addColumn('id', 'serial', (col) => col.primaryKey()) .addColumn('name', 'text', (col) => col.notNull()) .addColumn('email', 'text', (col) => col.unique().notNull()) .addColumn('age', 'integer') .execute();}async function down(db: Kysely<any>): Promise<void> { await db.schema.dropTable('users').execute();}<์ด๋ฌํ ์๋ ๋ฐฉ์์ ๋ณต์กํ ์คํค๋ง ๋ณ๊ฒฝ์์ ์ค์ํ ๊ฐ๋ฅ์ฑ์ด ๋์์ง๊ณ , ํนํ ํฐ ํ๋ก์ ํธ์์๋ ์์ ๋์ด ์๋นํ ์ฆ๊ฐํ ์ ์์์ต๋๋ค. ํ์ง๋ง Kysely์ ๋ง์ด๊ทธ๋ ์ด์ ์๋ ๋ ๊ฐ์ง ์ค์ํ ์ฅ์ ์ด ์์ต๋๋ค:<TypeScript ๊ธฐ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ : Kysely์ ๋ง์ด๊ทธ๋ ์ด์ ์คํฌ๋ฆฝํธ๋ TypeScript๋ก ์์ฑ๋๊ธฐ ๋๋ฌธ์, ๋ง์ด๊ทธ๋ ์ด์ ๋ก์ง์ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง์ ํตํฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, S3์ ๊ฐ์ ์ค๋ธ์ ํธ ์คํ ๋ฆฌ์ง์ ๋ฐ์ดํฐ๋ ํจ๊ป ๋ง์ด๊ทธ๋ ์ดํธํ๋ ๋ณต์กํ ์๋๋ฆฌ์ค๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. ๋ฐ๋ฉด Drizzle ORM์ SQL ๊ธฐ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ ์ด๋ฏ๋ก ์ด๋ฌํ ํตํฉ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.<์๋ฐฉํฅ ๋ง์ด๊ทธ๋ ์ด์ : Kysely๋ up๊ณผ down ํจ์๋ฅผ ๋ชจ๋ ์ ์ํ์ฌ ์ ๊ทธ๋ ์ด๋์ ๋ค์ด๊ทธ๋ ์ด๋๋ฅผ ๋ชจ๋ ์ง์ํฉ๋๋ค. ์ด๋ ํนํ ํ ํ์ ํ๊ฒฝ์์ ์ค์ํ๋ฐ, ๋ค๋ฅธ ๊ฐ๋ฐ์์ ๋ณ๊ฒฝ์ฌํญ๊ณผ ์ถฉ๋์ด ๋ฐ์ํ ๊ฒฝ์ฐ ๋กค๋ฐฑ์ด ํ์ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. Drizzle ORM์ ํ์ฌ ์ ๊ทธ๋ ์ด๋๋ง ์ง์ํ๋ฉฐ, ๋ค์ด๊ทธ๋ ์ด๋ ๊ธฐ๋ฅ์ด ์์ด ํ์ ์ ๋ถํธํ ์ ์์ต๋๋ค.<์ฐธ๊ณ ๋ก, Python ์ํ๊ณ์ SQLAlchemy ๋ง์ด๊ทธ๋ ์ด์ ๋๊ตฌ์ธ Alembic์ ํจ์ฌ ๋ ๋ฐ์ ๋ ํํ์ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ ๊ณตํฉ๋๋ค. Alembic์ ๋น์ ํ์ ์ธ ๋ง์ด๊ทธ๋ ์ด์ ๊ฒฝ๋ก(๋ธ๋์นํฌ์ธํธ ์์ฑ ๊ฐ๋ฅ)๋ฅผ ์ง์ํ์ฌ ๋ณต์กํ ํ ๊ฐ๋ฐ ํ๊ฒฝ์์๋ ์ ์ฐํ๊ฒ ๋์ํ ์ ์์ต๋๋ค. ์ด์์ ์ผ๋ก๋ JavaScript/TypeScript ์ํ๊ณ์ ORM๋ ์ด๋ฌํ ์์ค์ ๋ง์ด๊ทธ๋ ์ด์ ๋๊ตฌ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ๋ฐ๋์งํฉ๋๋ค.๊ด๊ณ ์ค์ ์ ์ฉ์ด์ฑ Drizzle ORM์์ ํ ์ด๋ธ ๊ฐ ๊ด๊ณ ์ค์ ์ด ๋งค์ฐ ์ง๊ด์ ์ด์์ต๋๋ค:import { relations } from 'drizzle-orm';export const usersRelations = relations(users, ({ one, many }) => ({ profile: one(profiles, { fields: [users.id], references: [profiles.userId], }), posts: many(posts)}));<์ด ๋ฐฉ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ณธ์ง์ ์ธ, ๊ด๊ณ์ ์ธ ์ธก๋ฉด์ ๋ช ํํ๊ฒ ํํํด์ฃผ์์ต๋๋ค.์ฟผ๋ฆฌ ์์ฑ์ ํธ์์ฑ๊ณผ ๋์ผ ์ด๋ฆ ์นผ๋ผ ๋ฌธ์ ์ฒ๋ฆฌ ๋ ORM ๋ชจ๋ ์ฟผ๋ฆฌ ์์ฑ์ ์ํ API๋ฅผ ์ ๊ณตํ์ง๋ง, Drizzle์ ์ ๊ทผ ๋ฐฉ์์ด ๋ ์ง๊ด์ ์ด๊ณ ๊ด๊ณํ ๋ชจ๋ธ์ ํ์ฉํ๊ธฐ ์ฌ์ ์ต๋๋ค:// Drizzle ORM - db.query ๋ฐฉ์์ผ๋ก ๊ด๊ณ ํ์ฉconst result = await db.query.posts.findMany({ where: eq(posts.published, true), with: { user: true // ๊ฒ์๋ฌผ ์์ฑ์ ์ ๋ณด๋ฅผ ํจ๊ป ์กฐํ }});// ๊ฒฐ๊ณผ ์ ๊ทผ์ด ์ง๊ด์ ์ด๊ณ ํ์ ์์ ํจconsole.log(result[0].title); // ๊ฒ์๋ฌผ ์ ๋ชฉconsole.log(result[0].user.name); // ์์ฑ์ ์ด๋ฆ - ๊ฐ์ฒด ๊ตฌ์กฐ๋ก ๋ช ํํ๊ฒ ๊ตฌ๋ถ๋จ console.log(result[0].user.id); // ์์ฑ์ ID - ๊ฒ์๋ฌผ ID์ ์ด๋ฆ์ด ๊ฐ์๋ ๋ฌธ์ ์์ // Kyselyconst result = await db .selectFrom('posts') .where('posts.published', '=', true) .leftJoin('users', 'posts.userId', 'users.id') .selectAll();// ๊ฒฐ๊ณผ ์ ๊ทผ ์ ์นผ๋ผ ์ด๋ฆ ์ถฉ๋ ๋ฌธ์ console.log(result[0].id) // ์ค๋ฅ: posts.id์ users.id ์ค ์ด๋ค ๊ฒ์ธ์ง ๋ชจํธํจ console.log(result[0].name) // ์ค๋ฅ: ๋ ๋ค name ์นผ๋ผ์ด ์๋ค๋ฉด ๋ชจํธํจ <Drizzle์ ์ ๊ทผ ๋ฐฉ์์ด ํ ์ด๋ธ๊ณผ ์ปฌ๋ผ์ ์ฐธ์กฐํ ๋ ํ์ ์์ ์ฑ์ ๋ ๊ฐ๋ ฅํ๊ฒ ๋ณด์ฅํ๊ณ , ๊ด๊ณ๋ฅผ ํ์ฉํ ์ฟผ๋ฆฌ ์์ฑ์ด ๋ ์ง๊ด์ ์ด์์ต๋๋ค. ํนํ ์ฌ๋ฌ ํ ์ด๋ธ ์กฐ์ธ ์ ๋์ผํ ์ด๋ฆ์ ์นผ๋ผ ์ฒ๋ฆฌ ๋ถ๋ถ์์ Drizzle ORM์ด ํจ์ฌ ๋ ํธ๋ฆฌํ์ต๋๋ค. ์ด๋ ์ ๊ฐ๋ฐ ๊ฒฝํ์์ ๊ฐ์ฅ ์ค์ํ ์ฐจ์ด์ ์ค ํ๋์์ต๋๋ค.// Drizzle ORM - ๋์ผ ์ด๋ฆ ์นผ๋ผ ์ฒ๋ฆฌconst result = await db.query.posts.findMany({ with: { user: true // posts.id์ users.id๊ฐ ๋ชจ๋ ์์ง๋ง ์๋์ผ๋ก ๊ตฌ๋ถ๋จ }});// ๊ฒฐ๊ณผ์ ์์ฐ์ค๋ฝ๊ฒ ์ ๊ทผ ๊ฐ๋ฅ console.log(result[0].id); // ๊ฒ์๋ฌผ ID console.log(result[0].user.id); // ์ฌ์ฉ์ ID - ๋ช ํํ๊ฒ ๊ตฌ๋ถ๋จ console.log(result[0].user.name); // ์ฌ์ฉ์ ์ด๋ฆ // Kysely - ๋์ผ ์ด๋ฆ ์นผ๋ผ ์ฒ๋ฆฌ๋ฅผ ์ํด ๋ณ์นญ ํ์const result = await db .selectFrom('posts') .leftJoin('users', 'posts.userId', 'users.id') .select([ 'posts.id as postId', // ๋ณ์นญ ํ์ 'posts.title', 'posts.content', 'users.id as userId', // ๋ณ์นญ ํ์ 'users.name as userName', // ์นผ๋ผ ์ด๋ฆ์ด ๊ฐ์ ์ ์์ผ๋ฏ๋ก ๋ณ์นญ ํ์ 'users.email as userEmail' // ์ผ๊ด์ฑ์ ์ํด ๋ชจ๋ ์ฌ์ฉ์ ๊ด๋ จ ์นผ๋ผ์ ์ ๋์ด ํ์ ]);// ๋ณ์นญ์ ํตํ ์ ๊ทผconsole.log(result[0].postId); // ๊ฒ์๋ฌผ IDconsole.log(result[0].userId); // ์ฌ์ฉ์ IDconsole.log(result[0].userName); // ์ฌ์ฉ์ ์ด๋ฆ<Drizzle ORM์ ํ ์ด๋ธ๊ณผ ์นผ๋ผ์ ๊ฐ์ฒด๋ก ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์, ๋์ผํ ์ด๋ฆ์ ์นผ๋ผ์ด ์์ด๋ ์์ฐ์ค๋ฝ๊ฒ ๊ณ์ธต ๊ตฌ์กฐ๋ก ์ฒ๋ฆฌ๋๋ฉฐ ํ์ ์ถ๋ก ๋ ์ ํํ๊ฒ ์๋ํฉ๋๋ค. ๋ฐ๋ฉด Kysely์์๋ ๋ฌธ์์ด ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์ ๋๋ฌธ์ ๋ณ์นญ์ ์๋์ผ๋ก ์ง์ ํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๊ณ , ๋ณต์กํ ์กฐ์ธ์์ ์ด๋ฐ ์์ ์ด ๋ฒ๊ฑฐ๋ก์์ก์ต๋๋ค. ํนํ ์ฌ๋ฌ ํ ์ด๋ธ์ ๊ฐ์ ์ด๋ฆ์ ์นผ๋ผ์ด ๋ง์์๋ก ๋ชจ๋ ์นผ๋ผ์ ๋ช ์์ ์ธ ๋ณ์นญ์ ์ง์ ํด์ผ ํ๋ ๋ถํธํจ์ด ์์์ต๋๋ค. ๋ํ Drizzle ORM์ ๊ฒฐ๊ณผ ํ์ ์ ์๋์ผ๋ก ์ ํํ๊ฒ ์ถ๋ก ํด์ฃผ์ด ๋ณ๋์ ํ์ ์ง์ ์์ด๋ ์์ ํ๊ฒ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉํ ์ ์์์ต๋๋ค.Kysely์ ์ฅ์ ๋ฌผ๋ก Kysely๋ ์ฌ๋ฌ ๊ฐ์ ์ด ์์ต๋๋ค:๋ ๊ฐ๋ฒผ์ด ๊ตฌ์กฐ: ํ์ํ ๊ธฐ๋ฅ๋ง ํฌํจํ ์ ์๋ ๋ชจ๋ํ๋ ๊ตฌ์กฐSQL์ ๋ ๊ฐ๊น์ด ์ ๊ทผ: SQL ๊ตฌ๋ฌธ์ ๋งค์ฐ ์ถฉ์คํ API ์ค๊ณ์ ์ฐ์ฑ: ๋ณต์กํ ์ฟผ๋ฆฌ์์ ๋๋ก ๋ ์ ์ฐํ ์์ฑ์ด ๊ฐ๋ฅ<๋ํ ์์ ์ธ๊ธํ๋ฏ์ด, Kysely์ TypeScript ๊ธฐ๋ฐ ๋ง์ด๊ทธ๋ ์ด์ ๊ณผ ์๋ฐฉํฅ(up/down) ๋ง์ด๊ทธ๋ ์ด์ ์ง์์ ํน์ ์ํฉ์์ Drizzle ORM๋ณด๋ค ์ฐ์์ ์๋ ๊ธฐ๋ฅ์ ๋๋ค.SQLAlchemy์์ ๋น๊ต ๋ฐ ์์ผ๋ก์ ๊ธฐ๋ JavaScript/TypeScript ์ํ๊ณ์ ORM์ ์ด์ผ๊ธฐํ๊ธฐ ์ ์, ์ฌ๋ฌ ์ธ์ด ์ค์์๋ Python์ SQLAlchemy๋ ํน๋ณํ ์์น๋ฅผ ์ฐจ์งํฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ์ฌํ ์ฌ์ฉํด๋ณธ ๋ค์ํ ์ธ์ด์ ORM ์ค์์ SQLAlchemy๊ฐ ๊ฐ์ฅ ๊ธฐ๋ฅ์ด ํ๋ถํ๊ณ ๊ฐ๋ ฅํ๋ค๊ณ ๋๊ผ์ต๋๋ค. ๋ณต์กํ ์ฟผ๋ฆฌ ๊ตฌ์ฑ, ๊ณ ๊ธ ๊ด๊ณ ๋งคํ, ํธ๋์ญ์ ๊ด๋ฆฌ, ์ด๋ฒคํธ ์์คํ ๋ฑ SQLAlchemy์ ๊ธฐ๋ฅ์ ์ ๋ง ๋ฐฉ๋ํฉ๋๋ค. Drizzle ORM์ JavaScript ์ํ๊ณ์์ ๋งค์ฐ ์ธ์์ ์ธ ๋ฐ์ ์ ์ด๋ฃจ์์ง๋ง, ์์ง SQLAlchemy์ ๊ฒฝ์ง์๋ ์ด๋ฅด์ง ๋ชปํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํนํ ๋ค์๊ณผ ๊ฐ์ ๋ถ๋ถ์์ SQLAlchemy์ ์ฑ์๋์ ๊ธฐ๋ฅ ํ๋ถํจ์ด ๋๋ณด์ ๋๋ค:๋ณต์กํ ์๋ธ์ฟผ๋ฆฌ์ ์๋์ฐ ํจ์ ์ง์๋ค์ํ ์ด๋ฒคํธ ๋ฆฌ์ค๋์ ํ ๋ค์ํ ์์ ์ ๋ต๋ณต์กํ ํธ๋์ญ์ ๊ด๋ฆฌ์ ์ธ์ ๊ด๋ฆฌ๋๊ท๋ชจ ํ๋ก์ ํธ์์ ๊ฒ์ฆ๋ ์์ ์ฑAlembic์ ํตํ ๋น์ ํ์ ๋ง์ด๊ทธ๋ ์ด์ ์ง์๋๋ผ์ธ ์ ๋๋ก ๋ฐฉ๋ํ๊ณ ์์ธํ ๋ฌธ์ํ<๊ฒฐ๋ก ๋ ORM ๋ชจ๋ ํ๋ฅญํ ๋๊ตฌ์ด์ง๋ง, ์ ๊ฐ๋ฐ ์คํ์ผ๊ณผ ํ๋ก์ ํธ ์๊ตฌ์ฌํญ์๋ Drizzle ORM์ด ๋ ์ ๋ง์์ต๋๋ค. ํนํ ์คํค๋ง ์ ์์ ์ง๊ด์ฑ, ๊ฐ๋ ฅํ ๋ง์ด๊ทธ๋ ์ด์ ๋๊ตฌ, ๊ทธ๋ฆฌ๊ณ ์ ๋ฐ์ ์ธ ๊ฐ๋ฐ์ ๊ฒฝํ ์ธก๋ฉด์์ Drizzle ORM์ด ๋ ์์ฐ์ ์ธ ๊ฐ๋ฐ์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ์์ต๋๋ค. ๋์ผ ์ด๋ฆ ์นผ๋ผ ์ฒ๋ฆฌ์ ๊ฐ์ ์ค์ง์ ์ธ ๋ฌธ์ ์์ Drizzle ORM์ ๊ฐ์ฒด ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ด ๊ฐ์ ธ๋ค์ฃผ๋ ํธ๋ฆฌํจ์ ์ค์ ํ๋ก์ ํธ์์ ํฐ ์ฐจ์ด๋ฅผ ๋ง๋ค์์ต๋๋ค. ORM ์ ํ์ ๊ฒฐ๊ตญ ํ๋ก์ ํธ ํน์ฑ๊ณผ ๊ฐ์ธ ์ ํธ๋์ ํฌ๊ฒ ์ข์ฐ๋ฉ๋๋ค. ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ํ๋ค๋ฉด ๋ ๋๊ตฌ ๋ชจ๋ ๊ฐ๋จํ ํ ์คํธํด๋ณด๊ณ ์์ ์ ์ํฌํ๋ก์ฐ์ ๋ ์ ํฉํ ๊ฒ์ ์ ํํ๋ ๊ฒ์ด ์ข๊ฒ ์ง๋ง, ์ ๊ฒฝ์ฐ์๋ Drizzle ORM์ด ๋ช ํํ ์น์์์ต๋๋ค. ์์ผ๋ก Drizzle ORM์ด ๋์ฑ ๋ฐ์ ํ์ฌ SQLAlchemy ์์ค์ ํ๋ถํ ๊ธฐ๋ฅ๊ณผ ์ ์ฐ์ฑ์ ์ ๊ณตํ๊ฒ ๋๊ธธ ๋ฐ๋๋๋ค. JavaScript/TypeScript ์ํ๊ณ์๋ ๊ทธ๋ฐ ์์ค์ ๊ฐ๋ ฅํ ORM์ด ์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ๋คํํ๋ Drizzle ORM์ ๊ณ์ํด์ ๋ฐ์ ํ๊ณ ์์ผ๋ฉฐ, ๊ทธ ๋ฐ์ ์๋๋ฅผ ๋ณด๋ฉด ๊ธฐ๋๊ฐ ํฝ๋๋ค. ์ฌ๋ฌ๋ถ์ ๊ฒฝํ์ ์ด๋ค๊ฐ์? ๋ค๋ฅธ ORM ๋๊ตฌ๋ ์ธ์ด๋ฅผ ์ฌ์ฉํด๋ณด์ จ๋ค๋ฉด ์๊ฒฌ์ ๊ณต์ ํด์ฃผ์ธ์!
Unpopular opinion might be an overhead but I wish most query builder be immutable by default until they process or execute any non building action. Having to clone a query builder because you need to re-use part of it or create a brand new instance seems anti-POLA (Principle of least astonishment)
Simplifying #MySQL Query Analysis with #Laravel Visual Explains ๐
๐ ๏ธ #Laravel package that transforms complex MySQL EXPLAIN outputs into clear, comprehensible metrics through https://mysqlexplain.com
๐ Features three key #QueryBuilder methods:
Updated my #foss project after a long time! ๐
CHANGELOG
- Minor UI/UX changes.
- Updated readme
DEMO:
https://swapnilmj.github.io/web-vqd/
Project page: https://codeberg.org/swapnilmj/web-vqd
Les ORMs sont rarement la solution qu'il vous faut. Ils apportent quelque chose mais รงa ร un prix que tout le monde n'est pas prรชt ร payer. Je prรฉfรจre de loin les query builders type Knex.js (qui est d'ailleurs utilisรฉ comme base de beaucoup d'ORMs JavaScript). You might not need an ORM https://sometechblog.com/posts/you-might-not-need-an-orm/ #orm โ https://links.kalvn.net/shaare/746Esw
So, I built this web based utility for generating SQL SELECT statements for MySQL. It works, but not tested heavily.
Feedback is welcome ๐