본문 바로가기
Web

[JavaScript]자바스크립트로 중복없는 쿠폰번호 생성(2)_코드 최적화

by 다봄이 2020. 8. 6.

앞선 포스팅대로, 중복 없는 쿠폰번호를 생성하기 위한 여러 방법을 탐구하고 간단하게 코드를 짜 보았다.

이제 이 너저분한 코드에 필요없는 부분들을 제거하자.

flow는 다음과 같다.

  1. 쿠폰 코드 생성(CRC32)
  2. 생성된 코드의 중복 검사(map) 및 중복되지 않은 데이터 등록
  3. 생성된 map의 값들을 db 등록(firebase.database().set())

쿠폰 코드 생성

for (let i = 0; i < count; i++) {
        let arr = new makeCouponStr(await getUnixTime(), 'seed2', 'seed3');
        coupons.push([i, arr.seed1, arr.seed2, arr.seed3]);
    }

    let x = coupons.join('-');
    let y = x.split('-');
    let cnt = 0;
    let temp = 0;

for (let i = 0; i < y.length; i++) {
    let buf = Buffer.from(y[i].toString(16));
    let num = CRC32.unsigned(buf);
    console.log('16진수 ', num.toString(16));

쿠폰 코드를 배열로 입력 받았기 때문에, Buffer-CRC32 모듈 사용을 위해 이중 배열을 스트링으로 다시 바꾸는 과정을 추가했었다.

Buffer의 특징은 node.js 공식문서에서 확인할 수 있다.

그렇다면 처음부터 스트링으로 쿠폰 코드에 대한 시드값을 받아 쿠폰별로 시드를 하나로 묶으면 .join .split과 같은 필요 없는 부분을 제거할 수 있을 것이다.

let couponInit = ''; //쿠폰코드에 관한 정보를 저장할 스트링 초기화

for(let i=0; i<count; i++){
     let str = new makeCouponInit(await getUnixTime(), 'seed2', 'seed3');
     let couponCode = couponInit.concat(i, str.seed1, str.seed2, str.seed3); //쿠폰코드 정보 str 생성

     let buf = Buffer.from(couponCode.toString(16));

자바스크립트의 .concat 메서드를 사용하면 매개변수로 받은 매개변수들을 합친 새로운 array 객체를 반환한다.

concat()

array.concat([value1[, value2[, ...[, valueN]]]])

매개변수 : 배열 또는 값

반환값 : 매개변수들을 합친 새로운 array 객체

* 예시

```
    let couponCode = couponInit.concat(i, str.seed1, str.seed2, str.seed3);

0 // i
1580290179097961 //str.seed1
seed2 //str.seed2
seed3 //str.seed3
01580290179097961seed2seed3 //couponCode
```

Map()

중복 검사를 위한 해쉬맵 부분에서는 자바스크립트에서 해시 테이블을 제공하는 구조를 몰라서 우선 자바의 해시맵 함수를 구현하여 사용하였다.

자바스크립트의 ES6부터 도입된 Map()의 공식문서를 살펴보면, Map() 자체도 [key, value] pair의 구조를 갖는 해시 테이블의 자료구조임을 알 수 있다.

따라서 해당 부분을 Map()으로 대체하여 코드를 정리한다.

if (map.has(hex) == false) { //해당 key가 map 객체 안에 없다면
    map.set(hex, amount); //map 객체에 쿠폰번호를 key, 쿠폰금액을 value로 집어넣음.
}
else { 
    //예외 처리 : (재귀)중복된 쿠폰 번호가 생성될 경우 처리 로직 만들어야 함
    console.log('내부 중복 발생!');
}

Firebase Database 등록 부분 추가

for (let [key, value] of map.entries()) {
    let dup = await couponRef.child('serial_num').equalTo(key).once('value');

    //예외처리 : (재귀)db의 쿠폰 번호와 새로 생성한 쿠폰 번호가 같을 때 처리 로직 만들어야 함

    if (dup.val()) { //db에 등록된 serial_num과 생성한 key(쿠폰코드)가 같다면
        console.log('db 중복 발생!!!');
        }
    else { //db에 새로 등록
        await couponRef.child(key).set({ //쿠폰 번호를 key로 등록

        })
    }
}

map에 저장된 key와 value를 가지고 db 데이터를 쿼리한다. 쿼리한 데이터가 없다면 db에 새로 등록하고, 쿼리한 데이터가 있다면 db에 동일한 쿠폰 번호가 등록 되어 있다는 것이므로 예외처리 한다.

equalTo()는 firebase에서 쿼리한 데이터와 현재 데이터가 같은지 비교하는 메서드이다.

let couponRef = firebase.database().ref('coupons'); //db 쿼리
let dup = await couponRef.child('serial_num').equalTo(key).once('value'); //쿼리한 데이터 비교

firebase의 데이터베이스에서 'coupons'라는 목록을 참조한다.

'coupons'의 하위 key가 'serial_num'를 갖고 있고, 이 'serial_num'이 갖는 값이 map에 key로 집어넣은 코드 번호와 같다면 한 번 호출하여 dup 변수에 저장한다.

if (dup.val()) { //db에 등록된 serial_num과 생성한 key(쿠폰코드)가 같다면
    console.log('db 중복 발생!!!');
}
else { //db에 새로 등록
    await couponRef.child(key).set({ //쿠폰 번호를 key로 등록
    amount: value,
    expired: this.expire
  })
}

dup 변수의 값이 있다면 생성한 쿠폰 코드가 db에 이미 등록된(중복된) 코드라는 뜻이므로, 우선 예외 처리를 위해 콘솔을 찍어둔다. 코드가 중복되지 않을 경우, db에 해당 코드를 .set()을 사용해 새로 등록한다. 등록 시 쿠폰 번호를 key로 등록한다.

댓글