회원 가입 시 핸드폰 번호 검증을 위해 네이버의 sens api (문자 보내주는 api)를 사용하기로 했다.
한 달 50건 까지 무료라 문자 테스트 하기에는 딱 좋았다.

시그니처 생성
시그니처란?
export class AuthService {
constructor() {}
private makeSignature(): string {
const space = ' ';
const newLine = '\n';
const method = 'POST';
const timeStamp = Date.now().toString();
// url은 https://sens.apigw.ntruss.com 뺀 뒤 부분
const url = this.configService.get('NCP_URL');
// 시크릿 키는 계정 관리의 인증키 관리의 secret 키
const secret = this.configService.get('NCP_SECRET_KEY');
const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, secret);
hmac.update(method);
hmac.update(space);
hmac.update(url);
hmac.update(newLine);
hmac.update(timeStamp);
hmac.update(newLine);
// 액세스 키는 정 관리의 인증키 관리의 access key id
hmac.update(this.configService.get('NCP_ACCESS_KEY'));
const hash = hmac.finalize();
return hash.toString(CryptoJS.enc.Base64);
}
// WTPItrmMIfLUk/UyUIyoQbA/z5hq9o3G8eQMolUzTEa= 이런 암호화된 값이 나옴headers: {
'Content-Type': 'application/json; charset=utf-8',
'x-ncp-iam-access-key': this.configService.get('NCP_ACCESS_KEY'),
'x-ncp-apigw-timestamp': Date.now().toString(),
// 시그니처 만든 함수 호출로 string화 된 시그니처 주입
'x-ncp-apigw-signature-v2': this.makeSignature(),
},const body = {
type: 'SMS',
// 일반 문자는 'COMM', 광고성 문자는 'AD'
contentType: 'COMM',
// 보낼 전화번호 (네이버 sens api 등록할 때 번호여야 함.)
from: this.configService.get('HOST_PHONE_NUMBER'),
// 보낼 문자 메시지
content: `인증번호 [${verifyCode}]를 입력 해주세요.`,
messages: [
{
to: phoneNumber,
},
],
};
// 인증번호를 만들기 위해 for문 및 랜덤 숫자 생성
let verifyCode = '';
for (let i = 1; i < 7; i++) {
verifyCode += Number(Math.random() * 10).toFixed(0);
}try {
const res = await axios.post(
this.configService.get('NCP_URI'),
body,
options,
);
} catch (error) {
throw new InternalServerErrorException('서버 에러');
}
위의 요청 후 await this.cacheManager.set(phoneNumber, verifyCode, 180000); 로 nest가 제공하는 인메모리 캐시에 저장
async checkSMS({ phoneNumber, verifyCode }) {
const cacheVerifyNum = await this.cacheManager.get(phoneNumber);
if (!cacheVerifyNum) {
throw new Error('인증 번호가 만료되었습니다');
} else if (cacheVerifyNum === verifyCode) {
return true;
} else {
throw new UnauthorizedException('인증 번호가 일치하지 않습니다');
}
}
cacheManager 를 사용하기 위해 constructor 및 module 파일에 등록해 줘야 한다.
// auth.service.ts
@Injectable()
@UseInterceptors(CacheInterceptor)
export class AuthService {
constructor(
private userRepository: UserRepository,
private jwtService: JwtService,
private configService: ConfigService,
@Inject(CACHE_MANAGER) private cacheManager: Cache,
) {}
// auth.module.ts
CacheModule.register({ ttl: 만료시간(milliseconds), max: 캐시에 저장할 아이템 개수(number)}),