[Golang] Random Unique String

체인코드를 개발하면서 Golang으로 유니크한 Random String을 생성할 필요가 있었습니다.

이 글에서는 난수를 사용해야할 때 주의점에 대해 설명합니다.

Random은 조심해야할 부분이 몇가지 있는데 아래와 같습니다.

  1. Seed값
  2. 고속의 동시 접속

Seed는 주로 시각(time.Now().UnixNano())을 인자로 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
package main

import (
"fmt"
"math/rand"
"time"
)

func main() {
rand.Seed(time.Now().UnixNano()) // 현재 시각의 nano초를 seed인자로 입력
fmt.Println(rand.Int63())
}

랜덤의 개념이기는 하지만 정확히는 Seed를 같은 값을 주게 되면 같은 순서의 랜덤 문자가 나오게됩니다.

여기에서 문제가 발생하는데 동시 접속이 많은 시스템이나 시스템 과부화의 테스트를 진행할 경우 같은 시간에 Seed값이 입력된다면 랜덤값이지만 같은 값이 나올 수 있다는 이야기가 됩니다.

실제로 제가 개발하고 있는 시스템에서 500명의 사용자로 시스템에 접근을 가정했을때 꽤 높은 확률로 일치하는 값의 결과가 나왔습니다.

따라서 저는 조금 더 수준높은 랜덤값을 생성하기위해 공부했는데 이때 사용한 패키지가 crypto/rand입니다.

https://golang.org/pkg/crypto/rand/

패키지 설명으로는 암호로 안전한 난수를 생성할수 있도록 구현했다고 하네요

Package rand implements a cryptographically secure random number generator.

코드 사용은 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
cryptoRand "crypto/rand"
"fmt"
"math"
"math/big"
"math/rand"
)

func main() {
seed, _ := cryptoRand.Int(cryptoRand.Reader, big.NewInt(math.MaxInt64))
rand.Seed(seed.Int64())
fmt.Println(rand.Int63())
}
1
2
// 결과
458626028109884820