TypeORM ์ž์ฒด ์บ์‹œ ๊ธฐ๋Šฅ ํ™œ์šฉ ๊ฐ€์ด๋“œ (feat. Redis)

seonhyung
  • #typeorm
  • #cache
  • #redis

๋“ค์–ด๊ฐ€๋ฉฐ

์ ์ ˆํ•œ ๊ณณ์— ์บ์‹œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ์ผ์€ ์ค‘์š”ํ•œ ์ผ์ด๋ฉฐ ์–ด๋ ค์šด ์ผ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” TypeORM์— ๋‚ด์žฅ๋œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ Redis์— ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณต์œ ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•˜๋ฉด ์ฝ”๋“œ ์ƒ์—์„œ์˜ ํฐ ๋ณ€๊ฒฝ ์—†์ด ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์บ์‹ฑํ•  ์ˆ˜ ์žˆ์–ด ์ €ํฌ ํŒ€์—์„œ๋„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

TypeORM์— Redis ์„ค์ •ํ•˜๊ธฐ

๊ธฐ๋ณธ์ ์œผ๋กœ TypeORM์€ db์— ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด ์บ์‹ฑํ•˜๋Š” default ์„ค์ • ๊ฐ’์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ €ํฌ๋Š” ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ์œ„ํ•˜์—ฌ Redis์— ์บ์‹œ๋ฅผ ์ €์žฅํ•˜๋Š” ์„ค์ •๊ฐ’์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Redis ์„ค์ •์€ TypeORM ์„ค์ •์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด์™ธ์—๋„ ioredis๋ฅผ ํ™œ์šฉํ•ด cluster ์„ค์ •๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

 cache: {
    type: 'redis',
    options: {
        host: 'localhost',
        port: 6379
    }
}

Cache ์„ค์ •ํ•˜๊ธฐ

์บ์‹œ ์„ค์ •์€ createQueryBuilder๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์™€ find, count ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‘๊ฐ€์ง€ ๊ฒฝ์šฐ ๋ชจ๋‘ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ € createQueryBuilder๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ž…๋‹ˆ๋‹ค. ์ด 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ๊ธฐ๋ณธ ์„ค์ • (๊ธฐ๋ณธ ๋งŒ๋ฃŒ ์‹œ๊ฐ„: 1s)
const posts = await dataSource
  .createQueryBuilder(Post, "post")
  .where("post.isPublic = :isPublic", { isPublic: true })
  .cache(true)
  .getMany();

// ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ • (5000ms)
const posts = await dataSource
  .createQueryBuilder(Post, "post")
  .where("post.isPublic = :isPublic", { isPublic: true })
  .cache(5000)
  .getMany();

// id, ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ • (5000ms)
const posts = await dataSource
  .createQueryBuilder(Post, "post")
  .where("post.isPublic = :isPublic", { isPublic: true })
  .cache("posts_public", 5000)
  .getMany();

find, count ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

// ๊ธฐ๋ณธ ์„ค์ • (๊ธฐ๋ณธ ๋งŒ๋ฃŒ ์‹œ๊ฐ„: 1s)
const posts = await dataSource.getRepository(Post).find({
  where: { isPublic: true },
  cache: true,
});

// id, ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ • (5000ms)
const posts = await dataSource.getRepository(Post).find({
  where: { isPublic: true },
  cache: {
    id: "posts_public",
    milliseconds: 5000,
  },
});

์บ์‹œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ •

์ƒ๊ธฐ ์„ค๋ช…๋Œ€๋กœ TypeORM์—์„œ ์ง€์›ํ•˜๋Š” ์บ์‹œ๋Š” ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์ž์œ ๋กญ๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์‹œ๊ฐ„์€ ์บ์‹ฑํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ์˜ ์„ฑ๊ฒฉ ๋“ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €ํฌ๋Š” ์บ์‹œ ์‹œ๊ฐ„์„ 1์ดˆ๋กœ ์„ค์ •ํ•˜์—ฌ ์บ์‹œ ๋งŒ๋ฃŒ์— ๋Œ€ํ•œ ๊ด€๋ฆฌํฌ์ธํŠธ๋ฅผ ์ค„์ด๋ฉฐ, ๋™์‹œ์— 1์ดˆ ์•ˆ์— ์ ‘์†ํ•˜๋Š” ์ŠคํŒŒ์ดํฌ ํŠธ๋ž˜ํ”ฝ์„ ๋Œ€๋น„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

์ง€๊ธˆ๊นŒ์ง€ TypeORM ์ž์ฒด ์บ์‹œ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•˜์—ฌ ์บ์‹ฑ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. TypeORM์— ์บ์‹œ๋ฅผ ๋„์ž…ํ•˜์‹œ๋ ค๋Š” ๋ถ„๋“ค๊ฒŒ ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ์ž๋ฃŒ

https://orkhan.gitbook.io/typeorm/docs/caching

โ† ๋ชฉ๋ก์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

Art Changes Life

๋…ธ๋จธ์Šค์™€ ํ•จ๊ป˜ ์—”ํ„ฐํ…Œํฌ ์‚ฐ์—…์„ ํ˜์‹ ํ•ด๋‚˜๊ฐˆ ๋ฉค๋ฒ„๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

์ฑ„์šฉ ์ค‘์ธ ๊ณต๊ณ  ๋ณด๊ธฐ