배열에서 무작위로 요소를 골라야 할 때나 순서를 뒤섞어야 할 때, 많은 개발자가 array_rand()와 shuffle() 중 뭘 써야 하는지 헷갈려한다. 둘 다 '무작위'를 다루지만 실제로는 전혀 다른 일을 한다. 이번에는 두 함수의 정확한 차이점, 각각 언제 써야 하는지, 그리고 실무에서 자주 마주치는 실수들을 완벽하게 정리해서 소개하겠다.
array_rand()는 배열에서 무작위로 선택된 키(key)를 반환한다. 배열 자체는 건드리지 않는다. 복권 추첨처럼 배열에서 '몇 개의 항목을 골라내기' 위해 쓴다.
shuffle()은 배열의 순서를 제자리에서(in-place) 무작위로 섞는다. 반환값은 성공 여부를 나타내는 불리언이고, 배열 자체가 변경된다. 카드를 셔플하는 것처럼 '배열의 모든 순서를 섞기' 위해 쓴다.
| 함수 | 반환값 | 배열 변경 | 용도 |
|---|---|---|---|
| array_rand() | 키(문자열/숫자) 또는 키 배열 | 아니오 | 무작위 항목 추출 |
| shuffle() | true/false | 예 | 배열 순서 재편성 |
단일 요소 추출
✗ 잘못된 코드
$colors = array('빨강', '파랑', '노랑', '초록');
$random_color = array_rand($colors); // 숫자 인덱스만 반환
echo $random_color; // 출력: 0, 1, 2, 또는 3 (문자열이 아님!)
✓ 올바른 코드
$colors = array('빨강', '파랑', '노랑', '초록');
$random_key = array_rand($colors);
$random_color = $colors[$random_key]; // 키를 사용해 값 접근
echo $random_color; // 출력: 빨강, 파랑, 노랑, 초록 중 하나
또는 한 줄로:
$random_color = $colors[array_rand($colors)];
echo $random_color; // 출력: 무작위 색상
여러 요소 추출
✗ 잘못된 코드
$items = array('사과', '바나나', '포도', '딸기', '수박');
$random_items = array_rand($items, 3); // array_rand(배열, 갯수)
echo $random_items[0]; // 어? 키인데 값이 필요하면 또 접근해야 함
✓ 올바른 코드
$items = array('사과', '바나나', '포도', '딸기', '수박');
$random_keys = array_rand($items, 3); // 3개의 키 반환
$selected_items = array();
foreach ($random_keys as $key) {
$selected_items[] = $items[$key]; // 키로부터 값 추출
}
print_r($selected_items);
// 출력: Array ( [0] => 포도 [1] => 딸기 [2] => 바나나 )
배열 순서 무작위 섞기
✗ 잘못된 코드
$deck = array('♠A', '♠2', '♠3', '♣A', '♣2', '♣3');
echo shuffle($deck); // 반환값이 true/false이지 섞인 배열이 아님!
// $deck의 순서는 섞여있지만, echo는 1만 출력됨
✓ 올바른 코드
$deck = array('♠A', '♠2', '♠3', '♣A', '♣2', '♣3');
shuffle($deck); // 제자리에서 배열 섞음, 반환값은 true
print_r($deck);
// 출력: Array ( [0] => ♣2 [1] => ♠A [2] => ♣A [3] => ♠3 [4] => ♣3 [5] => ♠2 )
연관 배열(키-값)에 주의
✗ 실수하기 쉬운 코드
$user = array('id' => 1, 'name' => '김철수', 'email' => 'kim@example.com');
shuffle($user);
print_r($user);
// 출력: Array ( [0] => 1 [1] => kim@example.com [2] => 김철수 )
// 키가 사라지고 숫자 인덱스만 남음! 키-값 연관성 완전히 깨짐
shuffle()은 **숫자 인덱스 배열**을 위해 설계되었다. 연관 배열에 사용하면 키가 모두 사라진다. 연관 배열을 섞어야 한다면 다른 방법을 써야 한다:
$user = array('id' => 1, 'name' => '김철수', 'email' => 'kim@example.com');
$keys = array_keys($user);
shuffle($keys); // 키만 섞음
$shuffled_user = array();
foreach ($keys as $key) {
$shuffled_user[$key] = $user[$key]; // 순서는 섞이지만 키는 유지
}
print_r($shuffled_user);
// 출력: Array ( [email] => kim@example.com [id] => 1 [name] => 김철수 )
예제 1. 복권 당첨자 선택
// 1000명 중 10명의 당첨자 선택
$participants = range(1, 1000); // 1부터 1000까지 배열 생성
$winners = array();
$winner_keys = array_rand($participants, 10);
foreach ($winner_keys as $key) {
$winners[] = $participants[$key];
}
sort($winners); // 결과를 정렬해서 보기 좋게
echo '당첨자: ' . implode(', ', $winners);
// 출력: 당첨자: 45, 123, 234, 456, ...
예제 2. 게임 카드 게임
// 52장 카드 덱을 섞기
$suits = array('♠', '♥', '♦', '♣');
$ranks = array('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K');
$deck = array();
foreach ($suits as $suit) {
foreach ($ranks as $rank) {
$deck[] = $suit . $rank;
}
}
shuffle($deck); // 카드 섞기
$my_hand = array_slice($deck, 0, 5); // 처음 5장
echo '내 카드: ' . implode(', ', $my_hand);
// 출력: 내 카드: ♦7, ♣K, ♠3, ♥10, ♦A
성능 비교
array_rand()는 내부적으로 무작위 키 몇 개만 선택하므로, 매우 큰 배열에서 소수의 요소만 필요할 때 효율적이다. 반면 shuffle()은 배열 전체를 순회하면서 모든 요소의 순서를 뒤섞으므로, 배열 크기에 상관없이 O(n) 시간이 걸린다.
// 1백만 개 배열에서 비교
$large_array = range(1, 1000000);
// array_rand(): 3개만 뽑을 때 빠름
$start = microtime(true);
$three_items = array_rand($large_array, 3);
echo '시간: ' . (microtime(true) - $start) . ' 초';
// 출력: 시간: 0.0001 초 (매우 빠름)
// shuffle(): 전체 섞기는 느림
$start = microtime(true);
shuffle($large_array);
echo '시간: ' . (microtime(true) - $start) . ' 초';
// 출력: 시간: 0.05 초 이상
✗ 실수 1. array_rand() 반환값을 직접 쓰기
$names = array('철수', '영희', '민수', '지은');
echo "당첨자: " . array_rand($names); // 0, 1, 2, 3 중 하나 출력
// 실제로는 숫자만 보임. 사람 이름이 아님!
✓ 해결
$names = array('철수', '영희', '민수', '지은');
echo "당첨자: " . $names[array_rand($names)]; // 이름이 출력됨
✗ 실수 2. shuffle() 반환값을 배열로 생각하기
$items = array('A', 'B', 'C', 'D');
$shuffled = shuffle($items); // true만 반환됨, 배열이 아님
echo $shuffled[0]; // 에러: int가 배열 아님
✓ 해결
$items = array('A', 'B', 'C', 'D');
shuffle($items); // 제자리에서 섞음
echo $items[0]; // $items 자체가 이미 섞여있음
✗ 실수 3. 연관 배열을 shuffle()로 섞고 키가 남아있다고 기대하기
$data = array('first' => 10, 'second' => 20, 'third' => 30);
shuffle($data);
echo $data['first']; // Notice: Undefined array key "first"
// 키가 모두 숫자 인덱스로 변환됨
✓ 해결: 키를 유지해야 한다면 위의 "4단계 실전 예제" 중 "연관 배열(키-값)에 주의" 섹션의 코드를 참고
array_rand()와 shuffle()은 비슷해 보이지만 완전히 다른 함수다. array_rand()는 배열에서 무작위 항목의 '키'를 반환하고, shuffle()은 배열 순서 자체를 제자리에서 뒤섞는다. 복권이나 추첨처럼 배열에서 '몇 개를 골라내기'만 하면 array_rand()를 쓰고, 카드 게임이나 추천 순서를 무작위로 섞어야 한다면 shuffle()을 써야 한다. 이 글의 코드 예제와 실수 섹션을 참고해 실제 프로젝트에 적용하면, 무작위 처리로 인한 버그 없이 깔끔한 코드를 만들 수 있을 것이다.