코딩테스트 JS 자료구조 로드맵: 배열, 해시, 스택, 투 포인터 순서

2025.12.24·수정 2026.07.20·약 12분
핵심 요약
JavaScript 코딩테스트는 배열 순회와 상태 추적을 먼저 익힌 뒤, 값의 빈도·존재 확인은 Map, 최근 값의 역순 처리는 스택, 정렬·단조 조건이 있는 범위 축소는 투 포인터, 연속 구간의 재계산 제거는 슬라이딩 윈도우로 확장하는 순서가 효율적입니다.

이 글은 자료구조 이름을 외우는 로드맵이 아니라 문제의 입력·필요한 상태·반복문의 불변식으로 도구를 선택하는 기준을 제공합니다. 404였던 본문 이미지 두 개는 제거하고, 끊어진 배열 메서드 링크는 현재 공개된 학습 글로 교체했습니다. MDN과 ECMAScript 명세를 기준으로 Map의 성능 표현과 reduce 예외도 정확히 구분합니다.

이 글에서 정리하는 내용

JS 코딩테스트는 배열 조작부터 익숙해져야 합니다

첫 단계는 입력을 숫자 배열로 바꾸고 인덱스, 현재 값, 누적 상태를 추적하는 연습입니다. map, filter, reduce를 모두 외우기 전에 반복문 한 번이 끝날 때 어떤 값이 변하는지 종이에 적어 보세요. 배열 메서드의 역할과 누적 패턴은 404였던 예전 경로 대신 현재 공개된 JavaScript reduce 학습 글에서 이어서 볼 수 있습니다.

const input = '10 20 30 40';
const values = input.trim().split(/\s+/).map(Number);
const total = values.reduce((sum, value) => sum + value, 0);

console.log(values); // [10, 20, 30, 40]
console.log(total);  // 100

MDN의 Array.prototype.reduce 문서ECMAScript 2026 reduce 명세는 callback과 선택적인 initialValue를 정의합니다. 빈 배열에서 initialValue 없이 reduce를 호출하면 TypeError가 발생하므로 코딩테스트에서는 합계의 0, 빈도 객체의 새 Map처럼 자료형에 맞는 초기값을 명시하는 편이 안전합니다.

배열 메서드가 항상 더 좋은 것은 아닙니다. 포인터가 여러 개이거나 중간에 종료해야 하거나 상태 변화가 복잡하면 for 또는 while이 불변식을 드러내기 쉽습니다. 반대로 모든 원소를 같은 규칙으로 변환·선별·누적할 때는 배열 메서드가 의도를 짧게 표현할 수 있습니다.

해시는 값을 세거나 빠르게 찾을 때 등장합니다

값의 등장 횟수, 이미 본 값, 키와 연결된 정보를 반복해서 확인한다면 Map을 후보로 봅니다. ECMAScript의 Map은 키와 값에 임의의 언어 값을 사용할 수 있고, 같은 키는 한 항목만 유지합니다. ECMAScript 2026 keyed collections 명세는 평균 접근 시간이 원소 수에 대해 선형보다 빨라야 한다고 요구하지만 내부 구현을 해시 테이블이나 엄격한 O(1)로 고정하지는 않습니다.

function countValues(values) {
  const counts = new Map();

  for (const value of values) {
    counts.set(value, (counts.get(value) ?? 0) + 1);
  }

  return counts;
}

console.log(countValues(['a', 'b', 'a']).get('a')); // 2

MDN Map 문서도 이 성능 요구와 키 비교 규칙을 설명합니다. 키가 문자열로 한정된 단순 빈도표는 객체로도 풀 수 있지만, 키의 자료형을 보존하거나 삽입 순회와 size가 필요하면 Map이 명확합니다. 반대로 값의 범위가 작고 고정된 정수라면 길이가 정해진 배열 카운터가 더 단순할 수 있습니다.

