Sonamu๋ BentoCache๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๊ฐ๋ ฅํ ์บ์ฑ ์์คํ
์ ์ ๊ณตํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ, Redis ๋ฑ ๋ค์ํ ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํ๋ฉฐ, ๋ค์ธต ์บ์(L1/L2)์ ๋ถ์ฐ ๋ฌดํจํ๋ฅผ ์ง์ํฉ๋๋ค.
๊ธฐ๋ณธ ๊ตฌ์กฐ
import { defineConfig } from "sonamu";
import { drivers, store } from "sonamu/cache";
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "100mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection })),
},
ttl: "5m",
prefix: "myapp:",
},
},
// ...
});
default
๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ ์บ์ ์คํ ์ด๋ฅผ ์ง์ ํฉ๋๋ค.
ํ์
: string
export default defineConfig({
server: {
cache: {
default: "main", // stores.main ์ฌ์ฉ
stores: {
main: store().useL1Layer(drivers.memory({ maxSize: "100mb" })),
},
},
},
});
์ฌ์ฉํ ์บ์ ์คํ ์ด๋ค์ ์ ์ํฉ๋๋ค.
ํ์
: Record<string, BentoCacheStore>
import { drivers, store } from "sonamu/cache";
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "100mb" })),
distributed: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection }))
.useBus(drivers.redisBus({ connection: redisConnection })),
},
},
},
});
๋จ์ผ ๋ ์ด์ด: ๋ฉ๋ชจ๋ฆฌ
๊ฐ์ฅ ๊ฐ๋จํ ์ค์ ์ผ๋ก, ๋ฉ๋ชจ๋ฆฌ์๋ง ์บ์๋ฅผ ์ ์ฅํฉ๋๋ค.
import { drivers, store } from "sonamu/cache";
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store().useL1Layer(drivers.memory({ maxSize: "100mb" })),
},
ttl: "5m",
},
},
});
์ฅ์ : ๋น ๋ฅธ ์๋, ์ค์ ๊ฐ๋จ
๋จ์ : ์๋ฒ ์ฌ์์ ์ ์บ์ ์์ค, ๋ค์ค ์๋ฒ ๊ฐ ๊ณต์ ๋ถ๊ฐ
๋ค์ธต ์บ์: L1 (๋ฉ๋ชจ๋ฆฌ) + L2 (Redis)
L1์ ๋ฉ๋ชจ๋ฆฌ๋ก ๋น ๋ฅด๊ฒ, L2๋ Redis๋ก ์๊ตฌ์ ์ผ๋ก ์บ์ฑํฉ๋๋ค.
import { drivers, store } from "sonamu/cache";
import { createClient } from "redis";
const redisConnection = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection })),
},
ttl: "1h",
},
},
});
๋์ ๋ฐฉ์:
- ์บ์ ์กฐํ ์ L1(๋ฉ๋ชจ๋ฆฌ) ๋จผ์ ํ์ธ
- L1์ ์์ผ๋ฉด L2(Redis) ํ์ธ
- L2์์ ์ฐพ์ผ๋ฉด L1์๋ ์ ์ฅ
- ๋ ๋ค ์์ผ๋ฉด ์๋ณธ ๋ฐ์ดํฐ ์กฐํ ํ L1, L2์ ์ ์ฅ
๋ถ์ฐ ์บ์: L1 + L2 + Bus
์ฌ๋ฌ ์๋ฒ ๊ฐ ์บ์ ๋ฌดํจํ๋ฅผ ๋๊ธฐํํฉ๋๋ค.
import { drivers, store } from "sonamu/cache";
import { createClient } from "redis";
const redisConnection = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection }))
.useBus(drivers.redisBus({ connection: redisConnection })),
},
ttl: "1h",
},
},
});
๋์ ๋ฐฉ์:
- ํ ์๋ฒ์์ ์บ์๋ฅผ ๋ฌดํจํํ๋ฉด
- Bus๋ฅผ ํตํด ๋ค๋ฅธ ๋ชจ๋ ์๋ฒ์ ์ ํ
- ๋ชจ๋ ์๋ฒ์ L1 ์บ์๋ ์๋ ๋ฌดํจํ
๋ค์ค ์๋ฒ(๋ก๋ ๋ฐธ๋ฐ์ ๋ค)๋ฅผ ์ด์ํ๋ค๋ฉด Bus๋ฅผ ํ์ฑํํ์ธ์. ์บ์ ์ผ๊ด์ฑ์ด ๋ณด์ฅ๋ฉ๋๋ค.
์บ์์ ๊ธฐ๋ณธ ์ ํจ ์๊ฐ(Time To Live)์ ์ค์ ํฉ๋๋ค.
ํ์
: string (์ ํ์ )
๊ธฐ๋ณธ๊ฐ: "5m" (5๋ถ)
export default defineConfig({
server: {
cache: {
default: "main",
stores: { /* ... */ },
ttl: "1h", // 1์๊ฐ
},
},
});
์๊ฐ ํ์:
"5s" - 5์ด
"1m" - 1๋ถ
"1h" - 1์๊ฐ
"1d" - 1์ผ
API๋ณ๋ก ๋ค๋ฅธ TTL ์ฌ์ฉ:
import { cache } from "sonamu";
export class ProductModel {
@cache({ ttl: "10m" }) // 10๋ถ ์บ์
@api()
static async list() {
// ...
}
@cache({ ttl: "1h" }) // 1์๊ฐ ์บ์
@api()
static async detail(id: number) {
// ...
}
}
๋ชจ๋ ์บ์ ํค์ ์ถ๊ฐ๋ ์ ๋์ฌ๋ฅผ ์ค์ ํฉ๋๋ค.
ํ์
: string (์ ํ์ )
๊ธฐ๋ณธ๊ฐ: ""
export default defineConfig({
server: {
cache: {
default: "main",
stores: { /* ... */ },
prefix: "myapp:", // ๋ชจ๋ ํค์ "myapp:" ์ถ๊ฐ
},
},
});
์์:
// prefix: "myapp:"๋ก ์ค์ ์
await cache.set("user:123", data);
// ์ค์ Redis ํค: "myapp:user:123"
๊ฐ์ Redis ์ธ์คํด์ค๋ฅผ ์ฌ๋ฌ ์ฑ์ด ๊ณต์ ํ๋ค๋ฉด prefix๋ฅผ ์ค์ ํ์ฌ ํค ์ถฉ๋์ ๋ฐฉ์งํ์ธ์.
๋๋ผ์ด๋ฒ ์ต์
memory ๋๋ผ์ด๋ฒ
๋ฉ๋ชจ๋ฆฌ์ ์บ์๋ฅผ ์ ์ฅํฉ๋๋ค.
drivers.memory({
maxSize: "100mb", // ์ต๋ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ
})
์ต์
:
maxSize: ์ต๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ("50mb", "100mb", "1gb" ๋ฑ)
redis ๋๋ผ์ด๋ฒ
Redis์ ์บ์๋ฅผ ์ ์ฅํฉ๋๋ค.
import { createClient } from "redis";
const redisConnection = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
password: process.env.REDIS_PASSWORD,
});
drivers.redis({
connection: redisConnection,
})
connection ์ค์ :
const redisConnection = createClient({
url: "redis://localhost:6379",
password: "your-password",
socket: {
connectTimeout: 10000,
},
});
await redisConnection.connect();
redisBus ๋๋ผ์ด๋ฒ
Redis Pub/Sub์ ์ฌ์ฉํ์ฌ ์บ์ ๋ฌดํจํ๋ฅผ ์ ํํฉ๋๋ค.
drivers.redisBus({
connection: redisConnection,
})
redisBus๋ redis ๋๋ผ์ด๋ฒ์ ๊ฐ์ ์ฐ๊ฒฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค์ ์์
๋จ์ผ ์๋ฒ: ๋ฉ๋ชจ๋ฆฌ๋ง ์ฌ์ฉ
import { defineConfig } from "sonamu";
import { drivers, store } from "sonamu/cache";
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store().useL1Layer(drivers.memory({ maxSize: "100mb" })),
},
ttl: "5m",
},
},
// ...
});
์ฉ๋: ์๊ท๋ชจ ์ฑ, ๋จ์ผ ์๋ฒ
๋ค์ธต ์บ์: ๋ฉ๋ชจ๋ฆฌ + Redis
import { defineConfig } from "sonamu";
import { drivers, store } from "sonamu/cache";
import { createClient } from "redis";
const redisConnection = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await redisConnection.connect();
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection })),
},
ttl: "1h",
prefix: "myapp:",
},
},
// ...
});
์ฉ๋: ์ค๊ท๋ชจ ์ฑ, ๋จ์ผ ์๋ฒ, ์๊ตฌ ์บ์ ํ์
๋ถ์ฐ ํ๊ฒฝ: ๋ฉ๋ชจ๋ฆฌ + Redis + Bus
import { defineConfig } from "sonamu";
import { drivers, store } from "sonamu/cache";
import { createClient } from "redis";
const redisConnection = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
password: process.env.REDIS_PASSWORD,
});
await redisConnection.connect();
export default defineConfig({
server: {
cache: {
default: "main",
stores: {
main: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection }))
.useBus(drivers.redisBus({ connection: redisConnection })),
},
ttl: "1h",
prefix: "prod:",
},
},
// ...
});
์ฉ๋: ๋๊ท๋ชจ ์ฑ, ๋ค์ค ์๋ฒ(๋ก๋ ๋ฐธ๋ฐ์), ์บ์ ์ผ๊ด์ฑ ํ์
๋ค์ค ์คํ ์ด: ์ฉ๋๋ณ ๋ถ๋ฆฌ
import { defineConfig } from "sonamu";
import { drivers, store } from "sonamu/cache";
export default defineConfig({
server: {
cache: {
default: "short",
stores: {
// ์งง์ ์บ์ (API ์๋ต)
short: store()
.useL1Layer(drivers.memory({ maxSize: "50mb" })),
// ๊ธด ์บ์ (์ ์ ๋ฐ์ดํฐ)
long: store()
.useL1Layer(drivers.memory({ maxSize: "30mb" }))
.useL2Layer(drivers.redis({ connection: redisConnection })),
},
ttl: "5m",
},
},
// ...
});
์ฌ์ฉ ์์:
import { cache } from "sonamu";
export class DataModel {
// ์งง์ ์บ์ (๊ธฐ๋ณธ ์คํ ์ด)
@cache({ ttl: "1m" })
@api()
static async list() { /* ... */ }
// ๊ธด ์บ์ (long ์คํ ์ด)
@cache({ store: "long", ttl: "1d" })
@api()
static async staticData() { /* ... */ }
}
์บ์ ์ฌ์ฉ
์ค์ ํ API์์ @cache ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
import { api, cache } from "sonamu";
export class ProductModel {
@cache({ ttl: "10m" })
@api()
static async list() {
// ์ฒซ ํธ์ถ: DB ์กฐํ ํ ์บ์ ์ ์ฅ
// ์ดํ 10๋ถ๊ฐ: ์บ์์์ ๋ฐํ
return this.getPuri().select("*");
}
@cache({ key: (id) => `product:${id}`, ttl: "1h" })
@api()
static async detail(id: number) {
// ์ํ๋ณ๋ก 1์๊ฐ ์บ์
return this.findById(id);
}
}
โ ์บ์ ๋ฐ์ฝ๋ ์ดํฐ ์ฌ์ฉ๋ฒ
Redis ์ค์น
Redis๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ ์ค์น๊ฐ ํ์ํฉ๋๋ค.
docker run -d \
--name redis \
-p 6379:6379 \
redis:7
brew install redis
brew services start redis
sudo apt-get install redis-server
sudo systemctl start redis
์ฐ๊ฒฐ ํ์ธ
์ฃผ์์ฌํญ
1. Redis ์ฐ๊ฒฐ ๊ด๋ฆฌ
// โ
์ข์ ์: ์ฐ๊ฒฐ ์ฌ์ฌ์ฉ
const redisConnection = createClient({ /* ... */ });
await redisConnection.connect();
export default defineConfig({
server: {
cache: {
stores: {
main: store()
.useL2Layer(drivers.redis({ connection: redisConnection }))
.useBus(drivers.redisBus({ connection: redisConnection })),
},
},
},
});
2. ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ ์ค์
// ์๋ฒ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ ๋ คํ์ฌ ์ค์
drivers.memory({
maxSize: "100mb", // ์๋ฒ ๋ฉ๋ชจ๋ฆฌ์ 10-20% ์ ๋
})
3. TTL ์ ํ
// ๋ฐ์ดํฐ ๋ณ๊ฒฝ ๋น๋์ ๋ฐ๋ผ ์กฐ์
ttl: "1m" // ์์ฃผ ๋ณ๊ฒฝ๋๋ ๋ฐ์ดํฐ
ttl: "10m" // ์ผ๋ฐ์ ์ธ API ์๋ต
ttl: "1h" // ๊ฑฐ์ ๋ณ๊ฒฝ๋์ง ์๋ ๋ฐ์ดํฐ
ttl: "1d" // ์ ์ ๋ฐ์ดํฐ
๋ค์ ๋จ๊ณ
์บ์ ์ค์ ์ ์๋ฃํ๋ค๋ฉด: