PostgreSQL ์•ˆํ‹ฐํŒจํ„ด: ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํƒ์ƒ‰

์˜ค๋Š˜๋‚  SQL์—๋Š” ๋ณต์žกํ•œ ์‚ฌ๋ก€์™€ ์ •๊ตํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์—†์Šต๋‹ˆ๋‹ค. Captain Obvious ์ˆ˜์ค€์—์„œ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋งค์šฐ ๊ฐ„๋‹จํ•ด์ง‘๋‹ˆ๋‹ค. ํ•ด๋ด…์‹œ๋‹ค. ์ด๋ฒคํŠธ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋ณด๊ธฐ ์‹œ๊ฐ„๋ณ„๋กœ ์ •๋ ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ธฐํ˜ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. events, ๊ทธ๋ฆฌ๊ณ  ๊ทธ๋…€๋Š” ๋ฐญ์„ ๊ฐ–๊ณ  ์žˆ์–ด์š” ts - ์ด๋Ÿฌํ•œ ๊ธฐ๋ก์„ ์ˆœ์„œ๋Œ€๋กœ ํ‘œ์‹œํ•˜๋ ค๋Š” ์ •ํ™•ํ•œ ์‹œ๊ฐ„:

CREATE TABLE events(
  id
    serial
      PRIMARY KEY
, ts
    timestamp
, data
    json
);

CREATE INDEX ON events(ts DESC);

๊ฑฐ๊ธฐ์—๋Š” XNUMX๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์—†์„ ๊ฒƒ์ด ๋ถ„๋ช…ํ•˜๋ฏ€๋กœ ์–ด๋–ค ํ˜•ํƒœ์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ํƒ์ƒ‰.

#0. โ€œ๋‚˜๋Š” ์šฐ๋ฆฌ ์—„๋งˆ์˜ ํ•™์‚ด์ž์˜ˆ์š”โ€

cur.execute("SELECT * FROM events;")
rows = cur.fetchall();
rows.sort(key=lambda row: row.ts, reverse=True);
limit = 26
print(rows[offset:offset+limit]);

๊ฑฐ์˜ ๋†๋‹ด์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋“œ๋ฌผ์ง€๋งŒ ์•ผ์ƒ์—์„œ ๋ฐœ๊ฒฌ๋ฉ๋‹ˆ๋‹ค. ๋•Œ๋กœ๋Š” ORM์œผ๋กœ ์ž‘์—…ํ•œ ํ›„ SQL์„ ์‚ฌ์šฉํ•˜์—ฌ "์ง์ ‘" ์ž‘์—…์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋” ์ผ๋ฐ˜์ ์ด๊ณ  ๋œ ๋ถ„๋ช…ํ•œ ๋ฌธ์ œ๋กœ ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

#1. ์˜คํ”„์…‹

SELECT
  ...
FROM
  events
ORDER BY
  ts DESC
LIMIT 26 OFFSET $1; -- 26 - ะทะฐะฟะธัะตะน ะฝะฐ ัั‚ั€ะฐะฝะธั†ะต, $1 - ะฝะฐั‡ะฐะปะพ ัั‚ั€ะฐะฝะธั†ั‹

