{"id":3006,"date":"2025-03-16T17:27:00","date_gmt":"2025-03-16T08:27:00","guid":{"rendered":"https:\/\/manvscloud.com\/?p=3006"},"modified":"2025-03-16T17:27:00","modified_gmt":"2025-03-16T08:27:00","slug":"ncloud-secret-manager%eb%a1%9c-cloud-db-for-postgresql-%ed%8c%a8%ec%8a%a4%ec%9b%8c%eb%93%9c-%ea%b4%80%eb%a6%ac%ed%95%98%ea%b8%b0","status":"publish","type":"post","link":"https:\/\/manvscloud.com\/?p=3006","title":{"rendered":"[NCLOUD] Secret Manager\ub85c Cloud DB for PostgreSQL \ud328\uc2a4\uc6cc\ub4dc \uad00\ub9ac\ud558\uae30"},"content":{"rendered":"\n<p>\uc548\ub155\ud558\uc138\uc694 MANVSCLOUD \uae40\uc218\ud604\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ubcf4\uc548\uc740 \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c \uac00\uc7a5 \uc911\uc694\ud55c \uc694\uc18c \uc911 \ud558\ub098\uc785\ub2c8\ub2e4. \ud2b9\ud788 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc554\ud638\uc640 \uac19\uc740 \uc911\uc694\ud55c \ubcf4\uc548 \uc815\ubcf4\ub97c \uc548\uc804\ud558\uac8c \uad00\ub9ac\ud558\ub294 \uac83\uc740 \ub9e4\uc6b0 \uc911\uc694\ud569\ub2c8\ub2e4. \uc624\ub298\uc740 \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc758 Secret Manager\ub97c \ud65c\uc6a9\ud558\uc5ec Cloud DB for PostgreSQL\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub97c \ud6a8\uacfc\uc801\uc73c\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc744 \uc18c\uac1c\ud574\ub4dc\ub9ac\uace0\uc790 \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\ud604\uc7ac \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \uacf5\uc2dd \uac00\uc774\ub4dc\uc5d0\uc11c\ub294 Secret Manager\ub97c \uc774\uc6a9\ud55c Cloud DB for MySQL \ud328\uc2a4\uc6cc\ub4dc \uad00\ub9ac \ubc29\ubc95\uc774 \uc81c\uacf5\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 Cloud DB for PostgreSQL\uc5d0 \ucd08\uc810\uc744 \ub9de\ucd94\uc5b4 \uc791\uc131\ud558\uc5ec \uc57d\uac04\uc758 \ucf54\ub4dc \uc218\uc815\ub9cc\uc73c\ub85c \ub2e4\uc591\ud55c \uc11c\ube44\uc2a4\uc5d0\ub3c4 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4\ub294 \uc810\uc744 \uacf5\uc720\ub4dc\ub9ac\uace0\uc790 \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-green-cyan-background-color has-text-color has-background has-link-color wp-elements-a6789067ed4fb6dcdb1a0a7a2be56083\"> \uc65c Secret Manager\ub97c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c?<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025610\/Secret-Manager.webp\" alt=\"\" class=\"wp-image-3012\" style=\"width:373px;height:auto\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025610\/Secret-Manager.webp 1024w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025610\/Secret-Manager-300x300.webp 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025610\/Secret-Manager-150x150.webp 150w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025610\/Secret-Manager-768x768.webp 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>\ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub97c  \uad00\ub9ac\ud560 \ub54c Secret Manager\ub97c \uc0ac\uc6a9\ud558\uba74 \uc88b\uc740 \uc810\uc740 \ud06c\uac8c \uc138 \uac00\uc9c0\ub85c \uc694\uc57d\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<ol>\n<li><strong>\ubcf4\uc548 \uac15\ud654<\/strong>: \ubbfc\uac10\ud55c \uc790\uaca9 \uc99d\uba85\uc774 \uc18c\uc2a4 \ucf54\ub4dc\uc5d0 \ud558\ub4dc\ucf54\ub529\ub418\uac70\ub098 \ud658\uacbd \ubcc0\uc218\uc5d0 \ub178\ucd9c\ub418\ub294 \uc704\ud5d8\uc744 \uc81c\uac70\ud569\ub2c8\ub2e4. <\/li>\n\n\n\n<li><strong>\uc790\ub3d9 \uad50\uccb4 \uc9c0\uc6d0<\/strong>: Secret Manager\uc5d0\uc11c \uc790\ub3d9 \uad50\uccb4 \uc8fc\uae30\ub97c \uc124\uc815\ud558\uba74 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud328\uc2a4\uc6cc\ub4dc\uac00 \uc815\uae30\uc801\uc73c\ub85c \ubcc0\uacbd\ub418\uc5b4\ub3c4 \uc560\ud50c\ub9ac\ucf00\uc774\uc158 \ucf54\ub4dc\ub97c \uc218\uc815\ud560 \ud544\uc694 \uc5c6\uc774 \ud56d\uc0c1 \ucd5c\uc2e0 \uc790\uaca9 \uc99d\uba85\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub530\ub77c\uc11c \ubcf4\uc548 \uc815\ucc45 \uc900\uc218\uc640 \ud568\uaed8 \uc6b4\uc601 \ubd80\ub2f4\ub3c4 \ud06c\uac8c \uc904\uc5ec\uc90d\ub2c8\ub2e4.<\/li>\n\n\n\n<li><strong>\uc911\uc559\ud654\ub41c \uc790\uaca9 \uc99d\uba85 \uad00\ub9ac<\/strong>: \ubaa8\ub4e0 \ube44\ubc00\ubc88\ud638\uc640 API \ud0a4\ub97c \ud55c \uacf3\uc5d0\uc11c \ud1b5\ud569 \uad00\ub9ac\ud568\uc73c\ub85c\uc368 \uc6b4\uc601 \ud6a8\uc728\uc131\uc744 \ub192\uc774\uace0 \uc561\uc138\uc2a4 \uc81c\uc5b4 \ubc0f \uac10\uc0ac\ub97c \ub354\uc6b1 \uc218\uc6d4\ud558\uac8c \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub610\ud55c \uc5ec\ub7ec \uc2dc\uc2a4\ud15c\uacfc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc5d0\uc11c \uc77c\uad00\ub41c \ubc29\uc2dd\uc73c\ub85c \ubcf4\uc548 \uc815\ubcf4\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-vivid-green-cyan-background-color has-text-color has-background has-link-color wp-elements-ffac39d13de22a187b042df54b79402c\"> Secret Manager \uc124\uc815\ud558\uae30<\/h3>\n\n\n\n<p>Secret Manager\uc758 \uc124\uc815\uc740 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. <br>\ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \ucf58\uc194\uc5d0\uc11c \uac04\ub2e8\ud558\uac8c \uc0dd\uc131\ud560 \uc218 \uc788\uc73c\uba70 \uc0dd\uc131 \uc2dc \ub450 \uac00\uc9c0 \uc124\uc815\ub9cc \uc798 \uc120\ud0dd \ubc0f \uc785\ub825\ud574\uc8fc\ub3c4\ub85d \ud569\uc2dc\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"992\" height=\"416\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025330\/secret-01.png\" alt=\"\" class=\"wp-image-3009\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025330\/secret-01.png 992w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025330\/secret-01-300x126.png 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025330\/secret-01-768x322.png 768w\" sizes=\"(max-width: 992px) 100vw, 992px\" \/><\/figure>\n\n\n\n<p> \uccab\uc9f8\ub85c &#8220;\uad50\uccb4 \uc124\uc815&#8221; \ubd80\ubd84\uc785\ub2c8\ub2e4. \uad50\uccb4 \uc124\uc815\uc5d0\uc11c\ub294 Secret\uc758 \uc790\ub3d9 \uad50\uccb4 \uae30\ub2a5\uc744 \ud65c\uc131\ud654\ud558\uace0 \uad50\uccb4 \uc8fc\uae30\ub97c \uc815\uc758\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br><ul class=\"[&amp;:not(:last-child)_ul]:pb-1 [&amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7\" depth=\"0\"><br><li class=\"whitespace-normal break-words\" index=\"0\"><strong>\uad50\uccb4 \uc8fc\uae30<\/strong>: \ucd5c\uc18c 1\uc77c\ubd80\ud130 \ucd5c\ub300 730\uc77c(\uc57d 2\ub144)\uae4c\uc9c0 \uc124\uc815 \uac00\ub2a5\ud569\ub2c8\ub2e4. \uc870\uc9c1 \ub0b4 \ubcf4\uc548 \uc815\ucc45\uc5d0 \ub9de\ub294 \uc8fc\uae30\ub85c \uc124\uc815\ud558\uba74 \ub429\ub2c8\ub2e4. <\/li><br><li class=\"whitespace-normal break-words\" index=\"1\"><strong>\ud2b8\ub9ac\uac70 \ucd94\uac00<\/strong>: \uad50\uccb4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\ud560 \ud2b8\ub9ac\uac70\ub97c \ubc18\ub4dc\uc2dc \ucd94\uac00\ud574\uc57c \ud569\ub2c8\ub2e4. \uc774 \ud2b8\ub9ac\uac70\ub294 \ub098\uc911\uc5d0 Cloud Functions\uc5d0 \uc5f0\uacb0\ub418\uc5b4 \uc2e4\uc81c \ud328\uc2a4\uc6cc\ub4dc \ubcc0\uacbd \uc791\uc5c5\uc744 \uc218\ud589\ud560 \ub54c \uc0ac\uc6a9\ud569\ub2c8\ub2e4.<\/li><\/ul><p class=\"whitespace-pre-wrap break-words\"><\/p><\/p>\n\n\n\n<p>\ub458\uc9f8\ub294 &#8220;Secret \uac12 \uc785\ub825&#8221; \ubd80\ubd84\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"319\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-1024x319.png\" alt=\"\" class=\"wp-image-3010\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-1024x319.png 1024w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-300x94.png 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-768x240.png 768w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-1536x479.png 1536w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02-1080x337.png 1080w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025336\/secret-02.png 1577w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Secret \uac12 \uc785\ub825 \ubd80\ubd84\uc5d0\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0a4-\uac12(Key-Value) \uc30d\uc744 \uc124\uc815\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<ul>\n<li><strong>cdbHost<\/strong>: Cloud DB for PostgreSQL\uc758 \ud638\uc2a4\ud2b8 \uc8fc\uc18c (\uc608: <code>example.vpc-cdb-kr.ntruss.com<\/code>)<\/li>\n\n\n\n<li><strong>cdbPort<\/strong>: PostgreSQL \uc11c\ubc84\uc758 \ud3ec\ud2b8 \ubc88\ud638 (\uae30\ubcf8\uac12: 5432 \ub610\ub294 \ucee4\uc2a4\ud140 \ud3ec\ud2b8)<\/li>\n\n\n\n<li><strong>cdbDatabase<\/strong>: \uc5f0\uacb0\ud560 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc774\ub984<\/li>\n\n\n\n<li><strong>cdbUser<\/strong>: \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc811\uc18d \uc0ac\uc6a9\uc790 \uc774\ub984<\/li>\n\n\n\n<li><strong>cdbPassword<\/strong>: \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc0ac\uc6a9\uc790\uc758 \ud604\uc7ac \ud328\uc2a4\uc6cc\ub4dc<\/li>\n<\/ul>\n\n\n\n<p>\uc5ec\uae30\uc11c \uc911\uc694\ud55c \uc810\uc740 \uad50\uccb4 \ub300\uc0c1 \ud56d\ubaa9\uc744 \uc120\ud0dd\ud558\ub294 \uac83\uc785\ub2c8\ub2e4. \uc704 \uc608\uc2dc\uc5d0\uc11c\ub294 <code>cdbPassword<\/code> \ud56d\ubaa9\ub9cc \uad50\uccb4 \ub300\uc0c1\uc73c\ub85c \uccb4\ud06c\ud588\uc2b5\ub2c8\ub2e4. \uc774\ub807\uac8c \uc124\uc815\ud558\uba74 \uad50\uccb4 \uc8fc\uae30\uc5d0 \ub530\ub77c <code>cdbPassword<\/code> \uac12(Value)\ub9cc \uc0c8 \uac12(Value)\uc73c\ub85c \ubcc0\uacbd\ub418\uba70 Cloud Functions\uc774 \ub3d9\uc791\ud558\uba74\uc11c Cloud DB for PostgreSQL\uc758 \uc2e4\uc81c \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub3c4 \ud568\uaed8 \uc5c5\ub370\uc774\ud2b8\ub429\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\uc774\ub807\uac8c \uc124\uc815\ud568\uc73c\ub85c\uc368 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud328\uc2a4\uc6cc\ub4dc\ub97c \uc218\ub3d9\uc73c\ub85c \uc8fc\uae30\uc801\uc73c\ub85c \ubcc0\uacbd\ud558\uace0 \ucd94\uc801\ud558\ub294 \ubc88\uac70\ub85c\uc6c0 \uc5c6\uc774 Secret Manager\uc5d0\uc11c \uc790\ub3d9\uc73c\ub85c \ubaa8\ub4e0 \uac83\uc744 \uad00\ub9ac\ud560 \uc218 \uc788\uac8c \ub429\ub2c8\ub2e4. <\/p>\n\n\n\n<p>\uc774\uc81c Secret Manager\uac00 \uc124\uc815\ub418\uc5c8\uc73c\ub2c8 \uc2e4\uc81c\ub85c Secret\uc774 \uc790\ub3d9 \uad50\uccb4\ub420 \ub54c Cloud DB for PostgreSQL\uc758 \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub3c4 \ud568\uaed8 \ubcc0\uacbd\ub418\ub3c4\ub85d Cloud Functions\uc744 \uad6c\uc131\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<ul>\n<li><strong>Custom Image \uc900\ube44\ud558\uae30<\/strong><\/li>\n<\/ul>\n\n\n\n<p>\uae30\ubcf8 Cloud Functions \ud658\uacbd\uc5d0\ub294 PostgreSQL \uc5f0\uacb0\uc5d0 \ud544\uc694\ud55c \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ub530\ub77c\uc11c \ud544\uc694\ud55c \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud3ec\ud568\ub41c \ucee4\uc2a4\ud140 \uc774\ubbf8\uc9c0\ub97c \uba3c\uc800 \uc0dd\uc131\ud574\uc57c \ud569\ub2c8\ub2e4. \uc774\ub97c \uc704\ud574 Container Registry\ub97c \ud65c\uc6a9\ud558\uaca0\uc2b5\ub2c8\ub2e4.<br>(\uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 Container Registry \uc0dd\uc131 \uac00\uc774\ub4dc\ub294 \uc81c\uacf5\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.)<\/p>\n\n\n\n<p>\ub2e4\uc74c\uc740 PostgreSQL \ud074\ub77c\uc774\uc5b8\ud2b8 \ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \ud3ec\ud568\ub41c Dockerfile \uc608\uc2dc\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">FROM cloudfunctions.kr.ncr.ntruss.com\/cloudfunctions-python-3.7:latest\n\nRUN dnf install -y python3.11 &amp;&amp; dnf remove -y python37\n\nRUN rm -f \/usr\/local\/bin\/python\nRUN ln -s \/usr\/bin\/python3.11 \/usr\/local\/bin\/python\n\nRUN dnf install -y python3.11-pip\nRUN \/usr\/bin\/pip3.11 install psycopg2-binary\nRUN \/usr\/bin\/pip3.11 install requests\n\nWORKDIR \/\n\nENTRYPOINT [\"\/bin\/proxy\"]<\/pre>\n\n\n\n<p>\ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc5d0\uc11c \uae30\ubcf8 \uc774\ubbf8\uc9c0\ub85c \uc81c\uacf5\ud558\ub294 Python 3.7 \ubc84\uc804 \uae30\ubcf8 \uc774\ubbf8\uc9c0\ub97c \uba3c\uc800 \uac00\uc838\uc640\uc11c \uc0ac\uc6a9\ud588\uc2b5\ub2c8\ub2e4. Python 3.11 \ubc84\uc804\uc744 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub3c4\ub85d \uae30\uc874 Python \uc81c\uac70 \ubc0f 3.11 \ubc84\uc804\uc73c\ub85c \uc124\uce58\ud574\uc8fc\uace0 pip\ub97c \uc774\uc6a9\ud558\uc5ec \ud544\uc694\ud55c \ub77c\uc774\ube0c\ub7ec\ub9ac(psycopg2-binary)\ub97c \uc124\uce58\ud574\uc92c\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc Container Registry\uc5d0 \ub85c\uadf8\uc778\ndocker login \ub808\uc9c0\uc2a4\ud2b8\ub9ac_\uc774\ub984.kr.ncr.ntruss.com\n\n# \uc774\ubbf8\uc9c0 \ube4c\ub4dc\ndocker build -t \ub808\uc9c0\uc2a4\ud2b8\ub9ac_\uc774\ub984.kr.ncr.ntruss.com\/secret-manager-psql:1.0 .\n\n# \uc774\ubbf8\uc9c0 \ud478\uc2dc\ndocker push \ub808\uc9c0\uc2a4\ud2b8\ub9ac_\uc774\ub984.kr.ncr.ntruss.com\/secret-manager-psql:1.0<\/pre>\n\n\n\n<p>Dockerfile\uc774 \uc0dd\uc131\ub418\uc5c8\ub2e4\uba74 \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc5d0 \uc0ac\uc804\uc5d0 \uc0dd\uc131\ud574\ub454 Container Registry\uc5d0 \ub85c\uadf8\uc778\ud558\uace0 \uc774\ubbf8\uc9c0 Build \ubc0f Push\ub97c \ud574\uc90d\ub2c8\ub2e4.<\/p>\n\n\n\n<ul>\n<li><strong>Cloud Functions Action \uc0dd\uc131<\/strong><\/li>\n<\/ul>\n\n\n\n<p>\uc774\uc81c \ucee4\uc2a4\ud140 \uc774\ubbf8\uc9c0\ub97c \uc0ac\uc6a9\ud558\ub294 Cloud Functions\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. <br>Cloud Functions \uc0dd\uc131 \uc2dc \ub2e4\uc74c \uc0ac\ud56d\uc744 \uc124\uc815\ud574\uc8fc\uc138\uc694.<\/p>\n\n\n\n<p>1) <strong>\ub7f0\ud0c0\uc784 \ud658\uacbd<\/strong>: \ucee4\uc2a4\ud140 \uc774\ubbf8\uc9c0 \uc120\ud0dd \ud6c4 \uc704\uc5d0\uc11c \ud478\uc2dc\ud55c \uc774\ubbf8\uc9c0 \uc9c0\uc815<br>2) <strong>\ud2b8\ub9ac\uac70 \uc5f0\uacb0<\/strong>: Secret Manager\uc5d0\uc11c \uc124\uc815\ud55c \ud2b8\ub9ac\uac70 \uc120\ud0dd<br>3) <strong>\uae30\ubcf8 \ud30c\ub77c\ubbf8\ud130<\/strong>:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n  \"secretId\": \"\uc0dd\uc131\ud55c Secret Manager\uc758 ID\",\n  \"accessKey\": \"Secret Manager \uad8c\ud55c\uc744 \uac00\uc9c4 \uc561\uc138\uc2a4 \ud0a4\",\n  \"secretKey\": \"Secret Manager \uad8c\ud55c\uc744 \uac00\uc9c4 \uc2dc\ud06c\ub9bf \ud0a4\"\n}<\/pre>\n\n\n\n<ul>\n<li><strong>Cloud Functions Action Code<\/strong><br> : \ucf54\ub4dc\ub294 \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \uac00\uc774\ub4dc\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 &#8216;MySQL \ud328\uc2a4\uc6cc\ub4dc &#8216;Cloud DB for MySQL\uc5d0\uc11c \ud328\uc2a4\uc6cc\ub4dc(cdbPassword)\ub97c \ub2e8\uc77c\u00a0<strong>\uad50\uccb4 \ub300\uc0c1<\/strong>\uc73c\ub85c \uc124\uc815\ud55c \uc0c1\ud0dc\uc5d0\uc11c \uad50\uccb4\ub97c \uc2e4\ud589\ud558\ub294 \ud30c\uc774\uc36c \uc561\uc158 \uc608\uc2dc \ucf54\ub4dc&#8217;\ub97c Cloud DB for PostgreSQL\ub85c \ubcc0\uacbd\ud55c \ucf54\ub4dc\uc785\ub2c8\ub2e4.<br><br>\uc8fc\uc11d(#)\ucc98\ub9ac \ud55c \ubd80\ubd84\uc744 \uc774\ud574\ud558\uace0 PostgreSQL\ubfd0\ub9cc \uc544\ub2c8\ub77c \ucf54\ub4dc\ub97c \uc218\uc815\ud558\uc5ec \ub2e4\ub978 \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc5d0\ub3c4 \ub2e4\uc591\ud558\uac8c \ud65c\uc6a9\ud558\uc2e4 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import hmac\nimport hashlib\nimport base64\nimport json\nimport requests\n# MySQL \ub77c\uc774\ube0c\ub7ec\ub9ac\uc5d0\uc11c PostgreSQL \ub77c\uc774\ube0c\ub7ec\ub9ac\ub85c \ubcc0\uacbd\n# import mysql.connector\n# from mysql.connector import Error\nimport psycopg2\nfrom psycopg2 import Error\nimport time\n\n# Constants\nACCESS_KEY = None\nSECRET_KEY = None\nBASE_URL = None\nJOB_TOKEN = None\n\ndef init_requests(secret_id, job_token, access_key, secret_key):\n    global BASE_URL, JOB_TOKEN, API_KEY, ACCESS_KEY, SECRET_KEY\n    BASE_URL = f\"https:\/\/secretmanager.apigw.ntruss.com\/action\/v1\/secrets\/{secret_id}\/jobs\/{job_token}\"\n    JOB_TOKEN = job_token\n    ACCESS_KEY = access_key\n    SECRET_KEY = secret_key\n\ndef make_signature(method, url, timestamp):\n    message = f\"{method} {url}\\n{timestamp}\\n{ACCESS_KEY}\"\n    signing_key = SECRET_KEY.encode('utf-8')\n    mac = hmac.new(signing_key, message.encode('utf-8'), hashlib.sha256)\n    return base64.b64encode(mac.digest()).decode('utf-8')\n\ndef main(args):\n    secret_id = args[\"secretId\"]\n    job_token = args[\"jobToken\"]\n    access_key = args[\"accessKey\"]\n    secret_key = args[\"secretKey\"]\n\n    result = {}\n    skip_update_pending = False\n\n    try:\n        init_requests(secret_id, job_token, access_key, secret_key)\n        print(f\"[Secret Rotation Job (secret_id={secret_id})]\")\n\n        secret_value_response = start_rotation()\n        print(\"[STEP1 COMPLETE] start rotation\")\n\n        secret_value = secret_value_response[\"data\"]\n        secret_chain = secret_value[\"decryptedSecretChain\"]\n        rotation_targets = secret_value[\"rotationTargets\"]\n\n        # Step 2: Generate secret value\n        if \"pending\" not in secret_chain or secret_chain[\"pending\"] is None:\n            pending = {\n                \"cdbHost\": json.loads(secret_chain[\"active\"])[\"cdbHost\"],\n                \"cdbPort\": json.loads(secret_chain[\"active\"])[\"cdbPort\"],\n                \"cdbUser\": json.loads(secret_chain[\"active\"])[\"cdbUser\"],\n                \"cdbDatabase\": json.loads(secret_chain[\"active\"])[\"cdbDatabase\"],\n                \"cdbPassword\": set_secret_value()\n            }\n            secret_chain[\"pending\"] = json.dumps(pending)\n            print(\"[STEP2 COMPLETE] update pending\")\n        else:\n            skip_update_pending = True\n            print(\"[STEP2 SIKP] already exist pending\")\n\n        change_password(secret_chain, rotation_targets)\n        print(\"[STEP3 COMPLETE] rotate secret\")\n\n        test_password(secret_chain, rotation_targets)\n        print(\"[STEP4 COMPLETE] test secret\")\n\n        # Step 5: Update Pending\n        if skip_update_pending:\n            print(\"[STEP5 SKIP] update pending\")\n        else:\n            update_pending(secret_chain, rotation_targets)\n            print(\"[STEP5 COMPLETE] update pending\")\n\n        complete_rotation()\n        print(\"[STEP6 COMPLETE] complete rotation\")\n\n        result[\"done\"] = True\n        result[\"pending\"] = secret_chain[\"pending\"]\n\n    except Exception as ex:\n        print(str(ex))\n        fail_rotation()\n        result[\"done\"] = False\n        result[\"error_message\"] = str(ex)\n\n    print(json.dumps(result, indent=4))\n    return result\n\ndef start_rotation():\n    return execute_request(\"\/start\", {}, \"POST\")\n\ndef set_secret_value():\n    req_body = {\n        \"length\": 16,\n        \"excludeCharacters\": \"\\\"&amp;'+\/\\\\`\",\n        \"requireEachIncludedType\": True\n    }\n    response = execute_request(\"\/generate-random-secret\", req_body, \"POST\")\n    print(json.dumps(response, indent=4))\n    return response.get(\"randomString\")\n\ndef change_password(secret_chain, rotation_targets):\n    if not rotation_targets:\n        raise ValueError(\"rotationTargets is empty\")\n\n    rotation_target = rotation_targets[0]\n    active_value = json.loads(secret_chain[\"active\"])\n\n    cdb_host = active_value[\"cdbHost\"]\n    cdb_database = active_value[\"cdbDatabase\"]\n    cdb_user = active_value[\"cdbUser\"]\n    cdb_port = int(active_value[\"cdbPort\"])\n    print(f\"cdbHost: {cdb_host}, cdbDatabase: {cdb_database}, cdbUser: {cdb_user}, cdbPort: {cdb_port}\")\n\n    if \"pending\" not in secret_chain:\n        raise ValueError(\"error_message: pending is None\")\n\n    update_password(cdb_host, cdb_port, cdb_user, cdb_database, rotation_target, secret_chain)\n\ndef update_password(cdb_host, cdb_port, cdb_user, cdb_database, rotation_target, secret_chain):\n    active = json.loads(secret_chain[\"active\"])\n    previous = json.loads(secret_chain.get(\"previous\", \"{}\"))\n    pending = json.loads(secret_chain[\"pending\"])\n    pending_password = pending[rotation_target]\n\n    try:\n        conn = try_connection(cdb_host, cdb_port, cdb_user, pending_password, cdb_database, \"pending\")\n        if conn:\n            conn.close()\n            return\n\n        active_password = active[rotation_target]\n        conn = try_connection(cdb_host, cdb_port, cdb_user, active_password, cdb_database, \"active\")\n        if conn:\n            update_db_password(conn, cdb_user, pending_password)\n            return\n\n        if \"previous\" in secret_chain:\n            previous_password = previous.get(rotation_target)\n            conn = try_connection(cdb_host, cdb_port, cdb_user, previous_password, cdb_database, \"previous\")\n            if conn:\n                update_db_password(conn, cdb_user, pending_password)\n            else:\n                raise ValueError(\"All Secret Values are not valid\")\n\n    except Error as ex:\n        print(\"[STEP3 ERROR]\", ex)\n        raise\n\ndef try_connection(cdb_host, cdb_port, cdb_user, password, cdb_database, password_type):\n    print(f\"Connecting using the {password_type} password\")\n    return db_connect(cdb_host, cdb_port, cdb_user, password, cdb_database)\n\ndef update_db_password(conn, cdb_user, new_password):\n    # MySQL \ucffc\ub9ac\ub97c PostgreSQL \ucffc\ub9ac\ub85c \ubcc0\uacbd\n    # query = f\"ALTER USER '{cdb_user}'@'%' IDENTIFIED BY '{new_password}'\"\n    query = f\"ALTER USER {cdb_user} WITH PASSWORD '{new_password}'\"\n    cursor = conn.cursor()\n    cursor.execute(query)\n    # PostgreSQL\uc5d0\uc11c\ub3c4 commit \ud544\uc694\n    conn.commit()\n    cursor.close()\n\ndef test_password(secret_chain, rotation_targets):\n    rotation_target = rotation_targets[0]\n\n    pending_value = json.loads(secret_chain[\"pending\"])\n    pending_password = pending_value[rotation_target]\n    active_value = json.loads(secret_chain[\"active\"])\n    cdb_host = active_value[\"cdbHost\"]\n    cdb_database = active_value[\"cdbDatabase\"]\n    cdb_user = active_value[\"cdbUser\"]\n    cdb_port = int(active_value[\"cdbPort\"])\n\n    conn = db_connect(cdb_host, cdb_port, cdb_user, pending_password, cdb_database)\n    if conn is None:\n        raise ValueError(\"error_message: connection failed\")\n    conn.close()\n\ndef update_pending(secret_chain, rotation_targets):\n    rotation_target = rotation_targets[0]\n\n    non_change_values = json.loads(secret_chain[\"active\"])\n    cdb_host = non_change_values[\"cdbHost\"]\n    cdb_database = non_change_values[\"cdbDatabase\"]\n    cdb_user = non_change_values[\"cdbUser\"]\n    cdb_port = non_change_values[\"cdbPort\"]\n\n    pending = {\n        \"cdbHost\": cdb_host,\n        \"cdbPort\": cdb_port,\n        \"cdbUser\": cdb_user,\n        \"cdbDatabase\": cdb_database,\n        \"cdbPassword\": json.loads(secret_chain[\"pending\"])[rotation_target]\n    }\n\n    req_body = {\n        \"value\": json.dumps(pending)\n    }\n    execute_request(\"\/pending\", req_body, \"PUT\")\n\ndef complete_rotation():\n    execute_request(\"\/complete\", {}, \"POST\")\n\ndef fail_rotation():\n    try:\n        execute_request(\"\/fail\", {}, \"POST\")\n    except Exception as ex:\n        print(\"[FAIL ROTATION NOTIFICATION ERROR]\", ex)\n\ndef execute_request(endpoint, request_body, method):\n    url = BASE_URL + endpoint\n    print(\"Request url:\", url)\n    timestamp = str(int(time.time() * 1000))\n    headers = {\n        \"Content-Type\": \"application\/json\",\n        \"x-ncp-apigw-timestamp\": timestamp,\n        \"x-ncp-iam-access-key\": ACCESS_KEY,\n        \"x-ncp-apigw-signature-v2\": make_signature(method, url.replace(\"https:\/\/secretmanager.apigw.ntruss.com\", \"\"), timestamp),\n        \"SECRET-JOB-TOKEN\": JOB_TOKEN\n    }\n    if method == \"POST\":\n        response = requests.post(url, headers=headers, json=request_body)\n    elif method == \"PUT\":\n        response = requests.put(url, headers=headers, json=request_body)\n    else:\n        raise ValueError(\"Invalid HTTP method\")\n\n    response_body = response.json()\n    print(\"Request Body:\", request_body)\n    print(\"Response Body:\", response_body)\n\n    if response.status_code != 200:\n        raise Exception(f\"Unexpected response {response.status_code}\")\n\n    return response_body\n\ndef db_connect(cdb_host, cdb_port, cdb_user, cdb_pass, cdb_database):\n    try:\n        # MySQL \uc5f0\uacb0 \ucf54\ub4dc\ub97c PostgreSQL \uc5f0\uacb0 \ucf54\ub4dc\ub85c \ubcc0\uacbd\n        # connection = mysql.connector.connect(\n        #     host=cdb_host,\n        #     port=cdb_port,\n        #     user=cdb_user,\n        #     password=cdb_pass,\n        #     database=cdb_database\n        # )\n        connection = psycopg2.connect(\n            host=cdb_host,\n            port=cdb_port,\n            user=cdb_user,\n            password=cdb_pass,\n            dbname=cdb_database\n        )\n        print(\"Database connection established successfully\")\n        return connection\n    except Error as e:\n        print(\"Database connection failed:\", e)\n        return None<\/pre>\n\n\n\n<p>Action \uc2e4\ud589 \uc804 \ud544\uc218 \uc124\uc815 \uc911 \ud558\ub098\ub85c Cloud Functions\uc774 Cloud DB for PostgreSQL\uc5d0 \uc5f0\uacb0\ud560 \uc218 \uc788\ub3c4\ub85d \ub124\ud2b8\uc6cc\ud06c \uc124\uc815\uc744 \ud574\uc57c \ud569\ub2c8\ub2e4. Cloud DB for PostgreSQL\uc758 ACG(Access Control Group)\uc5d0\uc11c Cloud Functions\uc774 \uc2e4\ud589\ub418\ub294 \uc11c\ube0c\ub137 \ub300\uc5ed\uc744 \ud5c8\uc6a9\ud574\uc8fc\uc138\uc694. Cloud Functions\uc774 Cloud DB for PostgreSQL\uc5d0 \uc811\uadfc\ud558\uc5ec \ud328\uc2a4\uc6cc\ub4dc\ub97c \ubcc0\uacbd\ud560 \uc218 \uc788\ub3c4\ub85d\uc694!<\/p>\n\n\n\n<p>\ubaa8\ub4e0 \uc124\uc815\uc774 \uc644\ub8cc\ub418\uc5c8\ub2e4\uba74 Secret Manager\uc5d0\uc11c \uc218\ub3d9\uc73c\ub85c [\uad50\uccb4 \uc2e4\ud589] \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \uc804\uccb4 \ud504\ub85c\uc138\uc2a4\ub97c \ud14c\uc2a4\ud2b8\ud574\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uc815\uc0c1\uc801\uc73c\ub85c Secret\uc774 \uad50\uccb4\ub418\uc5c8\ub2e4\uba74 \uc544\ub798\uc640 \uac19\uc774 &#8216;cdbPassword&#8217; \ubd80\ubd84\uc774 \ubcc0\uacbd\ub418\uc5b4 \uc774\uc804 \ud328\uc2a4\uc6cc\ub4dc\uac00 [Previous]\uc5d0 \uc0c8\ub85c \ubcc0\uacbd\ub41c \ud328\uc2a4\uc6cc\ub4dc\uac00 [Active]\uc5d0 \uc788\ub294 \uac83\uc744 \uc54c \uc218 \uc788\uc2b5\ub2c8\ub2e4. (Secret \uad50\uccb4 \ud6c4 \ubcc0\uacbd\ub41c \ud328\uc2a4\uc6cc\ub4dc\ub85c\ub3c4 \uc811\uc18d\ud574\ubcf4\uc138\uc694!)<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"356\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03-1024x356.png\" alt=\"\" class=\"wp-image-3007\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03-1024x356.png 1024w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03-300x104.png 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03-768x267.png 768w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03-1080x375.png 1080w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025133\/secret-03.png 1378w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\ub610\ud55c \uad50\uccb4\uac00 \uc815\uc0c1\uc801\uc73c\ub85c \uc9c4\ud589\ub418\uc5c8\ub2e4\uba74 \uc544\ub798\uc640 \uac19\uc774 \uc9c4\ud589 \ub2e8\uacc4\uc5d0\uc11c \uc624\ub958 \uc5c6\uc774 \uc815\uc0c1 \uad50\uccb4 \uc885\ub8cc \uc0c1\ud0dc\ub97c \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. \ub9cc\uc57d \uc2e4\ud328\ud588\ub2e4\uba74 \ub85c\uadf8 \ud655\uc778\uc774 \uac00\ub2a5\ud558\ub2c8 \ub85c\uadf8\ub97c \ud655\uc778\ud558\uc5ec \uc6d0\uc778 \ud30c\uc545\ub3c4 \ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"785\" height=\"265\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025259\/secret-04.png\" alt=\"\" class=\"wp-image-3008\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025259\/secret-04.png 785w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025259\/secret-04-300x101.png 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2025\/03\/16025259\/secret-04-768x259.png 768w\" sizes=\"(max-width: 785px) 100vw, 785px\" \/><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading has-white-color has-cyan-bluish-gray-background-color has-text-color has-background has-link-color wp-elements-790b4ede7486cf11fc8601a67c8dcb47\"> Personal Comments<\/h3>\n\n\n\n<p>\uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc758 Secret Manager\ub97c \uc0ac\uc6a9\ud558\uc5ec Cloud DB for PostgreSQL\uc758 \ud328\uc2a4\uc6cc\ub4dc\ub97c \uc548\uc804\ud558\uace0 \uc790\ub3d9\ud654\ub41c \ubc29\uc2dd\uc73c\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc744 \uc54c\uc544\ubcf4\uc558\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>Secret Manager\uc640 Cloud Functions\uc758 \uc870\ud569\uc740 \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c \uc790\uaca9 \uc99d\uba85 \uad00\ub9ac\ub97c \ud604\ub300\ud654\ud558\uace0 \ubcf4\uc548\uc744 \uac15\ud654\ud558\ub294 \uac15\ub825\ud55c \ubc29\ubc95\uc785\ub2c8\ub2e4. \uc774\ub7ec\ud55c \uc811\uadfc \ubc29\uc2dd\uc740 \uae08\uc735, \uc758\ub8cc, \uacf5\uacf5 \ubd80\ubb38\uacfc \uac19\uc774 \uaddc\uc81c\uac00 \uc5c4\uaca9\ud55c \uc0b0\uc5c5\uc5d0\uc11c \ud2b9\ud788 \uc720\uc6a9\ud558\uba70 \ubcf4\uc548 \ubaa8\ubc94 \uc0ac\ub840\ub97c \uc900\uc218\ud558\ub294 \ub370 \ud070 \ub3c4\uc6c0\uc774 \ub429\ub2c8\ub2e4.<\/p>\n\n\n\n<p>Secret Manager\uc758 \ud65c\uc6a9\uc740 \ub2e8\uc21c\ud788 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \ud328\uc2a4\uc6cc\ub4dc \uad00\ub9ac\uc5d0 \uad6d\ud55c\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. API \ud0a4, OAuth \ud074\ub77c\uc774\uc5b8\ud2b8 \uc2dc\ud06c\ub9bf, \uc778\uc99d\uc11c \ub4f1 \ub2e4\uc591\ud55c \ubcf4\uc548 \uc790\uaca9 \uc99d\uba85\uc744 \uad00\ub9ac\ud558\ub294 \ub370\ub3c4 \ub3d9\uc77c\ud55c \ud328\ud134\uc744 \uc801\uc6a9\ud560 \uc218 \uc788\ub294 \uc810 \ucc38\uace0\ud558\uba74 \uc88b\uc744 \uac83\uac19\uc2b5\ub2c8\ub2e4 \ud83d\ude42<\/p>\n\n\n\n<p>\uae34 \uae00 \uc77d\uc5b4\uc8fc\uc154\uc11c \uac10\uc0ac\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"773\" height=\"133\" src=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2021\/08\/12204137\/Ncloud_Master_logo.png\" alt=\"\" class=\"wp-image-1229\" srcset=\"https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2021\/08\/12204137\/Ncloud_Master_logo.png 773w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2021\/08\/12204137\/Ncloud_Master_logo-300x52.png 300w, https:\/\/cdn.manvscloud.com\/wp-content\/uploads\/2021\/08\/12204137\/Ncloud_Master_logo-768x132.png 768w\" sizes=\"(max-width: 773px) 100vw, 773px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>\uc548\ub155\ud558\uc138\uc694 MANVSCLOUD \uae40\uc218\ud604\uc785\ub2c8\ub2e4. \ubcf4\uc548\uc740 \ud074\ub77c\uc6b0\ub4dc \ud658\uacbd\uc5d0\uc11c \uac00\uc7a5 \uc911\uc694\ud55c \uc694\uc18c \uc911 \ud558\ub098\uc785\ub2c8\ub2e4. \ud2b9\ud788 \ub370\uc774\ud130\ubca0\uc774\uc2a4 \uc554\ud638\uc640 \uac19\uc740 \uc911\uc694\ud55c \ubcf4\uc548 \uc815\ubcf4\ub97c \uc548\uc804\ud558\uac8c \uad00\ub9ac\ud558\ub294 \uac83\uc740 \ub9e4\uc6b0 \uc911\uc694\ud569\ub2c8\ub2e4. \uc624\ub298\uc740 \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc758 Secret Manager\ub97c \ud65c\uc6a9\ud558\uc5ec Cloud DB for PostgreSQL\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub97c \ud6a8\uacfc\uc801\uc73c\ub85c \uad00\ub9ac\ud558\ub294 \ubc29\ubc95\uc744 \uc18c\uac1c\ud574\ub4dc\ub9ac\uace0\uc790 \ud569\ub2c8\ub2e4. \ud604\uc7ac \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \uacf5\uc2dd \uac00\uc774\ub4dc\uc5d0\uc11c\ub294 Secret Manager\ub97c \uc774\uc6a9\ud55c Cloud DB for MySQL \ud328\uc2a4\uc6cc\ub4dc \uad00\ub9ac \ubc29\ubc95\uc774 \uc81c\uacf5\ub418\uace0 \uc788\uc2b5\ub2c8\ub2e4. \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294 Cloud DB for PostgreSQL\uc5d0 \ucd08\uc810\uc744 \ub9de\ucd94\uc5b4 \uc791\uc131\ud558\uc5ec \uc57d\uac04\uc758 \ucf54\ub4dc \uc218\uc815\ub9cc\uc73c\ub85c \ub2e4\uc591\ud55c \uc11c\ube44\uc2a4\uc5d0\ub3c4 \uc801\uc6a9\ud560 \uc218 \uc788\ub2e4\ub294 \uc810\uc744 \uacf5\uc720\ub4dc\ub9ac\uace0\uc790 \ud569\ub2c8\ub2e4. \uc65c Secret Manager\ub97c \uc0ac\uc6a9\ud574\uc57c \ud560\uae4c? \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc\uc5d0\uc11c \ub370\uc774\ud130\ubca0\uc774\uc2a4\uc758 \uc0ac\uc6a9\uc790 \ud328\uc2a4\uc6cc\ub4dc\ub97c \uad00\ub9ac\ud560 \ub54c Secret Manager\ub97c \uc0ac\uc6a9\ud558\uba74 \uc88b\uc740 \uc810\uc740 \ud06c\uac8c \uc138 \uac00\uc9c0\ub85c \uc694\uc57d\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. Secret Manager \uc124\uc815\ud558\uae30 Secret Manager\uc758 \uc124\uc815\uc740 \ud06c\uac8c \uc5b4\ub835\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \ub124\uc774\ubc84 \ud074\ub77c\uc6b0\ub4dc \ucf58\uc194\uc5d0\uc11c \uac04\ub2e8\ud558\uac8c \uc0dd\uc131\ud560 \uc218 \uc788\uc73c\uba70 \uc0dd\uc131 \uc2dc \ub450 \uac00\uc9c0 \uc124\uc815\ub9cc \uc798 \uc120\ud0dd \ubc0f \uc785\ub825\ud574\uc8fc\ub3c4\ub85d \ud569\uc2dc\ub2e4. \uccab\uc9f8\ub85c &#8220;\uad50\uccb4 \uc124\uc815&#8221; \ubd80\ubd84\uc785\ub2c8\ub2e4. \uad50\uccb4 \uc124\uc815\uc5d0\uc11c\ub294 Secret\uc758 \uc790\ub3d9 \uad50\uccb4 \uae30\ub2a5\uc744 \ud65c\uc131\ud654\ud558\uace0 \uad50\uccb4 \uc8fc\uae30\ub97c \uc815\uc758\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uad50\uccb4 \uc8fc\uae30: \ucd5c\uc18c 1\uc77c\ubd80\ud130 \ucd5c\ub300 730\uc77c(\uc57d 2\ub144)\uae4c\uc9c0 \uc124\uc815 \uac00\ub2a5\ud569\ub2c8\ub2e4. \uc870\uc9c1 \ub0b4 \ubcf4\uc548 \uc815\ucc45\uc5d0 \ub9de\ub294 \uc8fc\uae30\ub85c \uc124\uc815\ud558\uba74 \ub429\ub2c8\ub2e4. \ud2b8\ub9ac\uac70 \ucd94\uac00: \uad50\uccb4 \ud504\ub85c\uc138\uc2a4\ub97c \uc2e4\ud589\ud560 \ud2b8\ub9ac\uac70\ub97c \ubc18\ub4dc\uc2dc \ucd94\uac00\ud574\uc57c \ud569\ub2c8\ub2e4. \uc774 \ud2b8\ub9ac\uac70\ub294 \ub098\uc911\uc5d0 Cloud Functions\uc5d0 \uc5f0\uacb0\ub418\uc5b4 \uc2e4\uc81c \ud328\uc2a4\uc6cc\ub4dc \ubcc0\uacbd \uc791\uc5c5\uc744 \uc218\ud589\ud560 \ub54c \uc0ac\uc6a9\ud569\ub2c8\ub2e4. \ub458\uc9f8\ub294 &#8220;Secret \uac12 \uc785\ub825&#8221; \ubd80\ubd84\uc785\ub2c8\ub2e4. Secret \uac12 \uc785\ub825 \ubd80\ubd84\uc5d0\uc11c\ub294 \ub2e4\uc74c\uacfc \uac19\uc740 \ud0a4-\uac12(Key-Value) \uc30d\uc744 \uc124\uc815\ud569\ub2c8\ub2e4. \uc5ec\uae30\uc11c \uc911\uc694\ud55c \uc810\uc740 \uad50\uccb4 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[1014,1008,456,457,32,87,91,17,90,16,1013,220,805,89,202,398,221,860,1015,244],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/posts\/3006"}],"collection":[{"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/manvscloud.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3006"}],"version-history":[{"count":2,"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/posts\/3006\/revisions"}],"predecessor-version":[{"id":3013,"href":"https:\/\/manvscloud.com\/index.php?rest_route=\/wp\/v2\/posts\/3006\/revisions\/3013"}],"wp:attachment":[{"href":"https:\/\/manvscloud.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3006"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/manvscloud.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3006"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/manvscloud.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}