๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
WIL

GraphQL๊ณผ N + 1 ๋ฌธ์ œ

by Jaeguk 2024. 2. 27.

์ฐพ์•„๋ณด๊ฒŒ ๋œ ๊ณ„๊ธฐ


ํ˜„์žฌ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ, ๋ฐฑ์—”๋“œ์™€ ํ”„๋ก ํŠธ์—”๋“œ๊ฐ„์˜ ์˜์กด๋„๋ฅผ ๋–จ์–ดํŠธ๋ฆฌ๊ณ ์ž GraphQL์„ ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค

  • GraphQL์„ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋ก ํŠธ์ธก์—์„œ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด๊ฐ€๋Š” ํ˜•์‹์ด๊ธฐ ๋•Œ๋ฌธ์—, RestAPI์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์•„๋„ ๋˜๊ธฐ ๋–„๋ฌธ์ด๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ GraphQL์„ ์‚ฌ์šฉํ•˜๋ฉด Resolver๊ฐ€ ์—ฐ์‡„์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” N + 1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋นˆ๋ฒˆํ•˜๋‹ค๊ณ  ํ•ด์„œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ์œ„ํ•ด ์•Œ์•„๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค.

 

N + 1 ๋ฌธ์ œ๋ž€?


1๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด์„œ ์ฐธ์กฐํ•˜๋Š” ๋ฐ์ดํ„ฐ N๊ฐœ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค N + 1 ๋ฒˆ์˜ ์ฟผ๋ฆฌ ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•˜๋‚˜์˜ ๋ธ”๋กœ๊ทธ์— 3๊ฐœ์˜ ๋Œ“๊ธ€์ด ์ž‘์„ฑ๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž.
  • ์ด๋•Œ, ๋ธ”๋กœ๊ทธ์™€ ๋Œ“๊ธ€์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š” SQL์˜ Join์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐ€ํ•ด๋ณด๋ฉด ๋ถ„๋ช… 1๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ์ถฉ๋ถ„ํ•˜๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ GraphQL์˜ Resolver๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ๋ธ”๋กœ๊ทธ์— ๋Œ€ํ•œ ๊ธ€์„ ๋จผ์ € ๊ฐ€์ ธ์˜ค๊ณ , ๋Œ“๊ธ€ ๊ฐ๊ฐ์— ๋Œ€ํ•ด์„œ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ค์„œ ๋Œ“๊ธ€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ ์ด 4๋ฒˆ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๊ฒƒ์ด N + 1 ๋ฌธ์ œ์ด๋‹ค.
  • Spring์˜ JPA์—์„œ๋Š” ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ํ•  ๊ฒฝ์šฐ์— ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

  • ์‹ค์ œ ์ง„ํ–‰์ค‘์ธ ํ”„๋กœ์ ํŠธ์—์„œ ๋กœ๊ทธ๋ฅผ ์ฐ์–ด๋ณธ ๊ฒฐ๊ณผ ์ •๋ง ์—ฌ๋Ÿฌ๋ฒˆ์˜ ์ฟผ๋ฆฌ๊ฐ€ ๋‚ ์•„๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
  • ํ•˜๋‚˜์˜ ์—”ํ‹ฐํ‹ฐ๊ฐ€ 5๊ฐœ์˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์˜€์Œ

 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•?


๊ทธ๋ ‡๋‹ค๋ฉด N + 1 ๋ฌธ์ œ๋ฅผ ์–ด๋–ค ์‹์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ?

  • ์ผ๋‹จ ํ˜„์žฌ ์šฐ๋ฆฌ๋Š” ๋ชฝ๊ณ  DB๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ชฝ๊ณ  DB ์‚ฌ์šฉ์„ ์ „์ œ๋กœ ์ฐพ์•„๋ณด์•˜๋‹ค.
  • ๊ทธ๋ ‡๊ฒŒ ํ–ˆ์„ ๋•Œ ํฌ๊ฒŒ 2๊ฐ€์ง€ ์ •๋„์˜ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์ด ์•Œ๋ ค์ ธ ์žˆ์—ˆ๋‹ค.
  1. Mongoose์˜ Populate ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ
  2. Dataloader ์‚ฌ์šฉ

 

Dataloader ?


Dataloader๋ž€ ๋ฌด์—‡์ผ๊นŒ?

๋ฐ์ดํ„ฐ๋กœ๋”๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ๋ชจ์•„์„œ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.
GraphQL์— ํ•œ์ •๋œ ๊ฐœ๋…์€ ์•„๋‹ˆ์ง€๋งŒ, GraphQL์—์„œ N + 1 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์ด ์‚ฌ์šฉ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

์ฟผ๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€, ์ฟผ๋ฆฌ๋ฅผ ๋ชจ์•„๋’€๋‹ค๊ฐ€ $in [id1, id2, id3, id4] ์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋ฉด ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ๋ฐฐ์น˜(batch)๋ผ๊ณ  ํ•œ๋‹ค.

 

