numpy 난수 생성 완전 정복 — randn·seed·ufunc 4가지 핵심 개념

F1 레이스에서 이런 상황을 상상해보자. 레이스 시뮬레이션 팀이 타이어 마모율을 예측하기 위해 수천 번의 가상 레이스를 돌린다. 매번 다른 노면 조건, 다른 기온, 다른 드라이버 반응을 집어넣어야 한다. 이때 필요한 게 바로 난수다. 그런데 문제가 있다. 시뮬레이션 결과를 동료에게 검증받으려면, 동료의 컴퓨터에서도 똑같은 난수가 나와야 한다.

numpy 난수는 이 두 가지를 동시에 해결한다. 무작위처럼 보이는 숫자를 대량으로 빠르게 만들면서, 필요할 때는 완전히 같은 결과를 재현할 수 있다. 요즘은 코드를 직접 작성하는 대신 AI에게 요청해서 결과를 받는 방식으로 분석 작업을 하는 경우가 많다. 그런데 개념을 모르면 AI에게 정확하게 요청할 수 없다. 어떤 함수를 써야 하는지, 파라미터를 어떻게 넣어야 하는지를 알아야 원하는 결과를 받을 수 있다. 이 글에서는 randn·random.normal·chisquare·seed 4가지 함수의 판단 기준과, numpy가 파이썬 기본 라이브러리보다 압도적으로 빠른 이유인 유니버셜 함수(ufunc)까지 한 번에 정리한다.

numpy 난수란 무엇인가 — 컴퓨터가 만드는 ‘가짜 무작위’

numpy 난수는 사실 완전한 무작위가 아니다. 내부적으로 시작 숫자(seed)를 기준으로 수학 공식을 돌려서 난수처럼 보이는 숫자열을 생성한다. 이를 **의사난수(Pseudo-random number)**라고 부른다.

완전한 무작위가 아니라는 게 단점처럼 들리지만, 현실에서는 오히려 강점이다. seed를 고정하면 누가 언제 실행해도 동일한 숫자열이 나오기 때문에, 실험 재현성을 보장할 수 있다. 머신러닝 모델 학습, 통계 시뮬레이션, 팀 공동 분석에서 seed 고정은 선택이 아니라 기본 습관이다.

numpy 난수 생성 함수 4가지 — 언제 무엇을 요청해야 하는가

함수마다 다루는 분포와 파라미터가 다르다. AI에게 난수 생성 코드를 요청하기 전에, 아래 판단 기준을 먼저 잡아두면 요청이 훨씬 정확해진다.

함수분포파라미터 지정언제 요청하나
np.random.randn()표준정규분포 (평균 0, 표준편차 1)불가분포 조건 없이 빠른 테스트용 샘플이 필요할 때
np.random.normal()가우시안 정규분포평균·표준편차 직접 지정현실 데이터 범위에 맞는 시뮬레이션이 필요할 때
np.random.chisquare()카이제곱분포자유도(df) 지정통계 검정 시뮬레이션 데이터가 필요할 때
np.random.seed()seed 값 지정결과를 재현 가능하게 고정해야 할 때

randn — 표준정규분포의 기본값

randn은 평균 0, 표준편차 1로 고정된 표준정규분포에서 numpy 난수를 추출한다. 파라미터 없이 개수만 넣으면 바로 동작한다. 빠른 테스트나 알고리즘 검증용 샘플을 만들 때 적합하다.

핵심 제약은 분포 파라미터를 바꿀 수 없다는 점이다. 평균 50, 표준편차 10인 현실 데이터를 흉내 내야 하는 상황이라면 randn은 맞지 않는다. 그 경우엔 random.normal을 써야 한다.

samples = np.random.randn(5)
# 예: [ 0.47  -1.23   0.89  -0.34   1.56 ]

random.normal — 평균·표준편차를 내가 정한다

