{"id":2678,"date":"2026-10-24T09:04:09","date_gmt":"2026-10-24T09:04:09","guid":{"rendered":"https:\/\/wayhope.kro.kr\/?p=2678"},"modified":"2026-10-24T09:04:09","modified_gmt":"2026-10-24T09:04:09","slug":"%ea%b2%8c%ec%9e%84-%ea%b2%bd%ec%a0%9c-%eb%b0%8f-%ec%a0%95%ec%82%b0-%ed%8f%ac%ec%9d%b8%ed%8a%b8-%ec%95%84%ec%9d%b4%ed%85%9c-%ea%b5%ac%eb%a7%a4-%eb%b3%b4%ec%83%81-%ec%a7%80%ea%b8%89%ec%9d%98","status":"publish","type":"post","link":"https:\/\/wayhope.kro.kr\/?p=2678","title":{"rendered":"\uac8c\uc784 \uacbd\uc81c \ubc0f \uc815\uc0b0 #\ud3ec\uc778\ud2b8, \uc544\uc774\ud15c \uad6c\ub9e4, \ubcf4\uc0c1 \uc9c0\uae09\uc758 \uc2e0\ub8b0\uc131 \uc124\uacc4"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uc11c\ubc84\uc5d0\uc11c \ud3ec\uc778\ud2b8 \ucc28\uac10, \uc544\uc774\ud15c \uad6c\ub9e4, \uac8c\uc784 \uacb0\uacfc\uc5d0 \ub530\ub978 \ubcf4\uc0c1 \uc9c0\uae09\uc740 \ub2e8\uc21c\ud55c \ub370\uc774\ud130 \ubcc0\uacbd\uc774 \uc544\ub2c8\ub2e4. \uc5ec\ub7ec \uc694\uccad\uc774 \ub3d9\uc2dc\uc5d0 \ubc1c\uc0dd\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c\uac00 \ub04a\uae30\uac70\ub098, \uc11c\ubc84\uac00 \uc911\uac04\uc5d0 \uc885\ub8cc\ub418\ub354\ub77c\ub3c4 \ud50c\ub808\uc774\uc5b4\uc758 \uc7ac\ud654\uc640 \uc544\uc774\ud15c\uc774 \uc815\ud655\ud558\uac8c \uc720\uc9c0\ub418\uc5b4\uc57c \ud558\ub294 \uc815\uc0b0 \uc2dc\uc2a4\ud15c\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud50c\ub808\uc774\uc5b4\uac00 1,000\ud3ec\uc778\ud2b8\ub97c \ubcf4\uc720\ud558\uace0 \uc788\uc744 \ub54c 700\ud3ec\uc778\ud2b8\uc9dc\ub9ac \uc544\uc774\ud15c\uc744 \ub3d9\uc2dc\uc5d0 \ub450 \ubc88 \uad6c\ub9e4\ud55c\ub2e4\uace0 \uac00\uc815\ud558\uc790. \uc11c\ubc84\uac00 \uc794\uc561\uc744 \uac80\uc99d\ud558\ub294 \uc2dc\uc810\uacfc \ucc28\uac10\ud558\ub294 \uc2dc\uc810\uc744 \uc801\uc808\ud558\uac8c \uc81c\uc5b4\ud558\uc9c0 \ubabb\ud558\uba74 \ub450 \uad6c\ub9e4\uac00 \ubaa8\ub450 \uc131\uacf5\ud558\uc5ec \uc794\uc561\uc774 \uc74c\uc218\uac00 \ub418\uac70\ub098, \ud3ec\uc778\ud2b8\ub294 \ucc28\uac10\ub418\uc5c8\uc9c0\ub9cc \uc544\uc774\ud15c\uc740 \uc9c0\uae09\ub418\uc9c0 \uc54a\ub294 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uacbd\uc81c \uc2dc\uc2a4\ud15c\uc744 \uc124\uacc4\ud560 \ub54c\ub294 \ub2e4\uc74c \uc6d0\uce59\uc744 \uc9c0\ucf1c\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc794\uc561\uacfc \uac70\ub798 \ub0b4\uc5ed\uc744 \uc77c\uad00\ub418\uac8c \uad00\ub9ac\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud3ec\uc778\ud2b8 \ucc28\uac10\uacfc \uc544\uc774\ud15c \uc9c0\uae09\uc744 \uc6d0\uc790\uc801\uc73c\ub85c \ucc98\ub9ac\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ub3d9\uc77c\ud55c \uad6c\ub9e4\ub098 \ubcf4\uc0c1\uc774 \uc911\ubcf5 \ucc98\ub9ac\ub418\uc9c0 \uc54a\ub3c4\ub85d \ud55c\ub2e4.<\/li>\n\n\n\n<li>\ub124\ud2b8\uc6cc\ud06c \uc624\ub958\uc640 \uc11c\ubc84 \uc7a5\uc560 \uc774\ud6c4\uc5d0\ub3c4 \uacb0\uacfc\ub97c \ubcf5\uad6c\ud560 \uc218 \uc788\uc5b4\uc57c \ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc544\ub2cc \uc11c\ubc84\uac00 \ucd5c\uc885 \uc815\uc0b0 \uacb0\uacfc\ub97c \uacb0\uc815\ud55c\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uae00\uc5d0\uc11c\ub294 Node.js, TypeScript, MySQL, Redis\ub97c \ud65c\uc6a9\ud558\ub294 \uba40\ud2f0\ud50c\ub808\uc774\uc5b4 \uac8c\uc784 \uc11c\ubc84\ub97c \uae30\uc900\uc73c\ub85c \uac01 \uac1c\ub150\uacfc \uad6c\ud604 \ubc29\ubc95\uc744 \uc0b4\ud3b4\ubcf8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud3ec\uc778\ud2b8 \uc794\uc561 \uad00\ub9ac<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ud3ec\uc778\ud2b8 \uc794\uc561\uc740 \ud50c\ub808\uc774\uc5b4\uac00 \ud604\uc7ac \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \uc7ac\ud654\uc758 \uc591\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud50c\ub808\uc774\uc5b4\uac00 10,000\ud3ec\uc778\ud2b8\ub97c \ubcf4\uc720\ud558\uace0 \uc788\uace0, 3,000\ud3ec\uc778\ud2b8\uc9dc\ub9ac \uc544\uc774\ud15c\uc744 \uad6c\ub9e4\ud588\ub2e4\uba74 \uc794\uc561\uc740 7,000\ud3ec\uc778\ud2b8\uac00 \ub41c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac00\uc7a5 \ub2e8\uc21c\ud55c \uad6c\ud604\uc740 \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE users\nSET points = points - 3000\nWHERE id = 1001;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ud558\uc9c0\ub9cc \uc774 \ucffc\ub9ac\ub9cc\uc73c\ub85c\ub294 \uc548\uc804\ud55c \uad6c\ub9e4\ub97c \ubcf4\uc7a5\ud560 \uc218 \uc5c6\ub2e4. \uc794\uc561\uc774 \ucda9\ubd84\ud55c\uc9c0 \ud655\uc778\ud558\uc9c0 \uc54a\uc73c\uba74 \uc74c\uc218 \uc794\uc561\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc870\uac74\uc744 \ucd94\uac00\ud558\uba74 \uc794\uc561 \ud655\uc778\uacfc \ucc28\uac10\uc744 \ud558\ub098\uc758 SQL \ubb38\uc73c\ub85c \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE users\nSET points = points - 3000\nWHERE id = 1001\n  AND points &gt;= 3000;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc601\ud5a5\ubc1b\uc740 \ud589\uc774 1\uac1c\ub77c\uba74 \ucc28\uac10\uc5d0 \uc131\uacf5\ud55c \uac83\uc774\uace0, 0\uac1c\ub77c\uba74 \uc0ac\uc6a9\uc790\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uac70\ub098 \uc794\uc561\uc774 \ubd80\uc871\ud55c \uac83\uc774\ub2e4. \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0\uc11c\ub294 \ub450 \uc6d0\uc778\uc744 \uad6c\ubd84\ud558\uae30 \uc704\ud55c \ucd94\uac00 \uc870\ud68c\uac00 \ud544\uc694\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ubc29\uc2dd\uc758 \uc911\uc694\ud55c \uc7a5\uc810\uc740 \uc794\uc561\uc744 \ubcc4\ub3c4\ub85c \uc870\ud68c\ud55c \ud6c4 \ucc28\uac10\ud558\ub294 \uac83\ubcf4\ub2e4 \ub3d9\uc2dc\uc131 \ubb38\uc81c\uc5d0 \uac15\ud558\ub2e4\ub294 \uac83\uc774\ub2e4. MySQL\uc758 InnoDB\ub294 \ud574\ub2f9 \ud589\uc744 \uc218\uc815\ud558\ub294 \uacfc\uc815\uc5d0\uc11c \ud544\uc694\ud55c \uc7a0\uae08\uc744 \uc0ac\uc6a9\ud558\ubbc0\ub85c, \ub3d9\uc2dc\uc5d0 \uc5ec\ub7ec \uad6c\ub9e4 \uc694\uccad\uc774 \ub4e4\uc5b4\uc624\ub354\ub77c\ub3c4 \uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 \uc694\uccad\ub9cc \ucc28\uac10\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ub9cc \uc794\uc561 \ucc28\uac10\uacfc \uc544\uc774\ud15c \uc9c0\uae09\uc744 \ud568\uaed8 \ubcf4\uc7a5\ud558\ub824\uba74 \ud2b8\ub79c\uc7ad\uc158\uc774 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud3ec\uc778\ud2b8 \uc6d0\uc7a5(Ledger)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc794\uc561\ub9cc \uc800\uc7a5\ud558\uba74 \ud604\uc7ac \uc0c1\ud0dc\ub294 \uc54c \uc218 \uc788\uc9c0\ub9cc, \uadf8 \uc0c1\ud0dc\uac00 \ub9cc\ub4e4\uc5b4\uc9c4 \uacfc\uc815\uc740 \uc54c \uc218 \uc5c6\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud3ec\uc778\ud2b8\uac00 5,000\uc5d0\uc11c 2,000\uc73c\ub85c \uac10\uc18c\ud588\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc740 \uc6d0\uc778\uc774 \uc788\uc744 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc544\uc774\ud15c \uad6c\ub9e4\ub85c 3,000\ud3ec\uc778\ud2b8 \ucc28\uac10<\/li>\n\n\n\n<li>\uc6b4\uc601\uc790\uc758 \ud3ec\uc778\ud2b8 \ud68c\uc218<\/li>\n\n\n\n<li>\uc798\ubabb \uc9c0\uae09\ub41c \ubcf4\uc0c1\uc758 \ucde8\uc18c<\/li>\n\n\n\n<li>\ub2e4\ub978 \uc11c\ube44\uc2a4\uc640\uc758 \uc815\uc0b0<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774\ub7f0 \ubb38\uc81c\ub97c \ud574\uacb0\ud558\uae30 \uc704\ud574 \ud3ec\uc778\ud2b8 \uc6d0\uc7a5(Ledger) \uc744 \uc0ac\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6d0\uc7a5\uc740 \ud3ec\uc778\ud2b8\uc758 \ubaa8\ub4e0 \uc99d\uac10 \ub0b4\uc5ed\uc744 \uae30\ub85d\ud558\ub294 \uac70\ub798 \uae30\ub85d\uc774\ub2e4. \uc794\uc561 \ud14c\uc774\ube14\uc774 \ud604\uc7ac \uc0c1\ud0dc\ub97c \ub098\ud0c0\ub0b8\ub2e4\uba74 \uc6d0\uc7a5\uc740 \uc0c1\ud0dc\uac00 \ubcc0\uacbd\ub41c \uadfc\uac70\ub97c \ub098\ud0c0\ub0b8\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc794\uc561 \ud14c\uc774\ube14<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud604\uc7ac \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud3ec\uc778\ud2b8<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">5,000 P<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">\ud3ec\uc778\ud2b8 \uc6d0\uc7a5 \uc608\uc2dc<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\uac70\ub798<\/td><td>\ubcc0\ub3d9<\/td><td>\uac70\ub798 \ud6c4 \uc794\uc561<\/td><\/tr><tr><td>\ucd5c\ucd08 \uc9c0\uae09<\/td><td>+10,000<\/td><td>10,000<\/td><\/tr><tr><td>\uc544\uc774\ud15c \uad6c\ub9e4<\/td><td>-3,000<\/td><td>7,000<\/td><\/tr><tr><td>\uac8c\uc784 \ubcf4\uc0c1<\/td><td>+2,000<\/td><td>9,000<\/td><\/tr><tr><td>\uc544\uc774\ud15c \uad6c\ub9e4<\/td><td>-4,000<\/td><td>5,000<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\uc2dc\ub97c \uc704\ud55c \ub2e8\uc21c\ud654\ub41c \uc6d0\uc7a5\uc774\ub2e4. \uc2e4\uc81c \uc2dc\uc2a4\ud15c\uc5d0\uc11c\ub294 \uac70\ub798 ID, \uac70\ub798 \uc720\ud615, \ub300\uc0c1 \uacc4\uc815, \uc0dd\uc131 \uc2dc\uac01, \uad00\ub828 \uc8fc\ubb38 ID \ub4f1\uc744 \ud568\uaed8 \uc800\uc7a5\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6d0\uc7a5 \ud14c\uc774\ube14\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uacc4\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE point_ledger (\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,\n    user_id BIGINT NOT NULL,\n    transaction_id VARCHAR(100) NOT NULL,\n    amount BIGINT NOT NULL,\n    balance_after BIGINT NOT NULL,\n    transaction_type VARCHAR(30) NOT NULL,\n    created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n\n    UNIQUE KEY uq_ledger_transaction (transaction_id),\n    INDEX idx_ledger_user_created (user_id, created_at)\n);<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>user_id<\/code>: \uac70\ub798 \ub300\uc0c1 \ud50c\ub808\uc774\uc5b4<\/li>\n\n\n\n<li><code>transaction_id<\/code>: \uac70\ub798\ub97c \uc2dd\ubcc4\ud558\ub294 \uace0\uc720 ID<\/li>\n\n\n\n<li><code>amount<\/code>: \uc99d\uac10\ub7c9. \uc591\uc218\ub294 \uc9c0\uae09, \uc74c\uc218\ub294 \ucc28\uac10<\/li>\n\n\n\n<li><code>balance_after<\/code>: \uac70\ub798 \ucc98\ub9ac \ud6c4 \uc794\uc561<\/li>\n\n\n\n<li><code>transaction_type<\/code>: \uad6c\ub9e4, \ubcf4\uc0c1, \ud658\ubd88 \ub4f1 \uac70\ub798 \uc720\ud615<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc5ec\uae30\uc11c <code>balance_after<\/code>\ub294 \uae30\ub85d \ub2f9\uc2dc\uc758 \uc794\uc561\uc774\ub2e4. \uac70\ub798 \uae30\ub85d\uc758 \uc21c\uc11c\uc640 \uc815\ud569\uc131\uc744 \uc62c\ubc14\ub974\uac8c \uad00\ub9ac\ud574\uc57c \uc758\ubbf8\uac00 \uc788\uc73c\uba70, \uc774\ub97c \uc784\uc758\ub85c \uc218\uc815\ud558\uc9c0 \uc54a\ub294 \uac83\uc774 \uc911\uc694\ud558\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6d0\uc7a5\uacfc \uc794\uc561 \ud14c\uc774\ube14\uc740 \uc11c\ub85c \ub2e4\ub978 \ubaa9\uc801\uc744 \uac00\uc9c4\ub2e4. \uc6d0\uc7a5\ub9cc\uc73c\ub85c \ub9e4\ubc88 \uc794\uc561\uc744 \uacc4\uc0b0\ud558\uba74 \uac70\ub798\uac00 \ub204\uc801\ub420\uc218\ub85d \uc870\ud68c \ube44\uc6a9\uc774 \uc99d\uac00\ud558\ubbc0\ub85c, \uc77c\ubc18\uc801\uc73c\ub85c \uc794\uc561\uc740 \ubcc4\ub3c4 \ud14c\uc774\ube14\uc5d0 \uc800\uc7a5\ud558\uace0 \uc6d0\uc7a5\uc744 \uac10\uc0ac \ubc0f \ubcf5\uad6c\uc758 \uadfc\uac70\ub85c \uc0ac\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c \uc6d0\uc7a5\uc740 \ucd94\uac00 \uae30\ub85d \uc911\uc2ec\uc73c\ub85c \uc6b4\uc601\ud574\uc57c \ud55c\ub2e4. \uc798\ubabb\ub41c \uac70\ub798\ub97c \ubc1c\uacac\ud588\uc744 \ub54c \uae30\uc874 \ub0b4\uc5ed\uc744 \uc0ad\uc81c\ud558\uac70\ub098 \uc218\uc815\ud558\uae30\ubcf4\ub2e4\ub294 \ubc18\ub300 \ubc29\ud5a5\uc758 \ubcf4\uc815 \uac70\ub798\ub97c \ucd94\uac00\ud558\ub294 \ud3b8\uc774 \ucd94\uc801 \uac00\ub2a5\uc131\uc744 \ub192\uc778\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc544\uc774\ud15c \uad6c\ub9e4 \ud2b8\ub79c\uc7ad\uc158<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc544\uc774\ud15c \uad6c\ub9e4\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \ub2e4\uc74c \uc791\uc5c5\uc73c\ub85c \uad6c\uc131\ub41c\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uad6c\ub9e4 \uc694\uccad \uac80\uc99d<\/li>\n\n\n\n<li>\ud3ec\uc778\ud2b8 \uc794\uc561 \ud655\uc778 \ubc0f \ucc28\uac10<\/li>\n\n\n\n<li>\uad6c\ub9e4 \ub0b4\uc5ed \uc0dd\uc131<\/li>\n\n\n\n<li>\uc778\ubca4\ud1a0\ub9ac\uc5d0 \uc544\uc774\ud15c \uc9c0\uae09<\/li>\n\n\n\n<li>\ud3ec\uc778\ud2b8 \uc6d0\uc7a5 \uae30\ub85d<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uc791\uc5c5 \uc911 \uc77c\ubd80\ub9cc \uc131\uacf5\ud558\uba74 \ub370\uc774\ud130 \ubd88\uc77c\uce58\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud3ec\uc778\ud2b8 \ucc28\uac10\uc740 \uc131\uacf5\ud588\uc9c0\ub9cc \uc544\uc774\ud15c \uc9c0\uae09\uc5d0 \uc2e4\ud328\ud558\uba74 \ud50c\ub808\uc774\uc5b4\ub294 \ub3c8\uc744 \uc9c0\ubd88\ud558\uace0 \uc544\uc774\ud15c\uc744 \ubc1b\uc9c0 \ubabb\ud55c\ub2e4. \ubc18\ub300\ub85c \uc544\uc774\ud15c\uc740 \uc9c0\uae09\ub410\uc9c0\ub9cc \ud3ec\uc778\ud2b8 \ucc28\uac10\uc5d0 \uc2e4\ud328\ud558\uba74 \ubb34\ub8cc \uad6c\ub9e4\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub530\ub77c\uc11c \ub3d9\uc77c\ud55c MySQL \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc548\uc5d0\uc11c \ucc98\ub9ac\ud560 \uc218 \uc788\ub294 \uc791\uc5c5\uc740 \ud558\ub098\uc758 \ud2b8\ub79c\uc7ad\uc158\uc73c\ub85c \ubb36\ub294 \uac83\uc774 \uae30\ubcf8\uc774\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>START TRANSACTION;\n\n-- \ud3ec\uc778\ud2b8 \ucc28\uac10\nUPDATE users\nSET points = points - 3000\nWHERE id = 1001\n  AND points &gt;= 3000;\n\n-- \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc601\ud5a5\ubc1b\uc740 \ud589\uc774 1\uac1c\uc778\uc9c0 \ud655\uc778\ud55c\ub2e4.\n-- 0\uac1c\ub77c\uba74 ROLLBACK \ud55c\ub2e4.\n\n-- \uad6c\ub9e4 \uae30\ub85d \uc0dd\uc131\nINSERT INTO purchases (\n    user_id,\n    item_id,\n    price,\n    status\n)\nVALUES (\n    1001,\n    2001,\n    3000,\n    'COMPLETED'\n);\n\n-- \uc778\ubca4\ud1a0\ub9ac\uc5d0 \uc544\uc774\ud15c \uc9c0\uae09\nINSERT INTO inventory (\n    user_id,\n    item_id,\n    quantity\n)\nVALUES (\n    1001,\n    2001,\n    1\n)\nON DUPLICATE KEY UPDATE\n    quantity = quantity + 1;\n\n-- \ud3ec\uc778\ud2b8 \uc6d0\uc7a5 \uae30\ub85d\nINSERT INTO point_ledger (\n    user_id,\n    transaction_id,\n    amount,\n    balance_after,\n    transaction_type\n)\nSELECT\n    id,\n    'purchase-uuid-001',\n    -3000,\n    points,\n    'PURCHASE'\nFROM users\nWHERE id = 1001;\n\nCOMMIT;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc704 \ucf54\ub4dc\ub294 \ub3d9\uc791 \uc6d0\ub9ac\ub97c \uc124\uba85\ud558\uae30 \uc704\ud55c SQL \uc608\uc2dc\ub2e4. \uc2e4\uc81c \uad6c\ud604\uc5d0\uc11c\ub294 \uc694\uccad ID\uc758 \uc720\uc77c\uc131, \uad6c\ub9e4 \ub0b4\uc5ed\uc758 \uc81c\uc57d \uc870\uac74, \uac00\uaca9\uc758 \uc11c\ubc84 \uce21 \uac80\uc99d, \ud2b8\ub79c\uc7ad\uc158 \uaca9\ub9ac \ubc0f \uc7a0\uae08 \uc21c\uc11c\ub97c \ud568\uaed8 \uc124\uacc4\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud575\uc2ec\uc740 <code>COMMIT<\/code> \uc774\uc804\uc5d0 \uc624\ub958\uac00 \ubc1c\uc0dd\ud558\uba74 \ubaa8\ub4e0 \ubcc0\uacbd\uc744 <code>ROLLBACK<\/code> \ud55c\ub2e4\ub294 \uc810\uc774\ub2e4. \ub2e8, \uc774\ubbf8 \ucee4\ubc0b\ub41c \ud2b8\ub79c\uc7ad\uc158\uc740 \uc77c\ubc18\uc801\uc778 \ub864\ubc31\uc73c\ub85c \ub418\ub3cc\ub9b4 \uc218 \uc5c6\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc804\ub2ec\ud55c \uac00\uaca9\uc744 \uadf8\ub300\ub85c \uc0ac\uc6a9\ud574\uc11c\ub294 \uc548 \ub41c\ub2e4. \uc11c\ubc84\uac00 \uc0c1\ud488 \ud14c\uc774\ube14\uc5d0\uc11c \uc2e4\uc81c \uac00\uaca9\uacfc \ud310\ub9e4 \uac00\ub2a5 \uc5ec\ubd80\ub97c \uc870\ud68c\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Node.js\uc640 TypeScript \uad6c\ud604<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>mysql2\/promise<\/code>\ub97c \uc0ac\uc6a9\ud55c\ub2e4\uba74 \ub2e4\uc74c\uacfc \uac19\uc774 \uc791\uc131\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import type { Pool } from \"mysql2\/promise\";\n\nasync function purchaseItem(\n  pool: Pool,\n  userId: number,\n  itemId: number,\n) {\n  const connection = await pool.getConnection();\n\n  try {\n    await connection.beginTransaction();\n\n    \/\/ \uc0c1\ud488 \uc815\ubcf4\ub294 \uc11c\ubc84\uac00 \uad00\ub9ac\ud558\ub294 \ub370\uc774\ud130\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\n    const &#91;items] = await connection.execute&lt;any&#91;]&gt;(\n      `SELECT id, price\n       FROM shop_items\n       WHERE id = ?\n         AND is_available = 1`,\n      &#91;itemId],\n    );\n\n    if (items.length === 0) {\n      throw new Error(\"ITEM_NOT_AVAILABLE\");\n    }\n\n    const price = items&#91;0].price;\n\n    \/\/ \uc794\uc561 \ud655\uc778\uacfc \ucc28\uac10\uc744 \uc6d0\uc790\uc801\uc73c\ub85c \ucc98\ub9ac\ud55c\ub2e4.\n    const &#91;result] = await connection.execute&lt;any&gt;(\n      `UPDATE users\n       SET points = points - ?\n       WHERE id = ?\n         AND points &gt;= ?`,\n      &#91;price, userId, price],\n    );\n\n    if (result.affectedRows !== 1) {\n      throw new Error(\"INSUFFICIENT_POINTS_OR_USER_NOT_FOUND\");\n    }\n\n    const &#91;balanceRows] = await connection.execute&lt;any&#91;]&gt;(\n      `SELECT points\n       FROM users\n       WHERE id = ?`,\n      &#91;userId],\n    );\n\n    const balance = balanceRows&#91;0].points;\n    const transactionId = crypto.randomUUID();\n\n    await connection.execute(\n      `INSERT INTO purchases\n       (user_id, item_id, price, transaction_id, status)\n       VALUES (?, ?, ?, ?, 'COMPLETED')`,\n      &#91;userId, itemId, price, transactionId],\n    );\n\n    await connection.execute(\n      `INSERT INTO inventory (user_id, item_id, quantity)\n       VALUES (?, ?, 1)\n       ON DUPLICATE KEY UPDATE quantity = quantity + 1`,\n      &#91;userId, itemId],\n    );\n\n    await connection.execute(\n      `INSERT INTO point_ledger\n       (user_id, transaction_id, amount,\n        balance_after, transaction_type)\n       VALUES (?, ?, ?, ?, 'PURCHASE')`,\n      &#91;userId, transactionId, -price, balance],\n    );\n\n    await connection.commit();\n\n    return {\n      success: true,\n      transactionId,\n      itemId,\n      balance,\n    };\n  } catch (error) {\n    await connection.rollback();\n    throw error;\n  } finally {\n    connection.release();\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uc608\uc81c\uc5d0\ub294 \uc911\uc694\ud55c \uc804\uc81c\uac00 \uc788\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>purchases.transaction_id<\/code>\uc5d0\ub294 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc774 \ud544\uc694\ud558\ub2e4.<\/li>\n\n\n\n<li><code>inventory<\/code>\uc5d0\ub294 <code>(user_id, item_id)<\/code> \ubcf5\ud569 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc774 \ud544\uc694\ud558\ub2e4.<\/li>\n\n\n\n<li><code>shop_items.price<\/code>\ub294 \uc815\uc218\ud615 \uc7ac\ud654 \ub2e8\uc704\ub85c \uc800\uc7a5\ud558\uace0, \uc0c1\ud488 \uac00\uaca9\uc758 \ubc94\uc704\uc640 \uc790\ub8cc\ud615\uc744 \uac80\uc99d\ud574\uc57c \ud55c\ub2e4.<\/li>\n\n\n\n<li><code>crypto.randomUUID()<\/code>\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 Node.js\uc758 <code>node:crypto<\/code> \ubaa8\ub4c8\uc744 \uac00\uc838\uc624\uac70\ub098 \ud574\ub2f9 API\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 \ud658\uacbd\uc774\uc5b4\uc57c \ud55c\ub2e4.<\/li>\n\n\n\n<li><code>catch<\/code>\uc5d0\uc11c \ubc1c\uc0dd\ud55c \uc624\ub958\ub97c \ubaa8\ub450 \ubb34\uc870\uac74 \ub864\ubc31\ud558\uba74 \uc548 \ub418\ub294 \uacbd\uc6b0\ub3c4 \uc788\ub2e4. \ud2b9\ud788 \ucee4\ubc0b \uc694\uccad\uc774 \uc11c\ubc84\uc5d0 \uc804\ub2ec\ub41c \ub4a4 \uc5f0\uacb0\uc774 \ub04a\uacbc\ub2e4\uba74 \uc2e4\uc81c \ucee4\ubc0b \uc5ec\ubd80\uac00 \ubd88\uba85\ud655\ud560 \uc218 \uc788\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ub9c8\uc9c0\ub9c9 \uc0c1\ud669\uc740 \ub2e8\uc21c\ud55c \uc608\uc678 \ucc98\ub9ac\ub9cc\uc73c\ub85c \ud574\uacb0\ud560 \uc218 \uc5c6\ub2e4. \uc774\ud6c4 \uc124\uba85\ud560 \uba71\ub4f1\uc131\uacfc \uac70\ub798 \uc0c1\ud0dc \uc870\ud68c\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uac8c\uc784 \uacb0\uacfc \ubc0f \ubcf4\uc0c1 \uc9c0\uae09<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uc885\ub8cc \ud6c4 \ubcf4\uc0c1\uc744 \uc9c0\uae09\ud558\ub294 \uacfc\uc815\ub3c4 \uad6c\ub9e4\uc640 \uac19\uc740 \uc815\uc0b0 \uc6d0\uce59\uc744 \uc801\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud50c\ub808\uc774\uc5b4\uac00 \uc2b9\ub9ac\ud558\uba74 500\ud3ec\uc778\ud2b8\ub97c \uc9c0\uae09\ud55c\ub2e4\uace0 \uac00\uc815\ud558\uc790.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uc11c\ubc84\ub294 \ub2e4\uc74c \uc21c\uc11c\ub85c \ucc98\ub9ac\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uc885\ub8cc \ud310\uc815<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84 \uad8c\ud55c\uc73c\ub85c \uc2b9\ud328\uc640 \uacb0\uacfc \ud655\uc815<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ubcf4\uc0c1 \uacc4\uc0b0 \ubc0f \uc9c0\uae09 \uc694\uccad \uc0dd\uc131<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 ID, \ud50c\ub808\uc774\uc5b4 ID, \ubcf4\uc0c1 \uaddc\uce59 \ud655\uc815<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud2b8\ub79c\uc7ad\uc158 \ucc98\ub9ac<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc911\ubcf5 \ud655\uc778 \u2192 \ud3ec\uc778\ud2b8 \uc99d\uac00 \u2192 \uc6d0\uc7a5 \uae30\ub85d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc9c0\uae09 \uacb0\uacfc \ud655\uc815<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc9c0\uae09 \uc644\ub8cc \uae30\ub85d \ubc0f \uacb0\uacfc \ubc18\ud658<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ubcf4\uc0c1 \uc9c0\uae09\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \ucc98\ub9ac\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>START TRANSACTION;\n\nUPDATE users\nSET points = points + 500\nWHERE id = 1001;\n\nINSERT INTO point_ledger (\n    user_id,\n    transaction_id,\n    amount,\n    balance_after,\n    transaction_type\n)\nSELECT\n    id,\n    'reward-match-9001-user-1001',\n    500,\n    points,\n    'GAME_REWARD'\nFROM users\nWHERE id = 1001;\n\nCOMMIT;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc5ec\uae30\uc11c <code>transaction_id<\/code>\ub294 \ub9e4 \uc694\uccad\ub9c8\ub2e4 \uc0c8\ub85c \ub9cc\ub4dc\ub294 \uac12\uc774 \uc544\ub2c8\ub77c, \ub3d9\uc77c\ud55c \uac8c\uc784 \uacb0\uacfc\uc5d0 \ub300\ud55c \ub3d9\uc77c\ud55c \ud50c\ub808\uc774\uc5b4\uc758 \ubcf4\uc0c1\uc744 \ud56d\uc0c1 \uc2dd\ubcc4\ud560 \uc218 \uc788\ub294 \uac12\uc774\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ub2e4\uc74c \uc870\ud569\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>matchId + userId + rewardType<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e8, \ud574\ub2f9 \uc870\ud569\uc774 \uc2e4\uc81c\ub85c \uc720\uc77c\ud558\ub3c4\ub85d \uc124\uacc4\ud574\uc57c \ud558\uba70, \uc5ec\ub7ec \ucc28\ub840 \uc9c0\uae09 \uac00\ub2a5\ud55c \ubcf4\uc0c1\uc774\ub77c\uba74 \ub77c\uc6b4\ub4dc ID\ub098 \uc9c0\uae09 \ud68c\ucc28 \ub4f1 \ucd94\uac00 \uc2dd\ubcc4\uc790\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c \uc2b9\ud328\uc640 \ubcf4\uc0c1 \uae08\uc561\uc744 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uacb0\uc815\ud558\uac8c \ud574\uc11c\ub294 \uc548 \ub41c\ub2e4. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uac8c\uc784 \uacb0\uacfc\ub97c \uc694\uccad\ud558\uac70\ub098 \uc804\ub2ec\ubc1b\uc744 \ubfd0\uc774\uba70, \uc11c\ubc84\uac00 \uac80\uc99d\ud55c \uacb0\uacfc\ub97c \uae30\uc900\uc73c\ub85c \uc815\uc0b0\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc911\ubcf5 \uad6c\ub9e4\u00b7\ubcf4\uc0c1 \uc9c0\uae09 \ubc29\uc9c0<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\ub124\ud2b8\uc6cc\ud06c \ud658\uacbd\uc5d0\uc11c \ub3d9\uc77c\ud55c \uc694\uccad\uc774 \uc5ec\ub7ec \ubc88 \ub3c4\ucc29\ud558\ub294 \uac83\uc740 \uc815\uc0c1\uc801\uc778 \uc0c1\ud669\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uad6c\ub9e4 \uc694\uccad\uc744 \ubcf4\ub0c8\uc9c0\ub9cc \uc751\ub2f5\uc744 \ubc1b\uc9c0 \ubabb\ud588\ub2e4\uace0 \uac00\uc815\ud558\uc790. \ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uad6c\ub9e4\uac00 \uc2e4\ud328\ud588\ub2e4\uace0 \ud310\ub2e8\ud574 \ub2e4\uc2dc \uc694\uccad\ud560 \uc218 \uc788\ub2e4. \ud558\uc9c0\ub9cc \uccab \uc694\uccad\uc774 \uc2e4\uc81c\ub85c\ub294 \uc131\uacf5\ud588\uc744 \uc218\ub3c4 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84\uac00 \uc7ac\uc694\uccad\uc744 \uc0c8\ub85c\uc6b4 \uad6c\ub9e4\ub85c \ucc98\ub9ac\ud558\uba74 \ud3ec\uc778\ud2b8\uac00 \ub450 \ubc88 \ucc28\uac10\ub418\uac70\ub098 \uc544\uc774\ud15c\uc774 \ub450 \ubc88 \uc9c0\uae09\ub420 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774\ub97c \ubc29\uc9c0\ud558\ub824\uba74 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucf54\ub4dc\uc758 \uc870\uac74\ubb38\ub9cc\uc73c\ub85c \ucc98\ub9ac\ud558\uc9c0 \ub9d0\uace0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc744 \ucd5c\uc885 \ubc29\uc5b4\uc120\uc73c\ub85c \uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE purchases (\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,\n    user_id BIGINT NOT NULL,\n    item_id BIGINT NOT NULL,\n    price BIGINT NOT NULL,\n    transaction_id VARCHAR(100) NOT NULL,\n    status VARCHAR(20) NOT NULL,\n    created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n\n    UNIQUE KEY uq_purchase_transaction (transaction_id)\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ubcf4\uc0c1 \uc9c0\uae09 \uae30\ub85d\ub3c4 \ub3d9\uc77c\ud55c \ubc29\uc2dd\uc73c\ub85c \uad6c\uc131\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE reward_claims (\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,\n    match_id VARCHAR(100) NOT NULL,\n    user_id BIGINT NOT NULL,\n    reward_type VARCHAR(30) NOT NULL,\n    amount BIGINT NOT NULL,\n    status VARCHAR(20) NOT NULL,\n\n    UNIQUE KEY uq_match_user_reward (\n        match_id,\n        user_id,\n        reward_type\n    )\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uc81c\uc57d \uc870\uac74\uc740 \uac19\uc740 \uacbd\uae30, \uac19\uc740 \ud50c\ub808\uc774\uc5b4, \uac19\uc740 \ubcf4\uc0c1 \uc720\ud615\uc5d0 \ub300\ud574 \uc9c0\uae09 \uae30\ub85d\uc774 \uc911\ubcf5 \uc0dd\uc131\ub418\ub294 \uac83\uc744 \ub9c9\ub294\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ub9cc \ubcf4\uc0c1 \uae30\ub85d\uc5d0 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc744 \uac78\uc5c8\ub2e4\uace0 \ud574\uc11c \ud3ec\uc778\ud2b8 \uc911\ubcf5 \uc9c0\uae09\uc774 \uc790\ub3d9\uc73c\ub85c \ud574\uacb0\ub418\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4. \ubcf4\uc0c1 \uae30\ub85d \uc0dd\uc131\uacfc \ud3ec\uc778\ud2b8 \uc99d\uac00\ub97c \ud558\ub098\uc758 \ud2b8\ub79c\uc7ad\uc158\uc73c\ub85c \ubb36\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c \uac8c\uc784 \uacb0\uacfc\ub97c \ub2e4\uc2dc \uacc4\uc0b0\ud558\uac70\ub098 \ubcf4\uc0c1 \uaddc\uce59\uc744 \ubcc0\uacbd\ud558\ub294 \uacbd\uc6b0\uc5d0\ub3c4 \uc774\ubbf8 \ud655\uc815\ub41c \ubcf4\uc0c1\uc744 \ubb34\uc870\uac74 \uc7ac\uc9c0\uae09\ud574\uc11c\ub294 \uc548 \ub41c\ub2e4. \uc9c0\uae09\ub41c \ubcf4\uc0c1\uc740 \uba85\uc2dc\uc801\uc778 \ubcf4\uc815 \uac70\ub798\ub97c \ud1b5\ud574 \ucc98\ub9ac\ud558\ub294 \uac83\uc774 \uc548\uc804\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uba71\ub4f1\uc131(Idempotency)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uba71\ub4f1\uc131\uc740 \ub3d9\uc77c\ud55c \uc791\uc5c5\uc744 \uc5ec\ub7ec \ubc88 \uc694\uccad\ud558\ub354\ub77c\ub3c4 \uacb0\uacfc\uac00 \ud55c \ubc88 \uc2e4\ud589\ud55c \uac83\uacfc \uac19\ub3c4\ub85d \ubcf4\uc7a5\ud558\ub294 \uc131\uc9c8\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc218\ud559\uc801\uc73c\ub85c\ub294 \ub2e4\uc74c\uacfc \uac19\uc774 \ud45c\ud604\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\\[ f(f(x)) = f(x) \\]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uac8c\uc784 \uc11c\ubc84\uc5d0\uc11c\ub294 \ub2e8\uc21c\ud788 \ud568\uc218\uc758 \ubc18\ud658\uac12\uc774 \uac19\uc740 \uac83\ubcf4\ub2e4 \uc911\uc694\ud55c \uc758\ubbf8\ub97c \uac00\uc9c4\ub2e4. \ub3d9\uc77c\ud55c \uad6c\ub9e4 \uc694\uccad\uc774 \uc7ac\uc804\uc1a1\ub418\ub354\ub77c\ub3c4 \ud3ec\uc778\ud2b8 \ucc28\uac10\uacfc \uc544\uc774\ud15c \uc9c0\uae09\uc774 \ud55c \ubc88\ub9cc \ubc1c\uc0dd\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 3,000\ud3ec\uc778\ud2b8\uc9dc\ub9ac \uc544\uc774\ud15c\uc744 \uad6c\ub9e4\ud558\ub294 \uc694\uccad\uc774 \uc138 \ubc88 \uc804\ub2ec\ub418\uc5c8\ub2e4\uace0 \uac00\uc815\ud558\uc790.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>\ucc98\ub9ac \ubc29\uc2dd<\/th><th>\ud3ec\uc778\ud2b8 \ucc28\uac10<\/th><th>\uc544\uc774\ud15c \uc9c0\uae09<\/th><\/tr><tr><td>\uba71\ub4f1\uc131 \uc5c6\uc74c<\/td><td>9,000<\/td><td>3\uac1c<\/td><\/tr><tr><td>\uba71\ub4f1\uc131 \uc801\uc6a9<\/td><td>3,000<\/td><td>1\uac1c<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\uba71\ub4f1\uc131\uc740 \ub124\ud2b8\uc6cc\ud06c \uc7ac\uc2dc\ub3c4, \ud074\ub77c\uc774\uc5b8\ud2b8\uc758 \uc911\ubcf5 \ud074\ub9ad, \ub85c\ub4dc\ubc38\ub7f0\uc11c\uc758 \uc7ac\uc804\uc1a1, \uba54\uc2dc\uc9c0 \ud050\uc758 \uc911\ubcf5 \uc804\ub2ec \ub4f1\uc5d0 \ub300\uc751\ud558\ub294 \ud575\uc2ec \uc124\uacc4\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Idempotency-Key<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\uc77c\ubc18\uc801\uc778 HTTP API\uc5d0\uc11c\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uac00 \uc694\uccad\ub9c8\ub2e4 \uace0\uc720\ud55c <code>Idempotency-Key<\/code>\ub97c \uc0dd\uc131\ud574 \uc804\ub2ec\ud558\ub3c4\ub85d \uc124\uacc4\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>POST \/api\/shop\/purchases\nAuthorization: Bearer &lt;access-token&gt;\nIdempotency-Key: 7c5b1e2a-5df3-4f9a-a1c4-8c8b2f6e31ab\nContent-Type: application\/json\n\n{\n  \"itemId\": 2001\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc5ec\uae30\uc11c \uc911\uc694\ud55c \uc810\uc740 \uac19\uc740 \uad6c\ub9e4 \uc791\uc5c5\uc744 \uc7ac\uc2dc\ub3c4\ud560 \ub54c\ub294 \uae30\uc874 \ud0a4\ub97c \uc7ac\uc0ac\uc6a9\ud574\uc57c \ud55c\ub2e4\ub294 \uac83\uc774\ub2e4. \uc0c8\ub85c\uc6b4 \ud0a4\ub97c \uc0dd\uc131\ud558\uba74 \uc11c\ubc84\ub294 \uc0c8\ub85c\uc6b4 \uad6c\ub9e4 \uc694\uccad\uc73c\ub85c \ud310\ub2e8\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc11c\ubc84\ub294 \uc77c\ubc18\uc801\uc73c\ub85c \ub2e4\uc74c \uc815\ubcf4\ub97c \uad00\ub9ac\ud55c\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>user_id<\/code>: \uc694\uccad \uc8fc\uccb4<\/li>\n\n\n\n<li><code>idempotency_key<\/code>: \uc694\uccad \uc2dd\ubcc4\uc790<\/li>\n\n\n\n<li><code>request_hash<\/code>: \uc694\uccad \ub0b4\uc6a9\uc758 \ud574\uc2dc<\/li>\n\n\n\n<li><code>status<\/code>: \ucc98\ub9ac \uc0c1\ud0dc<\/li>\n\n\n\n<li><code>response_body<\/code>: \ucd5c\ucd08 \ucc98\ub9ac \uacb0\uacfc<\/li>\n\n\n\n<li><code>created_at<\/code>: \uc0dd\uc131 \uc2dc\uac01<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud14c\uc774\ube14\uc740 \ub2e4\uc74c\uacfc \uac19\uc774 \uc124\uacc4\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE idempotency_requests (\n    id BIGINT AUTO_INCREMENT PRIMARY KEY,\n    user_id BIGINT NOT NULL,\n    idempotency_key VARCHAR(100) NOT NULL,\n    request_hash CHAR(64) NOT NULL,\n    status VARCHAR(20) NOT NULL,\n    response_body JSON NULL,\n    created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),\n    updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)\n        ON UPDATE CURRENT_TIMESTAMP(3),\n\n    UNIQUE KEY uq_idempotency_user_key (\n        user_id,\n        idempotency_key\n    )\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>request_hash<\/code>\ub294 \uac19\uc740 \ud0a4\ub85c \uc11c\ub85c \ub2e4\ub978 \uc694\uccad\uc774 \ub4e4\uc5b4\uc624\ub294 \ubb38\uc81c\ub97c \ud0d0\uc9c0\ud558\uae30 \uc704\ud55c \uac12\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \ub3d9\uc77c\ud55c \ud0a4\ub85c \ucc98\uc74c\uc5d0\ub294 <code>itemId: 2001<\/code>, \uc774\ud6c4\uc5d0\ub294 <code>itemId: 3001<\/code>\uc744 \uc694\uccad\ud55c\ub2e4\uba74 \uc11c\ubc84\ub294 \uc774\ub97c \uac19\uc740 \uc694\uccad\uc758 \uc7ac\uc2dc\ub3c4\ub85c \ucde8\uae09\ud558\uba74 \uc548 \ub41c\ub2e4. <code>409 Conflict<\/code> \ub4f1\uc73c\ub85c \uc694\uccad\uc744 \uac70\ubd80\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc694\uccad \ud574\uc2dc\ub294 \uc11c\ubc84\uc5d0\uc11c \uac80\uc99d\ub41c \uc694\uccad \ub370\uc774\ud130\ub97c \uae30\uc900\uc73c\ub85c \uacc4\uc0b0\ud574\uc57c \ud55c\ub2e4. JSON \ubb38\uc790\uc5f4\uc758 \ub2e8\uc21c \ud574\uc2dc\ub294 \ud544\ub4dc \uc21c\uc11c\ub098 \uc9c1\ub82c\ud654 \ubc29\uc2dd\uc5d0 \ub530\ub77c \ub2ec\ub77c\uc9c8 \uc218 \uc788\uc73c\ubbc0\ub85c, \ud544\uc694\ud558\ub2e4\uba74 \uc815\uaddc\ud654\ub41c \ud45c\ud604\uc744 \uc0ac\uc6a9\ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uacfc \uba71\ub4f1\uc131\uc758 \uad00\uacc4<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\uba71\ub4f1\uc131\uc744 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucf54\ub4dc\ub9cc\uc73c\ub85c \uad6c\ud604\ud558\uba74 \ub3d9\uc2dc \uc694\uccad\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const existing = await findRequest(key);\n\nif (!existing) {\n  await createPurchase();\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\ub450 \uc694\uccad\uc774 \ub3d9\uc2dc\uc5d0 \uc2e4\ud589\ub418\uba74 \ub458 \ub2e4 <code>existing<\/code>\uc774 \uc5c6\ub2e4\uace0 \ud310\ub2e8\ud560 \uc218 \uc788\ub2e4. \uc774\ud6c4 \ub450 \uc694\uccad \ubaa8\ub450 \uad6c\ub9e4\ub97c \uc9c4\ud589\ud560 \uac00\ub2a5\uc131\uc774 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub530\ub77c\uc11c \ub2e4\uc74c \ub450 \uac00\uc9c0\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74: \ub3d9\uc77c\ud55c \uc0ac\uc6a9\uc790\uc640 \ud0a4\uc758 \uc911\ubcf5 \ub4f1\ub85d\uc744 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c \ucc28\ub2e8\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud2b8\ub79c\uc7ad\uc158: \uba71\ub4f1\uc131 \uae30\ub85d\uacfc \uc2e4\uc81c \uc815\uc0b0 \uc791\uc5c5\uc744 \uc6d0\uc790\uc801\uc73c\ub85c \ucc98\ub9ac\ud55c\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\uba71\ub4f1\uc131 \ud0a4\ub294 \uc694\uccad\uc758 \uc911\ubcf5\uc744 \uc2dd\ubcc4\ud558\uace0, \uac70\ub798 ID\ub294 \uc2e4\uc81c \uc815\uc0b0 \uac70\ub798\ub97c \uc2dd\ubcc4\ud55c\ub2e4. \ub450 \uac1c\ub150\uc740 \uc5f0\uacb0\ub418\uc9c0\ub9cc \ubc18\ub4dc\uc2dc \uac19\uc740 \uac12\uc77c \ud544\uc694\ub294 \uc5c6\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uba71\ub4f1\uc131 \uad6c\ub9e4 API \uad6c\ud604<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc55e\uc11c \uc124\uba85\ud55c \uad6c\uc870\ub97c \uc2e4\uc81c \uad6c\ub9e4 API\uc5d0 \uc801\uc6a9\ud574 \ubcf4\uc790.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uba3c\uc800 \ucc98\ub9ac \ud750\ub984\uc744 \uc815\uc758\ud55c\ub2e4.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\uc778\uc99d\ub41c \uc0ac\uc6a9\uc790 ID\uc640 <code>Idempotency-Key<\/code>\ub97c \ud655\uc778\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uc694\uccad \ub0b4\uc6a9\uc744 \uac80\uc99d\ud558\uace0 \ud574\uc2dc\ub97c \uacc4\uc0b0\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud2b8\ub79c\uc7ad\uc158\uc744 \uc2dc\uc791\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uba71\ub4f1\uc131 \uae30\ub85d\uc744 \uc0dd\uc131\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uc774\ubbf8 \ucc98\ub9ac\ub41c \uc694\uccad\uc774\uba74 \uae30\uc874 \uacb0\uacfc\ub97c \ubc18\ud658\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud3ec\uc778\ud2b8 \ucc28\uac10, \uad6c\ub9e4 \uae30\ub85d, \uc778\ubca4\ud1a0\ub9ac \uc9c0\uae09, \uc6d0\uc7a5 \uae30\ub85d\uc744 \ucc98\ub9ac\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ucc98\ub9ac \uacb0\uacfc\ub97c \uba71\ub4f1\uc131 \ud14c\uc774\ube14\uc5d0 \uc800\uc7a5\ud55c\ub2e4.<\/li>\n\n\n\n<li>\ud2b8\ub79c\uc7ad\uc158\uc744 \ucee4\ubc0b\ud55c\ub2e4.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">\uc5ec\uae30\uc11c \ud575\uc2ec\uc740 \uba71\ub4f1\uc131 \uae30\ub85d\uacfc \uad6c\ub9e4 \uc791\uc5c5\uc774 \uac19\uc740 \ud2b8\ub79c\uc7ad\uc158\uc5d0 \ud3ec\ud568\ub41c\ub2e4\ub294 \uc810\uc774\ub2e4. \uadf8\ub798\uc57c \uad6c\ub9e4\uac00 \ub864\ubc31\ub418\uba74 \uba71\ub4f1\uc131 \uae30\ub85d\ub3c4 \ud568\uaed8 \ub864\ubc31\ub418\uc5b4 \uc7ac\uc2dc\ub3c4\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\uc74c\uc740 \uc774\ub97c \uad6c\ud604\ud55c TypeScript \uc608\uc2dc\ub2e4. <code>purchaseItem<\/code>\uc774\ub77c\ub294 \uae30\uc874 \uc11c\ube44\uc2a4\uac00 \uc544\ub2c8\ub77c, \uba71\ub4f1\uc131 \ucc98\ub9ac\ub97c \ud3ec\ud568\ud55c \ub3c5\ub9bd\uc801\uc778 \uad6c\ub9e4 \uc11c\ube44\uc2a4\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { createHash } from \"node:crypto\";\nimport type { Pool, ResultSetHeader, RowDataPacket } from \"mysql2\/promise\";\n\ninterface PurchaseResult {\n  success: true;\n  transactionId: string;\n  itemId: number;\n  balance: number;\n}\n\ninterface IdempotencyRow extends RowDataPacket {\n  request_hash: string;\n  status: string;\n  response_body: PurchaseResult | null;\n}\n\ninterface ItemRow extends RowDataPacket {\n  id: number;\n  price: number;\n}\n\ninterface UserRow extends RowDataPacket {\n  points: number;\n}\n\nexport async function purchaseItemIdempotently(\n  pool: Pool,\n  userId: number,\n  itemId: number,\n  idempotencyKey: string,\n): Promise&lt;PurchaseResult&gt; {\n  if (\n    !Number.isSafeInteger(userId) ||\n    userId &lt;= 0 ||\n    !Number.isSafeInteger(itemId) ||\n    itemId &lt;= 0\n  ) {\n    throw new Error(\"INVALID_INPUT\");\n  }\n\n  if (\n    idempotencyKey.length &lt; 1 ||\n    idempotencyKey.length &gt; 100\n  ) {\n    throw new Error(\"INVALID_IDEMPOTENCY_KEY\");\n  }\n\n  const requestHash = createHash(\"sha256\")\n    .update(JSON.stringify({ itemId }))\n    .digest(\"hex\");\n\n  const connection = await pool.getConnection();\n  let transactionStarted = false;\n\n  try {\n    await connection.beginTransaction();\n    transactionStarted = true;\n\n    \/\/ \uac19\uc740 \uc0ac\uc6a9\uc790\uc640 \ud0a4\uc758 \uc911\ubcf5 \ub4f1\ub85d\uc740 UNIQUE \uc81c\uc57d \uc870\uac74\uc774 \ucc28\ub2e8\ud55c\ub2e4.\n    await connection.execute(\n      `INSERT INTO idempotency_requests\n       (user_id, idempotency_key, request_hash, status)\n       VALUES (?, ?, ?, 'PROCESSING')`,\n      &#91;userId, idempotencyKey, requestHash],\n    );\n\n    const &#91;items] = await connection.execute&lt;ItemRow&#91;]&gt;(\n      `SELECT id, price\n       FROM shop_items\n       WHERE id = ?\n         AND is_available = 1`,\n      &#91;itemId],\n    );\n\n    if (items.length !== 1) {\n      throw new Error(\"ITEM_NOT_AVAILABLE\");\n    }\n\n    const price = items&#91;0].price;\n\n    if (!Number.isSafeInteger(price) || price &lt; 0) {\n      throw new Error(\"INVALID_ITEM_PRICE\");\n    }\n\n    const &#91;debit] = await connection.execute&lt;ResultSetHeader&gt;(\n      `UPDATE users\n       SET points = points - ?\n       WHERE id = ?\n         AND points &gt;= ?`,\n      &#91;price, userId, price],\n    );\n\n    if (debit.affectedRows !== 1) {\n      throw new Error(\"INSUFFICIENT_POINTS_OR_USER_NOT_FOUND\");\n    }\n\n    const &#91;users] = await connection.execute&lt;UserRow&#91;]&gt;(\n      `SELECT points\n       FROM users\n       WHERE id = ?`,\n      &#91;userId],\n    );\n\n    const balance = users&#91;0].points;\n    const transactionId = crypto.randomUUID();\n\n    await connection.execute(\n      `INSERT INTO purchases\n       (user_id, item_id, price, transaction_id, status)\n       VALUES (?, ?, ?, ?, 'COMPLETED')`,\n      &#91;userId, itemId, price, transactionId],\n    );\n\n    await connection.execute(\n      `INSERT INTO inventory (user_id, item_id, quantity)\n       VALUES (?, ?, 1)\n       ON DUPLICATE KEY UPDATE\n         quantity = quantity + 1`,\n      &#91;userId, itemId],\n    );\n\n    await connection.execute(\n      `INSERT INTO point_ledger\n       (user_id, transaction_id, amount,\n        balance_after, transaction_type)\n       VALUES (?, ?, ?, ?, 'PURCHASE')`,\n      &#91;userId, transactionId, -price, balance],\n    );\n\n    const response: PurchaseResult = {\n      success: true,\n      transactionId,\n      itemId,\n      balance,\n    };\n\n    await connection.execute(\n      `UPDATE idempotency_requests\n       SET status = 'COMPLETED',\n           response_body = ?\n       WHERE user_id = ?\n         AND idempotency_key = ?`,\n      &#91;\n        JSON.stringify(response),\n        userId,\n        idempotencyKey,\n      ],\n    );\n\n    await connection.commit();\n    transactionStarted = false;\n\n    return response;\n  } catch (error) {\n    if (transactionStarted) {\n      try {\n        await connection.rollback();\n      } catch {\n        \/\/ \uc5f0\uacb0 \uc7a5\uc560 \ub4f1\uc73c\ub85c \ub864\ubc31 \uacb0\uacfc\ub97c \ud655\uc815\ud560 \uc218 \uc5c6\ub294 \uc0c1\ud669\uc774\ub2e4.\n        \/\/ \uc0c8 \ud0a4\ub85c \ubb34\uc870\uac74 \uc7ac\uc2dc\ub3c4\ud558\uc9c0 \ub9d0\uace0 \uae30\uc874 \ud0a4\uc758 \uacb0\uacfc\ub97c \ud655\uc778\ud55c\ub2e4.\n      }\n    }\n\n    throw error;\n  } finally {\n    connection.release();\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ucf54\ub4dc\ub294 \ud575\uc2ec \uc815\uc0b0 \uacbd\ub85c\ub97c \ubcf4\uc5ec\uc8fc\ub294 \uc608\uc81c\ub2e4. \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \ucd94\uac00 \ucc98\ub9ac\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ub3d9\uc77c\ud55c \ud0a4\uac00 \uc774\ubbf8 \uc874\uc7ac\ud558\uba74 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74 \uc704\ubc18\uc744 \uac10\uc9c0\ud558\uace0, \ubcc4\ub3c4\uc758 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \uae30\uc874 \uc694\uccad \uacb0\uacfc\ub97c \uc870\ud68c\ud55c\ub2e4.<\/li>\n\n\n\n<li>\uae30\uc874 \uc694\uccad\uc758 <code>request_hash<\/code>\uac00 \ub2e4\ub974\uba74 \ucda9\ub3cc\ub85c \ucc98\ub9ac\ud55c\ub2e4.<\/li>\n\n\n\n<li><code>COMPLETED<\/code> \uc0c1\ud0dc\ub77c\uba74 \uc800\uc7a5\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud55c\ub2e4.<\/li>\n\n\n\n<li><code>PROCESSING<\/code> \uc0c1\ud0dc\ub97c \uc0ac\uc6a9\ud558\ub294 \ube44\ub3d9\uae30 \ucc98\ub9ac \uad6c\uc870\uc5d0\uc11c\ub294 \uc9c4\ud589 \uc911 \uc694\uccad\uc5d0 \ub300\ud55c \ub300\uae30 \ub610\ub294 \uc7ac\uc870\ud68c \uc815\ucc45\uc744 \uc815\uc758\ud55c\ub2e4.<\/li>\n\n\n\n<li>MySQL\uc758 JSON \ubc18\ud658 \ud615\ud0dc\uc640 \ub4dc\ub77c\uc774\ubc84 \ud0c0\uc785\uc744 \uc2e4\uc81c \ud658\uacbd\uc5d0 \ub9de\uac8c \ucc98\ub9ac\ud55c\ub2e4.<\/li>\n\n\n\n<li><code>crypto.randomUUID()<\/code>\ub97c \uc0ac\uc6a9\ud558\ub824\uba74 <code>import { randomUUID } from \"node:crypto\"<\/code>\ucc98\ub7fc \uba85\uc2dc\uc801\uc73c\ub85c \uac00\uc838\uc640 \uc0ac\uc6a9\ud558\ub294 \ud3b8\uc774 \uc88b\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ud2b9\ud788 \uc704 \uc608\uc81c\uc5d0\uc11c\ub294 \uba71\ub4f1\uc131 \ud0a4\uac00 \uc774\ubbf8 \uc874\uc7ac\ud560 \ub54c \ubc1c\uc0dd\ud558\ub294 \uc911\ubcf5 \ud0a4 \uc624\ub958\ub97c \uc131\uacf5 \uacb0\uacfc\ub85c \uac04\uc8fc\ud558\uc9c0 \uc54a\ub294\ub2e4. \uc774\ub97c \ucc98\ub9ac\ud558\ub294 API \uacc4\uce35\uc774 \uae30\uc874 \uae30\ub85d\uc744 \uc870\ud68c\ud574 \uacb0\uacfc\ub97c \ubc18\ud658\ud574\uc57c \ube44\ub85c\uc18c \uc7ac\uc2dc\ub3c4\uc5d0 \ub300\ud55c \uba71\ub4f1\uc131\uc774 \uc644\uc131\ub41c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c <code>PROCESSING<\/code> \uae30\ub85d\uc744 \ubcc4\ub3c4 \ud2b8\ub79c\uc7ad\uc158\uc73c\ub85c \uba3c\uc800 \ucee4\ubc0b\ud558\ub294 \uad6c\uc870\ub77c\uba74 \uc7a5\uc560 \uc774\ud6c4 \ucc98\ub9ac \uc0c1\ud0dc\uac00 \ub0a8\uc744 \uc218 \uc788\ub2e4. \uc774\ub7f0 \uc124\uacc4\uc5d0\uc11c\ub294 \ucc98\ub9ac \uc18c\uc720\uad8c, \ub9cc\ub8cc \uc2dc\uac04, \ubcf5\uad6c \uc791\uc5c5\uae4c\uc9c0 \uc815\uc758\ud574\uc57c \ud55c\ub2e4. \ub2e8\uc21c\ud788 \uc0c1\ud0dc \ubb38\uc790\uc5f4\ub9cc \ucd94\uac00\ud55c\ub2e4\uace0 \uc7a5\uc560 \ubcf5\uad6c\uac00 \uc644\uc131\ub418\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\ud328 \ubcf5\uad6c\uc640 \uc7ac\uc2dc\ub3c4<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc815\uc0b0 \uc2dc\uc2a4\ud15c\uc5d0\uc11c \uac00\uc7a5 \uc5b4\ub824\uc6b4 \ubb38\uc81c\ub294 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\ub2e4\ub294 \uc0ac\uc2e4 \uc790\uccb4\uac00 \uc544\ub2c8\ub77c, \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \uc2e4\uc81c\ub85c \uc5b4\ub514\uae4c\uc9c0 \ucc98\ub9ac\ub418\uc5c8\ub294\uc9c0 \ubd88\ud655\uc2e4\ud55c \uc0c1\ud669\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \uc11c\ubc84\uac00 \uad6c\ub9e4 \ud2b8\ub79c\uc7ad\uc158\uc744 \ucee4\ubc0b\ud55c \uc9c1\ud6c4 \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5f0\uacb0\uc774 \ub04a\uacbc\ub2e4\uace0 \uac00\uc815\ud558\uc790.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud074\ub77c\uc774\uc5b8\ud2b8\ub294 \uc2e4\ud328\ub85c \uc778\uc2dd\ud560 \uc218 \uc788\uc9c0\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\uc11c\ub294 \uad6c\ub9e4\uac00 \uc644\ub8cc\ub418\uc5c8\uc744 \uc218 \uc788\ub2e4. \uc774\ub54c \uc0c8\ub85c\uc6b4 \uad6c\ub9e4 \uc694\uccad\uc744 \uc0dd\uc131\ud558\uba74 \uc911\ubcf5 \uc815\uc0b0\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub530\ub77c\uc11c \uc2e4\ud328 \uc0c1\ud669\uc744 \uc720\ud615\ubcc4\ub85c \uad6c\ubd84\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><th>\uc0c1\ud669<\/th><th>\ucc98\ub9ac \ubc29\ubc95<\/th><\/tr><tr><td>\uc794\uc561 \ubd80\uc871<\/td><td>\uac70\ub798\ub97c \ub864\ubc31\ud558\uace0 \uc7ac\uc2dc\ub3c4\ud558\uc9c0 \uc54a\ub294\ub2e4.<\/td><\/tr><tr><td>\uc798\ubabb\ub41c \uc0c1\ud488 ID<\/td><td>\uc694\uccad \uc624\ub958\ub85c \ubc18\ud658\ud55c\ub2e4.<\/td><\/tr><tr><td>\ud2b8\ub79c\uc7ad\uc158 \uc911 \ud655\uc2e4\ud55c \uc2e4\ud328<\/td><td>\ub864\ubc31 \ud6c4 \ud544\uc694\uc5d0 \ub530\ub77c \uc7ac\uc2dc\ub3c4\ud55c\ub2e4.<\/td><\/tr><tr><td>\ub370\ub4dc\ub77d\uc73c\ub85c \ud2b8\ub79c\uc7ad\uc158 \ucde8\uc18c<\/td><td>\uc81c\ud55c\ub41c \ud69f\uc218\ub9cc\ud07c \ud2b8\ub79c\uc7ad\uc158 \uc804\uccb4\ub97c \uc7ac\uc2dc\ub3c4\ud55c\ub2e4.<\/td><\/tr><tr><td>DB \uc5f0\uacb0 \ud0c0\uc784\uc544\uc6c3<\/td><td>\ucee4\ubc0b \uc5ec\ubd80\uac00 \ubd88\uba85\ud655\ud560 \uc218 \uc788\uc73c\ubbc0\ub85c \uae30\uc874 \uac70\ub798\ub97c \uc870\ud68c\ud55c\ub2e4.<\/td><\/tr><tr><td>\ucee4\ubc0b \uc774\ud6c4 \uc751\ub2f5 \uc804\uc1a1 \uc2e4\ud328<\/td><td>\uae30\uc874 \uba71\ub4f1\uc131 \ud0a4\ub85c \uc800\uc7a5\ub41c \uacb0\uacfc\ub97c \ubc18\ud658\ud55c\ub2e4.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\uc7ac\uc2dc\ub3c4\ub294 \ud2b8\ub79c\uc7ad\uc158 \uc804\uccb4\uc5d0 \uc801\uc6a9\ud55c\ub2e4<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\ub370\ub4dc\ub77d\uc774 \ubc1c\uc0dd\ud558\uba74 MySQL\uc740 \ud76c\uc0dd \ud2b8\ub79c\uc7ad\uc158\uc744 \ub864\ubc31\ud560 \uc218 \uc788\ub2e4. \uc774\ub54c \uc2e4\ud328\ud55c SQL \ubb38 \ud558\ub098\ub9cc \ub2e4\uc2dc \uc2e4\ud589\ud574\uc11c\ub294 \uc548 \ub41c\ub2e4. \ud2b8\ub79c\uc7ad\uc158 \uc804\uccb4\ub97c \ub2e4\uc2dc \uc2e4\ud589\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>async function retryTransaction&lt;T&gt;(\n  operation: () =&gt; Promise&lt;T&gt;,\n  maxAttempts = 3,\n): Promise&lt;T&gt; {\n  for (let attempt = 1; ; attempt++) {\n    try {\n      return await operation();\n    } catch (error: any) {\n      const retryable =\n        error?.code === \"ER_LOCK_DEADLOCK\" ||\n        error?.code === \"ER_LOCK_WAIT_TIMEOUT\";\n\n      if (!retryable || attempt &gt;= maxAttempts) {\n        throw error;\n      }\n\n      const delay =\n        50 * 2 ** (attempt - 1) +\n        Math.random() * 50;\n\n      await new Promise((resolve) =&gt;\n        setTimeout(resolve, delay),\n      );\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ucf54\ub4dc\ub294 \uc7ac\uc2dc\ub3c4 \uc815\ucc45\uc758 \uc608\uc2dc\ub2e4. \uc2e4\uc81c \uc0ac\uc6a9 \uc2dc <code>operation<\/code>\uc740 \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \ud2b8\ub79c\uc7ad\uc158\uc744 \uc5f4\uace0, \uc791\uc5c5\uc744 \uc2e4\ud589\ud558\uace0, \ucee4\ubc0b\ud558\uac70\ub098 \ub864\ubc31\ud574\uc57c \ud55c\ub2e4. <code>ER_LOCK_WAIT_TIMEOUT<\/code>\uc758 \uacbd\uc6b0 MySQL \uc124\uc815\uc5d0 \ub530\ub77c \ud2b8\ub79c\uc7ad\uc158 \uc804\uccb4\uac00 \uc790\ub3d9 \ub864\ubc31\ub418\uc9c0 \uc54a\uc744 \uc218 \uc788\uc73c\ubbc0\ub85c, \uba85\uc2dc\uc801\uc73c\ub85c \ub864\ubc31\ud55c \ub4a4 \uc7ac\uc2dc\ub3c4\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub610\ud55c \ub124\ud2b8\uc6cc\ud06c \uc5f0\uacb0 \uc624\ub958\ub098 \ucee4\ubc0b \uacb0\uacfc\uac00 \ubd88\uba85\ud655\ud55c \uc624\ub958\ub97c \uc704 \uc7ac\uc2dc\ub3c4 \ubaa9\ub85d\uc5d0 \ubb34\uc870\uac74 \ucd94\uac00\ud574\uc11c\ub294 \uc548 \ub41c\ub2e4. \uc774\ub7f0 \uacbd\uc6b0\uc5d0\ub294 \uba3c\uc800 \uae30\uc874 \uac70\ub798\uc758 \uc0c1\ud0dc\ub97c \ud655\uc778\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc7ac\uc2dc\ub3c4\uc5d0\ub294 \uc9c0\uc218 \ubc31\uc624\ud504(Exponential Backoff)\ub97c \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4. \uc7ac\uc2dc\ub3c4 \uac04\uaca9\uc744 \uc810\ucc28 \ub298\ub9ac\uba74 \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud55c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \uc694\uccad\uc774 \uc9d1\uc911\ub418\ub294 \ud604\uc0c1\uc744 \uc904\uc77c \uc218 \uc788\ub2e4. \uc5ec\ub7ec \uc11c\ubc84\uac00 \ub3d9\uc2dc\uc5d0 \uc7ac\uc2dc\ub3c4\ud560 \ub54c\ub294 \ubb34\uc791\uc704 \uc9c0\uc5f0\uc778 Jitter\ub97c \ucd94\uac00\ud558\ub294 \uac83\ub3c4 \ud6a8\uacfc\uc801\uc774\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e8, \uc7ac\uc2dc\ub3c4 \ud69f\uc218\uc5d0\ub294 \ubc18\ub4dc\uc2dc \uc0c1\ud55c\uc774 \uc788\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Redis\ub97c \uc0ac\uc6a9\ud558\uba74 \ucda9\ubd84\ud560\uae4c?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Redis\uc758 <code>SET NX<\/code>\ub97c \uc0ac\uc6a9\ud558\uba74 \ud2b9\uc815 \ud0a4\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc744 \ub54c\ub9cc \uc0dd\uc131\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SET purchase:request:USER_1001:KEY_ABC 1 NX EX 3600<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \uba85\ub839\uc740 \uc911\ubcf5 \uc694\uccad\uc744 \ube60\ub974\uac8c \ucc28\ub2e8\ud558\ub294 \ub370 \uc720\uc6a9\ud558\ub2e4. \ud558\uc9c0\ub9cc Redis\uc5d0 \ud0a4\ub97c \uae30\ub85d\ud558\ub294 \uc791\uc5c5\uacfc MySQL\uc5d0\uc11c \ud3ec\uc778\ud2b8\ub97c \ucc28\uac10\ud558\ub294 \uc791\uc5c5\uc740 \uc11c\ub85c \ub2e4\ub978 \uc2dc\uc2a4\ud15c\uc5d0\uc11c \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\uc74c\uacfc \uac19\uc740 \ubb38\uc81c\uac00 \uc0dd\uae38 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Redis \ud0a4\ub294 \uc0dd\uc131\ub410\uc9c0\ub9cc MySQL \uad6c\ub9e4\ub294 \uc2e4\ud328\ud55c\ub2e4.<\/li>\n\n\n\n<li>MySQL \uad6c\ub9e4\ub294 \uc131\uacf5\ud588\uc9c0\ub9cc Redis \ud0a4\uac00 \ub9cc\ub8cc\ub41c\ub2e4.<\/li>\n\n\n\n<li>Redis\uc5d0\ub294 \uc131\uacf5 \uae30\ub85d\uc774 \uc788\uc9c0\ub9cc \uc2e4\uc81c \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ucee4\ubc0b \uc5ec\ubd80\ub97c \uc54c \uc218 \uc5c6\ub2e4.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\ub530\ub77c\uc11c Redis\uc758 \uc911\ubcf5 \uc694\uccad \ucc28\ub2e8\ub9cc\uc73c\ub85c \uc815\uc0b0\uc758 \uc815\ud655\uc131\uc744 \ubcf4\uc7a5\ud560 \uc218\ub294 \uc5c6\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc2e4\uc81c \uc7ac\ud654 \uc815\uc0b0\uc5d0\uc11c\ub294 MySQL\uc758 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc744 \ucd5c\uc885\uc801\uc778 \uc815\ud569\uc131 \ubcf4\uc7a5 \uc218\ub2e8\uc73c\ub85c \uc0ac\uc6a9\ud558\uace0, Redis\ub294 \uce90\uc2f1\uc774\ub098 \uc694\uccad\ub7c9 \uc81c\ud55c \ub4f1 \ubcf4\uc870\uc801\uc778 \uc6a9\ub3c4\ub85c \uc0ac\uc6a9\ud558\ub294 \uac83\uc774 \uc801\uc808\ud558\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud2b8\ub79c\uc7ad\uc158 \ubc16\uc758 \uc791\uc5c5\uacfc Outbox \ud328\ud134<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\uc544\uc774\ud15c \uad6c\ub9e4\uac00 \uc644\ub8cc\ub418\uba74 \uc11c\ubc84\ub294 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0 \uacb0\uacfc\ub97c \ubcf4\ub0b4\uac70\ub098, \uba54\uc2dc\uc9c0 \ud050\uc5d0 \uc774\ubca4\ud2b8\ub97c \ubc1c\ud589\ud558\uac70\ub098, \ub85c\uadf8 \uc2dc\uc2a4\ud15c\uc5d0 \uae30\ub85d\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud558\uc9c0\ub9cc \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud2b8\ub79c\uc7ad\uc158\uacfc \uc678\ubd80 \uc2dc\uc2a4\ud15c \ud638\ucd9c\uc744 \ud558\ub098\uc758 \uc77c\ubc18\uc801\uc778 MySQL \ud2b8\ub79c\uc7ad\uc158\uc73c\ub85c \ubb36\uc744 \uc218\ub294 \uc5c6\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc608\ub97c \ub4e4\uc5b4 \uad6c\ub9e4 \ud2b8\ub79c\uc7ad\uc158\uc740 \ucee4\ubc0b\ub418\uc5c8\uc9c0\ub9cc \uba54\uc2dc\uc9c0 \ud050 \ubc1c\ud589\uc5d0 \uc2e4\ud328\ud558\uba74 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\ub294 \uad6c\ub9e4 \ub0b4\uc5ed\uc774 \uc874\uc7ac\ud574\ub3c4 \ud6c4\uc18d \uc2dc\uc2a4\ud15c\uc740 \uad6c\ub9e4 \uc0ac\uc2e4\uc744 \uc54c\uc9c0 \ubabb\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ubb38\uc81c\uc5d0\ub294 Transactional Outbox \ud328\ud134\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">MySQL \ud2b8\ub79c\uc7ad\uc158<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud3ec\uc778\ud2b8 \ucc28\uac10 + \uc544\uc774\ud15c \uc9c0\uae09 + \uad6c\ub9e4 \uae30\ub85d + Outbox \uc774\ubca4\ud2b8 \uc0dd\uc131<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Outbox \ubc1c\ud589 \uc791\uc5c5\uc790<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ubbf8\ubc1c\ud589 \uc774\ubca4\ud2b8 \uc870\ud68c \ubc0f \uba54\uc2dc\uc9c0 \ubc1c\ud589<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uba54\uc2dc\uc9c0 \ud050 \ubc0f \ud6c4\uc18d \uc2dc\uc2a4\ud15c<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc54c\ub9bc, \ud1b5\uacc4, \uc5c5\uc801, \uc774\ubca4\ud2b8 \ubd84\uc11d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Outbox \uc774\ubca4\ud2b8\ub97c \uad6c\ub9e4 \ud2b8\ub79c\uc7ad\uc158 \uc548\uc5d0\uc11c \ud568\uaed8 \uc800\uc7a5\ud558\uba74 \uad6c\ub9e4\uac00 \ub864\ubc31\ub420 \ub54c \uc774\ubca4\ud2b8\ub3c4 \ub864\ubc31\ub41c\ub2e4. \uad6c\ub9e4\uac00 \ucee4\ubc0b\ub418\uc5c8\ub2e4\uba74 \ubc1c\ud589 \uc791\uc5c5\uc790\uac00 \uc774\ubca4\ud2b8\ub97c \ub098\uc911\uc5d0 \uc804\uc1a1\ud560 \uc218 \uc788\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ub2e4\ub9cc \uc774\ubca4\ud2b8 \ubc1c\ud589\uacfc \uc18c\ube44 \uacfc\uc815\uc5d0\uc11c\ub294 \uc911\ubcf5\uc774 \ubc1c\uc0dd\ud560 \uc218 \uc788\ub2e4. \ub530\ub77c\uc11c Outbox \ubc1c\ud589 \uc791\uc5c5\uc790\ub294 \ubc1c\ud589 \uc0c1\ud0dc\ub97c \uad00\ub9ac\ud574\uc57c \ud558\uace0, \uc18c\ube44\uc790\ub294 \uc774\ubca4\ud2b8 ID\ub97c \uae30\uc900\uc73c\ub85c \uc911\ubcf5 \ucc98\ub9ac\ub97c \ubc29\uc9c0\ud574\uc57c \ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc774 \ubc29\uc2dd\uc740 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc640 \uba54\uc2dc\uc9c0 \ud050 \uc0ac\uc774\uc758 \uc6d0\uc790\uc801 \ucee4\ubc0b\uc744 \uc81c\uacf5\ud558\ub294 \uac83\uc740 \uc544\ub2c8\ub2e4. \ub300\uc2e0 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0 \ud655\uc815\ub41c \uc791\uc5c5\uc744 \uc783\uc9c0 \uc54a\uace0 \ud6c4\uc18d \uc2dc\uc2a4\ud15c\uc73c\ub85c \uc804\ub2ec\ud560 \uc218 \uc788\ub3c4\ub85d \uc124\uacc4\ud558\ub294 \ubc29\uc2dd\uc774\ub2e4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\uc804 \uc124\uacc4 \uccb4\ud06c\ub9ac\uc2a4\ud2b8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uc815\uc0b0 \uc2dc\uc2a4\ud15c \uc810\uac80\ud45c<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">0\/16 \uc644\ub8cc<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc794\uc561 \ubc0f \uc6d0\uc7a5\uc794\uc561 \ubcc0\uacbd\uacfc \uc6d0\uc7a5 \uae30\ub85d\uc744 \uac19\uc740 \ud2b8\ub79c\uc7ad\uc158\uc5d0\uc11c \ucc98\ub9ac\ud55c\ub2e4.\ud3ec\uc778\ud2b8 \ucc28\uac10\uc740 \uc870\uac74\ubd80 UPDATE\ub85c \uc218\ud589\ud55c\ub2e4.\uc6d0\uc7a5 \uac70\ub798 ID\uc5d0 \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc744 \uc801\uc6a9\ud55c\ub2e4.\uc6b4\uc601\uc790 \ubcf4\uc815\uacfc \ud658\ubd88\ub3c4 \ubcc4\ub3c4 \uac70\ub798\ub85c \uae30\ub85d\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uad6c\ub9e4 \ubc0f \ubcf4\uc0c1\uc0c1\ud488 \uac00\uaca9\uacfc \uac8c\uc784 \ubcf4\uc0c1\uc740 \uc11c\ubc84\uc5d0\uc11c \uacb0\uc815\ud55c\ub2e4.\ud3ec\uc778\ud2b8 \ucc28\uac10\uacfc \uc544\uc774\ud15c \uc9c0\uae09\uc744 \uc6d0\uc790\uc801\uc73c\ub85c \ucc98\ub9ac\ud55c\ub2e4.\uacbd\uae30 ID\uc640 \ubcf4\uc0c1 \ub300\uc0c1\uc5d0 \ub9de\ub294 \uc911\ubcf5 \ubc29\uc9c0 \ud0a4\ub97c \uc815\uc758\ud55c\ub2e4.\uc778\ubca4\ud1a0\ub9ac\uc640 \uad6c\ub9e4 \uae30\ub85d\uc5d0 \uc801\uc808\ud55c \uc720\ub2c8\ud06c \uc81c\uc57d \uc870\uac74\uc744 \ub454\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uba71\ub4f1\uc131 \ubc0f \ubcf5\uad6c\ub3d9\uc77c \uc791\uc5c5\uc758 \uc7ac\uc2dc\ub3c4\uc5d0 \uac19\uc740 Idempotency-Key\ub97c \uc0ac\uc6a9\ud55c\ub2e4.\ub3d9\uc77c \ud0a4\uc5d0 \ub2e4\ub978 \uc694\uccad \ub0b4\uc6a9\uc774 \ub4e4\uc5b4\uc624\uba74 \uac70\ubd80\ud55c\ub2e4.\ucee4\ubc0b \uc5ec\ubd80\uac00 \ubd88\uba85\ud655\ud558\uba74 \uae30\uc874 \uac70\ub798 \uc0c1\ud0dc\ub97c \ud655\uc778\ud55c\ub2e4.\ub370\ub4dc\ub77d \uc7ac\uc2dc\ub3c4\uc640 \uc678\ubd80 \uc774\ubca4\ud2b8 \uc7ac\ubc1c\ud589 \uc815\ucc45\uc744 \uc815\uc758\ud55c\ub2e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\uc6b4\uc601 \ubc0f \uac80\uc99d\ub3d9\uc2dc \uad6c\ub9e4 \ubc0f \uc911\ubcf5 \ubcf4\uc0c1 \ud14c\uc2a4\ud2b8\ub97c \uc218\ud589\ud55c\ub2e4.\uc794\uc561\uacfc \uc6d0\uc7a5\uc758 \uc815\ud569\uc131\uc744 \uc8fc\uae30\uc801\uc73c\ub85c \uac80\uc99d\ud55c\ub2e4.\ubbf8\uc644\ub8cc \uac70\ub798\uc640 Outbox \ubbf8\ubc1c\ud589 \uc774\ubca4\ud2b8\ub97c \ubaa8\ub2c8\ud130\ub9c1\ud55c\ub2e4.\uc2e4\ud328 \uc6d0\uc778, \uac70\ub798 ID, \uc7ac\uc2dc\ub3c4 \ud69f\uc218\ub97c \ub85c\uadf8\ub85c \ub0a8\uae34\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uac8c\uc784 \uc11c\ubc84\uc5d0\uc11c \ud3ec\uc778\ud2b8 \ucc28\uac10, \uc544\uc774\ud15c \uad6c\ub9e4, \uac8c\uc784 \uacb0\uacfc\uc5d0 \ub530\ub978 \ubcf4\uc0c1 \uc9c0\uae09\uc740 \ub2e8\uc21c\ud55c \ub370\uc774\ud130 \ubcc0\uacbd\uc774 \uc544\ub2c8\ub2e4. \uc5ec\ub7ec \uc694\uccad\uc774 \ub3d9\uc2dc\uc5d0 \ubc1c\uc0dd\ud558\uace0, \ub124\ud2b8\uc6cc\ud06c\uac00 \ub04a\uae30\uac70\ub098, \uc11c\ubc84\uac00 \uc911\uac04\uc5d0 \uc885\ub8cc\ub418\ub354\ub77c\ub3c4 \ud50c\ub808\uc774\uc5b4\uc758 \uc7ac\ud654\uc640 \uc544\uc774\ud15c\uc774 \uc815\ud655\ud558\uac8c \uc720\uc9c0\ub418\uc5b4\uc57c \ud558\ub294 \uc815\uc0b0 \uc2dc\uc2a4\ud15c\uc774\ub2e4. \uc608\ub97c \ub4e4\uc5b4 \ud50c\ub808\uc774\uc5b4\uac00 1,000\ud3ec\uc778\ud2b8\ub97c \ubcf4\uc720\ud558\uace0 \uc788\uc744 \ub54c 700\ud3ec\uc778\ud2b8\uc9dc\ub9ac \uc544\uc774\ud15c\uc744 \ub3d9\uc2dc\uc5d0 \ub450 \ubc88 \uad6c\ub9e4\ud55c\ub2e4\uace0 \uac00\uc815\ud558\uc790. \uc11c\ubc84\uac00 \uc794\uc561\uc744 \uac80\uc99d\ud558\ub294 \uc2dc\uc810\uacfc \ucc28\uac10\ud558\ub294 \uc2dc\uc810\uc744 \uc801\uc808\ud558\uac8c \uc81c\uc5b4\ud558\uc9c0 \ubabb\ud558\uba74 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2678","post","type-post","status-publish","format-standard","hentry","category-dev-logs"],"_links":{"self":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2678"}],"version-history":[{"count":1,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2678\/revisions"}],"predecessor-version":[{"id":2679,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=\/wp\/v2\/posts\/2678\/revisions\/2679"}],"wp:attachment":[{"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wayhope.kro.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}