์ˆซ์ž 26์€ ์–ด๋””์—์„œ ์™”์Šต๋‹ˆ๊นŒ? ์ด๋Š” ํ•œ ํ™”๋ฉด์„ ์ฑ„์šฐ๋Š” ๋Œ€๋žต์ ์ธ ํ•ญ๋ชฉ ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ๋Š” 25๊ฐœ์˜ ํ‘œ์‹œ๋œ ๋ ˆ์ฝ”๋“œ์— 1์„ ๋”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์ƒ˜ํ”Œ์— ์ตœ์†Œํ•œ ๋‹ค๋ฅธ ํ•ญ๋ชฉ์ด ๋” ์žˆ์œผ๋ฏ€๋กœ ๊ณ„์† ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๋ผ๋Š” ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ด ๊ฐ’์€ ์š”์ฒญ ๋ณธ๋ฌธ์— "๊ฟฐ์–ด์งˆ" ์ˆ˜ ์—†์œผ๋ฉฐ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๊ฒฝ์šฐ PostgreSQL ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์ƒ๋Œ€์ ์œผ๋กœ ์ ์€ ์ˆ˜์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ง€์‹์— ์˜์กดํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ์‰ฝ๊ฒŒ ๋น„ํšจ์œจ์ ์ธ ๊ณ„ํš์„ ์„ ํƒํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋ณด๊ธฐ๋Š” ์‹œ๊ฐ์  "ํŽ˜์ด์ง€" ๊ฐ„ ์ „ํ™˜์œผ๋กœ ๊ตฌํ˜„๋˜๋ฏ€๋กœ ์˜ค๋žซ๋™์•ˆ ์•„๋ฌด๋„ ์˜์‹ฌ์Šค๋Ÿฌ์šด ์ ์„ ๋ˆˆ์น˜์ฑ„์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํŽธ์˜์„ฑ์„ ์œ„ํ•ด UI/UX๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ "๋์—†๋Š” ์Šคํฌ๋กค"๋กœ ๋‹ค์‹œ ๋งŒ๋“ค๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ๋ฐ”๋กœ ๊ทธ ์ˆœ๊ฐ„๊นŒ์ง€ ๋ง์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋ชจ๋“  ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํ•ญ๋ชฉ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์œ„์•„๋ž˜๋กœ ์Šคํฌ๋กคํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ผ ๋ชฉ๋ก์— ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์—์„œ ๋‹น์‹ ์€ ์žกํ˜”์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ก์˜ ๋ณต์ œ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์—์„œ. ์ด์œ ๋Š” ํ…Œ์ด๋ธ”์— ์ผ๋ฐ˜ ์ธ๋ฑ์Šค๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. (ts), ๊ท€ํ•˜์˜ ์ฟผ๋ฆฌ๋Š” ๋ฌด์—‡์— ์˜์กดํ•ฉ๋‹ˆ๊นŒ?

์ •ํ™•ํžˆ๋Š” ๋‹น์‹ ์ด ๊ทธ ์ ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค ts ๊ณ ์œ  ํ‚ค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด ํ…Œ์ด๋ธ”์—. ์‚ฌ์‹ค, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ฐ’์€ ๊ณ ์œ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค, ์‹ค์ œ ์กฐ๊ฑด์˜ "์‹œ๊ฐ„"๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋™์ผํ•œ ํ‚ค ๊ฐ’์„ ์ •๋ ฌํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ๋‚ด์—์„œ ์ตœ์ข… ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ ‘ํ•œ ๋‘ ์ฟผ๋ฆฌ์˜ ๋™์ผํ•œ ๋ ˆ์ฝ”๋“œ๊ฐ€ ํŽ˜์ด์ง€์—์„œ ํŽ˜์ด์ง€๋กœ ์‰ฝ๊ฒŒ "์ ํ”„"๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์‹ค ์—ฌ๊ธฐ์—๋Š” ํ›จ์”ฌ ๋” ๋ˆˆ์— ๋„๊ธฐ ์–ด๋ ค์šด ๋‘ ๋ฒˆ์งธ ๋ฌธ์ œ๊ฐ€ ์ˆจ๊ฒจ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ถ€ ํ•ญ๋ชฉ์€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ์กฐ๊ธˆ๋„! ๊ฒฐ๊ตญ "์ค‘๋ณต" ๊ธฐ๋ก์ด ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ ์ž๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•˜๊ฒŒ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ฆ„๋‹ค์šด ์‚ฌ์ง„๊ณผ ํ•จ๊ป˜ ์ž์„ธํ•œ ์„ค๋ช…์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ์—ฌ๊ธฐ๋ฅผ ์ฝ์œผ์‹ญ์‹œ์˜ค..

์ธ๋ฑ์Šค ํ™•์žฅ

๊ตํ™œํ•œ ๊ฐœ๋ฐœ์ž๋Š” ์ธ๋ฑ์Šค ํ‚ค๋ฅผ ๊ณ ์œ ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋ฉฐ ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ๋ถ„๋ช…ํžˆ ๊ณ ์œ ํ•œ ํ•„๋“œ๋กœ ์ธ๋ฑ์Šค ํ‚ค๋ฅผ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. PK๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

