| 서론
JavaScript를 사용하다 보면 “문법은 아는데, 막상 문제를 풀거나 코드를 짜려면 손이 안 움직이는 순간”이 자주 온다.
특히 코딩테스트나 알고리즘 문제, 혹은 실무에서 데이터를 가공할 때 배열, 문자열, 객체, Set/Map, 정렬 같은 기본 자료구조와 메서드에 익숙하지 않으면 불필요하게 for문을 늘리거나, 로직이 복잡해지는 경우가 많다.
이 글은 그런 상황을 줄이기 위해 JavaScript에서 가장 자주 쓰이는 기본 자료구조와 메서드들을 언제 쓰는지, 어떤 특징이 있는지, 실전에서 바로 적용 가능한 패턴 위주로 한 번에 정리한 노트다.
1. 배열
1) 배열 생성 & 순회
(1) 배열 생성
- new Array()
// ( ) 안에 값을 넣으면 된다.
const arr1 = new Array(1, 2, 3);
console.log(arr1); // [1, 2, 3]
// ( ) 안에 숫자 1개만 넣으면 '길이'로 인식된다.
const arr2 = new Array(3);
console.log(arr2); // [ <3 empty items> ]
- Array.from
// 문자열을 넣으면, 문자 단위로 쪼개진다.
const arr = Array.from("hello");
console.log(arr); // ['h', 'e', 'l', 'l', 'o']
// 이터러블 객체로 변환도 가능하다.
const numbers = Array.from({ length: 5 }, (_, i) => i);
console.log(numbers); // [0, 1, 2, 3, 4]
(2) 배열 순회
- for : 성능 제어, break/continuer가 필요할 때 유리
const arr = [10, 20, 30];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
- for ... of
const arr = [10, 20, 30];
for (const value of arr) {
console.log(value);
}
- forEach : 콜백 기반 순회, break/return으로 반복 중단 불가
const arr = [10, 20, 30];
arr.forEach((value, index) => {
console.log(index, value);
});
(3) 인덱스 접근
- 대괄호로 접근
const arr = ["apple", "banana", "cherry"];
console.log(arr[0]); // apple
console.log(arr[1]); // banana
console.log(arr[2]); // cherry
- 인덱스를 활용한 수정
arr[1] = "orange";
console.log(arr); // ["apple", "orange", "cherry"]
요약
1. 생성 : Array.from()
2. 순회
- 인덱스 필요 : for
- 값만 필요 : for..of
- 렌더/처리 : forEach
3. 접근 : arr[index]
2) 배열 메서드
(1) push, pop : stack에 적합
- push : 배열 끝에 추가
const arr = [1, 2];
arr.push(3);
console.log(arr) // [1, 2, 3]
- pop : 배열 끝 요소 제거
const arr = [1, 2, 3];
const last = arr.pop();
console.log(last); // 3
console.log(arr); // [1, 2]
(2) shift, unshift : queue에 적합
- unshift : 배열 앞에 추가
const arr = [2, 3];
arr.unshift(1);
console.log(arr); // [1, 2, 3]
- shift : 배열 앞 요소 제거
const arr = [1, 2, 3];
const first = arr.shift();
console.log(fisrt); // 1
console.log(arr); // [2, 3]
(3) slice, splice
- slice : 원본 유지, 잘라서 반환
// 방법1 : 특중 구간
array.slice(start, end)
// start : 시작 인덱스 (포함)
// end : 끝 인덱스 (미포함)
// 원본 배열은 변경되지 않음
// 방법 2 : 처음/끝 기준
array.slice(start)
// start : 시작 인덱스 (포함)
// 방법 3 : 음수 인덱스
arr.slice(음수)
// -1은 가장 끝
arr.slice(start, end)
// start : 시작 인덱스 (포함)
// end : 끝 인덱스 (포함)
const arr = [1, 2, 3, 4];
const sliced = arr.slice(1, 3);
console.log(sliced); // [2, 3]
console.log(arr); // [1, 2, 3, 4]
- splice : 원본 변경
arr.splice(start, deleteCount, ...items)
// start : 시작 인덱스
// deleteCount : 삭제할 개수
// ...items : 해당 위치에 추가할 값들
const arr = [1, 2, 3, 4];
arr.splice(1, 2); // index 1부터 2개 제거
console.log(arr); // [1, 4]
const arr = [1, 22, 4];
// 삭제만
arr.splice(1, 1);
console.log(arr); // [1, 4];
// 삽입만
arr.splice(1, 0, 99);
console.log(arr); // [1, 99, 4]
// 삭제 + 교체
arr.splice(1, 1, 100);
console.log(arr); // [1, 100, 4]
(4) sort
- 기본 정렬 (문자 기준)
// 대소문자 섞이지 않은 경우
const arr = ["c", "a", "b"];
arr.sort();
console.log(arr); // ["a", "b", "c"]
// 대소문자 섞인 경우 (오름차순)
const arr = ["c", "A", "b"];
arr.sort((a, b) => a.localeCompare(b));
console.log(arr); // ["A", "b", "c"]
// 대소문자 섞인 경우 (내림차순)
const arr = ["c", "A", "b"];
arr.sort((a, b) => b.localeCompare(a));
console.log(arr); // ["c", "b", "A"]
- 숫자 정렬 (비교 함수 필수)
// 오름차순 정렬
const nums = [10, 2, 30];
nums.sort((a, b) => a - b);
console.log(nums); // [2, 10, 30];
// 오름차순 정렬
const nums = [10, 2, 30];
nums.sort((a, b) => b - a);
console.log(nums); // [30, 10, 2];
(5) reverse
- 원본이 변경됨
const arr = [1, 2, 3];
arr.reverse();
console.log(arr); // [3, 2, 1]
(6) join
const arr = ["React", "is", "fun"];
const result = arr.join(" ");
console.log(result); // "React is fun"
3) 배열 변형 / 가공
(1) map
: 각 요소를 다른 값으로 바꾼 새 배열을 만든다.
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);
console.log(doubled); // [2, 4, 6]
(2) filter
const nums = [1, 2, 3, 4];
const even = nums.filter(n => n%2 === 0);
console.log(even); // [2, 4]
(3) reduce
const nums = [1, 2, 3, 4];
const sum = nums.reduce((arr, cur) => arr + cur, 0);
console.log(sum); // 10
2) 2차원 배열
(1) 생성 방법
const board = Array.fron({length : 3}, () =>
Array.from({length : 3}, () => 0)
);
console.log(board);
// [
// [0,0,0],
// [0,0,0],
// [0,0,0]
// ]
(2) 행/열 순회
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
console.log(i, j, board[i][j]);
}
}
(3) 좌표 기반 접근 (dx, dy 패턴)
const dx = [0, 0, -1, 1];
const dy = [-1, 1, 0, 0];
for (let d = 0; d < 4; d++) {
const nx = x + dx[d];
const ny = y + dy[d];
if (nx >= 0 && ny >= 0 && nx < n && ny < m) {
// 유효한 좌표
}
}
2. 문자열 (String) - 입력 처리 & 파싱
1) 문자열 메서드
(1) split
: 문자열을 기준 문자로 나눠 배열로 변환
const input = "apple,banana,orange";
const arr = input.split(",");
console.log(arr); // ["apple", "banana", "orange"]
// 공백 기준 분리
const line = "10 20 30";
const nums = line.split(" ").map(Number);
console.log(nums); // [10, 20, 30]
(2) trim
: 문자열 앞뒤 공백 제거
const input = " hello world ";
console.log(input.trim()); // "hello world"
(3) replace, replaceAll
// replace (첫 번째만 변경)
const str = "a-b-c";
console.log(str.replace("-", "_")); // "a_b-c"
// replaceAll (전체 변경)
console.log(str.replaceAll("-", "_")); // "a_b_c"
// 정규식활용
const dirty = "1,000,000";
const clean = dirty.replace(/,/g, "");
console.log(clean); // "1000000"
(4) includes
: 문자열에 포함 여부 확인
const str = "frontend developer";
console.log(str.includes("dev")); // true
console.log(str.includes("back")); // false
(5) startsWith, endsWith
const file = "image.png";
console.log(file.startsWith("img")); // false
console.log(file.endsWith(".png")); // true
(6) substring, slice
// substring(start, end)
const str = "abcdef";
console.log(str.substring(1, 4)); // "bcd"
2) 문자열 <-> 배열 패턴
(1) 한 글자씩 처리
- split("");
const str = "hello";
const chars = str.split("");
console.log(chars); // ["h", "e", "l", "l", "o"]
(2) 문자열 누적 vs 배열 push 후 join
// 문자열 누적
let result = "";
for (const ch of "abc") {
result += ch.toUpperCase();
}
console.log(result); // "ABC"
// 배열에 모아서 joi
const temp = [];
for (const ch of "abc") {
temp.push(ch.toUpperCase());
}
const result = temp.join("");
console.log(result); // "ABC"
3. 객체(Object) & 맵(Map)
1) Object (빈도수, 해시)
(1) {} 기본 사용법
const obj = {};
obj["apple"] = 1;
obj["banana"] = 2;
console.log(obj); // { apple: 1, banana: 2 }
obj.apple = 3;
console.log(obj.apple); // 3
(2) 키 존재 여부 확인
const obj = { a: 1 };
console.log("a" in obj); // true
console.log("b" in obj); // false
if (obj[key] === undefined) {
// 키가 없음
}
2) Map
(1) 메서드 종류
- set
const map = new Map();
map.set("a", 1);
map.set("b", 2);
- get
console.log(map.get("a")); // 1
- has
console.log(map.has("a")); // true
- delete
map.delete("a");
console.log(map.has("a")); // false
(2) Object vs Map 차이
| 구분 | Object | Map |
| 키 타입 | 문자열만 | 모든 타입 가능 |
| 순서 보장 | ❌ | ✅ |
| 크기 확인 | 직접 계산 | map.size |
| 빈도수 | 👍 | 👍👍 |
| 성능 | 보통 | 대량 데이터에 유리 |
(3) 숫자/배열 키 사용
// Object는 자동 문자열 변환
const obj = {};
obj[1] = "one";
obj[[1,2]] = "array";
console.log(obj);
// { '1': 'one', '1,2': 'array' }
// Map은 타입 유지
const map = new Map();
map.set(1, "one");
map.set([1, 2], "array");
console.log(map.get(1)); // one
console.log(map.get([1,2])); // undefined (참조 다름)
3) 빈도수 / 카운팅 패턴
(1) 문자 빈도
// Object 버전
const str = "banana";
const count = {};
for(const ch of str) {
count[ch] = (count[ch] || 0) + 1;
}
console.log(count);
// {b : 1, a : 3, n : 2}
// Map 버전
const map = new Map();
for(const ch of "banana"){
map.set(ch, (map.get(ch) || 0) + 1);
}
console.log(map.get("a")); // 3
(2) 숫자 등장 횟수
const nums = [1, 2, 2, 3, 1, 2];
const freq = {}
for(const n of nums) {
freq[n] = (freq[n] || 0) + 1;
}
console.logfreq);
// {1 : 2, 2 : 3, 3 : 1}
// reduce로 한 줄 처리
const freq = nums.reduce((acc, cur) => {
acc[cur] = (acc[cur] || 0) + 1;
return acc;
}, {});
4. Set - 중복 체크 & 방문 체크
1) add, has, delete
(1) add
const set = new Set();
set.add(1);
set.add(2);
set.add(2);
console.log(set); // Set {1, 2}
(2) has
console.log(set.has(1)); // true
console.log(set.has(3)); // false
(3) delete
set.delete(1);
console.log(set.has(1)); // false
(4) size
console.log(set.size);
2) 중복 제거
(1) 숫자 중복 제거
const nums = [1, 2, 2, 3, 3, 3];
const unique = [... new Set(nums)];
console.log(unique); // [1, 2, 3]
(2) 문자열 중복 제거
const str = "banana";
const uniqueStr = [... new Set(str)].join("");
console.log(uniqueStr); // "ban"
(3) 중복 개수 확인
const nums = [1, 1, 2, 2, 3];
const uniqueCount = new Set(nums).size;
console.log(uniqueCount); // 3
3) 방문 여부 체크 (그래프 / 시뮬레이션)
(1) 단순 방문 체크
const visited = new Set();
function visiti(node){
if(visited.has(node)) return;
viisted.add(node);
console.log("방문 : ", node);
}
visit(1);
visit(2);
visit(1); // 무시됨
(2) 그래프 / DFS / BFS 방문 체크
const graph = {
1 : [2, 3],
2 : [4],
3 : [],
4 : []
}
const visited = new Set();
function dfs(node) {
if(visited.has(node)) return;
visited.add(node);
console.log(node);
for(const next of graph[node]) {
dfs(next);
}
}
dfs(1);
/*
1
2
4
3
*/
(3) 2차원 좌표 방문 체크
const visited = new Set();
const x = 2, y = 3;
const key = `${x},${y}`;
if(!visited.has(key)) {
visited.add(key);
}
5. 수학(Math) & 숫자 처리
1) Math 객체
(1) Math.floor, Math.ceil, Math.round
- Math.floor : 내림
Math.floor(3.7); // 3
Math.floor(-3.2); // -4
- Math.ceil : 올림
Math.ceil(3.2); // 4
Math.ceil(-3.7); // -3
- Math.round : 반올림
Math.round(3.5); // 4
Math.round(3.4); // 3
(2) Math.abs
Math.abs(5); // 5
Math.abs(-5); // 5
const diff = Math.abs(a - b);
(3) Math.max, Math.min
Math.max(1, 3, 2); // 3
Math.min(1, 3, 2); // 1
// 배열에서 최대/최소 (스프레드 연산자와 세트로 기억)
const nums = [1, 5, 3];
Math.max(...nums); // 5
Math.min(...nums); // 1
(4) Math.pow, Math.sqrt
- Math.pow : 거듭 제곱
Math.pow(2, 3); // 8
// ES6
2 ** 3; // 8
- Math.sqrt : 제곱근
Math.sqrt(9); // 3
Math.sqrt(2); // 1.414...
2) 숫자 처리 패턴
(1) 자리수 분해
// 문자열 기반
const num = 1234;
const digits = String(num).split("").map(Number);
console.log(digits); // [1, 2, 3, 4]
// 수학적 분해
let n = 1234;
const digits = [];
while (n > 0) {
digits.push(n % 10);
n = Math.floor(n / 10);
}
digits.reverse();
console.log(digits); // [1, 2, 3, 4]
(2) 나머지 연산
// 짝수홀수
n % 2 === 0; // 짝수
n % 2 === 1; // 홀수
// 배수 체크
n % 3 === 0; // 3의 배수
// 순환 패턴 (인덱스)
const idx = i % arr.length;
6. 정렬 & 비교 로직
1) sort 심화
: sort는 원본 배열을 벼경하고, 비교함수가 없으면 문자열 기준 정렬을 한다.
(1) 숫자 정렬
// 오름차순
const nums = 10, 2, 30, 1];
nums.sort((a, b) => a - b);
console.log(nums); // [1, 2, 10, 30]
// 내림 차순
nums.sort((a, b) => b - a);
console.log(nums); // [30, 10, 2, 1];
(2) 문자열 정렬
const words = ["banana", "apple", "cherry"];
words.sort();
console.log(words); // ["apple", "banana", "cherry"]
// 대소문자 / 다국어 고려 시 localeCompare가 안전
// 오름차순
words.sort((a, b) => a.localeCompare(b));
// 내림차순
words.sort((a, b) => b.localeCompare(a));
(3) 객체 배열 정렬
const users = [
{name : "Kim", age : 30},
{name : "Lee", age : 20},
{name : "Park", age : 25},
];
// 숫자 기준 (예시로 나이)
users.sort((a, b) => a.age - b.age);
console.log(users);
/*
[
{ name: "Lee", age: 20 }, // 가장 나이가 적음
{ name: "Park", age: 25 }, // 중간
{ name: "Kim", age: 30 } // 가장 나이가 많음
]
*/
// 문자열 기준 (예시로 이름)
users.sort((a, b) => a.name.localeCompare(b.name));
console.log(users);
/*
[
{ name: "Kim", age: 30 }, // K
{ name: "Lee", age: 20 }, // L
{ name: "Park", age: 25 } // P
]
*/
(4) 다중 조건 정렬
// 1차 조건 -> 같으면 2차 조건
users.sort((a, b) => {
if (a.age !== b.age) {
return a.age - b.age;
}
return a.name.localeCompare(b.name);
});
// 1차 조건 (점수), 2차 조건 (이름)
const students = [
{ name: "Kim", score: 90 },
{ name: "Lee", score: 90 },
{ name: "Park", score: 80 }
];
students.sort((a, b) => {
if (a.score !== b.score) {
return b.score - a.score; // 점수 내림
}
return a.name.localeCompare(b.name); // 이름 오름
});
console.log(students);
/*
[
{ name: "Kim", score: 90 }, // 점수 90 (동점) → 이름 K
{ name: "Lee", score: 90 }, // 점수 90 (동점) → 이름 L
{ name: "Park", score: 80 } // 점수 80
]
*/
| 결론
JavaScript 기본기는 결국 “어떤 자료구조를 쓰고, 어떤 메서드를 고를 수 있느냐”에서 갈린다. 이 포스팅의 목표는
“외우는 문서”가 아니라 문제를 만났을 때 바로 떠올릴 수 있는 기준표를 만드는 것이다.
'💻 개발 > 📒 JavaScript' 카테고리의 다른 글
| [JavsScript] 자바스크립트의 마법사: Unary Plus(+) 연산자 활용법 (0) | 2026.03.14 |
|---|---|
| [SvelteKit] 프론트엔드 UX 개선의 디테일: tabindex="-1"와 .blur() 활용법 (1) | 2025.11.11 |
| 테스트보다 구현이 먼저,,? - 로또 발매기 프로젝트에서 배운 TDD의 전환점 (0) | 2025.11.03 |
| 하나의 클래스가 너무 많은 일을 할 때 — LottoMachine 리팩토링 이야기 (0) | 2025.11.03 |
| Matchers - Jest (0) | 2025.10.24 |
