배열은 순서가 있는 데이터 저장소이다.
각 요소는 인덱스(index) 를 통해 접근할 수 있으며, 데이터를 연속된 메모리 공간에 저장한다.
JavaScript에서 배열은 동적 배열로 구현되어 있으며, 크기가 자동으로 조정된다.
배열은 다양한 메서드를 제공하여 데이터를 쉽게 추가, 삭제, 정렬할 수 있다.
• arr[0], arr[1]과 같은 방식으로 요소를 가져올 수 있다.
• 새로운 요소를 추가하면 크기가 자동으로 늘어나고, 요소를 삭제하면 줄어든다.
• 특정 요소를 삭제하면 뒤에 있는 요소들이 한 칸씩 앞으로 이동해야 한다.
• JavaScript의 배열은 실제로 객체이며, length 속성과 다양한 메서드를 제공한다.
메서드 | 설명 | 시간 복잡도 |
---|---|---|
push(value) | 배열의 끝에 값을 추가한다 | O(1) |
pop() | 배열의 끝 값을 제거한다 | O(1) |
unshift(value) | 배열의 앞에 값을 추가한다 | O(n) |
shift() | 배열의 앞 값을 제거한다 | O(n) |
splice(index, count) | 특정 위치의 요소를 추가 또는 삭제한다 | O(n) |
slice(start, end) | 특정 범위의 요소를 복사하여 새로운 배열을 만든다 | O(n) |
map(callback) | 배열의 각 요소에 콜백 함수를 적용한 새로운 배열을 반환한다 | O(n) |
filter(callback) | 특정 조건을 만족하는 요소만을 포함하는 새로운 배열을 반환한다 | O(n) |
reduce(callback, initialValue) | 배열을 순회하며 누적 연산을 수행한다 | O(n) |
배열은 연속된 메모리 공간에 데이터를 저장하지만, JavaScript의 배열은 동적 배열이므로
공간이 부족할 경우 새로운 메모리를 할당하고 기존 데이터를 복사하는 과정이 발생한다.
배열의 인덱스 접근은 O(1)의 시간 복잡도를 가지지만, 중간 삽입 및 삭제는 O(n) 이 된다.
const arr = ["🍎", "🍌", "🍇"]; // 메모리 구조 예시
// 메모리 구조:
// 0x100 -> "🍎"
// 0x104 -> "🍌"
// 0x108 -> "🍇"
배열의 길이를 초과하여 요소를 추가하면 새로운 메모리를 할당하고 데이터를 복사하는 작업이 발생한다.
• JSON 데이터 구조를 다룰 때 배열을 사용한다.
• React와 같은 프레임워크에서 상태(state) 관리 시 배열을 사용한다.
• 배열을 정렬(sort())하거나 특정 조건에 맞는 요소를 찾을 때(filter(), find()) 사용한다.
2차원 배열은 1차원 배열을 확장한 것 이다. 2차원 배열은 다음과 같이 선언할수있다.
// 2 차원 배열을 리터럴로 표현
const arr = l[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]1;
// arr[2][3] 에 저장된 값을 출력
console. Log(arr [2J[3]); / / 12
// arr[2][3]에 저장된 값을 15로 변경
arr[2J[3] = 15;
// 변경된 값을 출 력
console. log(arr[2][3]); / / 15
스택은 후입선출(LIFO, Last In First Out) 방식으로 동작하는 자료구조이다.
데이터의 추가(push())와 제거(pop())가 맨 위(Top)에서만 이루어진다.
배열을 사용하여 쉽게 구현할 수 있으며, 실행 취소(Undo), 함수 호출 스택(Call Stack) 등 다양한 곳에서 사용된다.
• 마지막에 추가된 요소가 가장 먼저 제거된다.
• 중간의 요소를 제거할 수 없으며, 반드시 마지막 요소부터 제거해야 한다.
• JavaScript의 push()와 pop()을 활용하면 간단하게 스택을 구현할 수 있다.
메서드 | 설명 | 시간 복잡도 |
---|---|---|
push(value) | 스택의 맨 위에 값을 추가한다 | O(1) |
pop() | 스택의 맨 위 값을 제거한다 | O(1) |
peek() | 스택의 맨 위 값을 반환한다 (제거하지 않음) | O(1) |
isEmpty() | 스택이 비어 있는지 확인한다 | O(1) |
size() | 스택의 크기를 반환한다 | O(1) |
스택은 데이터를 배열의 끝에 추가하고(push()), 끝에서 제거(pop())하는 방식으로 동작한다.
이로 인해 O(1)의 시간 복잡도를 가지며, 매우 빠른 데이터 추가 및 삭제가 가능하다.
// 스택 구현 (배열 사용)
const stack = [];
// 데이터 추가
stack.push("🟥 빨강");
stack.push("🟦 파랑");
stack.push("🟩 초록");
console.log(stack); // ["🟥 빨강", "🟦 파랑", "🟩 초록"]
// 데이터 제거
const lastItem = stack.pop();
console.log(lastItem); // "🟩 초록" (마지막에 넣은 값이 먼저 나옴)
console.log(stack); // ["🟥 빨강", "🟦 파랑"]
• 문서 편집기에서 실행 취소할 때 마지막 작업을 먼저 제거하는 방식으로 동작한다.
• 사용자가 방문한 페이지를 스택에 저장하고, “뒤로 가기” 버튼을 누르면 최근 페이지부터 제거하는 방식이다.
• JavaScript의 함수 실행 과정에서 콜 스택(Call Stack)이 사용되며, 후입선출 방식으로 실행된다.
function first() {
console.log("첫 번째 실행");
second();
}
function second() {
console.log("두 번째 실행");
third();
}
function third() {
console.log("세 번째 실행");
}
first();
이처럼 실행이 끝난 함수는 마지막 실행된 함수부터 제거되며, 후입선출(LIFO) 방식으로 동작한다.
개념 | 배열(Array) | 스택(Stack) |
---|---|---|
구조 | 순차적으로 데이터를 저장 | 후입선출 (LIFO) |
추가 방식 | push(), unshift() 등 자유롭게 가능 | push() (맨 위에서만 추가) |
제거 방식 | pop(), shift(), splice() 등 가능 | pop() (맨 위에서만 제거) |
접근 방식 | index를 사용하여 특정 요소 접근 가능 | 맨 위 요소(top)만 접근 가능 |
사용 예시 | 리스트, 데이터 관리 | 실행 취소(Undo), 콜 스택(Call Stack) |
배열과 스택의 개념을 깊이 이해하면, 다양한 알고리즘과 데이터 구조를 쉽게 이해할 수 있다.
배열은 데이터 저장과 검색에 유용하고, 스택은 후입선출 방식이 필요한 곳에서 강력한 성능을 발휘한다.
ADT는 자료구조를 어떻게 구현할지보다는, 무엇을 할 수 있는지를 정의하는 개념적인 모델이다.
어떤 연산을 제공해야 하는지 명확하게 정의하는 것이 핵심이며, 내부 구현 방식은 중요하지 않다.
쉬운 예로 자동차와 운전자의 관계를 들수있다.
자동차를 운전할 때 자동차의 내부 엔진 구조를 몰라도 엑셀을 밟으면 가속하고, 브레이크를 밟으면 멈춘다는 기능만 알면된다.