CREATE UNIQUE INDEX ON events(ts DESC, id DESC);

๊ทธ๋ฆฌ๊ณ  ์š”์ฒญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.

SELECT
  ...
ORDER BY
  ts DESC, id DESC
LIMIT 26 OFFSET $1;

#2. "์ปค์„œ"๋กœ ์ „ํ™˜

์–ผ๋งˆ ํ›„ DBA๊ฐ€ ๊ท€ํ•˜์—๊ฒŒ ์™€์„œ ๊ท€ํ•˜์˜ ์š”์ฒญ์— "๊ธฐ๋ปํ•ฉ๋‹ˆ๋‹ค" ๊ทธ๋“ค์€ OFFSET ๊ทœ์น™์œผ๋กœ ์„œ๋ฒ„๋ฅผ ์ง€์˜ฅ์ฒ˜๋Ÿผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค., ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ์œผ๋กœ ์ „ํ™˜ํ•ด์•ผ ํ•  ๋•Œ์ž…๋‹ˆ๋‹ค. ํ‘œ์‹œ๋œ ๋งˆ์ง€๋ง‰ ๊ฐ’์—์„œ ํƒ์ƒ‰. ์ฟผ๋ฆฌ๊ฐ€ ๋‹ค์‹œ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

SELECT
  ...
WHERE
  (ts, id) < ($1, $2) -- ะฟะพัะปะตะดะฝะธะต ะฟะพะปัƒั‡ะตะฝะฝั‹ะต ะฝะฐ ะฟั€ะตะดั‹ะดัƒั‰ะตะผ ัˆะฐะณะต ะทะฝะฐั‡ะตะฝะธั
ORDER BY
  ts DESC, id DESC
LIMIT 26;

์˜ค๊ธฐ ์ „๊นŒ์ง€ ์•ˆ๋„์˜ ํ•œ์ˆจ์„ ์‰ฌ์…จ๋Š”๋ฐ...

#์‚ผ. ์ธ๋ฑ์Šค ์ฒญ์†Œ

์–ด๋Š ๋‚  ๋‹น์‹ ์˜ DBA๊ฐ€ ์ฝ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋น„ํšจ์œจ์ ์ธ ์ธ๋ฑ์Šค ์ฐพ๊ธฐ์— ๋Œ€ํ•œ ๊ธฐ์‚ฌ ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฑธ ๊นจ๋‹ฌ์•˜๋‹ค "์ตœ์‹ ์ด ์•„๋‹˜" ํƒ€์ž„์Šคํƒฌํ”„๊ฐ€ ์ข‹์ง€ ์•Š์Œ. ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ๋‹ค์‹œ ๋‹น์‹ ์—๊ฒŒ ์™”์Šต๋‹ˆ๋‹ค. ์ด์ œ ๊ทธ ์ง€์ˆ˜๋Š” ์—ฌ์ „ํžˆ ๋‹ค์‹œ (ts DESC).

๊ทธ๋Ÿฌ๋‚˜ ํŽ˜์ด์ง€ ์‚ฌ์ด์— ๋ ˆ์ฝ”๋“œ๋ฅผ "์ ํ”„"ํ•˜๋Š” ์ดˆ๊ธฐ ๋ฌธ์ œ๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ• ๊นŒ์š”?.. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ ˆ์ฝ”๋“œ ์ˆ˜๊ฐ€ ๊ณ ์ •๋˜์ง€ ์•Š์€ ๋ธ”๋ก์„ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!

์ผ๋ฐ˜์ ์œผ๋กœ "์ •ํ™•ํžˆ 26"์ด ์•„๋‹ˆ๋ผ "26 ์ด์ƒ"์„ ์ฝ๋Š” ๊ฒƒ์„ ๋ˆ„๊ฐ€ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ๋ธ”๋ก์—๋Š” ๋‹ค์Œ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช…๋ฐฑํžˆ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ์ง€๋‹Œ ๊ธฐ๋ก ts - ๊ทธ๋Ÿฌ๋ฉด ๋ธ”๋ก ์‚ฌ์ด์˜ ๊ธฐ๋ก์„ "์ ํ”„"ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค!

์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

SELECT
  ...
