Algae-rithm 개발 λΈ”λ‘œκ·Έ
Published on

πŸ“š JavaScript μœ μš©ν•œ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜ 및 ES2020+ μ΅œμ‹  문법 정리(2025 κΈ°μ€€)

1. μœ μš©ν•œ μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ“€

μ•Œκ³ λ¦¬μ¦˜ 문제 해결에 자주 μ‚¬μš©λ˜λŠ” μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ“€μž…λ‹ˆλ‹€. 버전과 관계없이 μ‹€λ¬΄μ—μ„œ μœ μš©ν•œ κΈ°λŠ₯듀을 μ •λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

1.1 Math κ΄€λ ¨ ν•¨μˆ˜λ“€

  • Math.trunc()

    • μ„€λͺ…: μ†Œμˆ˜μ μ„ 버리고 μ •μˆ˜ λΆ€λΆ„λ§Œ λ°˜ν™˜ν•©λ‹ˆλ‹€ (μ†Œμˆ˜μ  버림).
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ‚˜λˆ—μ…ˆμ˜ λͺ«μ„ κ΅¬ν•˜κ±°λ‚˜, μ •μˆ˜ λ³€ν™˜μ΄ ν•„μš”ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const quotient = Math.floor(a / b) // μŒμˆ˜μ—μ„œ λ‹€λ₯΄κ²Œ λ™μž‘
    const quotient2 = parseInt(a / b) // 느리고 λΆ€μ •ν™•
    
    // βœ… Math.trunc() μ‚¬μš©
    const quotient = Math.trunc(a / b) // μ†Œμˆ˜μ  버림 (λͺ«)
    Math.trunc(3.7) // 3
    Math.trunc(-3.7) // -3
    Math.trunc(3.1) // 3
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ‚˜λˆ—μ…ˆ λͺ« κ΅¬ν•˜κΈ°
    function divide(a, b) {
      return Math.trunc(a / b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ •μˆ˜ λ³€ν™˜
    function toInt(n) {
      return Math.trunc(n)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 자릿수 뢄리
    function getDigits(n) {
      return Math.trunc(Math.abs(n)).toString().length
    }
    
    • 주의점:
      • Math.floor()와 달리 μŒμˆ˜μ—μ„œλ„ μ†Œμˆ˜μ λ§Œ λ²„λ¦½λ‹ˆλ‹€ (Math.floor(-3.7) = -4, Math.trunc(-3.7) = -3).
      • parseInt()보닀 λΉ λ₯΄κ³  μ •ν™•ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ‚˜λˆ—μ…ˆμ˜ λͺ«μ„ ꡬ할 λ•Œ Math.floor()보닀 직관적이고 μ •ν™•ν•©λ‹ˆλ‹€.
  • Math.max() / Math.min()

    • μ„€λͺ…: μ—¬λŸ¬ κ°’ 쀑 μ΅œλŒ€κ°’/μ΅œμ†Œκ°’μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ°°μ—΄μ˜ μ΅œλŒ€/μ΅œμ†Œκ°’ μ°ΎκΈ°, 두 κ°’ 비ꡐ, 경계값 체크 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function findMax(arr) {
      let max = arr[0]
      for (let i = 1; i < arr.length; i++) {
        if (arr[i] > max) max = arr[i]
      }
      return max
    }
    
    // βœ… Math.max() μ‚¬μš©
    const max = Math.max(1, 5, 3, 9, 2) // 9
    const maxFromArray = Math.max(...arr) // λ°°μ—΄μ˜ μ΅œλŒ€κ°’
    const min = Math.min(1, 5, 3, 9, 2) // 1
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ μ΅œλŒ€/μ΅œμ†Œκ°’
    function getMaxMin(arr) {
      return { max: Math.max(...arr), min: Math.min(...arr) }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 경계값 μ œν•œ
    function clamp(value, min, max) {
      return Math.min(Math.max(value, min), max)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 두 κ°’ 쀑 큰/μž‘μ€ κ°’ 선택
    function maxPath(a, b) {
      return Math.max(a, b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ—¬λŸ¬ 경둜 쀑 μ΅œλ‹¨ 거리
    function shortestPath(paths) {
      return Math.min(...paths)
    }
    
    • 주의점:
      • μΈμžκ°€ μ—†μœΌλ©΄ Math.max()λŠ” -Infinity, Math.min()은 Infinityλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • 배열을 직접 λ°›μ§€ μ•ŠμœΌλ―€λ‘œ μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž(...)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ΅œλŒ€/μ΅œμ†Œκ°’ 계산이 κ°„κ²°ν•˜κ³  가독성이 μ’‹μŠ΅λ‹ˆλ‹€.
  • Math.abs()

    • μ„€λͺ…: 숫자의 μ ˆλŒ“κ°’μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 거리 계산, 차이값 계산, 음수 처리 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function abs(n) {
      return n < 0 ? -n : n
    }
    
    // βœ… Math.abs() μ‚¬μš©
    Math.abs(-5) // 5
    Math.abs(5) // 5
    Math.abs(0) // 0
    
    // μ‹€μ „ μ˜ˆμ‹œ: 두 점 사이 거리 (μ ˆλŒ“κ°’)
    function manhattanDistance(x1, y1, x2, y2) {
      return Math.abs(x2 - x1) + Math.abs(y2 - y1)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 차이값 계산
    function difference(a, b) {
      return Math.abs(a - b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 음수 λ°©μ§€
    function ensurePositive(n) {
      return Math.abs(n)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ μš”μ†Œ 차이의 μ΅œλŒ€κ°’
    function maxDifference(arr) {
      return Math.max(...arr) - Math.min(...arr)
    }
    
    • 주의점:
      • Math.abs(-0)은 0을 λ°˜ν™˜ν•©λ‹ˆλ‹€ (λΆ€ν˜Έ μžˆλŠ” 0 처리).
      • NaN을 μž…λ ₯ν•˜λ©΄ NaN을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ ˆλŒ“κ°’ 계산이 κ°„λ‹¨ν•˜κ³  λͺ…ν™•ν•©λ‹ˆλ‹€.
  • Math.floor(), Math.ceil(), Math.round()

    • μ„€λͺ…: 반올림 κ΄€λ ¨ ν•¨μˆ˜λ“€μž…λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 올림/λ‚΄λ¦Ό/반올림이 ν•„μš”ν•œ 계산에 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… 반올림 ν•¨μˆ˜λ“€
    Math.floor(3.7) // 3 (λ‚΄λ¦Ό)
    Math.ceil(3.2) // 4 (올림)
    Math.round(3.5) // 4 (반올림)
    Math.floor(-3.7) // -4 (음수 λ‚΄λ¦Ό)
    Math.ceil(-3.2) // -3 (음수 올림)
    
    // μ‹€μ „ μ˜ˆμ‹œ: 올림 λ‚˜λˆ—μ…ˆ
    function ceilDivide(a, b) {
      return Math.ceil(a / b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: νŽ˜μ΄μ§€ 계산
    function getTotalPages(items, itemsPerPage) {
      return Math.ceil(items / itemsPerPage)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 반올림
    function roundToDecimal(n, decimals) {
      const factor = 10 ** decimals
      return Math.round(n * factor) / factor
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ‚΄λ¦Ό λ‚˜λˆ—μ…ˆ
    function floorDivide(a, b) {
      return Math.floor(a / b)
    }
    
    • 주의점:
      • Math.floor()λŠ” 항상 μ•„λž˜λ‘œ, Math.ceil()은 항상 μœ„λ‘œ λ°˜μ˜¬λ¦Όν•©λ‹ˆλ‹€.
      • Math.round()λŠ” 0.5μ—μ„œ μœ„λ‘œ λ°˜μ˜¬λ¦Όν•©λ‹ˆλ‹€ (μ–‘μˆ˜ κΈ°μ€€).
      • μŒμˆ˜μ—μ„œ Math.floor()와 Math.trunc()의 λ™μž‘μ΄ λ‹€λ¦…λ‹ˆλ‹€.
    • κ°œμ„ μ : λ‹€μ–‘ν•œ 반올림 μš”κ΅¬μ‚¬ν•­μ„ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • Math.hypot(...values)

    • μ„€λͺ…: ν”Όνƒ€κ³ λΌμŠ€ 정리(x2+y2\sqrt{x^2 + y^2})λ₯Ό μ‰½κ²Œ κ³„μ‚°ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 두 점 μ‚¬μ΄μ˜ 거리 κ³„μ‚°μ΄λ‚˜ λ²‘ν„°μ˜ 크기 계산 μ‹œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function distance(x1, y1, x2, y2) {
      return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    }
    
    // βœ… Math.hypot() μ‚¬μš©
    const dist = Math.hypot(3, 4) // 5 (3-4-5 μ§κ°μ‚Όκ°ν˜•)
    const dist2 = Math.hypot(x2 - x1, y2 - y1) // 두 점 사이 거리
    
    // μ‹€μ „ μ˜ˆμ‹œ: μœ ν΄λ¦¬λ“œ 거리
    function euclideanDistance(p1, p2) {
      return Math.hypot(p2.x - p1.x, p2.y - p1.y)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 3D 거리
    function distance3D(p1, p2) {
      return Math.hypot(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 벑터 크기
    function vectorMagnitude(v) {
      return Math.hypot(...v)
    }
    
    • 주의점:
      • μ—¬λŸ¬ 인자λ₯Ό 받을 수 μžˆμ–΄μ„œ 2D, 3D, N차원 거리 계산이 λͺ¨λ‘ κ°€λŠ₯ν•©λ‹ˆλ‹€.
      • μ˜€λ²„ν”Œλ‘œμš°λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ λ‚΄λΆ€μ μœΌλ‘œ μ΅œμ ν™”λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : 거리 계산이 κ°„κ²°ν•˜κ³  μ˜€λ²„ν”Œλ‘œμš° μœ„ν—˜μ΄ μ μŠ΅λ‹ˆλ‹€.

1.2 Number κ΄€λ ¨ ν•¨μˆ˜λ“€

  • Number.isInteger()

    • μ„€λͺ…: 값이 μ •μˆ˜μΈμ§€ ν™•μΈν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: μž…λ ₯ κ²€μ¦μ΄λ‚˜ νƒ€μž… 체크 μ‹œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function isInt(n) {
      return n % 1 === 0
    }
    
    // βœ… Number.isInteger() μ‚¬μš©
    Number.isInteger(3) // true
    Number.isInteger(3.0) // true
    Number.isInteger(3.5) // false
    Number.isInteger('3') // false (λ¬Έμžμ—΄μ€ false)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μž…λ ₯ 검증
    function validateInput(n) {
      if (!Number.isInteger(n) || n < 0) {
        throw new Error('μ–‘μ˜ μ •μˆ˜λ§Œ μž…λ ₯ κ°€λŠ₯ν•©λ‹ˆλ‹€')
      }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ •μˆ˜ 필터링
    function filterIntegers(arr) {
      return arr.filter(Number.isInteger)
    }
    
    • 주의점:
      • λ¬Έμžμ—΄μ΄λ‚˜ λ‹€λ₯Έ νƒ€μž…μ€ falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • NaNκ³Ό Infinity도 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : νƒ€μž… μ•ˆμ „ν•œ μ •μˆ˜ 체크가 κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • parseInt(), parseFloat()

    • μ„€λͺ…: λ¬Έμžμ—΄μ„ 숫자둜 λ³€ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: μž…λ ₯ νŒŒμ‹±, 진법 λ³€ν™˜ 등에 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… λ¬Έμžμ—΄ 숫자 λ³€ν™˜
    parseInt('123') // 123
    parseInt('123.45') // 123 (μ •μˆ˜λ§Œ)
    parseFloat('123.45') // 123.45
    parseInt('1010', 2) // 10 (2μ§„μˆ˜)
    parseInt('FF', 16) // 255 (16μ§„μˆ˜)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μž…λ ₯ νŒŒμ‹±
    function parseInput(input) {
      return parseInt(input.trim(), 10)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 진법 λ³€ν™˜
    function binaryToDecimal(binary) {
      return parseInt(binary, 2)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ•ˆμ „ν•œ 숫자 λ³€ν™˜
    function safeParseInt(str, defaultValue = 0) {
      const parsed = parseInt(str, 10)
      return isNaN(parsed) ? defaultValue : parsed
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ—¬λŸ¬ 진법 지원
    function parseNumber(str, radix = 10) {
      return parseInt(str, radix)
    }
    
    • 주의점:
      • parseInt()λŠ” 두 번째 인자(radix)λ₯Ό λͺ…μ‹œν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€ (기본값이 10이 μ•„λ‹ˆλ―€λ‘œ).
      • parseInt('')λŠ” NaN을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • Number()와 달리 μ•žλΆ€λΆ„λ§Œ νŒŒμ‹±ν•©λ‹ˆλ‹€ (parseInt('123abc') = 123).
    • κ°œμ„ μ : λ¬Έμžμ—΄ μž…λ ₯을 숫자둜 λ³€ν™˜ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

1.3 Array κ΄€λ ¨ ν•¨μˆ˜λ“€

  • Array.from({ length: N }, mapFn)

    • μ„€λͺ…: νŠΉμ • 길이의 배열을 λ§Œλ“€κ³  λ™μ‹œμ— μ΄ˆκΈ°ν™”ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 2차원 λ°°μ—΄ μ΄ˆκΈ°ν™”λ‚˜ νŠΉμ • νŒ¨ν„΄μ˜ λ°°μ—΄ 생성에 μ΅œμ μž…λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const arr = []
    for (let i = 0; i < 10; i++) {
      arr.push(0)
    }
    // λ˜λŠ”
    const arr2 = new Array(10).fill(0)
    
    // βœ… Array.from() μ‚¬μš©
    const arr = Array.from({ length: 10 }, () => 0) // [0, 0, 0, ...]
    const arr2 = Array.from({ length: 10 }, (_, i) => i) // [0, 1, 2, ..., 9]
    
    // μ‹€μ „ μ˜ˆμ‹œ: 2차원 λ°°μ—΄ μ΄ˆκΈ°ν™”
    function create2DArray(rows, cols, defaultValue = 0) {
      return Array.from({ length: rows }, () => Array.from({ length: cols }, () => defaultValue))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 순차 λ°°μ—΄ 생성
    function range(start, end) {
      return Array.from({ length: end - start }, (_, i) => start + i)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: νŠΉμ • νŒ¨ν„΄ λ°°μ—΄
    function createPattern(length, patternFn) {
      return Array.from({ length }, (_, i) => patternFn(i))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 인덱슀 기반 μ΄ˆκΈ°ν™”
    const matrix = Array.from({ length: 5 }, (_, i) => Array.from({ length: 5 }, (_, j) => i * 5 + j))
    
    • 주의점:
      • 두 번째 인자(mapFn)λ₯Ό μƒλž΅ν•˜λ©΄ undefined둜 μ±„μ›Œμ§„ 배열이 μƒμ„±λ©λ‹ˆλ‹€.
      • new Array(n).fill()κ³Ό 달리 각 μš”μ†Œλ₯Ό λ…λ¦½μ μœΌλ‘œ μ΄ˆκΈ°ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : λ°°μ—΄ μ΄ˆκΈ°ν™”κ°€ 더 μœ μ—°ν•˜κ³  ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μŠ€νƒ€μΌμ— μ ν•©ν•©λ‹ˆλ‹€.
  • Array.prototype.includes()

    • μ„€λͺ…: 배열에 νŠΉμ • μš”μ†Œκ°€ ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 쑴재 μ—¬λΆ€ 체크, 쀑볡 검사, 필터링 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function contains(arr, item) {
      for (let i = 0; i < arr.length; i++) {
        if (arr[i] === item) return true
      }
      return false
    }
    // λ˜λŠ”
    arr.indexOf(item) !== -1
    
    // βœ… includes() μ‚¬μš©
    const arr = [1, 2, 3, 4, 5]
    arr.includes(3) // true
    arr.includes(6) // false
    arr.includes(2, 3) // false (인덱슀 3λΆ€ν„° 검색)
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쑴재 μ—¬λΆ€ 체크
    function isValid(value, allowedValues) {
      return allowedValues.includes(value)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쀑볡 체크
    function addIfNotExists(arr, item) {
      if (!arr.includes(item)) {
        arr.push(item)
      }
      return arr
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 필터링
    function filterByValues(arr, values) {
      return arr.filter((item) => values.includes(item))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ¬Έμžμ—΄ 포함 체크
    function hasVowel(str) {
      return ['a', 'e', 'i', 'o', 'u'].some((v) => str.includes(v))
    }
    
    • 주의점:
      • indexOf()와 달리 NaN도 μ˜¬λ°”λ₯΄κ²Œ μ²˜λ¦¬ν•©λ‹ˆλ‹€ ([NaN].includes(NaN) = true).
      • 두 번째 인자둜 μ‹œμž‘ 인덱슀λ₯Ό μ§€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : indexOf() !== -1보닀 가독성이 μ’‹κ³  μ§κ΄€μ μž…λ‹ˆλ‹€.
  • Array.prototype.slice() / String.prototype.slice()

    • μ„€λͺ…: λ°°μ—΄μ΄λ‚˜ λ¬Έμžμ—΄μ˜ 일뢀λ₯Ό μΆ”μΆœν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λΆ€λΆ„ λ°°μ—΄/λ¬Έμžμ—΄ μΆ”μΆœ, 볡사 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… slice() μ‚¬μš©
    const arr = [1, 2, 3, 4, 5]
    arr.slice(1, 3) // [2, 3] (인덱슀 1λΆ€ν„° 3 μ „κΉŒμ§€)
    arr.slice(2) // [3, 4, 5] (인덱슀 2λΆ€ν„° λκΉŒμ§€)
    arr.slice() // [1, 2, 3, 4, 5] (전체 볡사)
    arr.slice(-2) // [4, 5] (λ’€μ—μ„œ 2개)
    
    const str = 'hello'
    str.slice(1, 3) // 'el'
    str.slice(2) // 'llo'
    str.slice(-2) // 'lo'
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ 볡사
    function copyArray(arr) {
      return arr.slice()
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΆ€λΆ„ λ°°μ—΄ μΆ”μΆœ
    function getSubarray(arr, start, end) {
      return arr.slice(start, end)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ¬Έμžμ—΄ λΆ€λΆ„ μΆ”μΆœ
    function getSubstring(str, start, end) {
      return str.slice(start, end)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ§ˆμ§€λ§‰ N개 μš”μ†Œ
    function getLastN(arr, n) {
      return arr.slice(-n)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 첫 N개 μš”μ†Œ μ œμ™Έ
    function skipFirstN(arr, n) {
      return arr.slice(n)
    }
    
    • 주의점:
      • slice()λŠ” 원본을 λ³€κ²½ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (splice()와 닀름).
      • 음수 μΈλ±μŠ€λŠ” λ°°μ—΄/λ¬Έμžμ—΄ λμ—μ„œλΆ€ν„° κ³„μ‚°λ©λ‹ˆλ‹€.
      • 두 번째 인자λ₯Ό μƒλž΅ν•˜λ©΄ λκΉŒμ§€ μΆ”μΆœν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ°°μ—΄/λ¬Έμžμ—΄μ˜ λΆ€λΆ„ μΆ”μΆœμ΄ κ°„λ‹¨ν•˜κ³  μ•ˆμ „ν•©λ‹ˆλ‹€.

1.4 String κ΄€λ ¨ ν•¨μˆ˜λ“€

  • String.prototype.split() / Array.prototype.join()

    • μ„€λͺ…: 쀑첩 λ°˜λ³΅λ¬Έμ„ ν•œ λ²ˆμ— break ν•˜κ±°λ‚˜ continue ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 이쀑/삼쀑 λ£¨ν”„μ—μ„œ νŠΉμ • 쑰건 만쑱 μ‹œ λͺ¨λ“  루프λ₯Ό λΉ μ Έλ‚˜μ˜¬ λ•Œ μœ μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식 (flag λ³€μˆ˜ μ‚¬μš©)
    let found = false
    for (let i = 0; i < n; i++) {
      for (let j = 0; j < m; j++) {
        if (condition) {
          found = true
          break
        }
      }
      if (found) break
    }
    
    // βœ… Label μ‚¬μš©
    outerLoop: for (let i = 0; i < n; i++) {
      for (let j = 0; j < m; j++) {
        if (condition) {
          break outerLoop // λͺ¨λ“  루프 μ’…λ£Œ
        }
      }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 2D λ°°μ—΄ 탐색
    function findIn2D(grid, target) {
      searchLoop: for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
          if (grid[i][j] === target) {
            return [i, j]
          }
          if (grid[i][j] > target) {
            break searchLoop // μ •λ ¬λœ λ°°μ—΄μ—μ„œ μ‘°κΈ° μ’…λ£Œ
          }
        }
      }
      return null
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: continue둜 νŠΉμ • 루프 계속
    outer: for (let i = 0; i < 10; i++) {
      for (let j = 0; j < 10; j++) {
        if (j === 5) {
          continue outer // μ™ΈλΆ€ λ£¨ν”„μ˜ λ‹€μŒ 반볡으둜
        }
      }
    }
    
    • 주의점:
      • Label 이름은 μ‹λ³„μž κ·œμΉ™μ„ 따라야 ν•˜λ©°, 콜둠(:)으둜 λλ‚˜μ•Ό ν•©λ‹ˆλ‹€.
      • λ‚¨μš©ν•˜λ©΄ μ½”λ“œ 가독성이 λ–¨μ–΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : flag λ³€μˆ˜ 없이 κΉ”λ”ν•˜κ²Œ 쀑첩 루프λ₯Ό μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • Math.max() / Math.min()

    • μ„€λͺ…: μ—¬λŸ¬ κ°’ 쀑 μ΅œλŒ€κ°’/μ΅œμ†Œκ°’μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ°°μ—΄μ˜ μ΅œλŒ€/μ΅œμ†Œκ°’ μ°ΎκΈ°, 두 κ°’ 비ꡐ, 경계값 체크 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function findMax(arr) {
      let max = arr[0]
      for (let i = 1; i < arr.length; i++) {
        if (arr[i] > max) max = arr[i]
      }
      return max
    }
    
    // βœ… Math.max() μ‚¬μš©
    const max = Math.max(1, 5, 3, 9, 2) // 9
    const maxFromArray = Math.max(...arr) // λ°°μ—΄μ˜ μ΅œλŒ€κ°’
    const min = Math.min(1, 5, 3, 9, 2) // 1
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ μ΅œλŒ€/μ΅œμ†Œκ°’
    function getMaxMin(arr) {
      return { max: Math.max(...arr), min: Math.min(...arr) }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 경계값 μ œν•œ
    function clamp(value, min, max) {
      return Math.min(Math.max(value, min), max)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 두 κ°’ 쀑 큰/μž‘μ€ κ°’ 선택
    function maxPath(a, b) {
      return Math.max(a, b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ—¬λŸ¬ 경둜 쀑 μ΅œλ‹¨ 거리
    function shortestPath(paths) {
      return Math.min(...paths)
    }
    
    • 주의점:
      • μΈμžκ°€ μ—†μœΌλ©΄ Math.max()λŠ” -Infinity, Math.min()은 Infinityλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • 배열을 직접 λ°›μ§€ μ•ŠμœΌλ―€λ‘œ μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž(...)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ΅œλŒ€/μ΅œμ†Œκ°’ 계산이 κ°„κ²°ν•˜κ³  가독성이 μ’‹μŠ΅λ‹ˆλ‹€.
  • Math.abs()

    • μ„€λͺ…: 숫자의 μ ˆλŒ“κ°’μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 거리 계산, 차이값 계산, 음수 처리 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function abs(n) {
      return n < 0 ? -n : n
    }
    
    // βœ… Math.abs() μ‚¬μš©
    Math.abs(-5) // 5
    Math.abs(5) // 5
    Math.abs(0) // 0
    
    // μ‹€μ „ μ˜ˆμ‹œ: 두 점 사이 거리 (μ ˆλŒ“κ°’)
    function manhattanDistance(x1, y1, x2, y2) {
      return Math.abs(x2 - x1) + Math.abs(y2 - y1)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 차이값 계산
    function difference(a, b) {
      return Math.abs(a - b)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 음수 λ°©μ§€
    function ensurePositive(n) {
      return Math.abs(n)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ μš”μ†Œ 차이의 μ΅œλŒ€κ°’
    function maxDifference(arr) {
      return Math.max(...arr) - Math.min(...arr)
    }
    
    • 주의점:
      • Math.abs(-0)은 0을 λ°˜ν™˜ν•©λ‹ˆλ‹€ (λΆ€ν˜Έ μžˆλŠ” 0 처리).
      • NaN을 μž…λ ₯ν•˜λ©΄ NaN을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ ˆλŒ“κ°’ 계산이 κ°„λ‹¨ν•˜κ³  λͺ…ν™•ν•©λ‹ˆλ‹€.
  • Set을 ν™œμš©ν•œ 쀑볡 제거

    • μ„€λͺ…: Set 자료ꡬ쑰λ₯Ό μ‚¬μš©ν•˜μ—¬ λ°°μ—΄μ˜ 쀑볡을 μ œκ±°ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 쀑볡 체크, μœ λ‹ˆν¬ κ°’ μΆ”μΆœ, μ§‘ν•© μ—°μ‚° 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function removeDuplicates(arr) {
      const seen = {}
      const result = []
      for (const item of arr) {
        if (!seen[item]) {
          seen[item] = true
          result.push(item)
        }
      }
      return result
    }
    
    // βœ… Set μ‚¬μš©
    const arr = [1, 2, 2, 3, 3, 3, 4]
    const unique = [...new Set(arr)] // [1, 2, 3, 4]
    const uniqueSet = new Set(arr) // Set {1, 2, 3, 4}
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쀑볡 제거
    function getUnique(arr) {
      return [...new Set(arr)]
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쀑볡 체크
    function hasDuplicates(arr) {
      return arr.length !== new Set(arr).size
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 두 λ°°μ—΄μ˜ 곡톡 μš”μ†Œ
    function intersection(arr1, arr2) {
      const set2 = new Set(arr2)
      return [...new Set(arr1)].filter((x) => set2.has(x))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ¬Έμžμ—΄ 쀑볡 제거
    function uniqueChars(str) {
      return [...new Set(str)].join('')
    }
    
    • 주의점:
      • Set은 객체 μ°Έμ‘°λ₯Ό κΈ°μ€€μœΌλ‘œ λΉ„κ΅ν•˜λ―€λ‘œ, 객체 λ°°μ—΄μ—μ„œλŠ” μ£Όμ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€.
      • NaN은 Setμ—μ„œλ„ μ€‘λ³΅μœΌλ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€ (NaN === NaN은 falseμ§€λ§Œ Setμ—μ„œλŠ” ν•˜λ‚˜λ§Œ μ €μž₯).
    • κ°œμ„ μ : 쀑볡 μ œκ±°κ°€ κ°„κ²°ν•˜κ³  μ„±λŠ₯도 μ’‹μŠ΅λ‹ˆλ‹€ (O(n) μ‹œκ°„ λ³΅μž‘λ„).
  • Map 자료ꡬ쑰 ν™œμš©

    • μ„€λͺ…: ν‚€-κ°’ μŒμ„ μ €μž₯ν•˜λŠ” 자료ꡬ쑰둜, 객체보닀 λ‹€μ–‘ν•œ ν‚€ νƒ€μž…μ„ μ§€μ›ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: ν•΄μ‹œ λ§΅, λΉˆλ„μˆ˜ 카운트, 캐싱 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ 객체의 ν•œκ³„
    const obj = {}
    obj[1] = 'one' // ν‚€κ°€ λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ¨
    obj[[1, 2]] = 'array' // '[1,2]'둜 λ³€ν™˜λ¨
    
    // βœ… Map μ‚¬μš©
    const map = new Map()
    map.set(1, 'one')
    map.set([1, 2], 'array') // 배열도 ν‚€λ‘œ μ‚¬μš© κ°€λŠ₯
    map.set('key', 'value')
    map.get(1) // 'one'
    map.has(1) // true
    map.size // 3
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΉˆλ„μˆ˜ 카운트
    function countFrequency(arr) {
      const freq = new Map()
      for (const item of arr) {
        freq.set(item, (freq.get(item) || 0) + 1)
      }
      return freq
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 캐싱 (λ©”λͺ¨μ΄μ œμ΄μ…˜)
    const cache = new Map()
    function fibonacci(n) {
      if (cache.has(n)) return cache.get(n)
      const result = n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
      cache.set(n, result)
      return result
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: κ·Έλ£Ήν™”
    function groupBy(arr, keyFn) {
      const map = new Map()
      for (const item of arr) {
        const key = keyFn(item)
        if (!map.has(key)) map.set(key, [])
        map.get(key).push(item)
      }
      return map
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 순회
    for (const [key, value] of map) {
      console.log(key, value)
    }
    
    • 주의점:
      • 객체와 달리 size μ†μ„±μœΌλ‘œ 크기λ₯Ό λ°”λ‘œ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.
      • ν‚€λ‘œ NaN도 μ‚¬μš© κ°€λŠ₯ν•˜λ©°, NaN === NaN은 falseμ§€λ§Œ Mapμ—μ„œλŠ” 같은 ν‚€λ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€.
      • 객체보닀 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ μ•½κ°„ 더 λ§Žμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : λ‹€μ–‘ν•œ ν‚€ νƒ€μž… 지원과 λͺ…ν™•ν•œ API둜 ν•΄μ‹œ λ§΅ κ΅¬ν˜„μ— μ΅œμ μž…λ‹ˆλ‹€.
  • Object.keys() / Object.values() / Object.entries()

    • μ„€λͺ…: 객체의 ν‚€, κ°’, ν‚€-κ°’ μŒμ„ λ°°μ—΄λ‘œ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 객체 순회, ν•΄μ‹œ λ§΅ λ³€ν™˜, 객체 μ‘°μž‘ 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const obj = { a: 1, b: 2, c: 3 }
    const keys = []
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        keys.push(key)
      }
    }
    
    // βœ… Object λ©”μ„œλ“œ μ‚¬μš©
    const obj = { a: 1, b: 2, c: 3 }
    const keys = Object.keys(obj) // ['a', 'b', 'c']
    const values = Object.values(obj) // [1, 2, 3]
    const entries = Object.entries(obj) // [['a', 1], ['b', 2], ['c', 3]]
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 순회
    function sumValues(obj) {
      return Object.values(obj).reduce((sum, val) => sum + val, 0)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 필터링
    function filterObject(obj, predicate) {
      return Object.fromEntries(Object.entries(obj).filter(([k, v]) => predicate(k, v)))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 λ³€ν™˜
    function invertObject(obj) {
      return Object.fromEntries(Object.entries(obj).map(([k, v]) => [v, k]))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 크기
    function objectSize(obj) {
      return Object.keys(obj).length
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 병합
    function mergeObjects(...objs) {
      return Object.assign({}, ...objs)
    }
    
    • 주의점:
      • Object.keys()λŠ” μ—΄κ±° κ°€λŠ₯ν•œ μ†μ„±λ§Œ λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • Symbol ν‚€λŠ” ν¬ν•¨λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (Symbol ν‚€λŠ” Object.getOwnPropertySymbols() μ‚¬μš©).
    • κ°œμ„ μ : 객체λ₯Ό λ°°μ—΄μ²˜λŸΌ λ‹€λ£° 수 μžˆμ–΄ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μŠ€νƒ€μΌμ— μ ν•©ν•©λ‹ˆλ‹€.

1.6 μ—°μ‚°μž

  • μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž (...)

    • μ„€λͺ…: λ°°μ—΄μ΄λ‚˜ 객체λ₯Ό νŽΌμ³μ„œ κ°œλ³„ μš”μ†Œλ‘œ ν™•μž₯ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ°°μ—΄ 볡사, 병합, ν•¨μˆ˜ 인자 전달 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… μŠ€ν”„λ ˆλ“œ μ—°μ‚°μž μ‚¬μš©
    const arr1 = [1, 2, 3]
    const arr2 = [4, 5, 6]
    const merged = [...arr1, ...arr2] // [1, 2, 3, 4, 5, 6]
    const copied = [...arr1] // [1, 2, 3] (얕은 볡사)
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ 볡사
    function copyArray(arr) {
      return [...arr]
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ 병합
    function mergeArrays(...arrays) {
      return [].concat(...arrays)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: Math.max/min에 λ°°μ—΄ 전달
    const max = Math.max(...arr) // arr의 μ΅œλŒ€κ°’
    const min = Math.min(...arr) // arr의 μ΅œμ†Œκ°’
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 볡사 및 병합
    const obj1 = { a: 1, b: 2 }
    const obj2 = { ...obj1, c: 3 } // { a: 1, b: 2, c: 3 }
    
    // μ‹€μ „ μ˜ˆμ‹œ: ν•¨μˆ˜ 인자 전달
    function sum(a, b, c) {
      return a + b + c
    }
    const nums = [1, 2, 3]
    sum(...nums) // 6
    
    • 주의점:
      • λ°°μ—΄μ˜ 얕은 λ³΅μ‚¬λ§Œ μˆ˜ν–‰ν•˜λ―€λ‘œ, μ€‘μ²©λœ λ°°μ—΄/κ°μ²΄λŠ” μ°Έμ‘°κ°€ λ³΅μ‚¬λ©λ‹ˆλ‹€.
      • 객체 μŠ€ν”„λ ˆλ“œλŠ” ES2018(ES9)λΆ€ν„° μ§€μ›λ©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ°°μ—΄/객체 μ‘°μž‘μ΄ κ°„κ²°ν•˜κ³  ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μŠ€νƒ€μΌμ— μ ν•©ν•©λ‹ˆλ‹€.
  • λ””μŠ€νŠΈλŸ­μ²˜λ§ (Destructuring)

    • μ„€λͺ…: λ°°μ—΄μ΄λ‚˜ κ°μ²΄μ—μ„œ 값을 μΆ”μΆœν•˜μ—¬ λ³€μˆ˜μ— ν• λ‹Ήν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ³€μˆ˜ κ΅ν™˜, λ°°μ—΄/객체 μš”μ†Œ μΆ”μΆœ, ν•¨μˆ˜ νŒŒλΌλ―Έν„° 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… λ°°μ—΄ λ””μŠ€νŠΈλŸ­μ²˜λ§
    const arr = [1, 2, 3]
    const [first, second, third] = arr
    const [a, , c] = arr // 두 번째 μš”μ†Œ κ±΄λ„ˆλ›°κΈ°
    const [head, ...rest] = arr // 첫 μš”μ†Œμ™€ λ‚˜λ¨Έμ§€
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ³€μˆ˜ κ΅ν™˜
    let a = 1,
      b = 2
    ;[a, b] = [b, a] // a=2, b=1 (μž„μ‹œ λ³€μˆ˜ λΆˆν•„μš”!)
    
    // μ‹€μ „ μ˜ˆμ‹œ: ν•¨μˆ˜ λ°˜ν™˜κ°’ λΆ„ν•΄
    function getMinMax(arr) {
      return [Math.min(...arr), Math.max(...arr)]
    }
    const [min, max] = getMinMax([1, 5, 3, 9, 2])
    
    // βœ… 객체 λ””μŠ€νŠΈλŸ­μ²˜λ§
    const obj = { x: 1, y: 2, z: 3 }
    const { x, y } = obj
    const { x: xCoord, y: yCoord } = obj // 이름 λ³€κ²½
    
    // μ‹€μ „ μ˜ˆμ‹œ: ν•¨μˆ˜ νŒŒλΌλ―Έν„°
    function distance({ x: x1, y: y1 }, { x: x2, y: y2 }) {
      return Math.hypot(x2 - x1, y2 - y1)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: κΈ°λ³Έκ°’ μ„€μ •
    const { name = 'Unknown', age = 0 } = user
    
    • 주의점:
      • λ°°μ—΄ λ””μŠ€νŠΈλŸ­μ²˜λ§μ€ μˆœμ„œκ°€ μ€‘μš”ν•©λ‹ˆλ‹€.
      • 객체 λ””μŠ€νŠΈλŸ­μ²˜λ§μ€ 속성 이름이 μΌμΉ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
      • μ€‘μ²©λœ ꡬ쑰도 λ””μŠ€νŠΈλŸ­μ²˜λ§ κ°€λŠ₯ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ³€μˆ˜ 할당이 κ°„κ²°ν•˜κ³  가독성이 μ’‹μŠ΅λ‹ˆλ‹€.
  • λ‚˜λ¨Έμ§€ μ—°μ‚°μž (%) ν™œμš©

    • μ„€λͺ…: λ‚˜λˆ—μ…ˆμ˜ λ‚˜λ¨Έμ§€λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 홀짝 νŒλ³„, μˆœν™˜ 인덱슀, λͺ¨λ“ˆλŸ¬ μ—°μ‚° 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… λ‚˜λ¨Έμ§€ μ—°μ‚°μž ν™œμš©
    10 % 3 // 1
    10 % 2 // 0 (짝수)
    11 % 2 // 1 (ν™€μˆ˜)
    
    // μ‹€μ „ μ˜ˆμ‹œ: 홀짝 νŒλ³„
    function isEven(n) {
      return n % 2 === 0
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μˆœν™˜ 인덱슀
    function circularIndex(i, length) {
      return i % length
    }
    const arr = [0, 1, 2, 3, 4]
    arr[10 % arr.length] // 0 (10λ²ˆμ§ΈλŠ” 0λ²ˆμ§Έμ™€ κ°™μŒ)
    
    // μ‹€μ „ μ˜ˆμ‹œ: λͺ¨λ“ˆλŸ¬ μ—°μ‚° (큰 수 처리)
    function modPow(base, exp, mod) {
      let result = 1
      base = base % mod
      while (exp > 0) {
        if (exp % 2 === 1) result = (result * base) % mod
        exp = Math.floor(exp / 2)
        base = (base * base) % mod
      }
      return result
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 배수 체크
    function isMultiple(n, divisor) {
      return n % divisor === 0
    }
    
    • 주의점:
      • μŒμˆ˜μ— λŒ€ν•œ λ‚˜λ¨Έμ§€ μ—°μ‚° κ²°κ³ΌλŠ” μ–Έμ–΄λ§ˆλ‹€ λ‹€λ₯Ό 수 μžˆμ§€λ§Œ, JavaScriptμ—μ„œλŠ” ν”Όμ œμˆ˜μ˜ λΆ€ν˜Έλ₯Ό λ”°λ¦…λ‹ˆλ‹€.
      • -10 % 3은 -1μž…λ‹ˆλ‹€ (Pythonκ³Ό 닀름).
    • κ°œμ„ μ : μˆœν™˜ κ΅¬μ‘°λ‚˜ λͺ¨λ“ˆλŸ¬ 연산이 ν•„μš”ν•œ μ•Œκ³ λ¦¬μ¦˜μ—μ„œ ν•„μˆ˜μ μž…λ‹ˆλ‹€.
  • λΉ„νŠΈ μ—°μ‚°μž (<<, >>, &, |, ^)

    • μ„€λͺ…: λΉ„νŠΈ λ‹¨μœ„ 연산을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λΉ λ₯Έ κ³±μ…ˆ/λ‚˜λˆ—μ…ˆ, ν”Œλž˜κ·Έ 관리, μ§‘ν•© ν‘œν˜„ 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… λΉ„νŠΈ μ—°μ‚°μž ν™œμš©
    5 << 1 // 10 (2λ°°, 5 * 2)
    10 >> 1 // 5 (절반, 10 / 2)
    5 & 3 // 1 (AND: 101 & 011 = 001)
    5 | 3 // 7 (OR: 101 | 011 = 111)
    5 ^ 3 // 6 (XOR: 101 ^ 011 = 110)
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΉ λ₯Έ 2의 κ±°λ“­μ œκ³±
    function powerOfTwo(n) {
      return 1 << n // 2^n
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ§‘ν•© ν‘œν˜„ (λΉ„νŠΈλ§ˆμŠ€ν¬)
    const SET_A = 1 << 0 // 1 (0001)
    const SET_B = 1 << 1 // 2 (0010)
    const SET_C = 1 << 2 // 4 (0100)
    const combined = SET_A | SET_C // 5 (0101, A와 C 포함)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ§‘ν•© 포함 μ—¬λΆ€ 체크
    function hasSet(flags, set) {
      return (flags & set) !== 0
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 홀짝 νŒλ³„ (λΉ λ₯Έ 방법)
    function isOdd(n) {
      return (n & 1) === 1
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 2의 κ±°λ“­μ œκ³± 체크
    function isPowerOfTwo(n) {
      return n > 0 && (n & (n - 1)) === 0
    }
    
    • 주의점:
      • λΉ„νŠΈ 연산은 32λΉ„νŠΈ μ •μˆ˜λ‘œ λ³€ν™˜λ˜μ–΄ μˆ˜ν–‰λ©λ‹ˆλ‹€.
      • >>> (λΆ€ν˜Έ μ—†λŠ” 였λ₯Έμͺ½ μ‹œν”„νŠΈ)도 μžˆμ§€λ§Œ μΌλ°˜μ μœΌλ‘œλŠ” >>λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
      • 가독성이 λ–¨μ–΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ 주석을 μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : μ„±λŠ₯ μ΅œμ ν™”κ°€ ν•„μš”ν•œ κ²½μš°λ‚˜ λΉ„νŠΈλ§ˆμŠ€ν¬λ₯Ό μ‚¬μš©ν•œ μ§‘ν•© ν‘œν˜„μ— μœ μš©ν•©λ‹ˆλ‹€.
  • String.prototype.slice()

    • μ„€λͺ…: λ¬Έμžμ—΄μ˜ 일뢀λ₯Ό μΆ”μΆœν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λΆ€λΆ„ λ¬Έμžμ—΄ μΆ”μΆœ, 볡사 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… slice() μ‚¬μš©
    const str = 'hello world'
    str.slice(0, 5) // 'hello'
    str.slice(6) // 'world'
    str.slice(-5) // 'world'
    str.slice(0, -6) // 'hello'
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΆ€λΆ„ λ¬Έμžμ—΄ μΆ”μΆœ
    function getSubstring(str, start, end) {
      return str.slice(start, end)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ§ˆμ§€λ§‰ N개 문자
    function getLastNChars(str, n) {
      return str.slice(-n)
    }
    
    • 주의점:
      • slice()λŠ” 원본을 λ³€κ²½ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
      • 음수 μΈλ±μŠ€λŠ” λ¬Έμžμ—΄ λμ—μ„œλΆ€ν„° κ³„μ‚°λ©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ¬Έμžμ—΄μ˜ λΆ€λΆ„ μΆ”μΆœμ΄ κ°„λ‹¨ν•˜κ³  μ•ˆμ „ν•©λ‹ˆλ‹€.
  • μ •κ·œν‘œν˜„μ‹ κΈ°λ³Έ ν™œμš©

    • μ„€λͺ…: νŒ¨ν„΄ 맀칭을 μœ„ν•œ μ •κ·œν‘œν˜„μ‹μ˜ κΈ°λ³Έ μ‚¬μš©λ²•μž…λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ¬Έμžμ—΄ 검증, νŒ¨ν„΄ λ§€μΉ­, μΉ˜ν™˜ 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // βœ… μ •κ·œν‘œν˜„μ‹ κΈ°λ³Έ μ‚¬μš©
    const regex = /\d+/g // 숫자 ν•˜λ‚˜ 이상 (μ „μ—­ 검색)
    const str = 'abc123def456'
    str.match(regex) // ['123', '456']
    regex.test(str) // true
    
    // μ‹€μ „ μ˜ˆμ‹œ: 숫자 μΆ”μΆœ
    function extractNumbers(str) {
      return str.match(/\d+/g) || []
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 이메일 검증
    function isValidEmail(email) {
      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 숫자만 체크
    function isNumeric(str) {
      return /^\d+$/.test(str)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ•ŒνŒŒλ²³λ§Œ 체크
    function isAlpha(str) {
      return /^[a-zA-Z]+$/.test(str)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 곡백 제거
    function removeSpaces(str) {
      return str.replace(/\s+/g, '')
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 특수문자 제거
    function removeSpecialChars(str) {
      return str.replace(/[^a-zA-Z0-9]/g, '')
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: νŒ¨ν„΄ λ§€μΉ­
    function findPattern(str, pattern) {
      const regex = new RegExp(pattern, 'g')
      return str.match(regex) || []
    }
    
    • 주의점:
      • test()λŠ” boolean을 λ°˜ν™˜ν•˜κ³ , match()λŠ” 배열을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • μ „μ—­ ν”Œλž˜κ·Έ(g)λ₯Ό μ‚¬μš©ν•˜λ©΄ match()λŠ” λͺ¨λ“  맀칭을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • ^λŠ” μ‹œμž‘, $λŠ” 끝을 μ˜λ―Έν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ³΅μž‘ν•œ λ¬Έμžμ—΄ νŒ¨ν„΄ 검증이 κ°„κ²°ν•˜κ²Œ κ°€λŠ₯ν•©λ‹ˆλ‹€.

1.5 자료ꡬ쑰

  • Set을 ν™œμš©ν•œ 쀑볡 제거

    • μ„€λͺ…: ν‚€-κ°’ μŒμ„ μ €μž₯ν•˜λŠ” 자료ꡬ쑰둜, 객체보닀 λ‹€μ–‘ν•œ ν‚€ νƒ€μž…μ„ μ§€μ›ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: ν•΄μ‹œ λ§΅, λΉˆλ„μˆ˜ 카운트, 캐싱 등에 자주 μ‚¬μš©λ©λ‹ˆλ‹€.
    // ❌ 객체의 ν•œκ³„
    const obj = {}
    obj[1] = 'one' // ν‚€κ°€ λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ¨
    obj[[1, 2]] = 'array' // '[1,2]'둜 λ³€ν™˜λ¨
    
    // βœ… Map μ‚¬μš©
    const map = new Map()
    map.set(1, 'one')
    map.set([1, 2], 'array') // 배열도 ν‚€λ‘œ μ‚¬μš© κ°€λŠ₯
    map.set('key', 'value')
    map.get(1) // 'one'
    map.has(1) // true
    map.size // 3
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΉˆλ„μˆ˜ 카운트
    function countFrequency(arr) {
      const freq = new Map()
      for (const item of arr) {
        freq.set(item, (freq.get(item) || 0) + 1)
      }
      return freq
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 캐싱 (λ©”λͺ¨μ΄μ œμ΄μ…˜)
    const cache = new Map()
    function fibonacci(n) {
      if (cache.has(n)) return cache.get(n)
      const result = n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)
      cache.set(n, result)
      return result
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: κ·Έλ£Ήν™”
    function groupBy(arr, keyFn) {
      const map = new Map()
      for (const item of arr) {
        const key = keyFn(item)
        if (!map.has(key)) map.set(key, [])
        map.get(key).push(item)
      }
      return map
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 순회
    for (const [key, value] of map) {
      console.log(key, value)
    }
    
    • 주의점:
      • 객체와 달리 size μ†μ„±μœΌλ‘œ 크기λ₯Ό λ°”λ‘œ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.
      • ν‚€λ‘œ NaN도 μ‚¬μš© κ°€λŠ₯ν•˜λ©°, NaN === NaN은 falseμ§€λ§Œ Mapμ—μ„œλŠ” 같은 ν‚€λ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€.
      • 객체보닀 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ μ•½κ°„ 더 λ§Žμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : λ‹€μ–‘ν•œ ν‚€ νƒ€μž… 지원과 λͺ…ν™•ν•œ API둜 ν•΄μ‹œ λ§΅ κ΅¬ν˜„μ— μ΅œμ μž…λ‹ˆλ‹€.

1.7 기타

  • Label (loop:)

    • μ„€λͺ…: 쀑첩 λ°˜λ³΅λ¬Έμ„ ν•œ λ²ˆμ— break ν•˜κ±°λ‚˜ continue ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 이쀑/삼쀑 λ£¨ν”„μ—μ„œ νŠΉμ • 쑰건 만쑱 μ‹œ λͺ¨λ“  루프λ₯Ό λΉ μ Έλ‚˜μ˜¬ λ•Œ μœ μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식 (flag λ³€μˆ˜ μ‚¬μš©)
    let found = false
    for (let i = 0; i < n; i++) {
      for (let j = 0; j < m; j++) {
        if (condition) {
          found = true
          break
        }
      }
      if (found) break
    }
    
    // βœ… Label μ‚¬μš©
    outerLoop: for (let i = 0; i < n; i++) {
      for (let j = 0; j < m; j++) {
        if (condition) {
          break outerLoop // λͺ¨λ“  루프 μ’…λ£Œ
        }
      }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 2D λ°°μ—΄ 탐색
    function findIn2D(grid, target) {
      searchLoop: for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
          if (grid[i][j] === target) {
            return [i, j]
          }
          if (grid[i][j] > target) {
            break searchLoop // μ •λ ¬λœ λ°°μ—΄μ—μ„œ μ‘°κΈ° μ’…λ£Œ
          }
        }
      }
      return null
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: continue둜 νŠΉμ • 루프 계속
    outer: for (let i = 0; i < 10; i++) {
      for (let j = 0; j < 10; j++) {
        if (j === 5) {
          continue outer // μ™ΈλΆ€ λ£¨ν”„μ˜ λ‹€μŒ 반볡으둜
        }
      }
    }
    
    • 주의점:
      • Label 이름은 μ‹λ³„μž κ·œμΉ™μ„ 따라야 ν•˜λ©°, 콜둠(:)으둜 λλ‚˜μ•Ό ν•©λ‹ˆλ‹€.
      • λ‚¨μš©ν•˜λ©΄ μ½”λ“œ 가독성이 λ–¨μ–΄μ§ˆ 수 μžˆμœΌλ―€λ‘œ ν•„μš”ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : flag λ³€μˆ˜ 없이 κΉ”λ”ν•˜κ²Œ 쀑첩 루프λ₯Ό μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2. ES2020 (ES11): μ•ˆμ „ν•œ 탐색과 큰 수 처리

Node.js 지원: Node.js 14.0.0+ (2020λ…„ 4μ›”)

κ°€μž₯ λ²”μš©μ μœΌλ‘œ μ‚¬μš©λ˜λ©°, λŸ°νƒ€μž„ μ—λŸ¬λ₯Ό λ°©μ§€ν•˜λŠ” 핡심 λ¬Έλ²•μž…λ‹ˆλ‹€.

  • Optional Chaining (?.)

    • μ„€λͺ…: null λ˜λŠ” undefined일 수 μžˆλŠ” 객체 속성에 μ•ˆμ „ν•˜κ²Œ μ ‘κ·Όν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 2차원 λ°°μ—΄ 탐색 μ‹œ 인덱슀 λ²”μœ„λ₯Ό μ²΄ν¬ν•˜λŠ” 번거둜운 if문을 μ€„μ—¬μ€λ‹ˆλ‹€. (grid[r]?.[c])
    // ❌ κΈ°μ‘΄ 방식
    function getValue(grid, r, c) {
      if (grid && grid[r] && grid[r][c] !== undefined) {
        return grid[r][c]
      }
      return null
    }
    
    // βœ… Optional Chaining μ‚¬μš©
    function getValue(grid, r, c) {
      return grid?.[r]?.[c] ?? null
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 2D λ°°μ—΄ 경둜 탐색
    const grid = [
      [1, 2],
      [3, 4],
    ]
    const value = grid?.[5]?.[2] // undefined (μ—λŸ¬ μ—†μŒ)
    
    • 주의점:
      • ?.λŠ” null/undefinedμ—μ„œλ§Œ λ©ˆμΆ”κ³ , 0, false, "" 같은 falsy κ°’μ—μ„œλŠ” 계속 μ§„ν–‰ν•©λ‹ˆλ‹€.
      • λ©”μ„œλ“œ 호좜 μ‹œ obj.method?.() ν˜•νƒœλ‘œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ€‘μ²©λœ 객체 μ ‘κ·Ό μ‹œ 가독성과 μ•ˆμ „μ„±μ΄ 크게 ν–₯μƒλ©λ‹ˆλ‹€.
  • Nullish Coalescing (??)

    • μ„€λͺ…: 값이 nullμ΄λ‚˜ undefined일 λ•Œλ§Œ 기본값을 λΆ€μ—¬ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 0μ΄λ‚˜ ""이 μœ νš¨ν•œ 정닡일 수 μžˆλŠ” λ¬Έμ œμ—μ„œ || μ—°μ‚°μžμ˜ λΆ€μž‘μš©μ„ λ°©μ§€ν•©λ‹ˆλ‹€.
    // ❌ || μ—°μ‚°μžμ˜ 문제점
    const count = 0
    const result = count || 10 // 10 (0은 falsyμ΄λ―€λ‘œ)
    
    // βœ… ?? μ—°μ‚°μž μ‚¬μš©
    const count = 0
    const result = count ?? 10 // 0 (μœ νš¨ν•œ κ°’μœΌλ‘œ 처리)
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°°μ—΄ 합계 계산
    function sumArray(arr) {
      return arr.reduce((acc, val) => acc + (val ?? 0), 0)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: κΈ°λ³Έκ°’ μ„€μ •
    const userInput = getUserInput() ?? 'default'
    const maxValue = findMax(nums) ?? -Infinity
    
    • 주의점:
      • ??λŠ” nullκ³Ό undefined만 μ²΄ν¬ν•˜λ―€λ‘œ, 0, false, ""λŠ” μœ νš¨ν•œ κ°’μœΌλ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€.
      • ||와 ν˜Όμš©ν•˜μ§€ μ•Šλ„λ‘ 주의 (μ—°μ‚°μž μš°μ„ μˆœμœ„ 문제).
    • κ°œμ„ μ : 숫자 0μ΄λ‚˜ 빈 λ¬Έμžμ—΄μ΄ μœ νš¨ν•œ 값인 κ²½μš°μ— μ •ν™•ν•œ κΈ°λ³Έκ°’ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • BigInt (n)

    • μ„€λͺ…: μ •μˆ˜ 정밀도 μ œν•œ(253βˆ’12^{53} - 1)을 λ„˜μ–΄μ„  숫자λ₯Ό μ²˜λ¦¬ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 결과값이 맀우 큰 μ‘°ν•©(Combination)μ΄λ‚˜ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄ 계산 μ‹œ ν•„μˆ˜μž…λ‹ˆλ‹€.
    // ❌ Number νƒ€μž…μ˜ ν•œκ³„
    const maxSafe = Number.MAX_SAFE_INTEGER // 9007199254740991
    const overflow = maxSafe + 1 // 정밀도 손싀 λ°œμƒ κ°€λŠ₯
    
    // βœ… BigInt μ‚¬μš©
    const bigNum = 9007199254740992n
    const result = bigNum + 1n // μ •ν™•ν•œ 계산
    
    // μ‹€μ „ μ˜ˆμ‹œ: 큰 수 ν”Όλ³΄λ‚˜μΉ˜
    function fibonacciBigInt(n) {
      if (n <= 1) return BigInt(n)
      let a = 0n,
        b = 1n
      for (let i = 2; i <= n; i++) {
        ;[a, b] = [b, a + b]
      }
      return b
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ‘°ν•© 계산 (nCr)
    function combinationBigInt(n, r) {
      if (r > n) return 0n
      let result = 1n
      for (let i = 0; i < r; i++) {
        result = (result * BigInt(n - i)) / BigInt(i + 1)
      }
      return result
    }
    
    • 주의점:
      • BigInt와 NumberλŠ” 직접 μ—°μ‚°ν•  수 μ—†μŠ΅λ‹ˆλ‹€. (1n + 1 ❌, 1n + 1n βœ…)
      • JSON.stringify()μ—μ„œ BigIntλŠ” μ—λŸ¬κ°€ λ°œμƒν•˜λ―€λ‘œ λ¬Έμžμ—΄λ‘œ λ³€ν™˜ ν•„μš”.
      • 비ꡐ 연산은 κ°€λŠ₯ν•˜μ§€λ§Œ (1n < 2 βœ…), 일뢀 Math λ©”μ„œλ“œλŠ” μ‚¬μš© λΆˆκ°€.
    • κ°œμ„ μ : 맀우 큰 μ •μˆ˜ 계산이 ν•„μš”ν•œ μ•Œκ³ λ¦¬μ¦˜ λ¬Έμ œμ—μ„œ μ •ν™•ν•œ κ²°κ³Όλ₯Ό 보μž₯ν•©λ‹ˆλ‹€.
  • Number.MAX_SAFE_INTEGER

    • μ„€λͺ…: JavaScriptμ—μ„œ μ•ˆμ „ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλŠ” μ΅œλŒ€ μ •μˆ˜ κ°’ (253βˆ’12^{53} - 1)μž…λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ¬΄ν•œλŒ€ κ°’ λŒ€μ‹  μ‚¬μš©ν•˜κ±°λ‚˜, 큰 수 계산 μ‹œ 정밀도 ν•œκ³„λ₯Ό 확인할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    // βœ… λ¬΄ν•œλŒ€ κ°’ 처리
    const INF = Number.MAX_SAFE_INTEGER // 9007199254740991
    const MIN_INF = Number.MIN_SAFE_INTEGER // -9007199254740991
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ΅œλ‹¨ 경둜 μ•Œκ³ λ¦¬μ¦˜
    function dijkstra(graph, start) {
      const dist = new Array(graph.length).fill(Number.MAX_SAFE_INTEGER)
      dist[start] = 0
      // ...
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ΅œλŒ€κ°’ μ΄ˆκΈ°ν™”
    function findMaxPath(grid) {
      let maxPath = -Number.MAX_SAFE_INTEGER
      // ...
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 정밀도 체크
    function isSafeNumber(n) {
      return n <= Number.MAX_SAFE_INTEGER && n >= Number.MIN_SAFE_INTEGER
    }
    
    • 주의점:
      • 이 값을 λ„˜μ–΄μ„œλ©΄ 정밀도 손싀이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
      • 더 큰 μˆ˜κ°€ ν•„μš”ν•˜λ©΄ BigIntλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ¬΄ν•œλŒ€λ₯Ό ν‘œν˜„ν•  λ•Œ Infinity λŒ€μ‹  μ‚¬μš©ν•˜λ©΄ 비ꡐ 연산이 더 μ•ˆμ „ν•©λ‹ˆλ‹€.

3. ES2021 (ES12): λ¬Έμžμ—΄ μ •μ œμ™€ 가독성

Node.js 지원: Node.js 15.0.0+ (2020λ…„ 10μ›”)

  • String.prototype.replaceAll()

    • μ„€λͺ…: μ •κ·œμ‹ 없이 λͺ¨λ“  일치 ν•­λͺ©μ„ μΉ˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: λ¬Έμžμ—΄ μΉ˜ν™˜ 및 μ „μ²˜λ¦¬ λ¬Έμ œμ—μ„œ κ΅¬ν˜„ 속도λ₯Ό λ†’μ—¬μ€λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function replaceAll(str, search, replace) {
      return str.split(search).join(replace)
    }
    // λ˜λŠ” μ •κ·œμ‹ μ‚¬μš©
    str.replace(/old/g, 'new')
    
    // βœ… replaceAll μ‚¬μš©
    const text = 'hello world hello'
    const result = text.replaceAll('hello', 'hi') // "hi world hi"
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ¬Έμžμ—΄ μ •μ œ
    function cleanString(str) {
      return str.replaceAll(' ', '').replaceAll('\n', '').replaceAll('\t', '')
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: νŒ¨ν„΄ μΉ˜ν™˜
    function maskPhone(phone) {
      return phone.replaceAll(/\d(?=\d{4})/g, '*') // λ§ˆμ§€λ§‰ 4자리 μ œμ™Έ λ§ˆμŠ€ν‚Ή
    }
    
    • 주의점:
      • 첫 번째 μΈμžλŠ” λ¬Έμžμ—΄μ΄μ–΄μ•Ό ν•˜λ©°, μ •κ·œμ‹μ΄ μ•„λ‹™λ‹ˆλ‹€.
      • λŒ€μ†Œλ¬Έμžλ₯Ό κ΅¬λΆ„ν•˜λ―€λ‘œ ν•„μš”μ‹œ toLowerCase()와 ν•¨κ»˜ μ‚¬μš©.
    • κ°œμ„ μ : μ •κ·œμ‹ 없이 κ°„λ‹¨ν•˜κ²Œ λͺ¨λ“  일치 ν•­λͺ©μ„ μΉ˜ν™˜ν•  수 μžˆμ–΄ 가독성이 ν–₯μƒλ©λ‹ˆλ‹€.
  • Numeric Separators (_)

    • μ„€λͺ…: 큰 μˆ«μžμ— 언더바λ₯Ό μ‚¬μš©ν•˜μ—¬ 자릿수λ₯Ό κ΅¬λΆ„ν•©λ‹ˆλ‹€. (1_000_000_000)
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: MAX_SAFE_INTEGERλ‚˜ 큰 μƒμˆ˜λ₯Ό μ„€μ •ν•  λ•Œ 0의 개수λ₯Ό μ‹€μˆ˜ν•˜μ§€ μ•Šκ²Œ ν•΄μ€λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식 (가독성 μ €ν•˜)
    const billion = 1000000000
    const maxSafe = 9007199254740991
    
    // βœ… Numeric Separators μ‚¬μš©
    const billion = 1_000_000_000
    const maxSafe = 9_007_199_254_740_991
    
    // μ‹€μ „ μ˜ˆμ‹œ: μƒμˆ˜ μ •μ˜
    const MOD = 1_000_000_007 // λͺ¨λ“ˆλŸ¬ μ—°μ‚° μƒμˆ˜
    const INF = 1_000_000_000_000 // λ¬΄ν•œλŒ€ λŒ€μ²΄κ°’
    const MAX_N = 100_000 // μ΅œλŒ€ μž…λ ₯ 크기
    
    // λ‹€μ–‘ν•œ μ§„λ²•μ—μ„œλ„ μ‚¬μš© κ°€λŠ₯
    const binary = 0b1010_0001
    const hex = 0xff_ec_de_5e
    
    • 주의점:
      • μ–Έλ”λ°”λŠ” 숫자 값에 영ν–₯을 μ£Όμ§€ μ•ŠμœΌλ©°, μˆœμˆ˜ν•˜κ²Œ 가독성 ν–₯μƒμš©μž…λ‹ˆλ‹€.
      • 숫자 μ‹œμž‘μ΄λ‚˜ 끝, μ†Œμˆ˜μ  μ•žλ’€μ—λŠ” μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : 큰 숫자의 가독성이 크게 ν–₯μƒλ˜μ–΄ μ‹€μˆ˜λ₯Ό 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

4. ES2022 (ES13): λ°°μ—΄ μ ‘κ·Όμ˜ ν˜μ‹ 

Node.js 지원: Node.js 16.9.0+ (2021λ…„ 9μ›”)

  • Array.prototype.at(index)

    • μ„€λͺ…: 음수 인덱슀λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: μŠ€νƒ(Stack)의 Top μš”μ†Œλ₯Ό ν™•μΈν•˜κ±°λ‚˜ λ°°μ—΄ 끝의 값을 μ°Έμ‘°ν•  λ•Œ arr[arr.length - 1] λŒ€μ‹  arr.at(-1)둜 가독성을 λ†’μž…λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const arr = [1, 2, 3, 4, 5]
    const last = arr[arr.length - 1] // 5
    const secondLast = arr[arr.length - 2] // 4
    
    // βœ… at() μ‚¬μš©
    const last = arr.at(-1) // 5
    const secondLast = arr.at(-2) // 4
    const first = arr.at(0) // 1 (μ–‘μˆ˜ μΈλ±μŠ€λ„ κ°€λŠ₯)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μŠ€νƒ κ΅¬ν˜„
    class Stack {
      constructor() {
        this.items = []
      }
      push(item) {
        this.items.push(item)
      }
      pop() {
        return this.items.pop()
      }
      top() {
        return this.items.at(-1)
      } // λ§ˆμ§€λ§‰ μš”μ†Œ
      isEmpty() {
        return this.items.length === 0
      }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μŠ¬λΌμ΄λ”© μœˆλ„μš°
    function findMaxInWindow(arr, k) {
      const result = []
      for (let i = k - 1; i < arr.length; i++) {
        const window = arr.slice(i - k + 1, i + 1)
        result.push(Math.max(...window))
      }
      return result
    }
    
    • 주의점:
      • λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ μΈλ±μŠ€λŠ” undefinedλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€ (arr.at(100) β†’ undefined).
      • 음수 μΈλ±μŠ€λŠ” λ°°μ—΄ λμ—μ„œλΆ€ν„° κ³„μ‚°λ©λ‹ˆλ‹€ (-1 = λ§ˆμ§€λ§‰ μš”μ†Œ).
    • κ°œμ„ μ : λ°°μ—΄ 끝 μš”μ†Œ 접근이 더 직관적이고 가독성이 ν–₯μƒλ©λ‹ˆλ‹€.
  • Object.hasOwn()

    • μ„€λͺ…: hasOwnProperty의 μ•ˆμ „ν•œ 정적 λ©”μ„œλ“œ λ²„μ „μž…λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: ν•΄μ‹œ λ§΅ κ΅¬ν˜„ μ‹œ ν”„λ‘œν† νƒ€μž… 체인의 κ°„μ„­ 없이 속성 쑴재 μ—¬λΆ€λ₯Ό ν™•μΈν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ λ°©μ‹μ˜ 문제점
    const obj = { a: 1 }
    obj.hasOwnProperty('a') // true
    // ν•˜μ§€λ§Œ hasOwnPropertyκ°€ μ˜€λ²„λΌμ΄λ“œλ˜λ©΄ 문제 λ°œμƒ
    const obj2 = Object.create(null)
    obj2.hasOwnProperty('a') // TypeError!
    
    // βœ… Object.hasOwn() μ‚¬μš©
    const obj = { a: 1 }
    Object.hasOwn(obj, 'a') // true
    Object.hasOwn(obj, 'toString') // false (ν”„λ‘œν† νƒ€μž… 체인 λ¬΄μ‹œ)
    
    // μ‹€μ „ μ˜ˆμ‹œ: ν•΄μ‹œ λ§΅ κ΅¬ν˜„
    class HashMap {
      constructor() {
        this.data = {}
      }
      set(key, value) {
        this.data[key] = value
      }
      has(key) {
        return Object.hasOwn(this.data, key)
      }
      get(key) {
        return this.has(key) ? this.data[key] : undefined
      }
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 속성 체크
    function countProperties(obj) {
      return Object.keys(obj).filter((key) => Object.hasOwn(obj, key)).length
    }
    
    • 주의점:
      • ν”„λ‘œν† νƒ€μž… 체인을 ν™•μΈν•˜μ§€ μ•ŠμœΌλ―€λ‘œ, μƒμ†λœ 속성은 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • Object.hasOwn()은 정적 λ©”μ„œλ“œμ΄λ―€λ‘œ 객체 μΈμŠ€ν„΄μŠ€μ—μ„œ 직접 ν˜ΈμΆœν•  수 μ—†μŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : ν”„λ‘œν† νƒ€μž… 체인 κ°„μ„­ 없이 μ•ˆμ „ν•˜κ²Œ 속성 쑴재 μ—¬λΆ€λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • structuredClone() (μ „μ—­ API)

    • μ„€λͺ…: λΈŒλΌμš°μ €μ™€ Node.jsμ—μ„œ 곡식 μ§€μ›ν•˜λŠ” κΉŠμ€ 볡사(Deep Copy) ν•¨μˆ˜μž…λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 2차원 λ°°μ—΄μ˜ 원본을 λ³΄μ‘΄ν•˜λ©° DFS/BFS 탐색 μƒνƒœλ₯Ό λ„˜κΈΈ λ•Œ μ΅œμ μž…λ‹ˆλ‹€.
    // ❌ 얕은 λ³΅μ‚¬μ˜ 문제
    const arr = [
      [1, 2],
      [3, 4],
    ]
    const shallow = [...arr]
    shallow[0][0] = 999
    console.log(arr[0][0]) // 999 (원본도 변경됨!)
    
    // ❌ JSON λ°©μ‹μ˜ ν•œκ³„
    const deep1 = JSON.parse(JSON.stringify(arr)) // ν•¨μˆ˜, undefined λ“± 볡사 λΆˆκ°€
    
    // βœ… structuredClone() μ‚¬μš©
    const arr = [
      [1, 2],
      [3, 4],
    ]
    const deep = structuredClone(arr)
    deep[0][0] = 999
    console.log(arr[0][0]) // 1 (원본 μœ μ§€)
    
    // μ‹€μ „ μ˜ˆμ‹œ: DFS/BFS μƒνƒœ 볡사
    function dfs(grid, visited) {
      const newVisited = structuredClone(visited)
      // newVisitedλ₯Ό μˆ˜μ •ν•΄λ„ 원본 visitedλŠ” μ•ˆμ „
      // ...
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°±νŠΈλž˜ν‚Ή
    function backtrack(state, path) {
      const newState = structuredClone(state)
      const newPath = structuredClone(path)
      // μƒνƒœ 볡원 없이 μ•ˆμ „ν•˜κ²Œ 탐색
      // ...
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 객체 κΉŠμ€ 볡사
    const complex = {
      arr: [1, 2, { nested: true }],
      map: new Map([['key', 'value']]),
      set: new Set([1, 2, 3]),
    }
    const cloned = structuredClone(complex)
    
    • 주의점:
      • ν•¨μˆ˜, Symbol, DOM λ…Έλ“œ 등은 볡사할 수 μ—†μŠ΅λ‹ˆλ‹€.
      • μˆœν™˜ μ°Έμ‘°κ°€ 있으면 μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.
      • Map, Set, Date 등은 λ³΅μ‚¬λ˜μ§€λ§Œ 일뢀 νƒ€μž…μ€ μ œν•œμ μž…λ‹ˆλ‹€.
    • κ°œμ„ μ : JSON 방식보닀 훨씬 λ§Žμ€ νƒ€μž…μ„ μ§€μ›ν•˜λ©°, 원본 데이터λ₯Ό μ•ˆμ „ν•˜κ²Œ 보쑴할 수 μžˆμŠ΅λ‹ˆλ‹€.

5. ES2023 (ES14): λΆˆλ³€μ„± λ°°μ—΄ λ©”μ„œλ“œ

Node.js 지원: Node.js 20.0.0+ (2023λ…„ 4μ›”)

원본 데이터λ₯Ό μˆ˜μ •(Mutate)ν•˜μ§€ μ•Šκ³  'κ°€κ³΅λœ μƒˆ λ°°μ—΄'을 μ¦‰μ‹œ λ°˜ν™˜ν•˜μ—¬ μ‚¬μ΄λ“œ μ΄νŽ™νŠΈλ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€.

  • toSorted(), toReversed()

    • μ„€λͺ…: 원본을 μœ μ§€ν•˜λ©΄μ„œ μ •λ ¬/λ°˜μ „λœ μƒˆ 배열을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: const sorted = [...arr].sort() ν•˜λ˜ 과정을 arr.toSorted() ν•œ μ€„λ‘œ λŒ€μ²΄ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식 (원본 λ³€κ²½)
    const arr = [3, 1, 4, 1, 5]
    const sorted = [...arr].sort() // 볡사 ν›„ μ •λ ¬
    arr.sort() // 원본도 변경됨!
    
    // βœ… toSorted() μ‚¬μš©
    const arr = [3, 1, 4, 1, 5]
    const sorted = arr.toSorted() // [1, 1, 3, 4, 5]
    const reversed = arr.toReversed() // [5, 1, 4, 1, 3]
    console.log(arr) // [3, 1, 4, 1, 5] (원본 μœ μ§€)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ •λ ¬λœ λ°°μ—΄ 생성
    function findKthLargest(nums, k) {
      return nums.toSorted((a, b) => b - a)[k - 1]
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ—­μˆœ 처리
    function reverseWords(s) {
      return s.split(' ').toReversed().join(' ')
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΆˆλ³€μ„± μœ μ§€
    function processData(data) {
      const sorted = data.toSorted()
      const processed = sorted.map((x) => x * 2)
      return { original: data, processed } // 원본 보쑴
    }
    
    • 주의점:
      • toSorted()λŠ” 비ꡐ ν•¨μˆ˜λ₯Ό 인자둜 받을 수 μžˆμŠ΅λ‹ˆλ‹€ (arr.toSorted((a, b) => a - b)).
      • 원본 배열은 μ ˆλŒ€ λ³€κ²½λ˜μ§€ μ•ŠμœΌλ―€λ‘œ, λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 증가할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : λΆˆλ³€μ„±μ„ 보μž₯ν•˜λ©΄μ„œ μ½”λ“œκ°€ 더 κ°„κ²°ν•΄μ§€κ³ , μ‹€μˆ˜λ‘œ 원본을 λ³€κ²½ν•˜λŠ” 버그λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€.
  • with(index, value)

    • μ„€λͺ…: νŠΉμ • 인덱슀만 μˆ˜μ •λœ μƒˆ 배열을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: νŠΉμ • λ…Έλ“œλ§Œ λ°©λ¬Έ ν‘œμ‹œν•˜κ±°λ‚˜ 값을 λ°”κΎΌ μƒνƒœμ˜ 배열을 λ‹€μŒ μž¬κ·€ ν•¨μˆ˜λ‘œ 전달할 λ•Œ μœ μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const arr = [1, 2, 3, 4, 5]
    const newArr = [...arr]
    newArr[2] = 999 // μ—¬λŸ¬ 쀄 ν•„μš”
    
    // βœ… with() μ‚¬μš©
    const arr = [1, 2, 3, 4, 5]
    const newArr = arr.with(2, 999) // [1, 2, 999, 4, 5]
    console.log(arr) // [1, 2, 3, 4, 5] (원본 μœ μ§€)
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ°±νŠΈλž˜ν‚Ή
    function backtrack(nums, visited, path) {
      if (path.length === nums.length) {
        return [path]
      }
      const results = []
      for (let i = 0; i < nums.length; i++) {
        if (!visited[i]) {
          const newVisited = visited.with(i, true)
          const newPath = [...path, nums[i]]
          results.push(...backtrack(nums, newVisited, newPath))
        }
      }
      return results
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μƒνƒœ μ—…λ°μ΄νŠΈ
    function updateState(state, index, value) {
      return state.with(index, value)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λΆˆλ³€μ„± μœ μ§€ν•˜λ©° μˆ˜μ •
    function markVisited(grid, row, col) {
      return grid.with(row, grid[row].with(col, true))
    }
    
    • 주의점:
      • 음수 μΈλ±μŠ€λŠ” μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€ (arr.with(-1, 0) ❌).
      • λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ μΈλ±μŠ€λŠ” μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚΅λ‹ˆλ‹€.
      • 단일 인덱슀만 μˆ˜μ • κ°€λŠ₯ν•˜λ―€λ‘œ, μ—¬λŸ¬ 인덱슀λ₯Ό μˆ˜μ •ν•˜λ €λ©΄ 체이닝이 ν•„μš”ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λΆˆλ³€μ„±μ„ μœ μ§€ν•˜λ©΄μ„œ νŠΉμ • 인덱슀만 μˆ˜μ •ν•˜λŠ” 것이 κ°„κ²°ν•΄μ§‘λ‹ˆλ‹€.
  • findLast(), findLastIndex()

    • μ„€λͺ…: λ°°μ—΄μ˜ λμ—μ„œλΆ€ν„° μš”μ†Œλ₯Ό νƒμƒ‰ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const arr = [1, 2, 3, 4, 3, 5]
    let lastIndex = -1
    for (let i = arr.length - 1; i >= 0; i--) {
      if (arr[i] === 3) {
        lastIndex = i
        break
      }
    }
    
    // βœ… findLast(), findLastIndex() μ‚¬μš©
    const arr = [1, 2, 3, 4, 3, 5]
    const lastThree = arr.findLast((x) => x === 3) // 3
    const lastIndex = arr.findLastIndex((x) => x === 3) // 4
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ§ˆμ§€λ§‰ 쑰건 만쑱 μš”μ†Œ μ°ΎκΈ°
    function findLastEven(nums) {
      return nums.findLast((n) => n % 2 === 0)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: νŒ¨ν„΄ λ§€μΉ­
    function findLastMatch(str, pattern) {
      const chars = str.split('')
      const index = chars.findLastIndex((c) => pattern.test(c))
      return index !== -1 ? chars[index] : null
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μŠ€νƒμ—μ„œ νŠΉμ • κ°’ μ°ΎκΈ°
    class Stack {
      findLast(predicate) {
        return this.items.findLast(predicate)
      }
    }
    
    • 주의점:
      • 쑰건을 λ§Œμ‘±ν•˜λŠ” μš”μ†Œκ°€ μ—†μœΌλ©΄ findLast()λŠ” undefined, findLastIndex()λŠ” -1을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • find()와 λ™μΌν•œ 콜백 ν•¨μˆ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : λ°°μ—΄ λμ—μ„œλΆ€ν„° 탐색이 ν•„μš”ν•œ 경우 μ½”λ“œκ°€ 훨씬 κ°„κ²°ν•΄μ§‘λ‹ˆλ‹€.
  • toSpliced()

    • μ„€λͺ…: 원본을 λ°”κΎΈμ§€ μ•ŠμœΌλ©΄μ„œ μš”μ†Œλ₯Ό μ‚­μ œν•˜κ±°λ‚˜ μΆ”κ°€ν•œ μƒˆ 배열을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: splice()의 λΆˆλ³€μ„± λ²„μ „μœΌλ‘œ, λ°°μ—΄μ˜ νŠΉμ • 뢀뢄을 μˆ˜μ •ν•˜λ©΄μ„œ 원본을 보쑴할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식 (원본 λ³€κ²½)
    const arr = [1, 2, 3, 4, 5]
    const newArr = [...arr]
    newArr.splice(2, 1, 999) // 원본 볡사 ν›„ μˆ˜μ •
    
    // βœ… toSpliced() μ‚¬μš©
    const arr = [1, 2, 3, 4, 5]
    const newArr = arr.toSpliced(2, 1, 999) // [1, 2, 999, 4, 5]
    console.log(arr) // [1, 2, 3, 4, 5] (원본 μœ μ§€)
    
    // μ‹€μ „ μ˜ˆμ‹œ: μš”μ†Œ μ‚­μ œ
    function removeElement(arr, index) {
      return arr.toSpliced(index, 1)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μš”μ†Œ μΆ”κ°€
    function insertElement(arr, index, value) {
      return arr.toSpliced(index, 0, value)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μš”μ†Œ ꡐ체
    function replaceElement(arr, index, value) {
      return arr.toSpliced(index, 1, value)
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ—¬λŸ¬ μš”μ†Œ ꡐ체
    function replaceRange(arr, start, deleteCount, ...items) {
      return arr.toSpliced(start, deleteCount, ...items)
    }
    
    • 주의점:
      • splice(start, deleteCount, ...items)와 λ™μΌν•œ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
      • 음수 μΈλ±μŠ€λŠ” μ§€μ›ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
      • 원본 배열은 μ ˆλŒ€ λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    • κ°œμ„ μ : λΆˆλ³€μ„±μ„ μœ μ§€ν•˜λ©΄μ„œ 배열을 μˆ˜μ •ν•  수 μžˆμ–΄ 버그λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€.

6. ES2024 (ES15): 데이터 κ·Έλ£Ήν™” 및 μ§‘ν•© μ—°μ‚°

Node.js 지원: Node.js 22.0.0+ (2024λ…„ 4μ›”)

  • Object.groupBy(iterable, callback)

    • μ„€λͺ…: λ°°μ—΄μ˜ μš”μ†Œλ₯Ό νŠΉμ • 기쀀에 따라 객체둜 κ·Έλ£Ήν™”ν•©λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: ν•΄μ‹œ(Hash) μΉ΄ν…Œκ³ λ¦¬ λΆ„λ₯˜ 문제λ₯Ό reduce 없이 ν•œ μ€„λ‘œ ν•΄κ²°ν•©λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    const people = [
      { name: 'Alice', age: 25 },
      { name: 'Bob', age: 30 },
      { name: 'Charlie', age: 25 },
    ]
    const grouped = people.reduce((acc, person) => {
      const key = person.age
      if (!acc[key]) acc[key] = []
      acc[key].push(person)
      return acc
    }, {})
    
    // βœ… Object.groupBy() μ‚¬μš©
    const people = [
      { name: 'Alice', age: 25 },
      { name: 'Bob', age: 30 },
      { name: 'Charlie', age: 25 },
    ]
    const grouped = Object.groupBy(people, (person) => person.age)
    // { 25: [{name: 'Alice', age: 25}, {name: 'Charlie', age: 25}], 30: [{name: 'Bob', age: 30}] }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μΉ΄ν…Œκ³ λ¦¬λ³„ κ·Έλ£Ήν™”
    const products = [
      { name: 'Laptop', category: 'Electronics' },
      { name: 'Book', category: 'Education' },
      { name: 'Phone', category: 'Electronics' },
    ]
    const byCategory = Object.groupBy(products, (p) => p.category)
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쑰건별 λΆ„λ₯˜
    const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    const byParity = Object.groupBy(numbers, (n) => (n % 2 === 0 ? 'even' : 'odd'))
    // { even: [2, 4, 6, 8, 10], odd: [1, 3, 5, 7, 9] }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λ¬Έμžμ—΄ 길이별 κ·Έλ£Ήν™”
    const words = ['apple', 'banana', 'cat', 'dog', 'elephant']
    const byLength = Object.groupBy(words, (w) => w.length)
    
    • 주의점:
      • 콜백 ν•¨μˆ˜κ°€ λ°˜ν™˜ν•˜λŠ” ν‚€λŠ” λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ©λ‹ˆλ‹€.
      • nullμ΄λ‚˜ undefinedλ₯Ό ν‚€λ‘œ λ°˜ν™˜ν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€.
      • κ²°κ³Ό κ°μ²΄λŠ” λ°°μ—΄μ΄λ―€λ‘œ μˆœμ„œκ°€ 보μž₯λ©λ‹ˆλ‹€.
    • κ°œμ„ μ : reduceλ₯Ό μ‚¬μš©ν•œ λ³΅μž‘ν•œ κ·Έλ£Ήν™” λ‘œμ§μ„ ν•œ μ€„λ‘œ κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • Set.prototype μ§‘ν•© μ—°μ‚°

    • μ„€λͺ…: intersection(), union(), difference() λ©”μ„œλ“œκ°€ μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
    • μ•Œκ³ λ¦¬μ¦˜ ν™œμš©: 두 μ§‘ν•© κ°„μ˜ 곡톡 μš”μ†Œ μ°ΎκΈ°λ‚˜ μ°¨μ§‘ν•© 계산 μ‹œ 직접 λ°˜λ³΅λ¬Έμ„ 돌릴 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.
    // ❌ κΈ°μ‘΄ 방식
    function intersection(setA, setB) {
      const result = new Set()
      for (const item of setA) {
        if (setB.has(item)) {
          result.add(item)
        }
      }
      return result
    }
    
    function union(setA, setB) {
      return new Set([...setA, ...setB])
    }
    
    function difference(setA, setB) {
      const result = new Set()
      for (const item of setA) {
        if (!setB.has(item)) {
          result.add(item)
        }
      }
      return result
    }
    
    // βœ… Set λ©”μ„œλ“œ μ‚¬μš©
    const setA = new Set([1, 2, 3, 4])
    const setB = new Set([3, 4, 5, 6])
    
    const intersection = setA.intersection(setB) // Set {3, 4}
    const union = setA.union(setB) // Set {1, 2, 3, 4, 5, 6}
    const difference = setA.difference(setB) // Set {1, 2}
    const symmetricDiff = setA.symmetricDifference(setB) // Set {1, 2, 5, 6}
    
    // μ‹€μ „ μ˜ˆμ‹œ: 곡톡 μš”μ†Œ μ°ΎκΈ°
    function findCommonElements(arr1, arr2) {
      const set1 = new Set(arr1)
      const set2 = new Set(arr2)
      return Array.from(set1.intersection(set2))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: ν•©μ§‘ν•© 계산 (쀑볡 제거)
    function mergeArrays(arr1, arr2) {
      return Array.from(new Set(arr1).union(new Set(arr2)))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: 쀑볡 제거 ν•©μ§‘ν•© (κ°„λ‹¨ν•œ 방법)
    function uniqueUnion(arr1, arr2) {
      return [...new Set([...arr1, ...arr2])]
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: μ°¨μ§‘ν•© 계산
    function removeElements(base, toRemove) {
      return Array.from(new Set(base).difference(new Set(toRemove)))
    }
    
    // μ‹€μ „ μ˜ˆμ‹œ: λŒ€μΉ­ μ°¨μ§‘ν•© (ν•œμͺ½μ—λ§Œ μžˆλŠ” μš”μ†Œ)
    function findUniqueElements(arr1, arr2) {
      const set1 = new Set(arr1)
      const set2 = new Set(arr2)
      return Array.from(set1.symmetricDifference(set2))
    }
    
    • 주의점:
      • λ©”μ„œλ“œλŠ” μƒˆλ‘œμš΄ Set을 λ°˜ν™˜ν•˜λ©° 원본 Set은 λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
      • intersection(), union(), difference()λŠ” λ‹€λ₯Έ Set을 인자둜 λ°›μŠ΅λ‹ˆλ‹€.
      • symmetricDifference()λŠ” μ–‘μͺ½ 집합에 각각만 μžˆλŠ” μš”μ†Œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • κ°œμ„ μ : μ§‘ν•© 연산이 λ‚΄μž₯ λ©”μ„œλ“œλ‘œ μ œκ³΅λ˜μ–΄ μ½”λ“œκ°€ κ°„κ²°ν•˜κ³  μ„±λŠ₯도 μ΅œμ ν™”λ©λ‹ˆλ‹€.

πŸ’‘ μ‹€μ „ μ½”λ”© ν…ŒμŠ€νŠΈ ν™˜κ²½ 체크리슀트

ECMAScript 버전별 Node.js 지원 ν˜„ν™©

ECMAScript λ²„μ „μˆ«μž ν‘œκΈ°Node.js μ΅œμ†Œ λ²„μ „μ£Όμš” κΈ°λŠ₯
ES2020ES11Node.js 14.0.0+Optional Chaining (?.), Nullish Coalescing (??), BigInt
ES2021ES12Node.js 15.0.0+replaceAll(), Numeric Separators (_)
ES2022ES13Node.js 16.9.0+Array.at(), Object.hasOwn(), structuredClone()
ES2023ES14Node.js 20.0.0+toSorted(), toReversed(), with(), toSpliced(), findLast()
ES2024ES15Node.js 22.0.0+Object.groupBy(), Set μ§‘ν•© μ—°μ‚°

πŸš€ μ½”λ”© ν…ŒμŠ€νŠΈ ν”Œλž«νΌλ³„ Node.js 지원 ν˜„ν™© (2024-25 μ—…λ°μ΄νŠΈ)

ν”Œλž«νΌλ³„λ‘œ Node.js 버전과 μ§€μ›ν•˜λŠ” ECMAScript 버전이 λ‹€λ¦…λ‹ˆλ‹€. ES2023 문법을 μ§€μ›ν•˜μ§€ μ•ŠλŠ” ν”Œλž«νΌλ„ μ‘΄μž¬ν•˜λ―€λ‘œ, μ•ˆμ „ν•œ λ²”μš©μ„±μ„ μœ„ν•΄ ES2022κΉŒμ§€μ˜ 문법을 μ‚¬μš©ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

  • LeetCode: Node.js 20.x (ν™˜κ²½μ— 따라 ES2023 지원 μ—¬λΆ€ 상이)
  • Programmers: Node.js 버전 확인 ν•„μš” (ES2022κΉŒμ§€ μ•ˆμ „)
  • λ°±μ€€ (BOJ): Node.js 20.x (v20.12.2, ES2023 지원 μ—¬λΆ€ 확인 ν•„μš”)
  • HackerRank: Node.js 18.x ~ 20.x (ν™˜κ²½μ— 따라 상이, ES2022κΉŒμ§€ μ•ˆμ „)
  • 기타 ν”Œλž«νΌ: λŒ€λΆ€λΆ„ Node.js 18.x μ΄μƒμ΄μ§€λ§Œ, ES2023 미지원 ν™˜κ²½ 쑴재

⚠️ μ€‘μš”: ν”Œλž«νΌλ§ˆλ‹€ Node.js 버전과 ECMAScript 지원 μˆ˜μ€€μ΄ λ‹€λ₯΄λ―€λ‘œ, ES2023 문법(toSorted(), toReversed(), with() λ“±)은 μ‚¬μš© μ „ λ°˜λ“œμ‹œ ν”Œλž«νΌ 지원 μ—¬λΆ€λ₯Ό 확인해야 ν•©λ‹ˆλ‹€.


πŸ’‘ μ½”λ”© ν…ŒμŠ€νŠΈ μ΅œμ ν™” 문법 팁

1. μ•ˆμ „ν•œ λ²”μš© 문법 μ‚¬μš© (ꢌμž₯) κ°€μž₯ μ•ˆμ „ν•œ λ²”μš©μ„±μ„ ν™•λ³΄ν•˜λ €λ©΄ ES2022κΉŒμ§€μ˜ 문법을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€:

  • Optional Chaining (?.), Nullish Coalescing (??) - ES2020
  • BigInt, replaceAll() - ES2020
  • Array.at(), Object.hasOwn(), structuredClone() - ES2022

2. ES2023 문법 μ‚¬μš© μ‹œ μ£Όμ˜μ‚¬ν•­ toSorted(), toReversed(), with(), toSpliced(), findLast() λ“± ES2023 문법은 ν”Œλž«νΌμ— 따라 μ§€μ›λ˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. μ‚¬μš© μ „ λ°˜λ“œμ‹œ ν”Œλž«νΌμ˜ Node.js 버전과 지원 μ—¬λΆ€λ₯Ό ν™•μΈν•˜κ±°λ‚˜, λŒ€μ²΄ 방법을 μ€€λΉ„ν•΄μ•Ό ν•©λ‹ˆλ‹€.

3. 보수적 접근이 ν•„μš”ν•œ 경우 κΈ°μ—… 자체 μ±„μš© μ†”λ£¨μ…˜μ΄λ‚˜ μ—…λ°μ΄νŠΈκ°€ 느린 일뢀 ν”Œλž«νΌμ€ μ—¬μ „νžˆ Node.js 18.x (ES2022) ν™˜κ²½μΈ κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€. κ°€μž₯ μ•ˆμ „ν•œ λ²”μš©μ„±μ„ ν™•λ³΄ν•˜λ €λ©΄ ES2022 문법을 λ§ˆμ§€λ…Έμ„ μœΌλ‘œ μž‘λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

3. λŸ°νƒ€μž„ ν™˜κ²½ 확인법 ν”Œλž«νΌμ˜ μ •ν™•ν•œ 버전이 κΆκΈˆν•˜λ‹€λ©΄ μ½”λ“œ 상단에 μ•„λž˜ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•˜μ—¬ 직접 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

console.log(process.version)