8.6 KiB
개발 문서: SMS 인증 기능 구현
1. 완료된 작업: SMS 인증 전체 플로우 구현 (발송 및 검증)
작업 내역
Backend (Go)
-
Naver SENS API 연동 서비스 구현: (
internal/service/sms_service.go)- 내용: Naver SENS API를 호출하여 SMS 발송을 요청하는 핵심 모듈을 구현했습니다.
- 필요 이유: 실제 SMS 메시지를 외부로 발송하기 위한 통신 기능이 필요했습니다.
-
API 엔드포인트 및 핸들러 추가: (
cmd/server/main.go,internal/handler/auth_handler.go)- 내용:
POST /api/v1/auth/sms엔드포인트를 추가하고, 인증 코드 생성 및 SMS 서비스 호출 로직을 구현했습니다. - 필요 이유: 프론트엔드에서 보낸 SMS 발송 요청을 수신하고 처리하기 위한 접점이 필요했습니다.
- 내용:
-
데이터 모델 정의: (
internal/domain/sms_models.go)- 내용: API 요청/응답 처리를 위한 Go 데이터 구조(struct)를 정의했습니다.
- 필요 이유: JSON 데이터를 Go 코드 내에서 타입-세이프(type-safe)하게 다루기 위해 필요했습니다.
-
입력 값 처리 및 로깅 강화: (
internal/handler/auth_handler.go)- 내용: 전화번호에서 하이픈(
-)을 제거하고, 발송/검증 실패 시 상세 오류를 기록하도록 구현했습니다. - 필요 이유: 외부 API의 요구사항을 충족시키고, 운영 중 문제 발생 시 신속하게 원인을 진단하기 위해 필요했습니다.
- 내용: 전화번호에서 하이픈(
-
Redis 서비스 구현 및 연동: (
internal/service/redis_service.go,internal/handler/auth_handler.go)- 내용: Redis 클라이언트 초기화, 인증 코드 저장(
StoreVerificationCode), 조회(GetVerificationCode), 삭제(DeleteVerificationCode) 기능을 구현하고,AuthHandler와SendSms함수에 Redis 저장 로직을 추가했습니다. - 필요 이유: 발급된 인증 코드를 임시로 저장하여 사용자가 나중에 입력한 코드와 비교 검증하기 위한 안정적인 저장소가 필요했습니다.
- 내용: Redis 클라이언트 초기화, 인증 코드 저장(
-
인증 코드 검증 API 엔드포인트 구현: (
cmd/server/main.go,internal/handler/auth_handler.go,internal/domain/sms_models.go)- 내용:
POST /api/v1/auth/verify-sms엔드포인트를 추가하고, 사용자가 입력한 코드와 Redis에 저장된 코드를 비교 검증하는VerifySms함수를 구현했습니다. 관련 데이터 모델도 추가했습니다. - 필요 이유: 사용자가 받은 인증 코드를 백엔드에서 확인하고, 인증 성공/실패 여부를 결정하기 위한 API와 로직이 필요했습니다.
- 내용:
-
인증 성공 시 JWT 발급 로직: (
internal/handler/auth_handler.go)- 내용: 코드 검증이 성공하면, 해당 사용자에 대한 세션 토큰(JWT)을 생성하여 프론트엔드에 반환합니다.
- 필요 이유: 사용자가 로그인 상태를 유지하고, 인증이 필요한 다른 API를 호출할 수 있도록 하기 위함입니다.
Frontend (Flutter)
-
SMS 인증 요청 서비스 구현: (
lib/core/services/auth_proxy_service.dart)- 내용: 백엔드의 SMS 발송 API를 호출하는
sendSms함수를 추가했습니다. - 필요 이유: UI와 백엔드 API 간의 통신을 담당하는 재사용 가능한 서비스 계층을 만들어 코드의 관심사를 분리하기 위해 필요했습니다.
- 내용: 백엔드의 SMS 발송 API를 호출하는
-
로그인 화면 UI/UX 개선: (
lib/features/auth/presentation/login_screen.dart)- 내용: 이메일/SMS 인증 탭 UI와 전화번호 입력 필드 및 버튼을 구현했습니다.
- 필요 이유: 사용자가 SMS 인증 방식을 선택하고 사용할 수 있는 명확한 UI가 필요했습니다.
-
SMS 인증 발송 플로우 로직 구현: (
lib/features/auth/presentation/login_screen.dart)- 내용: '인증 코드 발송' 버튼 클릭 시 API를 호출하고, 결과에 따라 UI 상태를 동적으로 변경하는 로직을 구현했습니다.
- 필요 이유: 사용자의 상호작용에 응답하고, 통신 결과에 따라 UI를 동적으로 변경하는 로직이 필요했습니다.
-
인증 코드 검증 서비스 구현: (
lib/core/services/auth_proxy_service.dart)- 내용:
AuthProxyService에 백엔드의verify-smsAPI를 호출하는 함수를 추가했습니다. - 필요 이유: 인증 코드 검증을 위해 백엔드와 통신하는 서비스 로직이 필요했습니다.
- 내용:
-
인증 코드 검증 플로우 로직 구현: (
lib/features/auth/presentation/login_screen.dart)- 내용: '코드 확인' 버튼 클릭 시, 입력된 코드와 전화번호를 백엔드로 보내 검증을 요청하는 로직을 구현했습니다.
- 필요 이유: 사용자의 코드 제출 액션에 응답하는 로직이 필요했습니다.
-
인증 결과 처리: (
lib/features/auth/presentation/login_screen.dart)- 내용: 검증 성공 시 JWT를 콘솔에 출력하고 성공 다이얼로그를 표시합니다. (JWT 저장 및 대시보드 이동은
TODO상태) - 필요 이유: 인증 결과에 따라 사용자에게 적절한 피드백(화면 전환 또는 오류 안내)을 제공해야 합니다.
- 내용: 검증 성공 시 JWT를 콘솔에 출력하고 성공 다이얼로그를 표시합니다. (JWT 저장 및 대시보드 이동은
전체 인증 플로우: 시퀀스 다이어그램
sequenceDiagram
participant 사용자
participant Flutter as Flutter (Frontend)
participant Go as Go (Backend)
participant NaverSMS as Naver SMS API
Note over 사용자, NaverSMS: 1. 인증 코드 발송 단계
사용자->>Flutter: 전화번호 입력 후 '인증 코드 발송' 요청
Flutter->>Go: POST /api/v1/auth/sms
Go->>Go: 6자리 인증 코드 생성 & 임시 저장 (Redis)
Go->>NaverSMS: SMS 발송 요청 (인증 코드 포함)
NaverSMS-->>사용자: [SMS] 인증번호 메시지 수신
NaverSMS-->>Go: 발송 요청 결과 응답
Go-->>Flutter: 처리 결과 응답 (성공)
Flutter->>사용자: UI 업데이트 (인증번호 입력창 표시)
Note over 사용자, Go: 2. 인증 코드 검증 단계
사용자->>Flutter: 수신한 인증 코드 입력 후 '코드 확인' 요청
Flutter->>Go: POST /api/v1/auth/verify-sms (전화번호, 입력 코드)
Go->>Go: 임시 저장된 코드와 비교 및 검증 (Redis)
alt 인증 성공
Go->>Go: JWT(세션 토큰) 생성
Go-->>Flutter: 인증 성공 응답 (JWT 포함)
Flutter->>Flutter: JWT 수신 및 처리 (저장 및 대시보드 이동 예정)
Flutter->>사용자: 성공 메시지 표시
else 인증 실패
Go-->>Flutter: 인증 실패 응답
Flutter->>사용자: 오류 메시지 표시
end
2. 발생 이슈 및 해결 과정 (통합)
-
발신자 번호 미인증 오류
- 이슈: SENS API에서
'from' is not an authenticated tel number오류 반환. - 해결: 네이버 클라우드 플랫폼 콘솔에서 SMS 발신 번호를 등록하고 인증 절차를 완료한 후,
.env파일의NAVER_SENDER_PHONE_NUMBER값을 인증된 번호로 수정.
- 이슈: SENS API에서
-
환경 변수 누락으로 인한 API URL 생성 실패
- 이슈: 백엔드 컨테이너가
NAVER_CLOUD_SERVICE_ID환경 변수를 읽지 못해URL not found오류 발생. - 해결:
docker-compose.yaml의backend서비스에env_file: [".env"]설정을 추가하여 컨테이너가.env파일의 모든 변수를 로드하도록 수정.
- 이슈: 백엔드 컨테이너가
-
전화번호 형식 불일치 오류
- 이슈: SENS API에서
phone number format excluding dash(-)오류 반환. - 해결: 백엔드
AuthHandler에서 SENS API로 전화번호를 전달하기 전,strings.ReplaceAll함수를 사용하여 하이픈(-)을 모두 제거하는 로직 추가.
- 이슈: SENS API에서
-
Redis 연결 실패 오류
- 이슈: 백엔드 컨테이너가 Redis에 접속하지 못하고
Failed to connect to Redis: dial tcp [::1]:6379: connect: connection refused오류 발생. - 해결: 프로젝트 루트의
.env파일에REDIS_ADDR=redis:6379를 추가하고,docker-compose up -d --force-recreate명령을 통해 컨테이너를 강제로 재생성하여 변경된 환경 변수를 적용.
- 이슈: 백엔드 컨테이너가 Redis에 접속하지 못하고
-
Go 백엔드 빌드 실패 (JWT 라이브러리 import 누락)
- 이슈: Docker 이미지 빌드 중
undefined: jwt컴파일 오류 발생. - 해결:
backend/internal/handler/auth_handler.go파일에"github.com/golang-jwt/jwt/v4"import 구문을 추가하여 해결.
- 이슈: Docker 이미지 빌드 중