@portone/mcp-server 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +165 -0
- package/assets/docs/README.md +27 -0
- package/assets/docs/api/backward-compatibility.md +40 -0
- package/assets/docs/blog/posts/2024-02/v2-oom.md +341 -0
- package/assets/docs/blog/posts/2024-02/v2-webhook.md +314 -0
- package/assets/docs/blog/posts/2024-02/v2-zio.md +529 -0
- package/assets/docs/blog/posts/2024-03/tgs.md +238 -0
- package/assets/docs/blog/posts/2024-04/gcp-datastream.md +307 -0
- package/assets/docs/blog/posts/2024-04/solid.md +558 -0
- package/assets/docs/blog/posts/2024-07/v2-event-sourcing-basic.md +231 -0
- package/assets/docs/help/admin-console/analytics/content32.md +270 -0
- package/assets/docs/help/admin-console/console-account/content31.md +94 -0
- package/assets/docs/help/admin-console/console_home/content34.md +82 -0
- package/assets/docs/help/admin-console/integration/content28.md +79 -0
- package/assets/docs/help/admin-console/payment-service/content29.md +260 -0
- package/assets/docs/help/admin-console/pg-settlement/content30.md +352 -0
- package/assets/docs/help/admin-console/platform-settlement/content33-1.md +201 -0
- package/assets/docs/help/api-sdk-2024-12-19.md +64 -0
- package/assets/docs/help/api-sdk-2025-01-15.md +84 -0
- package/assets/docs/help/applepay.md +46 -0
- package/assets/docs/help/content100000.md +46 -0
- package/assets/docs/help/content100002.md +52 -0
- package/assets/docs/help/content100004.md +29 -0
- package/assets/docs/help/content100014.md +50 -0
- package/assets/docs/help/content100015.md +20 -0
- package/assets/docs/help/content100016.md +28 -0
- package/assets/docs/help/content100020.md +28 -0
- package/assets/docs/help/content100022.md +40 -0
- package/assets/docs/help/content100023.md +21 -0
- package/assets/docs/help/content100024.md +25 -0
- package/assets/docs/help/content100025.md +40 -0
- package/assets/docs/help/content100026.md +20 -0
- package/assets/docs/help/content100027.md +24 -0
- package/assets/docs/help/content100029.md +29 -0
- package/assets/docs/help/content100030.md +82 -0
- package/assets/docs/help/content100033.md +44 -0
- package/assets/docs/help/content100035.md +34 -0
- package/assets/docs/help/content100036.md +14 -0
- package/assets/docs/help/content100037.md +16 -0
- package/assets/docs/help/content100038.md +32 -0
- package/assets/docs/help/content100039.md +28 -0
- package/assets/docs/help/content100040.md +31 -0
- package/assets/docs/help/content100041.md +37 -0
- package/assets/docs/help/content100044.md +15 -0
- package/assets/docs/help/content100045.md +21 -0
- package/assets/docs/help/content100046.md +34 -0
- package/assets/docs/help/content100047.md +32 -0
- package/assets/docs/help/content100048.md +25 -0
- package/assets/docs/help/content100049.md +20 -0
- package/assets/docs/help/content100052.md +147 -0
- package/assets/docs/help/content100053.md +40 -0
- package/assets/docs/help/content100054.md +18 -0
- package/assets/docs/help/content100055.md +37 -0
- package/assets/docs/help/content100056.md +15 -0
- package/assets/docs/help/content100057.md +28 -0
- package/assets/docs/help/content100058.md +36 -0
- package/assets/docs/help/content100059.md +23 -0
- package/assets/docs/help/content100060.md +43 -0
- package/assets/docs/help/content200001.md +21 -0
- package/assets/docs/help/content200002.md +38 -0
- package/assets/docs/help/content200005.md +30 -0
- package/assets/docs/help/content200012.md +91 -0
- package/assets/docs/help/content200013.md +52 -0
- package/assets/docs/help/content200015.md +41 -0
- package/assets/docs/help/content200016.md +30 -0
- package/assets/docs/help/content200017.md +39 -0
- package/assets/docs/help/content200018.md +105 -0
- package/assets/docs/help/content200019.md +59 -0
- package/assets/docs/help/content200020.md +42 -0
- package/assets/docs/help/content200023.md +54 -0
- package/assets/docs/help/content200024.md +49 -0
- package/assets/docs/help/content200025.md +68 -0
- package/assets/docs/help/content200027.md +34 -0
- package/assets/docs/help/content200028.md +70 -0
- package/assets/docs/help/content200029.md +71 -0
- package/assets/docs/help/content200030.md +67 -0
- package/assets/docs/help/content200032.md +39 -0
- package/assets/docs/help/content200033.md +21 -0
- package/assets/docs/help/content200034.md +34 -0
- package/assets/docs/help/content200037.md +38 -0
- package/assets/docs/help/content200038.md +50 -0
- package/assets/docs/help/content200039.md +45 -0
- package/assets/docs/help/content200040.md +15 -0
- package/assets/docs/help/content200043.md +23 -0
- package/assets/docs/help/content200044.md +33 -0
- package/assets/docs/help/content200045.md +25 -0
- package/assets/docs/help/content200046.md +104 -0
- package/assets/docs/help/content200048.md +34 -0
- package/assets/docs/help/content200049.md +54 -0
- package/assets/docs/help/content200050.md +43 -0
- package/assets/docs/help/content200051.md +81 -0
- package/assets/docs/help/content51.md +38 -0
- package/assets/docs/help/content61.md +165 -0
- package/assets/docs/help/core-service/channel-setting/danal.md +170 -0
- package/assets/docs/help/core-service/channel-setting/daou.md +118 -0
- package/assets/docs/help/core-service/channel-setting/eximbay.md +136 -0
- package/assets/docs/help/core-service/channel-setting/inicis.md +340 -0
- package/assets/docs/help/core-service/channel-setting/kakaopay.md +107 -0
- package/assets/docs/help/core-service/channel-setting/kcp_channel.md +235 -0
- package/assets/docs/help/core-service/channel-setting/kicc.md +114 -0
- package/assets/docs/help/core-service/channel-setting/kpn.md +93 -0
- package/assets/docs/help/core-service/channel-setting/ksnet.md +116 -0
- package/assets/docs/help/core-service/channel-setting/mobilians.md +107 -0
- package/assets/docs/help/core-service/channel-setting/naverpay.md +179 -0
- package/assets/docs/help/core-service/channel-setting/nice.md +210 -0
- package/assets/docs/help/core-service/channel-setting/payco.md +124 -0
- package/assets/docs/help/core-service/channel-setting/paymentwall.md +107 -0
- package/assets/docs/help/core-service/channel-setting/paypal.md +247 -0
- package/assets/docs/help/core-service/channel-setting/settle.md +123 -0
- package/assets/docs/help/core-service/channel-setting/smartro.md +164 -0
- package/assets/docs/help/core-service/channel-setting/smilepay.md +83 -0
- package/assets/docs/help/core-service/channel-setting/tosspay.md +168 -0
- package/assets/docs/help/core-service/channel-setting/tosspayments.md +232 -0
- package/assets/docs/help/core-service/channel-setting/welcome.md +110 -0
- package/assets/docs/help/core-service/how-to-use/additional-danal.md +71 -0
- package/assets/docs/help/core-service/how-to-use/additional-daou.md +65 -0
- package/assets/docs/help/core-service/how-to-use/additional-eximbay.md +54 -0
- package/assets/docs/help/core-service/how-to-use/additional-inicis.md +97 -0
- package/assets/docs/help/core-service/how-to-use/additional-kakaopay.md +56 -0
- package/assets/docs/help/core-service/how-to-use/additional-kcp.md +53 -0
- package/assets/docs/help/core-service/how-to-use/additional-kicc.md +67 -0
- package/assets/docs/help/core-service/how-to-use/additional-ksnet.md +68 -0
- package/assets/docs/help/core-service/how-to-use/additional-mobilians.md +71 -0
- package/assets/docs/help/core-service/how-to-use/additional-naverpay-order.md +69 -0
- package/assets/docs/help/core-service/how-to-use/additional-naverpay.md +72 -0
- package/assets/docs/help/core-service/how-to-use/additional-nice.md +112 -0
- package/assets/docs/help/core-service/how-to-use/additional-payco.md +68 -0
- package/assets/docs/help/core-service/how-to-use/additional-settle.md +70 -0
- package/assets/docs/help/core-service/how-to-use/additional-smartro.md +70 -0
- package/assets/docs/help/core-service/how-to-use/additional-tosspay.md +57 -0
- package/assets/docs/help/core-service/how-to-use/additional-tosspayments.md +47 -0
- package/assets/docs/help/core-service/how-to-use/additional-welcome.md +72 -0
- package/assets/docs/help/core-service/how-to-use/cancel-deadline-by-paymethod.md +68 -0
- package/assets/docs/help/core-service/how-to-use/cancel-guide-using-admin-console.md +49 -0
- package/assets/docs/help/core-service/how-to-use/cancel-reversal.md +114 -0
- package/assets/docs/help/core-service/how-to-use/cellphone-identity-verification.md +62 -0
- package/assets/docs/help/core-service/how-to-use/content200000.md +72 -0
- package/assets/docs/help/core-service/how-to-use/content200009.md +83 -0
- package/assets/docs/help/core-service/how-to-use/danal-contract.md +82 -0
- package/assets/docs/help/core-service/how-to-use/daou-contract.md +82 -0
- package/assets/docs/help/core-service/how-to-use/eximbay-contract.md +75 -0
- package/assets/docs/help/core-service/how-to-use/high-risk-industry.md +554 -0
- package/assets/docs/help/core-service/how-to-use/identity-verification-value.md +61 -0
- package/assets/docs/help/core-service/how-to-use/impossible-partial-cancel.md +53 -0
- package/assets/docs/help/core-service/how-to-use/information-pg.md +151 -0
- package/assets/docs/help/core-service/how-to-use/inicis-contract.md +95 -0
- package/assets/docs/help/core-service/how-to-use/inicis-vat.md +45 -0
- package/assets/docs/help/core-service/how-to-use/inicis-vbank-refund.md +45 -0
- package/assets/docs/help/core-service/how-to-use/kakao-contract.md +73 -0
- package/assets/docs/help/core-service/how-to-use/kakaopay-contract.md +41 -0
- package/assets/docs/help/core-service/how-to-use/kcp-contract.md +82 -0
- package/assets/docs/help/core-service/how-to-use/kcp-vat.md +39 -0
- package/assets/docs/help/core-service/how-to-use/kcp-vbank-refund.md +46 -0
- package/assets/docs/help/core-service/how-to-use/kicc-contract.md +81 -0
- package/assets/docs/help/core-service/how-to-use/ksnet-contract.md +78 -0
- package/assets/docs/help/core-service/how-to-use/mobilians-contract.md +81 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-contract.md +86 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-order-1.md +36 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-order-contract.md +88 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-order-diff.md +66 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-order-review-items.md +66 -0
- package/assets/docs/help/core-service/how-to-use/naverpay-review-items.md +199 -0
- package/assets/docs/help/core-service/how-to-use/nice-contract.md +81 -0
- package/assets/docs/help/core-service/how-to-use/open-immediately.md +60 -0
- package/assets/docs/help/core-service/how-to-use/other-hosting-company.md +38 -0
- package/assets/docs/help/core-service/how-to-use/payco-contract.md +74 -0
- package/assets/docs/help/core-service/how-to-use/payment-settlement-method.md +30 -0
- package/assets/docs/help/core-service/how-to-use/paymentwall-contract.md +85 -0
- package/assets/docs/help/core-service/how-to-use/paypal-contract.md +66 -0
- package/assets/docs/help/core-service/how-to-use/point-service.md +293 -0
- package/assets/docs/help/core-service/how-to-use/refund-date.md +66 -0
- package/assets/docs/help/core-service/how-to-use/requirements.md +100 -0
- package/assets/docs/help/core-service/how-to-use/settle-contract.md +79 -0
- package/assets/docs/help/core-service/how-to-use/shopify-available-list.md +65 -0
- package/assets/docs/help/core-service/how-to-use/shopify-guide.md +62 -0
- package/assets/docs/help/core-service/how-to-use/small-business-commission-fee.md +55 -0
- package/assets/docs/help/core-service/how-to-use/smartro-contract.md +77 -0
- package/assets/docs/help/core-service/how-to-use/test-mode-cancel.md +63 -0
- package/assets/docs/help/core-service/how-to-use/tosspay-contract.md +82 -0
- package/assets/docs/help/core-service/how-to-use/tosspayments-contract.md +82 -0
- package/assets/docs/help/core-service/how-to-use/welcome-contract.md +81 -0
- package/assets/docs/help/core-service/how-to-use/withsoft-guide.md +69 -0
- package/assets/docs/help/core-service/how-to-use/wordpress-available-pg.md +49 -0
- package/assets/docs/help/core-service/how-to-use/wordpress-setting.md +50 -0
- package/assets/docs/help/core-service/payment-type/billing-key.md +72 -0
- package/assets/docs/help/core-service/payment-type/content200003.md +39 -0
- package/assets/docs/help/core-service/payment-type/content200007.md +176 -0
- package/assets/docs/help/core-service/payment-type/content200036.md +37 -0
- package/assets/docs/help/core-service/payment-type/content200042.md +150 -0
- package/assets/docs/help/core-service/payment-type/content200047.md +215 -0
- package/assets/docs/help/core-service/payment-type/content200052.md +142 -0
- package/assets/docs/help/core-service/payment-type/content200053.md +128 -0
- package/assets/docs/help/core-service/payment-type/crossborder.md +132 -0
- package/assets/docs/help/core-service/payment-type/eximbay-international.md +96 -0
- package/assets/docs/help/core-service/payment-type/hub-service-fee.md +79 -0
- package/assets/docs/help/core-service/payment-type/inicis-easypay-hub-fee.md +45 -0
- package/assets/docs/help/core-service/payment-type/inicis-international.md +65 -0
- package/assets/docs/help/core-service/payment-type/internationl-high-risk-industry.md +267 -0
- package/assets/docs/help/core-service/payment-type/internationl-pg.md +42 -0
- package/assets/docs/help/core-service/payment-type/kcp-easypay-hub-apply.md +49 -0
- package/assets/docs/help/core-service/payment-type/kcp-international.md +60 -0
- package/assets/docs/help/core-service/payment-type/nice-easypay-hub-fee.md +72 -0
- package/assets/docs/help/core-service/payment-type/nice-international.md +51 -0
- package/assets/docs/help/core-service/payment-type/paymentwall-international.md +84 -0
- package/assets/docs/help/core-service/payment-type/paypal-international.md +86 -0
- package/assets/docs/help/core-service/payment-type/paypal-payment-status.md +55 -0
- package/assets/docs/help/core-service/payment-type/schedule-logic-guide.md +49 -0
- package/assets/docs/help/core-service/payment-type/schedule-requirement.md +111 -0
- package/assets/docs/help/core-service/payment-type/schedule-validity-guide.md +68 -0
- package/assets/docs/help/core-service/payment-type/tosspayment-international.md +54 -0
- package/assets/docs/help/core-service/payment-type/tosspayments-easypay-hub-fee.md +42 -0
- package/assets/docs/help/core-service/payment-type/webhook-re-send.md +41 -0
- package/assets/docs/help/faq/console-faq/2-depth-auth.md +53 -0
- package/assets/docs/help/faq/console-faq/add-admin-account.md +42 -0
- package/assets/docs/help/faq/console-faq/change-console-url.md +51 -0
- package/assets/docs/help/faq/console-faq/impossible-login.md +30 -0
- package/assets/docs/help/faq/console-faq/payment-list.md +45 -0
- package/assets/docs/help/faq/console-faq/sub-store-mgnt.md +97 -0
- package/assets/docs/help/faq/general-inquiry/change-business-number.md +32 -0
- package/assets/docs/help/faq/general-inquiry/confirm-process.md +118 -0
- package/assets/docs/help/faq/general-inquiry/content200004.md +55 -0
- package/assets/docs/help/faq/general-inquiry/content200006.md +86 -0
- package/assets/docs/help/faq/general-inquiry/content200011.md +24 -0
- package/assets/docs/help/faq/general-inquiry/content200031.md +194 -0
- package/assets/docs/help/faq/general-inquiry/content200041.md +21 -0
- package/assets/docs/help/faq/general-inquiry/contract-checkpoint.md +49 -0
- package/assets/docs/help/faq/general-inquiry/main-user.md +56 -0
- package/assets/docs/help/faq/general-inquiry/platform-contract-method.md +67 -0
- package/assets/docs/help/faq/general-inquiry/platform-contract-pg.md +234 -0
- package/assets/docs/help/faq/general-inquiry/portone-advantages.md +71 -0
- package/assets/docs/help/faq/general-inquiry/real-channel-info.md +70 -0
- package/assets/docs/help/faq/general-inquiry/what-is-the-small-business-fee.md +41 -0
- package/assets/docs/help/faq/payment-faq/business-card-available.md +55 -0
- package/assets/docs/help/faq/payment-faq/business-info-change.md +96 -0
- package/assets/docs/help/faq/payment-faq/cancel-deadline.md +32 -0
- package/assets/docs/help/faq/payment-faq/cancel-guide.md +48 -0
- package/assets/docs/help/faq/payment-faq/cash-receipt-guide.md +64 -0
- package/assets/docs/help/faq/payment-faq/content200022.md +73 -0
- package/assets/docs/help/faq/payment-faq/pg-max-min-amount.md +158 -0
- package/assets/docs/help/faq/payment-faq/receipt-guide.md +38 -0
- package/assets/docs/help/faq/payment-faq/tosspayments-cash-receipt.md +32 -0
- package/assets/docs/help/faq/payment-faq/vbank-info.md +35 -0
- package/assets/docs/help/faq/payment-faq/vbank-service-detail.md +67 -0
- package/assets/docs/help/faq/payment-faq/vbank-test-guide.md +65 -0
- package/assets/docs/help/faq/platform-faq/platform_function_partnerbulkupload.md +190 -0
- package/assets/docs/help/faq/platform-faq/platform_infosec.md +56 -0
- package/assets/docs/help/faq/platform-faq/platform_nocode_guide.md +104 -0
- package/assets/docs/help/faq/platform-faq/platform_payout_guide.md +75 -0
- package/assets/docs/help/faq/platform-faq/platform_policymanagement_calculator.md +73 -0
- package/assets/docs/help/faq/platform-faq/platform_settlmentandpayout_guide.md +83 -0
- package/assets/docs/help/faq/platform-faq/platform_tax_setting_guide.md +108 -0
- package/assets/docs/help/faq/platform-faq/taxinvoice_guide.md +107 -0
- package/assets/docs/help/faq/platform-faq/taxinvoice_signupemail.md +67 -0
- package/assets/docs/help/holidays.md +29 -0
- package/assets/docs/help/notice-kakaopay-2025-06-30.md +47 -0
- package/assets/docs/help/platform-2024-11-07.md +73 -0
- package/assets/docs/help/platform-2024-11-25.md +91 -0
- package/assets/docs/help/platform-2024-12-10.md +71 -0
- package/assets/docs/help/platform-2025-03-04.md +54 -0
- package/assets/docs/help/platform-2025-04-03.md +105 -0
- package/assets/docs/help/platform-2025-04-08.md +120 -0
- package/assets/docs/help/platform-2025-05-14.md +70 -0
- package/assets/docs/help/platform-2025-1-16.md +65 -0
- package/assets/docs/help/platform-2025-2-10.md +75 -0
- package/assets/docs/help/platform-2025-2-13.md +43 -0
- package/assets/docs/help/portone-service/portone-service/content50.md +80 -0
- package/assets/docs/help/pricing/pg/domestic-and-oversea-fees.md +34 -0
- package/assets/docs/help/pricing/portone/portone-pricing.md +116 -0
- package/assets/docs/help/procedure/payment-integration/real-integration.md +43 -0
- package/assets/docs/help/procedure/payment-integration/test-integration.md +91 -0
- package/assets/docs/help/procedure/pg-application/content53.md +49 -0
- package/assets/docs/help/procedure/pg-application/content54.md +136 -0
- package/assets/docs/help/procedure/pg-application/content59.md +53 -0
- package/assets/docs/help/procedure/pg-application/start.md +154 -0
- package/assets/docs/help/procedure/recommendation/package.md +98 -0
- package/assets/docs/help/procedure/service-addition/add-service.md +98 -0
- package/assets/docs/help/recon_issue1.md +25 -0
- package/assets/docs/help/recon_issue2.md +29 -0
- package/assets/docs/help/service/identity-verification/identity-verification.md +65 -0
- package/assets/docs/help/service/integration-type/integration-type.md +49 -0
- package/assets/docs/help/service/payment-type/payment-type.md +100 -0
- package/assets/docs/help/service/paymethod/paymethod.md +100 -0
- package/assets/docs/help/service/pg/pg-service-list.md +339 -0
- package/assets/docs/help/service/version/portone-version.md +61 -0
- package/assets/docs/opi/ko/console/guide/account.md +111 -0
- package/assets/docs/opi/ko/console/guide/api-keys.md +34 -0
- package/assets/docs/opi/ko/console/guide/billing-payments.md +312 -0
- package/assets/docs/opi/ko/console/guide/channel-manage.md +303 -0
- package/assets/docs/opi/ko/console/guide/connect.md +84 -0
- package/assets/docs/opi/ko/console/guide/home.md +37 -0
- package/assets/docs/opi/ko/console/guide/integration.md +18 -0
- package/assets/docs/opi/ko/console/guide/list.md +183 -0
- package/assets/docs/opi/ko/console/guide/pay.md +14 -0
- package/assets/docs/opi/ko/console/guide/payments.md +298 -0
- package/assets/docs/opi/ko/console/guide/promotion.md +140 -0
- package/assets/docs/opi/ko/console/guide/readme.md +22 -0
- package/assets/docs/opi/ko/console/guide/reg.md +159 -0
- package/assets/docs/opi/ko/console/guide/smartrouting.md +74 -0
- package/assets/docs/opi/ko/console/pg.md +92 -0
- package/assets/docs/opi/ko/etc/recon.md +286 -0
- package/assets/docs/opi/ko/extra/confirm-process/readme-v1.md +98 -0
- package/assets/docs/opi/ko/extra/confirm-process/readme-v2.md +152 -0
- package/assets/docs/opi/ko/extra/identity-verification/readme-v2.md +261 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/all/0.md +35 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/all/1.md +44 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/all/2.md +75 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/all/3.md +134 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/all/readme.md +17 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/credit-auth/1.md +35 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/credit-auth/2.md +78 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/credit-auth/3.md +75 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/credit-auth/4.md +134 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/credit-auth/readme.md +17 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/phone/1.md +37 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/phone/2.md +86 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/phone/3.md +77 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/phone/4.md +149 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/phone/readme.md +19 -0
- package/assets/docs/opi/ko/extra/identity-verification/v1/readme.md +9 -0
- package/assets/docs/opi/ko/extra/link-pay/readme-v1.md +235 -0
- package/assets/docs/opi/ko/extra/plugins/readme-v1.md +7 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/readme-v1.md +54 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/shopify/shopify-1.md +16 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/shopify/shopify-2.md +32 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/shopify/shopify-3.md +16 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/shopify/shopify-4.md +35 -0
- package/assets/docs/opi/ko/extra/plugins/shopify/shopify/shopify-5.md +27 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/button.md +166 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/edd.md +56 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/readme-v1.md +10 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/woocommerce/payment.md +62 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/woocommerce/readme.md +30 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/woocommerce/subscription.md +60 -0
- package/assets/docs/opi/ko/extra/plugins/wordpress/woocommerce/vbank.md +64 -0
- package/assets/docs/opi/ko/extra/promotion/console-guide.md +148 -0
- package/assets/docs/opi/ko/extra/promotion/integration.md +769 -0
- package/assets/docs/opi/ko/extra/promotion/intro.md +31 -0
- package/assets/docs/opi/ko/extra/promotion/refund.md +316 -0
- package/assets/docs/opi/ko/extra/smart-routing/console-guide.md +73 -0
- package/assets/docs/opi/ko/extra/smart-routing/integration.md +1324 -0
- package/assets/docs/opi/ko/extra/smart-routing/intro.md +155 -0
- package/assets/docs/opi/ko/integration/cancel/v1/basic.md +324 -0
- package/assets/docs/opi/ko/integration/cancel/v1/virtual-account.md +99 -0
- package/assets/docs/opi/ko/integration/cancel/v2/readme.md +378 -0
- package/assets/docs/opi/ko/integration/checklist/readme-v1.md +83 -0
- package/assets/docs/opi/ko/integration/pg/v1/blue.md +99 -0
- package/assets/docs/opi/ko/integration/pg/v1/danal.md +409 -0
- package/assets/docs/opi/ko/integration/pg/v1/daou/readme.md +305 -0
- package/assets/docs/opi/ko/integration/pg/v1/daou/undefined.md +214 -0
- package/assets/docs/opi/ko/integration/pg/v1/eximbay.md +242 -0
- package/assets/docs/opi/ko/integration/pg/v1/hyphen.md +196 -0
- package/assets/docs/opi/ko/integration/pg/v1/inicis.md +444 -0
- package/assets/docs/opi/ko/integration/pg/v1/kakaopay.md +207 -0
- package/assets/docs/opi/ko/integration/pg/v1/kcp-v2-identity-verification.md +188 -0
- package/assets/docs/opi/ko/integration/pg/v1/kg.md +177 -0
- package/assets/docs/opi/ko/integration/pg/v1/kicc.md +308 -0
- package/assets/docs/opi/ko/integration/pg/v1/ksnet/readme.md +533 -0
- package/assets/docs/opi/ko/integration/pg/v1/ksnet/warning.md +175 -0
- package/assets/docs/opi/ko/integration/pg/v1/naver.md +558 -0
- package/assets/docs/opi/ko/integration/pg/v1/newtoss/readme.md +503 -0
- package/assets/docs/opi/ko/integration/pg/v1/newtoss/warning.md +364 -0
- package/assets/docs/opi/ko/integration/pg/v1/nhn-kcp.md +1186 -0
- package/assets/docs/opi/ko/integration/pg/v1/nice-v2/billing-api-caution.md +150 -0
- package/assets/docs/opi/ko/integration/pg/v1/nice-v2/payment-caution.md +429 -0
- package/assets/docs/opi/ko/integration/pg/v1/nice-v2/readme.md +364 -0
- package/assets/docs/opi/ko/integration/pg/v1/nice.md +319 -0
- package/assets/docs/opi/ko/integration/pg/v1/payco.md +201 -0
- package/assets/docs/opi/ko/integration/pg/v1/paymentwall.md +283 -0
- package/assets/docs/opi/ko/integration/pg/v1/paypal.md +158 -0
- package/assets/docs/opi/ko/integration/pg/v1/readme.md +73 -0
- package/assets/docs/opi/ko/integration/pg/v1/rt/readme.md +501 -0
- package/assets/docs/opi/ko/integration/pg/v1/rt/warning.md +297 -0
- package/assets/docs/opi/ko/integration/pg/v1/settle/mybank.md +304 -0
- package/assets/docs/opi/ko/integration/pg/v1/settle/readme.md +185 -0
- package/assets/docs/opi/ko/integration/pg/v1/smartro-v2/api.md +197 -0
- package/assets/docs/opi/ko/integration/pg/v1/smartro-v2/caution.md +387 -0
- package/assets/docs/opi/ko/integration/pg/v1/smartro-v2/readme.md +293 -0
- package/assets/docs/opi/ko/integration/pg/v1/smartro.md +104 -0
- package/assets/docs/opi/ko/integration/pg/v1/smilepay.md +97 -0
- package/assets/docs/opi/ko/integration/pg/v1/spb/readme.md +441 -0
- package/assets/docs/opi/ko/integration/pg/v1/spb/stc.md +226 -0
- package/assets/docs/opi/ko/integration/pg/v1/spb/warning.md +729 -0
- package/assets/docs/opi/ko/integration/pg/v1/toss-brandpay/module.md +227 -0
- package/assets/docs/opi/ko/integration/pg/v1/toss-brandpay/readme.md +404 -0
- package/assets/docs/opi/ko/integration/pg/v1/toss-brandpay/warning.md +81 -0
- package/assets/docs/opi/ko/integration/pg/v1/toss-brandpay/widget.md +152 -0
- package/assets/docs/opi/ko/integration/pg/v1/toss.md +112 -0
- package/assets/docs/opi/ko/integration/pg/v1/tosspay-v2/caution.md +65 -0
- package/assets/docs/opi/ko/integration/pg/v1/tosspay-v2/readme.md +308 -0
- package/assets/docs/opi/ko/integration/pg/v1/tosspay.md +110 -0
- package/assets/docs/opi/ko/integration/pg/v1/welcome/api.md +229 -0
- package/assets/docs/opi/ko/integration/pg/v1/welcome/caution.md +517 -0
- package/assets/docs/opi/ko/integration/pg/v1/welcome/readme.md +795 -0
- package/assets/docs/opi/ko/integration/pg/v2/danal-identity-verification.md +121 -0
- package/assets/docs/opi/ko/integration/pg/v2/eximbay-v2.md +964 -0
- package/assets/docs/opi/ko/integration/pg/v2/hyphen.md +205 -0
- package/assets/docs/opi/ko/integration/pg/v2/inicis-jp.md +403 -0
- package/assets/docs/opi/ko/integration/pg/v2/inicis-unified-identity-verification.md +89 -0
- package/assets/docs/opi/ko/integration/pg/v2/inicis-v2.md +1598 -0
- package/assets/docs/opi/ko/integration/pg/v2/kakaopay.md +108 -0
- package/assets/docs/opi/ko/integration/pg/v2/kcp-v2-identity-verification.md +291 -0
- package/assets/docs/opi/ko/integration/pg/v2/kcp-v2.md +1273 -0
- package/assets/docs/opi/ko/integration/pg/v2/kpn.md +1133 -0
- package/assets/docs/opi/ko/integration/pg/v2/ksnet.md +526 -0
- package/assets/docs/opi/ko/integration/pg/v2/naverpay.md +186 -0
- package/assets/docs/opi/ko/integration/pg/v2/nice-v2.md +868 -0
- package/assets/docs/opi/ko/integration/pg/v2/payletter-global.md +62 -0
- package/assets/docs/opi/ko/integration/pg/v2/paypal-v2.md +1874 -0
- package/assets/docs/opi/ko/integration/pg/v2/readme.md +194 -0
- package/assets/docs/opi/ko/integration/pg/v2/smartro-v2.md +1043 -0
- package/assets/docs/opi/ko/integration/pg/v2/tosspay-v2.md +433 -0
- package/assets/docs/opi/ko/integration/pg/v2/tosspayments.md +551 -0
- package/assets/docs/opi/ko/integration/pg/v2/welcome.md +1441 -0
- package/assets/docs/opi/ko/integration/ready/readme.md +1069 -0
- package/assets/docs/opi/ko/integration/start/v1/auth.md +483 -0
- package/assets/docs/opi/ko/integration/start/v1/non-auth.md +420 -0
- package/assets/docs/opi/ko/integration/start/v1/readme.md +9 -0
- package/assets/docs/opi/ko/integration/start/v2/billing/issue.md +122 -0
- package/assets/docs/opi/ko/integration/start/v2/billing/payment.md +41 -0
- package/assets/docs/opi/ko/integration/start/v2/billing/readme.md +24 -0
- package/assets/docs/opi/ko/integration/start/v2/billing/schedule.md +54 -0
- package/assets/docs/opi/ko/integration/start/v2/checkout.md +258 -0
- package/assets/docs/opi/ko/integration/start/v2/keyin.md +54 -0
- package/assets/docs/opi/ko/integration/start/v2/readme.md +120 -0
- package/assets/docs/opi/ko/integration/using-ai-tools.md +140 -0
- package/assets/docs/opi/ko/integration/virtual-account/readme.md +268 -0
- package/assets/docs/opi/ko/integration/webhook/readme-v1.md +242 -0
- package/assets/docs/opi/ko/integration/webhook/readme-v2.md +599 -0
- package/assets/docs/opi/ko/quick-guide/payment.md +3305 -0
- package/assets/docs/opi/ko/readme.md +193 -0
- package/assets/docs/opi/ko/support/agency-and-tier.md +51 -0
- package/assets/docs/opi/ko/support/code-info/card-code.md +29 -0
- package/assets/docs/opi/ko/support/code-info/code.md +22 -0
- package/assets/docs/opi/ko/support/code-info/pg-1.md +161 -0
- package/assets/docs/opi/ko/support/code-info/pg-2.md +41 -0
- package/assets/docs/opi/ko/support/code-info/pg-3.md +36 -0
- package/assets/docs/opi/ko/support/code-info/pg.md +41 -0
- package/assets/docs/opi/ko/support/code-info/portone-code.md +15 -0
- package/assets/docs/opi/ko/support/code-info/readme.md +20 -0
- package/assets/docs/opi/ko/support/contact.md +23 -0
- package/assets/docs/opi/ko/support/faq/undefined.md +60 -0
- package/assets/docs/opi/ko/support/flow.md +24 -0
- package/assets/docs/opi/ko/support/redirect.md +26 -0
- package/assets/docs/opi/ko/support/tax.md +142 -0
- package/assets/docs/opi/ko/support/tls-support.md +497 -0
- package/assets/docs/platform/ko/guides/dictionary.md +20 -0
- package/assets/docs/platform/ko/guides/process.md +33 -0
- package/assets/docs/platform/ko/guides/webhook.md +171 -0
- package/assets/docs/platform/ko/readme.md +64 -0
- package/assets/docs/platform/ko/usages/client.md +17 -0
- package/assets/docs/platform/ko/usages/contract.md +126 -0
- package/assets/docs/platform/ko/usages/discount.md +89 -0
- package/assets/docs/platform/ko/usages/fee.md +97 -0
- package/assets/docs/platform/ko/usages/order.md +1666 -0
- package/assets/docs/platform/ko/usages/partner.md +115 -0
- package/assets/docs/platform/ko/using-ai-tools.md +140 -0
- package/assets/docs/release-notes/api-sdk/2023-04-24.md +10 -0
- package/assets/docs/release-notes/api-sdk/2023-05-08.md +22 -0
- package/assets/docs/release-notes/api-sdk/2023-05-12.md +24 -0
- package/assets/docs/release-notes/api-sdk/2023-05-22.md +46 -0
- package/assets/docs/release-notes/api-sdk/2023-05-25.md +15 -0
- package/assets/docs/release-notes/api-sdk/2023-06-19.md +20 -0
- package/assets/docs/release-notes/api-sdk/2023-07-03.md +26 -0
- package/assets/docs/release-notes/api-sdk/2023-07-10.md +35 -0
- package/assets/docs/release-notes/api-sdk/2023-07-17.md +31 -0
- package/assets/docs/release-notes/api-sdk/2023-07-31.md +14 -0
- package/assets/docs/release-notes/api-sdk/2023-08-31.md +29 -0
- package/assets/docs/release-notes/api-sdk/2023-12-15.md +12 -0
- package/assets/docs/release-notes/api-sdk/2024-01-08.md +36 -0
- package/assets/docs/release-notes/api-sdk/2024-01-11.md +18 -0
- package/assets/docs/release-notes/api-sdk/2024-01-25.md +35 -0
- package/assets/docs/release-notes/api-sdk/2024-01-30.md +19 -0
- package/assets/docs/release-notes/api-sdk/2024-02-23.md +26 -0
- package/assets/docs/release-notes/api-sdk/2024-03-08.md +12 -0
- package/assets/docs/release-notes/api-sdk/2024-03-15.md +30 -0
- package/assets/docs/release-notes/api-sdk/2024-03-25.md +23 -0
- package/assets/docs/release-notes/api-sdk/2024-04-01.md +37 -0
- package/assets/docs/release-notes/api-sdk/2024-04-05.md +10 -0
- package/assets/docs/release-notes/api-sdk/2024-04-12.md +32 -0
- package/assets/docs/release-notes/api-sdk/2024-05-08.md +34 -0
- package/assets/docs/release-notes/api-sdk/2024-05-14.md +17 -0
- package/assets/docs/release-notes/api-sdk/2024-06-03.md +48 -0
- package/assets/docs/release-notes/api-sdk/2024-06-17.md +37 -0
- package/assets/docs/release-notes/api-sdk/2024-06-19.md +39 -0
- package/assets/docs/release-notes/api-sdk/2024-06-20.md +13 -0
- package/assets/docs/release-notes/api-sdk/2024-07-04.md +15 -0
- package/assets/docs/release-notes/api-sdk/2024-07-11.md +47 -0
- package/assets/docs/release-notes/api-sdk/2024-09-05.md +36 -0
- package/assets/docs/release-notes/api-sdk/2024-09-27.md +27 -0
- package/assets/docs/release-notes/api-sdk/2024-12-19.md +52 -0
- package/assets/docs/release-notes/api-sdk/2025-01-15.md +76 -0
- package/assets/docs/release-notes/api-sdk/2025-05-19.md +49 -0
- package/assets/docs/release-notes/console/2023-04-24.md +41 -0
- package/assets/docs/release-notes/console/2023-05-08.md +6 -0
- package/assets/docs/release-notes/console/2023-05-22.md +15 -0
- package/assets/docs/release-notes/console/2023-07-05.md +29 -0
- package/assets/docs/release-notes/console/2023-07-07.md +25 -0
- package/assets/docs/release-notes/console/2023-07-17.md +16 -0
- package/assets/docs/release-notes/console/2023-08-23.md +17 -0
- package/assets/docs/release-notes/console/2023-09-12.md +16 -0
- package/assets/docs/release-notes/console/2023-12-27.md +24 -0
- package/assets/docs/release-notes/console/2024-09-05.md +23 -0
- package/assets/docs/release-notes/platform/2023-08-31.md +16 -0
- package/assets/docs/release-notes/platform/2023-11-08.md +37 -0
- package/assets/docs/release-notes/platform/2023-11-14.md +28 -0
- package/assets/docs/release-notes/platform/2023-12-15.md +11 -0
- package/assets/docs/release-notes/platform/2024-05-20.md +31 -0
- package/assets/docs/release-notes/platform/2024-05-29.md +159 -0
- package/assets/docs/release-notes/platform/2024-06-05.md +30 -0
- package/assets/docs/release-notes/platform/2024-07-05.md +49 -0
- package/assets/docs/release-notes/platform/2024-07-11.md +62 -0
- package/assets/docs/release-notes/platform/2024-07-30.md +44 -0
- package/assets/docs/release-notes/platform/2024-08-07.md +37 -0
- package/assets/docs/release-notes/platform/2024-08-22.md +111 -0
- package/assets/docs/release-notes/platform/2024-10-21.md +75 -0
- package/assets/docs/release-notes/platform/2024-11-07.md +65 -0
- package/assets/docs/release-notes/platform/2024-11-25.md +82 -0
- package/assets/docs/release-notes/platform/2024-12-10.md +61 -0
- package/assets/docs/release-notes/platform/2025-01-16.md +56 -0
- package/assets/docs/release-notes/platform/2025-02-10.md +67 -0
- package/assets/docs/release-notes/platform/2025-02-13.md +27 -0
- package/assets/docs/release-notes/platform/2025-03-04.md +49 -0
- package/assets/docs/release-notes/platform/2025-03-17.md +40 -0
- package/assets/docs/release-notes/platform/2025-04-03.md +96 -0
- package/assets/docs/release-notes/platform/2025-04-08.md +119 -0
- package/assets/docs/release-notes/platform/2025-05-14.md +77 -0
- package/assets/docs/release-notes/platform/2025-07-02.md +64 -0
- package/assets/docs/release-notes/platform/2025-07-07.md +55 -0
- package/assets/docs/schema/browser-sdk.yml +6349 -0
- package/assets/docs/schema/v1.openapi.json +11632 -0
- package/assets/docs/schema/v1.openapi.yml +11489 -0
- package/assets/docs/schema/v2.graphql +13849 -0
- package/assets/docs/schema/v2.openapi.json +47721 -0
- package/assets/docs/schema/v2.openapi.yml +34749 -0
- package/assets/docs/sdk/ko/readme.md +56 -0
- package/assets/docs/sdk/ko/v1-mobile-sdk/readme.md +31 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/cft-rt.md +32 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/cft.md +108 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/load-module-rt.md +10 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/load-module.md +55 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/payrq.md +502 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/payrt.md +300 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk/readme.md +46 -0
- package/assets/docs/sdk/ko/v1-sdk/javascript-sdk-old/readme.md +33 -0
- package/assets/docs/sdk/ko/v2-mobile-sdk/android.md +268 -0
- package/assets/docs/sdk/ko/v2-mobile-sdk/react-native.md +239 -0
- package/assets/docs/sdk/ko/v2-mobile-sdk/readme.md +30 -0
- package/assets/docs/sdk/ko/v2-sdk/billing-key-and-pay-request.md +26 -0
- package/assets/docs/sdk/ko/v2-sdk/billing-key-and-pay-response.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/billing-key-request.md +24 -0
- package/assets/docs/sdk/ko/v2-sdk/billing-key-response.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/changelog.md +8 -0
- package/assets/docs/sdk/ko/v2-sdk/identity-verification-request.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/identity-verification-response.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/load-issue-billing-key-ui-request.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/load-issue-billing-key-ui-response.md +23 -0
- package/assets/docs/sdk/ko/v2-sdk/load-payment-ui-request.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/load-payment-ui-response.md +23 -0
- package/assets/docs/sdk/ko/v2-sdk/payment-request.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/payment-response.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/readme.md +73 -0
- package/assets/docs/sdk/ko/v2-sdk/update-load-issue-billing-key-ui-request.md +15 -0
- package/assets/docs/sdk/ko/v2-sdk/update-load-payment-ui-request.md +15 -0
- package/assets/docs/sdk/ko/v2-server-sdk/javascript.md +170 -0
- package/assets/docs/sdk/ko/v2-server-sdk/jvm.md +170 -0
- package/assets/docs/sdk/ko/v2-server-sdk/python.md +152 -0
- package/assets/docs/sdk/ko/v2-server-sdk/readme.md +259 -0
- package/assets/docs/v1-docs-full.md +36540 -0
- package/assets/docs/v2-docs-full.md +34980 -0
- package/assets/docs/website-links.md +331 -0
- package/assets/instructions.md +19 -0
- package/manifest.json +50 -0
- package/package.json +66 -0
- package/server/index.js +1764 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 포트원이 여러 PG사의 인터페이스를 연동하는 방법
|
|
3
|
+
description: 여러 PG사의 인터페이스를 효율적으로 연동하기 위한 결정사항들을 소개합니다.
|
|
4
|
+
author: ChanceKim
|
|
5
|
+
date: 2024-03-11T15:00:00.000Z
|
|
6
|
+
tags:
|
|
7
|
+
- Backend
|
|
8
|
+
- MSA
|
|
9
|
+
- gRPC
|
|
10
|
+
- DDD
|
|
11
|
+
- Typed Error
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
소프트웨어 엔지니어로서 새로운 서비스를 개발하다 보면 결제 기능을 구현해야 하는 경우가 생깁니다.
|
|
15
|
+
일반적으로 엔지니어들은 결제 기능을 구현하기 위해 특정 PG사가 제공하는 연동 가이드를 따라가며 개발을 진행하고, 서비스를 런칭합니다.
|
|
16
|
+
그러나 포트원은 여러 PG사의 인터페이스를 추상화하여 어떤 PG사를 사용하는지와 관계없이 통일된 인터페이스를 제공하는 것을 핵심 가치로 삼고 있습니다.
|
|
17
|
+
따라서 포트원의 엔지니어들은 일반적인 PG 연동 작업과는 다른 차원의 문제들을 해결해 나가야 합니다.
|
|
18
|
+
|
|
19
|
+
다른 한편으로 포트원은 현재 모놀리식 아키텍처(V1)에서 MSA(V2)로의 전환을 진행중입니다.
|
|
20
|
+
V1을 완전히 버리고 V2로 넘어가는 것이 아니기 때문에 하나의 PG사를 새로 연동할 때, V1과 V2 모두에 연동해주어야 하죠.
|
|
21
|
+
흔히 잘 운영되는 시스템의 특정 모듈을 변경하는 작업을 달리는 자동차의 바퀴를 갈아 끼우는 일에 빗대어 이야기하곤 하는데,
|
|
22
|
+
포트원의 현재 상황은 나란히 달리고 있는 구형 자동차와 신형 자동차의 바퀴를 한꺼번에 갈아 끼워야 하는 상황입니다.
|
|
23
|
+
|
|
24
|
+
이 글에서는 이와 같은 어려움 속에서 최적의 업무 효율을 달성하기 위해 선택한 아키텍처 레벨 및 단일 서비스 레벨의 결정사항에 대해 설명드리려 합니다.
|
|
25
|
+
|
|
26
|
+
## PG사 간의 인터페이스 차이
|
|
27
|
+
|
|
28
|
+
먼저, PG사 간의 인터페이스가 얼마나 다른지를 살펴보기 위해 예시를 들어 보겠습니다.
|
|
29
|
+
아래는 대표적인 간편결제사 두 곳에서 결제창을 생성하기 위해 필요한 파라미터 목록입니다.
|
|
30
|
+
|
|
31
|
+
- 카카오페이 결제 파라미터
|
|
32
|
+
|
|
33
|
+
| Name | 타입 |필수여부| 설명 |
|
|
34
|
+
|:----------------:|:--------:|:------:|:--------------------------------------------------------------------------------------------------------------------:|
|
|
35
|
+
| cid | String | O | 가맹점 코드, 10자 |
|
|
36
|
+
| cid\_secret | String | X | 가맹점 코드 인증키, 24자, 숫자와 영문 소문자 조합 |
|
|
37
|
+
|partner\_order\_id| String | O | 가맹점 주문번호, 최대 100자 |
|
|
38
|
+
| partner\_user\_id| String | O | 가맹점 회원 id, 최대 100자 |
|
|
39
|
+
| item\_name | String | O | 상품명, 최대 100자 |
|
|
40
|
+
| item\_code | String | X | 상품코드, 최대 100자 |
|
|
41
|
+
| quantity | Integer | O | 상품 수량 |
|
|
42
|
+
| total\_amount | Integer | O | 상품 총액 |
|
|
43
|
+
| tax\_free\_amount| Integer | O | 상품 비과세 금액 |
|
|
44
|
+
| vat\_amount | Integer | X |상품 부가세 금액 값을 보내지 않을 경우 다음과 같이 VAT 자동 계산 (상품총액 - 상품 비과세 금액)/11 : 소숫점 이하 반올림|
|
|
45
|
+
| green\_deposit | Integer | X | 컵 보증금 |
|
|
46
|
+
| approval\_url | String | O | 결제 성공 시 redirect url, 최대 255자 |
|
|
47
|
+
| cancel\_url | String | O | 결제 취소 시 redirect url, 최대 255자 |
|
|
48
|
+
| fail\_url | String | O | 결제 실패 시 redirect url, 최대 255자 |
|
|
49
|
+
| available\_cards |JSON Array| X | 결제 수단으로써 사용 허가할 카드사를 지정해야 하는 경우 사용 |
|
|
50
|
+
|
|
51
|
+
- 네이버페이 결제 파라미터
|
|
52
|
+
|
|
53
|
+
| Name | 타입 |필수여부| 설명 |
|
|
54
|
+
|:-----------------------:|:-----:|:------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
|
55
|
+
| merchantPayKey | String| O | 가맹점 주문내역 확인 가능한 가맹점 결제번호 또는 주문번호를 전달해야 합니다 |
|
|
56
|
+
|merchantPayTransactionKey| String| | 가맹점 주문내역 히스토리 확인이 가능한 가맹점 결제 트랜잭션 번호 또는 주문 트랜잭션 번호를 전달해야 합니다. |
|
|
57
|
+
| merchantUserKey | String| | 가맹점의 사용자 키(개인 아이디와 같은 개인정보 데이터는 제외하여 전달해야 합니다) |
|
|
58
|
+
| productName | String| O | 대표 상품명. 예: 장미의 이름 외 1건(X), 장미의 이름(O) |
|
|
59
|
+
| productCount | Number| O | 상품 수량 예: A 상품 2개 + B 상품 1개의 경우 productCount 3으로 전달 |
|
|
60
|
+
| totalPayAmount | Number| O | 총 결제 금액. 최소 결제금액은 10원 |
|
|
61
|
+
| taxScopeAmount | Number| O | 과세 대상 금액. 과세 대상 금액 + 면세 대상 금액 + 컵 보증금 금액 (옵션) = 총 결제 금액 |
|
|
62
|
+
| taxExScopeAmount | Number| O | 면세 대상 금액. 과세 대상 금액 + 면세 대상 금액 + 컵 보증금 금액 (옵션) = 총 결제 금액 |
|
|
63
|
+
| environmentDepositAmount| Number| | 1회용 컵에 담은 상품의 결제건인 경우에만 필수값이며, 그 외에는 전달할 필요가 없습니다. 컵 보증금 금액. 과세 대상 금액 + 면세 대상 금액 + 컵 보증금 금액 (옵션) = 총 결제 금액 |
|
|
64
|
+
| returnUrl | String| O | 결제 인증 결과 전달 URL, 결제 완료 후 이동할 URL(returnUrl + 가맹점 파라미터 전달이 가능합니다) 네이버페이는 결제 작업 완료 후, 가맹점이 등록한 returnUrl로 리디렉션을 수행합니다 가맹점은 이를 활용하여 내부 처리를 수행하거나 구매자에게 결제 결과 화면을 노출할 수 있습니다 |
|
|
65
|
+
| purchaserName | String| | 구매자 성명. 결제 상품이 보험 및 위험 업종 등인 경우에만 필수 값입니다. 그 외에는 전달할 필요가 없습니다 |
|
|
66
|
+
| purchaserBirthday | String| | 구매자 생년월일(yyyymmdd). 결제 상품이 보험 및 위험 업종 등인 경우에만 필수 값입니다. 그 외에는 전달할 필요가 없습니다 |
|
|
67
|
+
| extraDeduction |Boolean| | 도서 / 공연 / 영화 소득공제 대상 여부. 문화체육관광부에서 인증한 소득공제 제공 사업자가 대상 상품을 판매하는 경우 필수 값입니다. 해당 파라미터를 사용하기 위해서는 별도 요청을 주셔야 합니다. true : 대상, false : 비 대상 |
|
|
68
|
+
| useCfmYmdt | String| |이용완료일(yyyymmdd) 가맹점 타입이 이용완료일 정산 또는 이용완료일 포인트 적립인 경우 필수 해당 값을 기준으로 이용완료일 정산의 경우 '정산기준일' 또는 이용완료일 포인트 적립인 경우 '포인트적립 기준일'이 지정됩니다. 이용완료일은 반드시 결제일과 같거나 결제일 이후여야 하며, 이용완료일이 결제일자 이전으로 적용될 경우 에러(InvalidUseCfmYmdt)가 발생됩니다. 이용완료일이 결제일자 기준으로 1년을 초과할 경우 별도 에러가 발생되지는 않으나 전달한 이용완료일(useCfmYmdt) 값이 결제일자 +365일로 조정 처리됩니다.|
|
|
69
|
+
| merchantExtraParameter | String| | 가맹점 자체적으로 추가 구분값으로 활용 가능한 별도의 예비 필드 (개인 아이디와 같은 개인정보 데이터는 제외하여 전달해야 합니다) |
|
|
70
|
+
| productItems | Array | O | productItem 배열 |
|
|
71
|
+
| subMerchantInfo | Object| | 하부가맹점 정보. PG 업종 가맹점인 경우에만 필수값입니다 |
|
|
72
|
+
|
|
73
|
+
위처럼 같은 기능을 하는 인터페이스임에도 PG사에 따라 파라미터 명과 파라미터 타입, 필수 파라미터 목록 모두 상이한 것을 볼 수 있습니다.
|
|
74
|
+
심지어 사용하는 통신 프로토콜마저 PG사마다 상이하죠.
|
|
75
|
+
2개의 PG사만을 비교해도 이러한 차이가 뚜렷한데, 포트원은 30개가 넘는 PG사 모듈을 제공하고 있기 때문에 인터페이스를 효과적으로 추상화하는 것이 매우 중요한 과제입니다.
|
|
76
|
+
|
|
77
|
+
## 아키텍처 레벨 결정사항
|
|
78
|
+
|
|
79
|
+
### 추상화만을 담당하는 마이크로서비스
|
|
80
|
+
|
|
81
|
+
앞서 설명드린 것처럼 현재 포트원은 모놀리식 아키텍처(V1)에서 MSA(V2)로의 전환 작업을 진행 중입니다.
|
|
82
|
+
이러한 전환 과정에서 V1과 V2를 모두 운영하며 새로운 PG를 연동하려면 V1과 V2 양쪽에 모두 연동 작업을 수행해야 합니다.
|
|
83
|
+
이는 개발 리소스를 두 배로 소모하는 일이며 매우 비효율적인 작업입니다.
|
|
84
|
+
|
|
85
|
+
이러한 비효율을 최소화하기 위해 저희는 V1과 V2에서 모두 사용 가능한 PG 인터페이스 추상화용 마이크로서비스인
|
|
86
|
+
TGS(Transaction Gateway Service)를 도입했습니다.
|
|
87
|
+
이 서비스 도입을 통해 V1과 V2에서 고객사의 요청을 처리하는 서비스들은 어떤 PG사로 결제가 이루어지든 통일된 인터페이스를 이용해 결제를 발생시킬 수 있습니다.
|
|
88
|
+
포트원이 고객사에게 주는 편리함을 포트원 내부에서는 TGS가 다른 서비스들에게 제공하는 것이죠.
|
|
89
|
+
|
|
90
|
+
다만 TGS의 도입에 앞서 선행돼야 하는 작업이 있었습니다.
|
|
91
|
+
모놀리식 서비스인 V1의 코드를 일부 수정하여 PG사의 인터페이스를 직접 호출하는 것이 아니라 TGS의 인터페이스를 호출하도록 변경해주어야 했습니다.
|
|
92
|
+
이 작업 역시 작지 않은 작업이었지만 V1과 V2가 언제까지 함께 운영될지 모르는 상황에서
|
|
93
|
+
서비스를 계속해서 발전시켜 나가려면 어느 정도 시간이 들더라도 반드시 해야만 하는 일이라는 결론에 도달했습니다.
|
|
94
|
+
|
|
95
|
+
TGS가 PG의 인터페이스를 추상화하는 역할을 담당하게 되면서 외부로부터 결제 요청을 처리하는 서비스는 결제 데이터를 저장하고 서빙하는 본연의 역할에 충실할 수 있게 됐습니다.
|
|
96
|
+
|
|
97
|
+
### gRPC를 통한 API 제공
|
|
98
|
+
|
|
99
|
+
(이미지 첨부: 효율적인 PG사 연동을 위한 아키텍처)
|
|
100
|
+
|
|
101
|
+
TGS가 API를 제공하는 방식 역시 아키텍처를 설계할 때의 주요 결정사항 중 하나였습니다.
|
|
102
|
+
가장 흔히 사용되는 방식으로는 REST API가 있지만 저희는 gRPC를 이용하여 API를 제공하기로 결정했습니다.
|
|
103
|
+
저희는 gRPC가 가지는 여러 장점 중 아래 두 가지에 집중했습니다.
|
|
104
|
+
|
|
105
|
+
#### 1. 인터페이스 우선 개발
|
|
106
|
+
|
|
107
|
+
TGS는 포트원의 내부 서비스와 PG사의 중간 다리 역할을 하는 만큼 신규로 연동할 PG사가 기존에 연동된 PG사에서 요구하던 파라미터 이외의 파라미터를 요구하거나,
|
|
108
|
+
기존에 연동된 PG사가 새로운 파라미터를 제공하는 경우에는 인터페이스의 수정이 불가피합니다.
|
|
109
|
+
만약 이런 수정 작업 중 TGS의 작업자가 변경된 인터페이스의 공유를 깜빡하는 경우에는 외부로 API를 제공하는 서비스들에서 해당 기능을 제공하기 어려워지기 때문에,
|
|
110
|
+
TGS 작업자는 다른 서비스로 인터페이스를 공유하는 것이 매우 중요합니다.
|
|
111
|
+
|
|
112
|
+
gRPC를 사용하는 경우 proto file로 인터페이스를 우선 정의하고 해당 파일을 기반으로 생성된 서버/클라이언트 코드를 사용하여 통신하게 됩니다.
|
|
113
|
+
인터페이스가 먼저 정의가 돼야지만 서버 기능 추가가 가능하기 때문에, proto file에 수정이 있는 경우 클라이언트가 되는 서비스의 개발자들로부터
|
|
114
|
+
반드시 리뷰를 받도록 PR 정책을 수립하면 인터페이스가 공유되지 않는 상황을 프로세스적으로 방지할 수 있습니다.
|
|
115
|
+
|
|
116
|
+
#### 2. 언어별로 자동 생성되는 클라이언트
|
|
117
|
+
|
|
118
|
+
위에서 언급했듯이 gRPC는 proto file로 작성된 인터페이스를 기반으로 클라이언트 코드를 생성할 수 있습니다.
|
|
119
|
+
현재 V1, V2는 각각 PHP와 Scala를 사용하여 개발 돼 있기 때문에 proto file을 기반으로 클라이언트 코드를 생성할 수 있다면,
|
|
120
|
+
TGS의 인터페이스가 변경되더라도 각기 다른 언어로 작성된 클라이언트 코드를 수정해주어야 한다는 부담이 사라지게 됩니다.
|
|
121
|
+
|
|
122
|
+
물론 REST API의 경우 이미 널리 사용되고 있어 학습을 위한 기간이 거의 필요하지 않고, 다양한 라이브러리들이 지원된다는 장점이 있지만,
|
|
123
|
+
포트원 내부 서비스와 PG사들 사이에서 인터페이스를 추상화해 주어야 한다는 목적에 맞춰 보았을 때
|
|
124
|
+
위 2가지의 장점이 REST API가 가지는 장점보다 더 많은 이득을 준다고 판단되어 최종적으로 gRPC를 사용하고 있습니다.
|
|
125
|
+
|
|
126
|
+
## 서비스 레벨의 결정사항
|
|
127
|
+
|
|
128
|
+
### Domain Driven Design(DDD)
|
|
129
|
+
|
|
130
|
+
TGS는 PG사마다 다른 용어와 개념을 공통화하여 도메인 영역을 최대한 간결하게 만들어야 합니다.
|
|
131
|
+
만약 PG사에서 사용되는 용어가 도메인 영역에 침범하도록 개발을 진행한다면
|
|
132
|
+
도메인 영역은 너무 많은 개념을 담게 되어 처음부터 개발을 해온 사람이 아니라면 도저히 이해할 수 없는 서비스가 돼버릴 것입니다.
|
|
133
|
+
|
|
134
|
+
실제로 TGS의 초기 구현은 이와 같은 문제를 가진 채로 개발이 진행됐습니다.
|
|
135
|
+
TGS는 프레젠테이션, 어플리케이션, 도메인, 인프라 레이어로 이루어진
|
|
136
|
+
[레이어드 아키텍처](https://www.baeldung.com/cs/layered-architecture)를 따릅니다.
|
|
137
|
+
아래 사진은 이런 구조에서 토스페이먼츠를 위한 클래스들이 도메인 레이어를 침범하여 포트원 도메인 클래스와 혼재되어 있는 모습을 보여주는 사진입니다.
|
|
138
|
+
|
|
139
|
+
(이미지 첨부: 개발초기 TGS의 도메인 레이어)
|
|
140
|
+
|
|
141
|
+
이대로 계속 개발을 진행했다면 TGS에 연동하는 PG사가 늘어남에 따라 도메인 레이어가 계속해서 비대해질 수밖에 없었을 것입니다.
|
|
142
|
+
어플리케이션 레이어의 경우에는 상황이 더 심각합니다.
|
|
143
|
+
비즈니스 로직은 포트원 도메인 엔티티에 정의돼 있기 때문에 어플리케이션 로직에서는 PG사별 객체를 포트원 엔티티로 전환한 후 비즈니스 로직을 실행하고,
|
|
144
|
+
이를 다시 프레젠테이션 레이어로 올려보내주어야 하죠.
|
|
145
|
+
이렇게 프레젠테이션 레이어를 제외한 모든 레이어에 구석구석 침투해 있는 PG사별 클래스로 인해 프로젝트 전체 구조를 파악하지 못한 경우에
|
|
146
|
+
신규 기능 연동이 매우 어려운 상황이었습니다.
|
|
147
|
+
|
|
148
|
+
이와 같은 문제를 해결하기 위해서 TGS에는 DDD 방법론을 도입하여,
|
|
149
|
+
도메인 영역에서 사용되는 용어들을 정리하고 이를 기반으로 어플리케이션 및 프레젠테이션 영역을 보다 깔끔하게 만들어 주기로 결정했습니다.
|
|
150
|
+
TGS에 DDD를 도입하는 과정은 크게 3단계로 나누어 진행됐습니다.
|
|
151
|
+
|
|
152
|
+
#### 1. 보편 언어(Ubiquitous Language) 정리
|
|
153
|
+
|
|
154
|
+
보편 언어를 정리하는 일은 DDD의 시작이라고 할 수 있습니다.
|
|
155
|
+
명확하게 정리된 보편 언어는 도메인을 이해하기 쉽게 만들어주고, 구성원들간의 미스 커뮤니케이션이 일어나지 않도록 도움을 줍니다.
|
|
156
|
+
TGS는 여러 PG사와의 통신을 담당하는 서비스인 만큼, 여러 PG 연동을 경험한 분들에게 도움의 받아 보편 언어를 정리했습니다.
|
|
157
|
+
정리된 보편 언어는 항상 접근이 간편한 곳에 위치해 있어야 하기 때문에 저희는 이를 위한 레포지토리를 생성하고 용어들을 마크다운 파일로 정리했습니다.
|
|
158
|
+
|
|
159
|
+
(이미지 첨부: 보편 언어를 위한 레파지토리)
|
|
160
|
+
|
|
161
|
+
#### 2. 보편 언어를 이용해 도메인 엔티티와 값 객체(VO) 정의
|
|
162
|
+
|
|
163
|
+
정리된 보편 언어는 코드에도 그대로 녹아들어야 합니다. 그래야만 엔지니어와 관련자 사이에 통일된 언어로 커뮤니케이션이 가능하기 때문이죠.
|
|
164
|
+
리팩토링 전 KSNET의 API를 통해 발생한 거래를 저장하기 위한 클래스와 리팩토링 후의 클래스 모습입니다.
|
|
165
|
+
변경 전에는 `aid`, `tid`, `tradeDate` 처럼 PG사에서 사용하는 언어를 이용해 데이터를 저장했다면,
|
|
166
|
+
변경 후에는 포트원의 보편 언어로 모두 대체된 모습을 볼 수 있습니다.
|
|
167
|
+
|
|
168
|
+
<div class="hint" data-style="info">
|
|
169
|
+
|
|
170
|
+
클래스명에 PG사의 명칭이 들어가있어서 도메인 엔티티가 아니라고 느껴질 수 있지만,
|
|
171
|
+
각 PG사와의 거래는 분명하게 TGS의 [bounded context](https://martinfowler.com/bliki/BoundedContext.html) 안에 존재하는 개념이기에 PG사의 명칭을 클래스명에 포함시켰습니다.
|
|
172
|
+
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
(이미지 첨부: 보편 언어를 사용하는 클래스)
|
|
176
|
+
|
|
177
|
+
#### 3. 각 PG사를 위한 데이터 클래스는 인프라 레이어로 이동
|
|
178
|
+
|
|
179
|
+
도메인 레이어를 보편 언어를 이용한 엔티티와 값 객체로 채우게 되면서 PG사를 위한 클래스들은 자연스럽게 인프라 레이어로 이동시켰습니다.
|
|
180
|
+
그리고 인프라 레이어에서 PG사의 클래스를 도메인 엔티티와 값 객체로 변환하여 반환하게 만들었습니다.
|
|
181
|
+
이제 PG사의 클래스들은 인프라 레이어에서 DTO로써만 존재하게 됐습니다.
|
|
182
|
+
그리고 자연스럽게 PG사와 통신하는 Client 구현체는 부패 방지 계층의 역할을 띄게 됩니다.
|
|
183
|
+
부패 방지 계층이란 연동하고자 하는 시스템과 기존 시스템 사이에 존재하는 도메인 모델의 차이를 기존 시스템에 맞게 변환하기 위한 계층으로,
|
|
184
|
+
도메인 레이어를 외부의 용어와 완벽하게 분리할 수 있게 도와줍니다.
|
|
185
|
+
|
|
186
|
+
(이미지 첨부: 인프라 레이어에 존재하는 PG사별 Client 구현체)
|
|
187
|
+
|
|
188
|
+
도메인 레이어와 어플리케이션 레이어를 수정하는 개발자는 더 이상 인프라 레이어의 구현에 대해서 알 필요가 없습니다.
|
|
189
|
+
그저 Client가 반환한 도메인 엔티티와 값 객체를 이용해 로직을 구성하기만 하면 되는 것이죠.
|
|
190
|
+
|
|
191
|
+
3단계로 진행된 리팩토링 과정에서 사실 대단한 DDD 기법을 사용하지는 않았습니다.
|
|
192
|
+
Aggregate, CQRS, 이벤트 소싱 등의 기법은 전혀 등장하지 않았죠.
|
|
193
|
+
그렇지만 보편 언어를 정의하여 커뮤니케이션의 효율을 높이고,
|
|
194
|
+
기술 의존도가 없는 도메인 레이어에 비즈니스 로직을 응축해 놓음으로써 이식성이 높아졌기에 DDD가 추구하던 본질적인 장점은 취할 수 있게 되었습니다.
|
|
195
|
+
덤으로 간단해진 어플리케이션 레이어 로직 덕분에 PG 연동 속도도 빨라지게 되어 생산성도 비약적으로 증가했습니다.
|
|
196
|
+
|
|
197
|
+
### Typed Error 활용
|
|
198
|
+
|
|
199
|
+
결제 도메인에서 에러 처리는 다른 도메인보다 특히나 중요합니다. 잘못된 에러 처리로 인해 결제 내역이 사라진다거나 결제가 여러 번 처리된다면 매우 큰 혼란이 생길 것입니다.
|
|
200
|
+
명확한 에러 처리를 위해서는 특정 함수에서 어떤 에러가 발생할 수 있는지 문서화하는 것이 중요하나,
|
|
201
|
+
문서와 주석은 outdated 되기 쉽다는 단점이 있습니다.
|
|
202
|
+
저희는 이런 문제를 해결하기 위한 방법으로 함수형 프로그래밍을 위한 Kotlin 라이브러리인
|
|
203
|
+
[Arrow](https://arrow-kt.io/)의 typed error를 적극적으로 활용하고 있습니다.
|
|
204
|
+
|
|
205
|
+
Typed error를 사용하면 특정 함수에서 발생할 수 있는 에러를 코드를 통해 문서화할 수 있기 때문에 outdated 될 염려가 없고,
|
|
206
|
+
에러 처리가 강제되기 때문에 특정 에러 케이스를 놓친다거나 하는 문제가 발생할 염려가 적습니다.
|
|
207
|
+
예를 들어, Arrow를 사용해 함수 시그니처에 typed error를 적용하면 아래와 같은 코드를 작성하게 됩니다.
|
|
208
|
+
Typed error를 적용함으로써 예시 코드의 `pay()` 함수에선 `AmountTooBig`, `InvalidCardInfo`, `TransactionAlreadyExists`
|
|
209
|
+
에러가 발생할 수 있다는 것을 코드 레벨에서 확인할 수 있습니다.
|
|
210
|
+
|
|
211
|
+
```kotlin
|
|
212
|
+
interface Example {
|
|
213
|
+
fun pay(): Effect<PayError, Unit>
|
|
214
|
+
|
|
215
|
+
sealed interface PayError {
|
|
216
|
+
data object AmountTooBig: PayError
|
|
217
|
+
data object InvalidCardInfo: PayError
|
|
218
|
+
data object TransactionAlreadyExists: PayError
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
반면 typed error를 사용하는 코드는 이런 의문을 가지게 합니다. ‘Kotlin에서 의도적으로 삭제한 checked exception를 다시 되살리는 것 아닌가?’.
|
|
224
|
+
네, typed error는 checked exception과 거의 동일한 의도로 사용됩니다.
|
|
225
|
+
Kotlin에서 checked exception을 삭제한 주요 이유는 대부분의 exception은 처리할 수 없는 exception이기 때문입니다.
|
|
226
|
+
하지만 저희는 꼭 처리해 주어야 하는 예외 케이스가 있다면 checked exception을 사용하는 것이 그렇지 않은 경우보다 코드 퀄리티를 높여줄 수 있다고 생각했으며,
|
|
227
|
+
결제가 예외 처리에 매우 민감한 도메인이라는 점을 감안하여 checked exception을 대신할 수 있는 typed error를 사용하고 있습니다.
|
|
228
|
+
|
|
229
|
+
물론 typed error를 잘못 사용할 경우에는 checked exception이 가지던 문제점들이 그대로 발생할 수 있습니다.
|
|
230
|
+
때문에 올바른 방법으로 사용하는 것이 매우 중요하며, 이에 대한 내용은 추후 별도의 글에서 다뤄보도록 하겠습니다.
|
|
231
|
+
|
|
232
|
+
## 마치며
|
|
233
|
+
|
|
234
|
+
지금까지 포트원이 여러 PG사의 인터페이스를 효율적으로 연동하기 위해 논의했던 기술적 결정사항들에 대해 알아보았습니다.
|
|
235
|
+
부디 이 글이 비슷한 문제를 해결하고자 하는 분들에게 작게나마 도움이 된다면 좋겠습니다.
|
|
236
|
+
|
|
237
|
+
포트원은 지금도 고객사에게 더 좋은 결제 경험을 제공하기 위해 노력하고 있습니다.
|
|
238
|
+
저희와 함께 간편한 결제 연동이라는 문제를 함께 풀어나가고 싶으신 분이 계시다면 포트원의 문을 두드려 주시면 감사하겠습니다!
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Data Evolution: The Shift from AWS DMS to GCP Datastream'
|
|
3
|
+
description: >-
|
|
4
|
+
Gives an overview of the PortOne Data Infrastructure and the migration story
|
|
5
|
+
from AWS DMS to GCP Datastream.
|
|
6
|
+
author: chandulal
|
|
7
|
+
date: 2024-04-03T15:00:00.000Z
|
|
8
|
+
tags:
|
|
9
|
+
- Data Infra
|
|
10
|
+
- Data Ingestion
|
|
11
|
+
- GCP
|
|
12
|
+
- Data Engineering
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<div class="hint" data-style="info">이 글은 PortOne Global 소속 엔지니어가 작성한 글입니다.</div>
|
|
16
|
+
|
|
17
|
+
## Introduction
|
|
18
|
+
|
|
19
|
+
At PortOne, we use AWS DMS to capture changes from our service databases
|
|
20
|
+
using Change Data Capture (CDC) and ingest them into our Data Lake.
|
|
21
|
+
We store all our CDC data in AWS S3 and merge it with the BigQuery table
|
|
22
|
+
every hour using Airflow as a scheduler.
|
|
23
|
+
Our pipeline code, written in Python's Pandas library,
|
|
24
|
+
merges incremental changes into the BigQuery table.
|
|
25
|
+
We have multiple mart tables built on top of the raw tables in BigQuery.
|
|
26
|
+
|
|
27
|
+
Although this solution has worked well for us, we encountered several challenges along the way:
|
|
28
|
+
|
|
29
|
+
- **High Latency:** at least an hour.
|
|
30
|
+
|
|
31
|
+
- **Manual Backfill:** requires multiple steps to backfill data
|
|
32
|
+
from the source database to the BigQuery table.
|
|
33
|
+
|
|
34
|
+
- **Missing Rows:** There are instances of missing records if there are delays or complications
|
|
35
|
+
with the writing process of AWS DMS.
|
|
36
|
+
|
|
37
|
+
- **High Maintenance:** the solution requires multiple components to maintain,
|
|
38
|
+
such as AWS DMS, Airflow, and a Kubernetes cluster to run all our pipelines.
|
|
39
|
+
|
|
40
|
+
Our approach involves utilizing GCP Datastream as our Change Data Capture (CDC) solution
|
|
41
|
+
to address and overcome the aforementioned challenges.
|
|
42
|
+
|
|
43
|
+
### About GCP Datastream
|
|
44
|
+
|
|
45
|
+
GCP Datastream is a managed CDC service provided by Google Cloud Platform (GCP)
|
|
46
|
+
that enables real-time, automated, and reliable data replication
|
|
47
|
+
from various sources to target destinations.
|
|
48
|
+
It is a serverless and easy-to-use change data capture and replication service
|
|
49
|
+
that directly ingests data from sources such as MySQL and Postgres into BigQuery.
|
|
50
|
+
|
|
51
|
+
It supports integrating various Google Cloud services,
|
|
52
|
+
including BigQuery, Cloud Storage, and Pub/Sub.
|
|
53
|
+
|
|
54
|
+
## Data Infrastructure Change
|
|
55
|
+
|
|
56
|
+
### Before
|
|
57
|
+
|
|
58
|
+
(이미지 첨부: Architecture using AWS DMS)
|
|
59
|
+
|
|
60
|
+
Here, we utilize AWS Database Migration Service(DMS) to capture changes in data
|
|
61
|
+
from six to seven databases. The DMS consistently copies CDC data from RDS
|
|
62
|
+
to Amazon S3 with hourly partitioning on S3.
|
|
63
|
+
Next, Airflow initiates a DAG every hour to combine new CDC data from S3 to BigQuery.
|
|
64
|
+
The underlying job, written in Pandas DataFrame,
|
|
65
|
+
runs on Kubernetes and upserts the data in BigQuery.
|
|
66
|
+
|
|
67
|
+
### After
|
|
68
|
+
|
|
69
|
+
(이미지 첨부: Architecture using GCP Datastream)
|
|
70
|
+
|
|
71
|
+
Here, we simplified the previous architecture
|
|
72
|
+
by removing AWS DMS, AWS S3, and Data Pipelines run by Airflow.
|
|
73
|
+
Instead, we utilize GCP Datastream, which directly connects to databases like PostgreSQL and MySQL,
|
|
74
|
+
copies CDC data, and merges it into BigQuery.
|
|
75
|
+
It provides the option to specify the staleness
|
|
76
|
+
to balance BigQuery query performance and cost versus data freshness.
|
|
77
|
+
Further details will be covered later in this blog.
|
|
78
|
+
|
|
79
|
+
## Data Partitioning
|
|
80
|
+
|
|
81
|
+
Data partitioning allows for more efficient and scalable data processing
|
|
82
|
+
by dividing data into smaller, manageable segments.
|
|
83
|
+
This can lead to faster query performance, reduced costs, and improved data availability.
|
|
84
|
+
It also allows for easier data management by providing the ability
|
|
85
|
+
to load or delete data partitions selectively.
|
|
86
|
+
Data partitioning plays a crucial role as we pay for the data
|
|
87
|
+
scanned by the queries we run in BigQuery.
|
|
88
|
+
|
|
89
|
+
The main challenge with GCP Datastream is its lack of support
|
|
90
|
+
for partitioning when writing data into BigQuery.
|
|
91
|
+
As a result, all mart tables, which build incrementally every hour,
|
|
92
|
+
must scan the full table ingested by Datastream, causing our BigQuery costs to skyrocket.
|
|
93
|
+
|
|
94
|
+
We manually created a partition for all large tables to mitigate this issue.
|
|
95
|
+
Although this solution worked for us, we do not recommend it
|
|
96
|
+
because it can affect your data ingestion.
|
|
97
|
+
Please use it cautiously and consult GCP support if you encounter any issues.
|
|
98
|
+
|
|
99
|
+
Here are the steps we took to add a partition to the table ingested using Datastream.
|
|
100
|
+
For example, we have a _**transaction**_ table with over 100 million rows
|
|
101
|
+
being ingested via Datastream and want to add a partition.
|
|
102
|
+
|
|
103
|
+
- Pause the Datastream that ingests the _**transaction**_ table.
|
|
104
|
+
|
|
105
|
+
- Create a new _**transaction\_v2**_ table using the same Data Definition Language (DDL)
|
|
106
|
+
as the original _**transaction**_ table but by appending the partition clause.
|
|
107
|
+
|
|
108
|
+
Find the DDL for the existing _**transaction**_ table.
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
SELECT
|
|
112
|
+
ddl
|
|
113
|
+
FROM
|
|
114
|
+
`<project-id>`.`region-<region-anme>`.INFORMATION_SCHEMA.TABLES
|
|
115
|
+
WHERE
|
|
116
|
+
table_name="transaction" and table_schema='<dataset name>'
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use the DDL statement retrieve from above query
|
|
120
|
+
and add your partition using `PARTITION BY` clause.
|
|
121
|
+
|
|
122
|
+
```sql
|
|
123
|
+
CREATE TABLE transaction_v2
|
|
124
|
+
(
|
|
125
|
+
id INT64,
|
|
126
|
+
amount NUMERIC
|
|
127
|
+
)
|
|
128
|
+
PARTITION BY DATE(updated_at)
|
|
129
|
+
CLUSTER BY id;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
- Insert data from the _**transaction**_ into _**transaction\_v2**_.
|
|
133
|
+
|
|
134
|
+
- Drop the _**transaction**_ table.
|
|
135
|
+
|
|
136
|
+
- Create a new _**transaction**_ table using the DDL of _**transaction\_v2**_,
|
|
137
|
+
which has the partition clause.
|
|
138
|
+
|
|
139
|
+
- Insert data from _**transaction\_v2**_ into the new _**transaction**_ table.
|
|
140
|
+
|
|
141
|
+
- Drop the _**transaction\_v2**_ table.
|
|
142
|
+
|
|
143
|
+
- Resume the Datastream.
|
|
144
|
+
|
|
145
|
+
Using **updated\_at** as a partition column in the raw tables
|
|
146
|
+
allows us to retrieve any new changes from the raw table
|
|
147
|
+
without scanning the entire table for mart table updates.
|
|
148
|
+
|
|
149
|
+
## Data Transformation
|
|
150
|
+
|
|
151
|
+
**Key Features**
|
|
152
|
+
|
|
153
|
+
We started using GCP Dataform for data transformation,
|
|
154
|
+
enabling users to define, test, and deploy data models in a reproducible and modular manner.
|
|
155
|
+
It helps data teams manage complex pipelines and maintain data quality efficiently.
|
|
156
|
+
|
|
157
|
+
- **SQL-based Data Transformations:** Define and run SQL transformations on your data,
|
|
158
|
+
and build complex pipelines with reusable scripts.
|
|
159
|
+
|
|
160
|
+
- **Dependency Management:** Ensure transformations are executed in the right order
|
|
161
|
+
and manage dependencies among them.
|
|
162
|
+
|
|
163
|
+
- **Version Control:** Version control your data transformation code with Git,
|
|
164
|
+
track changes, collaborate, and revert to previous versions if needed.
|
|
165
|
+
|
|
166
|
+
- **Testing and Validation:** Write tests and validations for your data,
|
|
167
|
+
and define rules and expectations to ensure quality and integrity.
|
|
168
|
+
|
|
169
|
+
- **Incremental Builds:** Optimize the execution time of your data pipelines
|
|
170
|
+
by processing only changed data since the last build.
|
|
171
|
+
|
|
172
|
+
- **Collaboration and Sharing:** Share and reuse data transformation code with your team,
|
|
173
|
+
create and manage projects, grant access, and promote code reuse across projects.
|
|
174
|
+
|
|
175
|
+
- **Scheduler Integration:** Automate execution of your data pipelines at specified intervals
|
|
176
|
+
with scheduling tools like Airflow or Google Cloud Scheduler.
|
|
177
|
+
|
|
178
|
+
- **Extensibility:** Extend Dataform through plugins and custom JavaScript code,
|
|
179
|
+
write custom logic, integrate with external systems,
|
|
180
|
+
or implement advanced data processing tasks using JavaScript.
|
|
181
|
+
|
|
182
|
+
We haven't used GCP Dataform extensively at this time.
|
|
183
|
+
We will share more information in the future after using it more.
|
|
184
|
+
|
|
185
|
+
## Security
|
|
186
|
+
|
|
187
|
+
### Datastream security
|
|
188
|
+
|
|
189
|
+
GCP Datastream is designed with security in mind and provides several features
|
|
190
|
+
to ensure the security of data replication.
|
|
191
|
+
Key features include encryption at rest and in transit, VPC service control,
|
|
192
|
+
IAM roles and permissions, and audit logging.
|
|
193
|
+
|
|
194
|
+
### PII column security
|
|
195
|
+
|
|
196
|
+
Our GCP Datastream-based pipeline uses two methods to handle
|
|
197
|
+
Personally Identifiable Information (PII) columns.
|
|
198
|
+
The first method completely blocks specific PII column(s) from being included in the Datastream.
|
|
199
|
+
This ensures that Datastream does not ingest PII columns into BigQuery.
|
|
200
|
+
|
|
201
|
+
In some cases, our customer support or marketing team needs the PII of our customers,
|
|
202
|
+
such as email, phone number, etc.
|
|
203
|
+
In those cases, we ingest the PII column(s) into BigQuery and mask them
|
|
204
|
+
using the dynamic data masking feature of BigQuery.
|
|
205
|
+
|
|
206
|
+
**About Dynamic Data Masking**
|
|
207
|
+
|
|
208
|
+
BigQuery provides dynamic data masking at the column level,
|
|
209
|
+
enabling access to a column while obscuring its data for privileged user groups.
|
|
210
|
+
Combining data masking with column-level access control allows you to configure
|
|
211
|
+
access to column data at different levels based on user privileges.
|
|
212
|
+
This simplifies data sharing, eliminates the need to modify existing queries,
|
|
213
|
+
allows scalability when applying data access policies, and enables attribute-based access control.
|
|
214
|
+
|
|
215
|
+
Here are the benefits of using BigQuery for dynamic data masking at the column level:
|
|
216
|
+
|
|
217
|
+
- Simplifies data sharing with larger groups by masking sensitive columns.
|
|
218
|
+
|
|
219
|
+
- Existing queries automatically mask column data based on user roles,
|
|
220
|
+
eliminating the need to exclude inaccessible columns.
|
|
221
|
+
|
|
222
|
+
- Enables scalability of data access policies by writing a policy tag once
|
|
223
|
+
and applying it to any number of columns.
|
|
224
|
+
|
|
225
|
+
- Provides contextual data access based on data policy and associated principals
|
|
226
|
+
through attribute-based access control.
|
|
227
|
+
|
|
228
|
+
## Cost
|
|
229
|
+
|
|
230
|
+
### Ingest required columns only
|
|
231
|
+
|
|
232
|
+
When using GCP Datastream, it is important to be mindful of the volume of data
|
|
233
|
+
being ingested into BigQuery.
|
|
234
|
+
Datastream charges based on the amount of data processed through it,
|
|
235
|
+
so ensure to ingest only necessary tables and columns.
|
|
236
|
+
|
|
237
|
+
### Use staleness settings
|
|
238
|
+
|
|
239
|
+
Data staleness in Datastream refers to the amount of time between
|
|
240
|
+
when a change is made in the source database and when that change is captured
|
|
241
|
+
and replicated in the target destination.
|
|
242
|
+
Datastream provides an option to specify the staleness
|
|
243
|
+
to balance BigQuery query performance and cost versus data freshness.
|
|
244
|
+
By setting the staleness settings, merging costs can be reduced.
|
|
245
|
+
However, setting too low of a staleness value can result in higher costs
|
|
246
|
+
due to more frequent querying of the target destination.
|
|
247
|
+
|
|
248
|
+
To increase or decrease the staleness in the existing tables ingesting via Datastream.
|
|
249
|
+
|
|
250
|
+
```sql
|
|
251
|
+
ALTER TABLE <dataset-name>.<table_name>
|
|
252
|
+
SET OPTIONS (
|
|
253
|
+
max_staleness = INTERVAL 30 MINUTE
|
|
254
|
+
);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Use BigQuery reservation for backfill
|
|
258
|
+
|
|
259
|
+
Setting reservation pricing before starting the backfill of large tables
|
|
260
|
+
is important to reduce high backfill costs.
|
|
261
|
+
In our case, we started the backfill of a large table without using BigQuery reservation,
|
|
262
|
+
and the cost was 2 times higher than it would have been with reservation pricing.
|
|
263
|
+
|
|
264
|
+
(이미지 첨부: BigQuery Cost during the Backfill without Reservation)
|
|
265
|
+
|
|
266
|
+
(이미지 첨부: BigQuery Cost during the Backfill with Reservation)
|
|
267
|
+
|
|
268
|
+
## The bottleneck of GCP Datastream
|
|
269
|
+
|
|
270
|
+
### Lack of data partitioning
|
|
271
|
+
|
|
272
|
+
GCP Datastream is a powerful tool for real-time data replication,
|
|
273
|
+
but it can still be improved in some areas.
|
|
274
|
+
One major bottleneck is the lack of built-in partitioning.
|
|
275
|
+
When a large table is ingested through Datastream,
|
|
276
|
+
there should be an option to create a partition in the target table.
|
|
277
|
+
|
|
278
|
+
### Lack of pre-transformation
|
|
279
|
+
|
|
280
|
+
Another challenge with GCP Datastream is the absence of pre-transformation.
|
|
281
|
+
There is no option to transform the data before it is sent to the target system.
|
|
282
|
+
This feature can help encrypt source columns, create derived columns, etc.
|
|
283
|
+
|
|
284
|
+
### Full table scan while merging incremental changes
|
|
285
|
+
|
|
286
|
+
GCP Datastream scans the full table to apply a few incremental rows.
|
|
287
|
+
This approach can be inefficient and expensive.
|
|
288
|
+
To optimize the performance of GCP Datastream,
|
|
289
|
+
developing a more efficient way of scanning the table and applying incremental rows is essential.
|
|
290
|
+
|
|
291
|
+
## What’s Next?
|
|
292
|
+
|
|
293
|
+
We have made significant changes in our latest solution for ingesting real-time data
|
|
294
|
+
from our source database to BigQuery.
|
|
295
|
+
We have replaced AWS DMS with GCP Datastream.
|
|
296
|
+
This has allowed us to take advantage of the unique features that GCP Datastream offers.
|
|
297
|
+
|
|
298
|
+
Additionally, we have implemented GCP Dataform for data modelling and mart tables.
|
|
299
|
+
This has given us more flexibility and control over our data.
|
|
300
|
+
|
|
301
|
+
However, we have encountered a few challenges with GCP Datastream.
|
|
302
|
+
It does not support pre-transformation, which is essential for our use case.
|
|
303
|
+
To address this, we are considering using Dataflow for real-time pre-transformation.
|
|
304
|
+
This would allow us to apply transformations to the data before it is ingested into BigQuery,
|
|
305
|
+
giving us more control over the quality and consistency of our data.
|
|
306
|
+
Overall, we believe that these changes have greatly improved the efficiency and effectiveness
|
|
307
|
+
of our data ingestion process.
|