GitHub - graphql/dataloader: DataLoader is a generic utility to be used as part of your application's data fetching layer to pro

DataLoader is a generic utility to be used as part of your application's data fetching layer to provide a consistent API over various backends and reduce requests to those backends via batching...

github.com

 

๊ณ ๋ฏผํ–ˆ๋˜ ๋ถ€๋ถ„


๊ทธ๋ ‡๊ฒŒ ์šฐ๋ฆฌ๋Š” N + 1 ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฐ์ดํ„ฐ๋กœ๋”๋ฅผ ๋„์ž…ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ ํ—ท๊ฐˆ๋ ธ๋˜ ๋ถ€๋ถ„์ด ์žˆ๋‹ค.

๋‚˜๋Š” MongoDB๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ฒ˜์Œ์ด๋ผ, MongoDB์—์„œ๋Š” ์ฐธ์กฐํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ค ์‹์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๋Š”์ง€ ๊ถ๊ธˆํ–ˆ๋‹ค.
MySQL์˜ ๊ฒฝ์šฐ์—๋Š” Join์œผ๋กœ ์ฐธ์กฐํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, MongoDB์—์„œ๋Š” ์–ด๋–ค ์‹์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๋Š”์ง€๋ฅผ ๋ชฐ๋ž๋‹ค.

๋ชฝ๊ตฌ์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” populate() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐธ์กฐํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.๊ทธ๋ ‡๋‹ค๋ฉด, ๋ชฝ๊ตฌ์Šค์˜ populate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ฐ์ดํ„ฐ๋กœ๋”๋Š” ์–ด๋””์— ๋„์ž…ํ•ด์•ผ ํ•˜๋Š” ๊ฑธ๊นŒ?

๊ตฌ๊ธ€์— ๋‚˜์™€์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์˜ˆ์‹œ์—๋Š” ๋ฐ์ดํ„ฐ๋กœ๋”๋Š” Resolver๋‹จ์— ๋„์ž…ํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์„œ๋น„์Šค๋‹จ์—์„œ populate() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜จ ์ƒํƒœ์ผํ…๋ฐ ๋ฐ์ดํ„ฐ๋กœ๋”๋Š” ์–ด๋””์— ์“ฐ์ด๋Š”์ง€๊ฐ€ ์˜๋ฌธ์ด์—ˆ๋‹ค.

 

Mongoose Populate


๊ทธ ์ „์— Mongoose์˜ Populate๋Š” ์–ด๋–ค ๋ฉ”์„œ๋“œ์ธ์ง€ ๋จผ์ € ์•Œ์•„๋ณด์•˜๋‹ค.

๋ชฝ๊ตฌ์Šค ๊ณต์‹๋ฌธ์„œ๋ฅผ ํ†ตํ•ด์„œ populate๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€, ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์€ ์–ด๋–ค ๊ฒƒ๋“ค์ด ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์•˜๋‹ค.

 

Population


3.2 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” $lookup์ด๋ผ๋Š” operator๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™”์ง€๋งŒ, 3.2 ์ดํ›„ ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” populate() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐธ์กฐํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

const mongoose = require('mongoose');
const {Schema } = mongoose;

const personSchema =Schema({
  _id:Schema.Types.ObjectId,
  name:String,
  age:Number,
  stories: [{ type:Schema.Types.ObjectId, ref: 'Story' }]
});

const storySchema =Schema({
  author: { type:Schema.Types.ObjectId, ref: 'Person' },
  title:String,
  fans: [{ type:Schema.Types.ObjectId, ref: 'Person' }]
});

constStory = mongoose.model('Story', storySchema);
constPerson = mongoose.model('Person', personSchema);
  • Person์€ id๊ฐ’์„ ์ด์šฉํ•ด์„œ Story๋ฅผ ์ฐธ์กฐ
  • Story๋Š” id๊ฐ’์„ ์ด์šฉํ•ด์„œ Person ๊ฐ์ฒด๋ฅผ author, fans๋ผ๋Š” ์ด๋ฆ„์˜ ํ•„๋“œ๋กœ ์ฐธ์กฐ

 

์‚ฌ์šฉ๋ฒ•

const story =awaitStory.
findOne({ title: 'Casino Royale' }).
populate('author').
exec();
// prints "The author is Ian Fleming"
console.log('The author is %s', story.author.name);
  • populate()๋ฅผ ์ด์šฉํ•ด์„œ Story์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” author์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  • title์ด 'Casino Royale'์ธ Story๋ฅผ author(Person) ์ •๋ณด์™€ ํ•จ๊ป˜ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋œ๋‹ค.

 

Field Selection