WHERE
  ts < $1 AND
  ts >= coalesce((
    SELECT
      ts
    FROM
      events
    WHERE
      ts < $1
    ORDER BY
      ts DESC
    LIMIT 1 OFFSET 25
  ), '-infinity')
ORDER BY
  ts DESC;

์—ฌ๊ธฐ์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š” ๊ฑธ๊นŒ์š”?

  1. 25๊ฐœ์˜ ๋ ˆ์ฝ”๋“œ๋ฅผ "์•„๋ž˜๋กœ" ๋‹จ๊ณ„ํ™”ํ•˜๊ณ  "๊ฒฝ๊ณ„" ๊ฐ’์„ ์–ป์Šต๋‹ˆ๋‹ค. ts.
  2. ์ด๋ฏธ ์•„๋ฌด๊ฒƒ๋„ ์—†์œผ๋ฉด NULL ๊ฐ’์„ ๋‹ค์Œ์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. -infinity.
  3. ๋ฐ›์€ ๊ฐ’ ์‚ฌ์ด์—์„œ ์ „์ฒด ๊ฐ’ ์„ธ๊ทธ๋จผํŠธ๋ฅผ ๋บ๋‹ˆ๋‹ค. ts ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ „๋‹ฌ๋œ $1 ๋งค๊ฐœ๋ณ€์ˆ˜(์ด์ „์˜ "๋งˆ์ง€๋ง‰" ๋ Œ๋”๋ง๋œ ๊ฐ’)์ž…๋‹ˆ๋‹ค.
  4. 26๊ฐœ ๋ฏธ๋งŒ์˜ ๋ ˆ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ๋ธ”๋ก์ด ๋ฐ˜ํ™˜๋˜๋ฉด ์ด๊ฒƒ์ด ๋งˆ์ง€๋ง‰ ๋ธ”๋ก์ž…๋‹ˆ๋‹ค.

์•„๋‹ˆ๋ฉด ๊ฐ™์€ ์‚ฌ์ง„:
PostgreSQL ์•ˆํ‹ฐํŒจํ„ด: ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ํƒ์ƒ‰

์™œ๋ƒ๋ฉด ์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” ์ƒ˜ํ”Œ์—๋Š” ํŠน์ • "์‹œ์ž‘"์ด ์—†์Šต๋‹ˆ๋‹ค., ๊ทธ๋Ÿฌ๋ฉด ์ด ์š”์ฒญ์„ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ "ํ™•์žฅ"ํ•˜๊ณ  "์ฐธ์กฐ ์ง€์ "์—์„œ ์–‘๋ฐฉํ–ฅ(์•„๋ž˜์ชฝ๊ณผ ์œ„์ชฝ ๋ชจ๋‘)์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ธ”๋ก์˜ ๋™์  ๋กœ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉํ•ดํ•˜๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  :

  1. ์˜ˆ, ์ด ๊ฒฝ์šฐ ์ธ๋ฑ์Šค์— ๋‘ ๋ฒˆ ์•ก์„ธ์Šคํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ฒƒ์ด "์ˆœ์ „ํžˆ ์ธ๋ฑ์Šค ๊ธฐ์ค€"์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•˜์œ„ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ถ”๊ฐ€ ์ธ๋ฑ์Šค ์ „์šฉ ์Šค์บ”์—.
  2. ์ด ๊ธฐ์ˆ ์€ ๊ฐ’์ด ์žˆ์„ ๋•Œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค. ts ์šฐ์—ฐํžˆ๋งŒ ๊ฑด๋„ˆ๊ฐˆ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ์ค‘ ๋งŽ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์‚ฌ๋ก€๊ฐ€ "00:00:00.000์— ๋ ˆ์ฝ”๋“œ ๋ฐฑ๋งŒ ๊ฐœ"์ธ ๊ฒฝ์šฐ์—๋Š” ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋‚ด ๋ง์€, ๊ทธ๋Ÿฐ ์ผ์ด ์ผ์–ด๋‚˜๋„๋ก ๋†”๋‘ฌ์„œ๋Š” ์•ˆ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋ฉด ํ™•์žฅ ์ธ๋ฑ์Šค๊ฐ€ ์žˆ๋Š” ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€