feat: 근로자 보안 링크 SMS 발송 연동 - #134
Merged
Merged
Conversation
SOLAPI REST Adapter와 발송 API를 추가하고, Provider 접수 성공 후에만 기존 Worker Link를 SENT로 기록합니다. 전화번호와 원본 token은 저장하지 않으며 사업장 격리와 중복 발송 방지를 유지합니다.
Provider 인증 요청, 접수 실패와 timeout, 중복 호출, token 불일치, 사업장 격리, 감사로그 생성을 단위·통합 테스트로 확인합니다.
로컬·데모 환경변수와 실제 수신 Smoke 순서, 개인정보 비저장 원칙, Provider 장애 시 수동 전달 방법을 정리합니다.
외부 Provider 호출 전에 SENDING 상태를 별도 트랜잭션으로 확정합니다. 타임아웃처럼 접수 여부가 불명확하면 REVIEW_REQUIRED로 전환해 자동 재발송을 차단하고, Provider가 명확히 거부한 경우에만 NOT_SENT로 되돌립니다. 발급 응답의 전체 URL과 원본 토큰도 분리합니다.
Provider 호출 전 SENDING 커밋, 발송 중 링크 만료, 불명확한 응답의 REVIEW_REQUIRED 전환과 재호출 차단을 검증합니다. Provider 거부와 timeout을 구분하고 PostgreSQL 상태 제약도 확인합니다.
SENT를 휴대전화 수신 성공이 아닌 Provider 접수 또는 수동 전달 기록으로 정의합니다. 불명확한 결과의 자동 재발송 금지와 worker_url·worker_link_token 사용 기준을 문서화합니다.
4 tasks
BcKmini
approved these changes
Aug 11, 2026
Member
There was a problem hiding this comment.
코드 확인했습니다.
- Idempotency-Key + raw token 이중 검증(
MessageDigest.isEqual로 상수시간 비교)이라 다른 링크 오발송 위험이 없어 보입니다. - 상태 전이(NOT_SENT → SENDING → SENT/REVIEW_REQUIRED)를
findForUpdate로 행 잠금하고 트랜잭션 분리해서 처리한 게 동시 요청/재시도 상황에서 안전해 보입니다. - 전화번호·원본 토큰을 감사로그·일반 로그에 남기지 않는 부분,
worker_link_token을 발급 직후에만 노출하는 것도 문서와 코드가 일치합니다. - SOLAPI 어댑터는 HMAC-SHA256 서명 + timeout + 응답 크기 제한까지 다 있어서 외부 호출 경계 처리도 꼼꼼합니다.
.env.example기본값이WORKER_LINK_SMS_PROVIDER=none이라 기존 수동 전달 흐름을 안 건드리는 것도 좋습니다.
사소한 확인차 질문: normalizeKoreanMobile이 010만 허용하는데(011~019 구형 번호 제외) 문서에도 동일하게 "국내 휴대전화 번호(010...)"로 명시돼 있어서 의도된 MVP 스코프로 이해함 --> 맞나요
CI 전부 통과했고 merge 진행하겠습니다.
Contributor
Author
|
사소한 확인차 질문: normalizeKoreanMobile이 010만 허용하는데(011~019 구형 번호 제외) 문서에도 동일하게 "국내 휴대전화 번호(010...)"로 명시돼 있어서 의도된 MVP 스코프로 이해함 --> 맞나요 일단 제 번호로 보내니까 0104729**** 맞습니다 |
43 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
왜 필요한가요?
현재 Worker Link는 발급과 수동 전달 완료 기록만 가능해, HR이 링크를 복사해 별도 문자 앱으로 보내야 합니다. 이번 변경은 Server가 선택적으로 SMS Provider를 호출하면서, 외부 발송과 DB 기록이 어긋날 때 같은 문자가 자동 재발송되지 않도록 전달 상태를 관리합니다.
Closes #133
무엇이 바뀌나요?
POST /api/v1/worker-links/{workerLinkId}/sms-deliveriesAPI를 추가했습니다.Idempotency-Key와 원본 token hash를 검증합니다.WorkerLinkSmsSenderPort와 SOLAPI REST Adapter를 추가했습니다.SENDING을 별도 트랜잭션으로 먼저 저장합니다.NOT_SENT, timeout·응답 단절처럼 접수 여부가 불명확하면REVIEW_REQUIRED로 기록합니다.SENDING과REVIEW_REQUIRED에서는 자동 재발송을 막아 중복 문자를 방지합니다.SENT로 기록합니다.worker_url은 전체 URL,worker_link_token은 발급 직후만 반환하는 원본 token으로 구분했습니다.V39__extend_worker_link_delivery_status.sql에서 전달 상태 DB 제약을 확장했습니다.상태 의미
NOT_SENTSENDINGREVIEW_REQUIREDSENTSENT는 휴대전화의 최종 수신 성공을 의미하지 않습니다. 기존/sent수동 기록도 같은 업무 상태를 사용하므로 이미SENT인 링크에는 SMS를 추가 발송하지 않습니다.사용자·개발 영향
none이며, 이 상태에서는 성공으로 가장하지 않고 503을 반환합니다.worker_link_token을 SMS 요청에 사용해야 합니다.SENT처리됐다면 기존 링크를 회전·재발급한 뒤 새 링크를 발송합니다.검증
./gradlew clean test— 성공SENDING상태가 커밋되는지 확인SENT로 기록하는지 확인REVIEW_REQUIRED전환과 재호출 시 Provider 미호출 확인완료 현황
Server 완료
SENDING·REVIEW_REQUIRED상태 처리외부 연동·배포 대기
worker_link_id,worker_link_token, 발급 시 사용한Idempotency-Key로 SMS API 연결SENDING,REVIEW_REQUIRED추가WORKER_PORTAL_BASE_URL로 설정