์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋Œ€์ƒ์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๊ฐ€์ ธ์˜ฌ ํ•„์š”๊ฐ€ ์—†์„ ๋•Œ, ์›ํ•˜๋Š” ํ•„๋“œ๋ช…์„ ์ง€์ • ํ•  ์ˆ˜ ์žˆ๋‹ค.

const story =awaitStory.
findOne({ title: /casino royale/i }).
populate('author', 'name').
exec();// only return the Persons name
// prints "The author is Ian Fleming"
console.log('The author is %s', story.author.name);
// prints "The authors age is null"
console.log('The authors age is %s', story.author.age);
  • author์— ๋Œ€ํ•ด์„œ name ์ •๋ณด๋งŒ ๊ฐ€์ ธ์˜ค๊ฒ ๋‹ค๊ณ  ๋ช…์‹œ
  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— age๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด null๊ฐ’์ด ๋“ค์–ด์žˆ๋‹ค.

 

Multiple Paths


Story์˜ ๊ฒฝ์šฐ์—๋Š” author, fans ๋‘๊ฐœ์˜ ํ•„๋“œ์—์„œ Person ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ๋งŒ์•ฝ ๋‘ ํ•„๋“œ ๋ชจ๋‘ ์ฐธ์กฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด populate()๋ฅผ ์—ฐ๋‹ฌ์•„์„œ ์“ฐ๋ฉด ๋œ๋‹ค.

await Story.
    find({/* ... */ }).
    populate('fans').
    populate('author').
    exec();
  • fans, author ๋ชจ๋‘ ์ฐธ์กฐํ•ด์„œ ๊ฐ€์ ธ์˜จ๋‹ค.

๋‹จ, ๊ฐ™์€ path์— ๋Œ€ํ•ด์„œ ์—ฌ๋Ÿฌ๋ฒˆ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆด ๊ฒฝ์šฐ, ๋งˆ์ง€๋ง‰์— ์š”์ฒญํ•œ ์ฟผ๋ฆฌ๋งŒ ์ธ์ •๋œ๋‹ค.

// The 2nd `populate()` call below overwrites the first because they// both populate 'fans'.awaitStory.
find().
populate({ path: 'fans', select: 'name' }).
populate({ path: 'fans', select: 'email' });
// The above is equivalent to:awaitStory.find().populate({ path: 'fans', select: 'email' });
  • ์œ„์˜ ์˜ˆ์‹œ์—์„œ fans์— ๋Œ€ํ•ด 2๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ์š”์ฒญํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ดํ›„์— ์š”์ฒญํ•œ email์ •๋ณด๋งŒ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ ๋œ๋‹ค.

 

N + 1 Problem ?


populate()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด N + 1 ๋ฌธ์ œ๊ฐ€ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ๋ ๊นŒ

  • ๋” ๋‚˜์€ ์ดํ•ด๋ฅผ ์œ„ํ•ด์„œ ๊ณต์‹๋ฌธ์„œ์™€๋Š” ๋‹ค๋ฅธ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ–ˆ๋‹ค.
 

N+1 Problem in MongoDB

์ธํ”„๋Ÿฐ์˜ ํ•ด๋‹น ๊ฐ•์ขŒ๋ฅผ ํ•™์Šตํ•˜๋ฉฐ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.ํ•ด๋‹น ์ด๋ฏธ์ง€๋Š” ๋ชจ๋“  Blog์˜ ๋ชฉ๋ก์„ ์กฐํšŒํ–ˆ์„ ๋•Œ, Blog๊ฐ€ ์ด 2๊ฐœ์ด๊ณ  ๊ฐ๊ฐ์˜ Blog๋‚ด์— 3๊ฐœ์˜ ๋Œ“๊ธ€์ด ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.์ด 2๊ฐœ์˜ Blog๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒฝ์šฐ

velog.io

 

์œ„์˜ ๋ธ”๋กœ๊ทธ์˜ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด N + 1 ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  • ํ˜„์žฌ DB์—๋Š” 2๊ฐœ์˜ ๋ธ”๋กœ๊ทธ๊ฐ€ ์กด์žฌํ•˜๊ณ , ๊ฐ ๋ธ”๋กœ๊ทธ์—๋Š” 3๊ฐœ์˜ ๋Œ“๊ธ€์ด ๋‹ฌ๋ ค์žˆ๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•œ๋‹ค.
  • ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ •๋ณด๋Š” 2๊ฐœ์˜ ๋ธ”๋กœ๊ทธ, ํ•ด๋‹น ๋ธ”๋กœ๊ทธ์˜ ๋Œ“๊ธ€๋“ค, ๊ทธ๋ฆฌ๊ณ  ๋Œ“๊ธ€์˜ ์ž‘์„ฑ์ž์— ๋Œ€ํ•œ ์ •๋ณด์ด๋‹ค.

 

  • populate๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ ์ด 9๋ฒˆ์˜ ์ฟผ๋ฆฌ๋ฅผ ์š”์ฒญํ•ด์•ผ ํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๋ธ”๋กœ๊ทธ์˜ ์ˆ˜๊ฐ€ ๋” ๋งŽ์•˜๊ฑฐ๋‚˜, ๋Œ“๊ธ€์˜ ์ˆ˜๊ฐ€ ๋” ๋งŽ์•˜๋‹ค๋ผ๋ฉด ๊ทธ์— ๋”ฐ๋ผ ์ฟผ๋ฆฌ์˜ ์ˆ˜๊ฐ€ ๊ธ‰์ˆ˜์ ์œผ๋กœ ๋Š˜์–ด๋‚  ๊ฒƒ์ด๋‹ค.
  • ๋˜ํ•œ ๊ฐ™์€ ์œ ์ €๊ฐ€ ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, ๋งค๋ฒˆ ์ฟผ๋ฆฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ๋น„ํšจ์œจ์ ์ด๋‹ค.

 

