
개발을 하다 보면 겉보기엔 같은 결과를 내는 코드가 실제로는 완전히 다른 결과를 만들어내는 경우가 있습니다. 최근 프로그래머스의 문제를 풀면서 저 역시 비슷한 경험을 했습니다.
// 첫 번째 코드
answer = Array(n).fill(Array(n).fill(0));
// 두 번째 코드
answer = Array.from({ length: n }, () => Array(n).fill(0));
두 코드 모두 n x n 크기의 2차원 배열을 생성하는 코드처럼 보입니다. 그러나 결과는 완전히 달랐습니다.
Array(n).fill(Array(n).fill(0)) 코드는 Array(n).fill(0)로 만들어진 배열을 복사해서 모든 행에 채워 넣는 방식입니다. 하지만 여기서 중요한 점은 복사가 아닌 참조라는 것!
즉, 모든 행이 같은 배열 객체를 참조합니다. 그래서 한 행을 수정하면, 다른 행도 영향을 받습니다.
let n = 3;
let answer = Array(n).fill(Array(n).fill(0));
answer[0][0] = 1; // 첫 번째 원소만 바꾼다고 생각했는데...
console.log(answer);
// 결과: [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
이처럼 모든 행이 같은 배열을 참조하므로, 한 행을 수정하면 나머지 행도 수정됩니다.
반면, Array.from({ length: n }, () => Array(n).fill(0))는 각 행에 대해 새로운 배열을 생성합니다. 따라서 각 행이 서로 다른 배열 인스턴스를 참조하며 독립적으로 동작합니다.
let n = 3;
let answer = Array.from({ length: n }, () => Array(n).fill(0));
answer[0][0] = 1; // 첫 번째 원소만 바꿨더니...
console.log(answer);
// 결과: [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
각 행이 독립적이기 때문에 예상한 대로 한 행만 수정됩니다.
첫 번째 코드에서는 같은 배열 객체를 참조하기 때문에 한 곳을 수정하면 모두가 영향을 받습니다.
두 번째 코드에서는 새로운 배열을 생성하므로 독립적으로 동작합니다. 참조 vs 생성의 차이가 결과를 좌우한 것이죠.
겉보기 결과가 같다고 같은 코드는 아니다
내부 동작 방식이 다르면 예상치 못한 결과가 나올 수 있습니다.
내장 메소드를 신중하게 사용하라
코드의 간결함만 신경 쓰는 대신, 메소드가 어떻게 동작하는지 이해하는 것이 중요합니다.
문제 해결 능력을 기르자
문제의 원인을 찾고 해결하는 과정에서 더 깊이 배울 수 있습니다.
우리는 흔히 “결과만 보면 비슷하니까, 그냥 편한 거 쓰지 뭐” 하고 넘어가기 쉽습니다.
하지만 이렇게 같은 모양의 2차원 배열이라도, 생성 메서드가 달라서 내부 참조 방식이 달라지는 경우가 있죠.
내부 동작까지 완전히 동일한 내장 메서드는 거의 없습니다. 그리고 존재할 필요도 없어요!
왜냐하면 다양한 상황에서, 다양한 로직과 최적화가 가능하도록 자바스크립트가 메서드를 다양하게 제공하기 때문입니다.
결국 개발을 하다 보면, “한 가지 방법만 알면 끝!”이 아니라, “어떤 방식으로 동작하며, 어떤 상황에서 사용할 때 적합한가?”를 고민할 줄 아는 게 중요합니다.