random.normal은 randn의 유연한 버전이다. 가우시안 정규분포에서 numpy 난수를 추출하되, 평균(loc)과 표준편차(scale)를 직접 지정할 수 있다. 장비 측정값이나 센서 출력값처럼 특정 범위에 분포하는 데이터를 시뮬레이션할 때 쓴다.

AI에게 요청할 때 판단 기준은 단순하다. 평균과 표준편차를 알고 있으면 random.normal, 모르거나 표준 분포로 충분하면 randn을 요청하면 된다.

samples = np.random.normal(loc=50, scale=10, size=100)
# 평균 50, 표준편차 10인 분포에서 100개 추출

💬 AI 요청 예시 “numpy로 평균 50, 표준편차 10인 정규분포에서 100개의 샘플을 생성하는 코드를 작성해줘. seed는 42로 고정해줘.”

chisquare — 카이제곱분포 표본 추출

카이제곱분포는 정규분포 변수를 제곱해서 합산한 형태의 분포다. 통계 검정, 특히 범주형 데이터의 독립성 검정 시뮬레이션에서 등장한다. df 파라미터로 자유도를 지정한다.

가설검정 시리즈에서 다뤘던 자유도 개념이 여기서 직접 연결된다. 자유도를 몇으로 설정하느냐에 따라 분포의 모양 자체가 달라지기 때문에, AI에게 요청할 때 자유도 값을 반드시 함께 전달해야 한다.

💬 AI 요청 예시 “numpy로 자유도 3인 카이제곱분포에서 1000개의 샘플을 추출하고, 히스토그램으로 시각화하는 코드를 작성해줘.”

seed 고정 — 재현 가능한 실험의 핵심

np.random.seed()는 난수 생성의 시작점을 고정한다. 같은 seed 값을 쓰면 이후 생성되는 numpy 난수 전체가 동일한 순서로 나온다. seed 값 자체(2026이든 42든 0이든)는 결과의 품질과 무관하다. 중요한 건 팀원과 같은 값을 공유하는 것이다.

분석 코드 최상단에 seed를 한 줄 고정해두는 것만으로 실험 재현성 문제의 절반이 해결된다. AI에게 난수 생성 코드를 요청할 때도 seed 고정 여부를 명시하는 습관을 들이면 결과를 그대로 재사용할 수 있다.

💬 AI 요청 예시 “numpy로 정규분포 난수 500개를 생성하는 코드를 작성해줘. seed는 2026으로 고정하고, 같은 seed로 두 번 실행했을 때 결과가 동일한지 확인하는 코드도 포함해줘.”

numpy 난수 생성 함수와 유니버셜 함수 개념 정리

normalvariate vs random.normal — 왜 numpy가 압도적으로 빠른가

파이썬 기본 random 모듈에도 정규분포 난수를 생성하는 normalvariate 함수가 있다. 결과는 같아 보이지만 속도에서 하늘과 땅 차이가 난다.

항목random.normalvariatenp.random.normal
출처파이썬 기본 random 모듈NumPy
1회 호출 결과숫자 1개N개 한꺼번에
내부 처리 방식파이썬 인터프리터 루프C언어 벡터 연산
대량 생성 속도느림수십~수백 배 빠름
AI 요청 시 권장 여부❌ 대량 생성 비권장✅ 권장

루프를 1만 번 돌리는 것과 C언어 내부에서 벡터 연산을 한 번 실행하는 것의 차이다. 시뮬레이션 규모가 커질수록 이 격차는 더 벌어진다. AI에게 난수 생성 코드를 요청할 때 “파이썬 random 모듈”이 아닌 “numpy”를 명시하는 이유가 여기에 있다.

💬 AI 요청 예시 “numpy random.normal을 사용해서 정규분포 난수 10만 개를 생성하는 코드를 작성해줘. 파이썬 기본 random 모듈 대신 numpy를 쓰는 이유도 주석으로 설명해줘.”