빈도표와 구간 이동이 함께 나오는 문제는 모든 아나그램 JS 풀이로 확장해 보세요. Map을 선택했다는 사실보다 반복문이 진행되는 동안 “현재 구간의 빈도가 정확하다”는 불변식을 유지하는 것이 핵심입니다.

스택은 순서가 되돌아가는 문제에서 의심합니다

스택은 마지막에 넣은 값을 먼저 꺼내는 LIFO 구조입니다. 괄호 짝, 최근 작업 취소, 중첩 구조, 이전의 더 큰 값처럼 현재 원소가 가장 최근의 미해결 원소와 연결될 때 의심합니다. JavaScript에서는 배열의 pushpop으로 기본 스택을 구현할 수 있습니다.

function isValidParentheses(input) {
  const stack = [];

  for (const char of input) {
    if (char === '(') stack.push(char);
    if (char === ')') {
      if (stack.length === 0) return false;
      stack.pop();
    }
  }

  return stack.length === 0;
}

console.log(isValidParentheses('(())')); // true
console.log(isValidParentheses('(()'));  // false

이 코드의 불변식은 지금까지 읽은 접두사에서 닫히지 않은 여는 괄호만 stack에 남는다는 것입니다. 닫는 괄호를 만났을 때 stack이 비어 있으면 즉시 실패하고, 순회가 끝났을 때도 비어 있어야 합니다. 자세한 개념은 자료구조 스택 push·pop을, 적용 문제는 올바른 괄호 JS 풀이를 이어서 보세요.

투 포인터는 범위를 줄이는 사고방식입니다

투 포인터는 두 위치가 한 방향 또는 양쪽에서 움직이며 이미 확인한 후보를 다시 보지 않는 패턴입니다. 정렬된 두 배열 병합, 정렬된 배열의 합 찾기, 중복 제거가 입문 예시입니다. 포인터를 움직였을 때 버리는 후보가 다시 정답이 될 수 없다는 단조성 또는 정렬 근거가 있어야 합니다.

function mergeSorted(left, right) {
  const result = [];
  let i = 0;
  let j = 0;

  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) result.push(left[i++]);
    else result.push(right[j++]);
  }

  return result.concat(left.slice(i), right.slice(j));
}

console.log(mergeSorted([1, 3, 5], [2, 4])); // [1, 2, 3, 4, 5]

입력이 정렬되지 않았거나 포인터 이동이 어떤 후보를 안전하게 버리는지 설명할 수 없다면 투 포인터를 바로 적용하면 안 됩니다. 정렬 비용을 포함해도 이득인지 확인하고, 원래 인덱스가 필요한 문제라면 정렬 전에 인덱스를 함께 저장합니다. 이동이 눈에 보이는 연습은 두 배열 합치기 JS 풀이가 좋습니다.

슬라이딩 윈도우는 구간을 다시 계산하지 않는 방식입니다

슬라이딩 윈도우는 연속 구간의 상태를 유지하면서 오른쪽 값을 추가하고 왼쪽 값을 제거합니다. 고정 길이 k의 최대 합은 첫 구간을 한 번 계산한 뒤 창이 이동할 때 들어온 값과 나간 값만 반영하면 됩니다.

function maxFixedWindow(values, k) {
  if (k <= 0 || k > values.length) return null;

  let sum = values.slice(0, k).reduce((acc, value) => acc + value, 0);
  let best = sum;

  for (let right = k; right < values.length; right += 1) {
    sum += values[right] - values[right - k];
    best = Math.max(best, sum);
  }

  return best;
}

console.log(maxFixedWindow([2, 1, 5, 1, 3, 2], 3)); // 9

가변 길이 창에서 합이 기준을 넘으면 왼쪽을 줄이는 전형은 값이 모두 양수처럼 창 변화가 단조로울 때 성립합니다. 음수가 섞이면 왼쪽을 줄였을 때 합이 반드시 작아지지 않으므로 같은 규칙이 정답을 놓칠 수 있습니다. 이 경우 누적합, Map, 다른 탐색을 검토해야 합니다. “연속 구간”이라는 말만 보고 윈도우를 선택하지 말고 상태를 O(1)에 갱신할 수 있는지와 이동 근거를 확인하세요.