populate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด blogId ๋˜๋Š” userId๋ฅผ ์ทจํ•ฉํ•ด์„œ $in ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•œ๋‹ค

  • ๋”ฐ๋ผ์„œ ๋ธ”๋กœ๊ทธ์˜ ์ˆ˜๋‚˜ ๋Œ“๊ธ€์˜ ์ˆ˜๊ฐ€ ๋งŽ์•„๋„ ํ•œ ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๋œ๋‹ค.
  • popluate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ์˜ ์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ณ , ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์™€์˜ ํ†ต์‹  ํšŸ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋ณด๋‹ค ์ฟผ๋ฆฌ๋ฅผ ๋” ์ค„์ด๋ ค๋ฉด Embed ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜์ง€๋งŒ, Embed ๋ฐฉ์‹์€ Update์‹œ์— ์„ฑ๋Šฅ์ด ์ €ํ•˜๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์ž˜ ์ƒ๊ฐํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

Dataloader vs Populate


๊ทธ๋ ‡๋‹ค๋ฉด Dataloader์™€ Populate ์ค‘์— ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

์‚ฌ์‹ค ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋ช‡ ๊ฐ€์ง€ ๊ธ€์„ ์ฐพ์•„๋ณด์•˜์ง€๋งŒ, ๋ช…์พŒํ•˜๊ฒŒ ์ด๊ฒŒ ๋” ์ข‹์œผ๋‹ˆ๊นŒ ์ด๊ฑธ ์‚ฌ์šฉํ•˜์„ธ์š”! ๋ผ๊ณ  ํ•˜๋Š” ๊ธ€์€ ์—†์—ˆ๋‹ค.
๊ทธ ์ด์œ ๋Š” ์•„๋งˆ ๋‘ ๊ฐœ๊ฐ€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜์ง€๋งŒ, ์™„์ „ํžˆ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜์ง€ ์•Š๊ณ  ์ƒํ™ฉ๋งˆ๋‹ค ์„ ํƒํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ผ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค.

  • Populate๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์ฟผ๋ฆฌ์˜ ์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ณ , ์‚ฌ์šฉ๋ฒ•์ด ๋‹จ์ˆœํ•˜๊ณ  ๊ฐ„๋‹จํ•œ๋‹ค.
    • ํ•˜์ง€๋งŒ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋˜ํ•œ ๋ฏธ๋ฆฌ ์„œ๋น„์Šค๋‹จ์—์„œ populate๋ฅผ ๊ฑธ์–ด๋‘๋ฉด ํด๋ผ์ด์–ธํŠธ์ธก overfetching ๋ฌธ์ œ๋Š” GraphL์„ ํ†ตํ•ด ํ•ด๊ฒฐ๋ ์ง€๋ผ๋„,
      ์„œ๋ฒ„๋‹จ์—์„œ overfetching ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • Dataloader๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฟผ๋ฆฌ๋ฅผ ๋ชจ์•„์„œ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ณ , ๋ฏธ๋ฆฌ ๋กœ๋“œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต๋œ ์ฟผ๋ฆฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
    • ํ•˜์ง€๋งŒ ์บ์‹ฑ์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ์—, ์›๋ณธ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋”๋ผ๋„ ์บ์‹ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜์˜์ด ์•ˆ ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค.
    • ๋˜ํ•œ ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ ์›น ์„œ๋ฒ„์—์„œ๋Š” ๋งค ์š”์ฒญ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋กœ๋” ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.
728x90

'WIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Two-Phase Locking (2PL)  (0) 2024.05.10
๋ ˆ์ธ๋ณด์šฐ ํ…Œ์ด๋ธ”  (0) 2024.05.01
๋ฌด์ƒํƒœ ํ”„๋กœํ† ์ฝœ  (1) 2024.03.08