유니버셜 함수(ufunc)란 무엇인가 — numpy가 빠른 진짜 이유

numpy 난수로 배열을 만든 뒤 연산을 가하면 뭔가 이상하다는 걸 느낄 수 있다. for 루프 없이 배열 전체에 함수를 적용했는데 결과가 나온다.

arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr))  # [1.  2.  3.  4.]

이게 가능한 이유가 바로 **유니버셜 함수(Universal Function, ufunc)**다. ufunc는 배열의 각 원소에 자동으로 반복 적용되는 함수다. 내부에서 C언어로 원소별 연산을 병렬 처리하기 때문에, 개발자가 루프를 작성할 필요가 없고 속도도 압도적으로 빠르다.

numpy 함수 대부분이 ufunc다. np.sqrt, np.exp, np.log, np.abs, 배열 간 사칙연산(+, -, *, /)까지 전부 해당된다. “numpy 함수 대부분이 ufunc”라는 말은 곧 “numpy 배열에 함수를 쓸 때마다 C언어 병렬 처리가 돌아가고 있다”는 뜻이다.

AI에게 배열 연산 코드를 요청할 때 “루프 없이 numpy 배열 전체에 적용”이라고 명시하면 ufunc를 활용한 코드를 자연스럽게 받을 수 있다. 개념을 알고 요청하는 것과 모르고 요청하는 것의 차이가 여기서 나온다.

💬 AI 요청 예시 “numpy 배열 [1, 4, 9, 16, 25]에 루프 없이 제곱근을 적용하는 코드를 작성해줘. ufunc를 사용하는 방식으로 해줘.”

핵심 요약

개념핵심AI 요청 시 포인트
randn평균 0, 표준편차 1 고정분포 조건 없는 빠른 샘플링 요청 시
random.normal평균·표준편차 직접 지정파라미터 값을 함께 명시해야 정확한 결과
chisquare자유도 지정 카이제곱분포자유도(df) 값을 반드시 함께 전달
seed난수 시작점 고정재현 필요 시 seed 값 명시
normalvariate vs random.normal1개씩 vs N개 한꺼번에numpy 명시 필수 — 기본 random 모듈과 다름
ufunc배열 원소별 자동 적용 + C언어 병렬 처리“루프 없이 배열 전체에 적용”으로 요청

numpy 난수를 쓸 줄 아는 것과 왜 빠른지를 아는 것은 다른 수준의 이해다. 개념을 알고 AI에게 요청하면 원하는 코드를 정확하게 받을 수 있고, 결과가 왜 그렇게 나왔는지도 검증할 수 있다.

[링크 제안]

난수를 만들기 전에 배열 구조 자체가 흔들린다면, 이 글이 그 전 단계다.

난수 생성을 넘어 numpy 전체 작업을 AI에게 맡기는 구조가 궁금하다면 이어서 읽을 만하다.

numpy 난수 생성에 쓸 수 있는 분포 함수 전체 목록은 numpy 공식 문서 Random Generator에서 확인할 수 있다.

FAQ

분포 종류(정규분포·카이제곱 등), 평균·표준편차 또는 자유도 값, 생성 개수(size), seed 고정 여부 — 이 네 가지를 함께 명시하면 원하는 코드를 정확하게 받을 수 있다.

평균과 표준편차를 직접 지정해야 하는 상황이면 random.normal, 표준 분포로 충분한 빠른 테스트라면 randn을 요청하면 된다. 현실 데이터를 시뮬레이션하는 대부분의 상황에서는 random.normal이 맞다.

for 루프를 사용하는 코드가 나올 수 있다. 데이터 규모가 작으면 차이가 없지만, 배열이 수만 개 이상으로 커지면 속도 차이가 크게 벌어진다. “루프 없이 numpy ufunc를 활용해서”라고 명시하면 최적화된 코드를 받을 수 있다.

관련 글 보기