![[코디테스트 공부] - JavaScript Array.fill()의 함정 (참조 타입과 원시 타입의 차이)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FbSccbu%2FbtsL87EtsJw%2FAAAAAAAAAAAAAAAAAAAAAMS8NSau-S6kgKaywq2fxMbSblxmx5ZFcH5mWg38VYLF%2Fimg.png%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1759244399%26allow_ip%3D%26allow_referer%3D%26signature%3DivQkY%252FFYwOK1blmu%252F8NzWjTZ77g%253D)
[코디테스트 공부] - JavaScript Array.fill()의 함정 (참조 타입과 원시 타입의 차이)Frontend/취준 - 코딩테스트 공부2025. 2. 5. 16:17
Table of Contents
JavaScript Array.fill()의 함정 (참조 타입과 원시 타입의 차이)
작성 배경
DFS, BFS와 같은 그래프 알고리즘을 구현하면서 2차원 배열을 만들어 초기화하는 경우가 많습니다.
특히 인접 리스트를 만들거나 방문(boolean) 배열을 초기화할 때 충분히 만날 수 있는 문제라고 생각합니다. (그게 바로 저..)
사전 지식
JavaScript에서 데이터 타입은 크게 두 가지로 나뉠 수 있습니다.
1. 원시 타입
- Number, String, Boolean, null, undefined 등
- 값 자체가 복사됨
2. 참조 타입
- Object, Array 등
- 메모리 주소가 복사됨
예시 코드
// 1. 원시 타입 예시
const 원시타입배열 = new Array(3).fill(false);
원시타입배열[0] = true;
console.log(원시타입배열);
// 출력: [true, false, false]
// 2. 참조 타입 예시
const 참조타입배열 = new Array(3).fill([]);
참조타입배열[0].push(1);
console.log(참조타입배열);
// 출력: [[1], [1], [1]]
// 3. 객체로 보는 더 명확한 예시
const 객체배열 = new Array(3).fill({ count: 0 });
객체배열[0].count = 1;
console.log(객체배열);
// 출력: [{ count: 1 }, { count: 1 }, { count: 1 }]
혹시 위 예시 코드를 보고 감이 오시는 분은 굳이 아래까지 안읽으셔도 좋을 것 같습니다!!
여기서 이해가 안되시는 분들이 있기 때문에
메모리 주소를 이용한 예시를 보겠습니다.
// 원시 타입의 경우
const primitive = new Array(3).fill(false);
/*
메모리:
[false] <- primitive[0]
[false] <- primitive[1]
[false] <- primitive[2]
*/
// 참조 타입의 경우
const reference = new Array(3).fill([]);
/*
메모리: [](배열) <- 주소1234
[주소1234] <- reference[0]
[주소1234] <- reference[1]
[주소1234] <- reference[2]
*/
해결 방법
// 1. map과 화살표 함수 사용
const correct1 = new Array(3).fill(0).map(() => []);
// 2. Array.from 사용
const correct2 = Array.from({ length: 3 }, () => []);
// 3. 반복문 사용
실제 알고리즘에서 활용 예시
예를 들어, 그래프를 표현하는 인접 리스트를 만들때
// 잘못된 방법
const graph1 = new Array(5).fill([]); // 모든 정점이 같은 배열을 공유
// 올바른 방법
const graph2 = new Array(5).fill(0).map(() => []); // 각 정점이 독립적인 배열을 가짐
// 차이점 확인
graph1[0].push(1);
graph2[0].push(1);
console.log('잘못된 방법:', graph1);
// 출력: [[1], [1], [1], [1], [1]]
console.log('올바른 방법:', graph2);
// 출력: [[1], [], [], [], []]
결론
fill() 메서드를 사용할 때는 원시 타입과 참조 타입의 차이를 반드시 이해해야 한다는 것을 코딩 테스트 문제를 풀면서 다시 한 번 이해를 하게되었습니다.
2차원 배열이나 객체 배열을 초기화할 때는 map()이나 Array.from()을 사용하여 각 요소가 독립적인 참조를 가지도록 해야 합니다.
이렇게 게시글을 작성해서 이 글을 읽고 계신 분들은 JavaScript의 참조 타입과 원시 타입의 차이를 이해하고, 실제 코딩 테스트나 프로젝트에서 이 지식을 활용 했으면 좋겠습니다!!
@동혁이 :: Eun_Frontend
프론트엔드 공부일지 입니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!