문제 유형은 쉬운 입력 추적부터 쌓아가는 것이 좋습니다

단계 연습 문제의 모양 통과 기준
1. 배열 순회 합계, 최댓값, 변환, 필터 한 반복 뒤 변하는 상태를 설명함
2. Map·Set 빈도, 중복, 존재 여부 키와 저장 값, 갱신 시점을 설명함
3. 스택 괄호, 중첩, 최근 미해결 값 stack에 남은 값의 의미를 설명함
4. 투 포인터 정렬 병합, 양끝 범위 축소 버린 후보가 돌아오지 않는 근거를 설명함
5. 윈도우 고정·가변 연속 구간 추가·제거 후 유지되는 상태를 설명함

각 단계에서 쉬운 문제 세 개를 풀고, 정답 코드 없이 불변식과 시간·공간 복잡도를 말할 수 있을 때 다음 단계로 넘어가세요. 전체 준비 흐름은 프론트엔드 코딩테스트 5단계 준비 전략과 연결하면 좋습니다.

반드시 기록할 검증 항목

  • 빈 배열, 원소 하나, 중복만 있는 입력, 정렬 여부 등 경계값을 적습니다.
  • 반복문 시작과 끝에 참이어야 하는 불변식을 한 문장으로 씁니다.
  • 시간 복잡도에 정렬·slice·concat·중첩 메서드 비용까지 포함합니다.
  • Map을 무조건 O(1)이라고 단정하지 않고 명세가 보장하는 범위와 문제 제한을 구분합니다.
  • 브루트포스와 작은 무작위 입력을 비교해 최적화 풀이의 결과를 검산합니다.

마지막에는 독자가 바로 적용할 기준을 남깁니다

문제에서 보이는 신호 첫 후보 적용 전 반례 질문
모든 원소를 한 번 처리 배열 순회·reduce 중간 종료나 복잡한 상태가 더 중요한가?
빈도·중복·존재 확인 반복 Map·Set 키 범위가 작아 배열이 더 단순한가?
최근 값부터 되돌아감 스택 FIFO 순서라면 큐가 맞지 않는가?
정렬된 범위를 줄일 수 있음 투 포인터 포인터 이동이 후보를 안전하게 버리는가?
연속 구간 상태 재사용 슬라이딩 윈도우 음수·비단조 조건 때문에 이동 규칙이 깨지는가?

도구를 고른 뒤에는 “왜 이 자료구조가 필요한가”, “반복문이 진행돼도 무엇이 항상 맞는가”, “어떤 입력에서 규칙이 깨지는가”를 답하세요. 세 질문에 답하지 못하면 이름을 외운 것이지 풀이를 설계한 것은 아닙니다.

읽는 순서를 정하면 글도 덜 흩어집니다

결론: 배열은 모든 풀이의 입력과 순회의 바닥이고, Map·스택은 필요한 상태의 모양을 바꾸며, 투 포인터·슬라이딩 윈도우는 반복해서 보던 후보나 구간 계산을 줄입니다. 배열 → Map·Set → 스택 → 투 포인터 → 슬라이딩 윈도우 순서로 학습하되, 각 단계는 코드 암기가 아니라 불변식·예외·검증으로 통과하세요.

오늘은 새 알고리즘을 더 외우기보다 이미 푼 문제 하나를 골라 입력 크기, 저장 상태, 불변식, 경계값, 시간 복잡도를 다섯 줄로 다시 적어 보세요. 그 기록이 다음 문제에서 자료구조를 선택하는 실제 기준이 됩니다.

공식 근거

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

“코딩테스트 JS 자료구조 로드맵: 배열, 해시, 스택, 투 포인터 순서”에 대한 1개의 생각

댓글 남기기