From 55806974e3480b1a9187651e43aa04c98e59c894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Tue, 24 Feb 2026 03:07:12 +0900 Subject: [PATCH 1/4] =?UTF-8?q?hotfix=20:=20=EA=B2=B0=EC=A0=9C=20=EC=8B=A0?= =?UTF-8?q?=EC=B2=AD=EC=8B=9C=20customerKey=20=ED=98=95=EC=8B=9D=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/payment/paymentActionClient.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/payment/paymentActionClient.tsx b/src/components/payment/paymentActionClient.tsx index 12a4accb..531476bf 100644 --- a/src/components/payment/paymentActionClient.tsx +++ b/src/components/payment/paymentActionClient.tsx @@ -116,8 +116,18 @@ export default function PaymentCheckoutPage({ study }: Props) { // 회원 결제 // @docs https://docs.tosspayments.com/sdk/v2/js#tosspaymentspayment + // customerKey 형식: 영문 대소문자, 숫자, 특수문자 -, _, =, ., @로 2자 이상 50자 이하 + // memberId를 안전한 형식으로 변환 (예: 기존 123 -> 변경 후 member-123) + const customerKey = `member-${study.memberId}`.replace(/[^a-zA-Z0-9\-_=\.@]/g, ''); + + // Toss 에서 2자이상 50자이하 문자열을 요구함 + if (customerKey.length < 2 || customerKey.length > 50) { + throw new Error( + `customerKey가 유효하지 않습니다: ${customerKey} (길이: ${customerKey.length})`, + ); + } const payment = tossPayments.payment({ - customerKey: String(study.memberId), + customerKey, }); setPayment(payment); From 16ace9d38a148be407e53b1caaef158d2297878a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Tue, 24 Feb 2026 03:16:57 +0900 Subject: [PATCH 2/4] chore : prettier, lint fix --- src/components/payment/paymentActionClient.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/payment/paymentActionClient.tsx b/src/components/payment/paymentActionClient.tsx index 531476bf..d4e615f3 100644 --- a/src/components/payment/paymentActionClient.tsx +++ b/src/components/payment/paymentActionClient.tsx @@ -118,7 +118,10 @@ export default function PaymentCheckoutPage({ study }: Props) { // @docs https://docs.tosspayments.com/sdk/v2/js#tosspaymentspayment // customerKey 형식: 영문 대소문자, 숫자, 특수문자 -, _, =, ., @로 2자 이상 50자 이하 // memberId를 안전한 형식으로 변환 (예: 기존 123 -> 변경 후 member-123) - const customerKey = `member-${study.memberId}`.replace(/[^a-zA-Z0-9\-_=\.@]/g, ''); + const customerKey = `member-${study.memberId}`.replace( + /[^a-zA-Z0-9\-_=\.@]/g, + '', + ); // Toss 에서 2자이상 50자이하 문자열을 요구함 if (customerKey.length < 2 || customerKey.length > 50) { From 4163c6c37b889d0dca6fbaed2a2b32b30d2ba9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Tue, 24 Feb 2026 03:35:58 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix=20:=20github=20PR=20noti=20=EB=A9=98?= =?UTF-8?q?=EC=85=98=20=EB=A7=B5=EC=9D=84=20=EC=BD=94=EB=93=9C=EB=B2=A0?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EB=A1=9C=20=EB=B0=94=EA=BE=B8=EA=B3=A0=20?= =?UTF-8?q?=ED=95=98=EC=8A=B9,=ED=98=84=EC=A4=80,=EC=A0=95=ED=99=98,?= =?UTF-8?q?=EB=8F=99=EC=A3=BC=EB=8B=98=EC=9C=BC=EB=A1=9C=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/memberMap.json | 22 +++++++++++++++++++ .../workflows/notify-pr-author-on-review.yml | 12 +++++----- .../workflows/notify-slack-on-pr-opened.yml | 22 ++++++++++++++----- 3 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 .github/memberMap.json diff --git a/.github/memberMap.json b/.github/memberMap.json new file mode 100644 index 00000000..dc451241 --- /dev/null +++ b/.github/memberMap.json @@ -0,0 +1,22 @@ +{ + "seong-jin-jo": { + "name": "조성진", + "slackId": "U07V0TY7CF9" + }, + "dongjooyun": { + "name": "윤동주", + "slackId": "U09KJ5DTD2B" + }, + "Hyeonjun0527": { + "name": "최현준", + "slackId": "U08298MKCBE" + }, + "HA-SEUNG-JEONG": { + "name": "정하승", + "slackId": "U0A6HD2AB0E" + }, + "solvedacuser": { + "name": "노정환", + "slackId": "U0A6NRTGK2Q" + } +} \ No newline at end of file diff --git a/.github/workflows/notify-pr-author-on-review.yml b/.github/workflows/notify-pr-author-on-review.yml index 9f60a07c..2946c441 100644 --- a/.github/workflows/notify-pr-author-on-review.yml +++ b/.github/workflows/notify-pr-author-on-review.yml @@ -9,10 +9,11 @@ jobs: runs-on: ubuntu-latest steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Extract Slack IDs and DM Text id: extract_info - env: - MEMBER_INFO: ${{ secrets.MEMBER_INFO_MAP }} run: | PR_AUTHOR="${{ github.event.pull_request.user.login }}" REVIEWER="${{ github.event.review.user.login }}" @@ -26,10 +27,11 @@ jobs: exit 0 fi - echo "$MEMBER_INFO" | base64 --decode > memberMap.json - AUTHOR_SLACK_ID=$(jq -r --arg id "$PR_AUTHOR" '.[$id].slackId' memberMap.json) - REVIEWER_SLACK_ID=$(jq -r --arg id "$REVIEWER" '.[$id].slackId' memberMap.json) + # 코드베이스의 memberMap.json에서 Slack ID 조회 + AUTHOR_SLACK_ID=$(jq -r --arg id "$PR_AUTHOR" '.[$id].slackId // empty' .github/memberMap.json) + REVIEWER_SLACK_ID=$(jq -r --arg id "$REVIEWER" '.[$id].slackId // empty' .github/memberMap.json) + # slackId가 없으면 DM 전송 불가 (skip) if [ -z "$AUTHOR_SLACK_ID" ] || [ -z "$REVIEWER_SLACK_ID" ] || \ [ "$AUTHOR_SLACK_ID" = "null" ] || [ "$REVIEWER_SLACK_ID" = "null" ]; then echo "skip=true" >> $GITHUB_OUTPUT diff --git a/.github/workflows/notify-slack-on-pr-opened.yml b/.github/workflows/notify-slack-on-pr-opened.yml index 9a67acf0..0d1f67a2 100644 --- a/.github/workflows/notify-slack-on-pr-opened.yml +++ b/.github/workflows/notify-slack-on-pr-opened.yml @@ -13,19 +13,29 @@ jobs: runs-on: ubuntu-latest steps: - - name: Decode memberMap.json from secret - run: | - echo "${{ secrets.MEMBER_INFO_MAP }}" | base64 --decode > memberMap.json + - name: Checkout + uses: actions/checkout@v4 + - name: Get PR author and reviewers id: get_member_info run: | # PR 작성자 이름 추출 PR_AUTHOR_GITHUB_ID="${{ github.event.pull_request.user.login }}" - PR_AUTHOR_NAME=$(jq -r --arg id "$PR_AUTHOR_GITHUB_ID" '.[$id].name' memberMap.json) + PR_AUTHOR_NAME=$(jq -r --arg id "$PR_AUTHOR_GITHUB_ID" '.[$id].name // "알 수 없음"' .github/memberMap.json) echo "pr_author_name=$PR_AUTHOR_NAME" >> $GITHUB_OUTPUT - # PR 작성자 제외한 멤버들의 slackId를 멘션으로 모으기 - MENTIONS=$(jq -r --arg author "$PR_AUTHOR_GITHUB_ID" 'to_entries | map(select(.key != $author)) | map("<@" + .value.slackId + ">") | join(" ")' memberMap.json) + # PR 작성자 제외한 멤버들의 slackId를 멘션으로 모으기 (slackId가 있는 경우만) + MENTIONS=$(jq -r --arg author "$PR_AUTHOR_GITHUB_ID" ' + to_entries + | map(select(.key != $author and .value.slackId != null and .value.slackId != "")) + | map("<@" + .value.slackId + ">") + | join(" ") + ' .github/memberMap.json) + + # 멘션이 없으면 빈 문자열로 설정 + if [ -z "$MENTIONS" ] || [ "$MENTIONS" = "null" ]; then + MENTIONS="" + fi echo "reviewers_mention=$MENTIONS" >> $GITHUB_OUTPUT - name: Send Slack message From 15fcd49f82965f4d8483e23bdf348d42ec08e0f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=84=B1=EC=A7=84?= Date: Tue, 24 Feb 2026 03:43:42 +0900 Subject: [PATCH 4/4] chore : lint, prettier fix --- src/components/payment/paymentActionClient.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/payment/paymentActionClient.tsx b/src/components/payment/paymentActionClient.tsx index d4e615f3..44df25fb 100644 --- a/src/components/payment/paymentActionClient.tsx +++ b/src/components/payment/paymentActionClient.tsx @@ -119,7 +119,7 @@ export default function PaymentCheckoutPage({ study }: Props) { // customerKey 형식: 영문 대소문자, 숫자, 특수문자 -, _, =, ., @로 2자 이상 50자 이하 // memberId를 안전한 형식으로 변환 (예: 기존 123 -> 변경 후 member-123) const customerKey = `member-${study.memberId}`.replace( - /[^a-zA-Z0-9\-_=\.@]/g, + /[^a-zA-Z0-9\-_=.@]/g, '', );