자바스크립트의 배열은 객체다

ljjunh·2024년 11월 18일

clean-code-javascript

목록 보기
21/38
post-thumbnail

자바스크립트에서 배열은 특별한 존재다. 겉으로 보기에는 단순한 배열이지만, 내부적으로는 객체의 특성을 가지고 있다. 오늘은 이 특별한 관계를 알아보고, 클린코드 관점에서 어떻게 다뤄야 할지 살펴보자

1. 🔍 배열과 객체의 유사성

// 1. 배열 선언
const arr = [1, 2, 3];
arr[3] = 'test';
arr['property'] = 'string value';   
arr['obj'] = {};
arr['{}'] = [1, 2, 3];
arr['func'] = function() {
    return 'hello';
};

// 2. 동일한 구조의 객체
const obj = {
    0: 1,                 // obj[0]
    1: 2,                 // obj[1]
    2: 3,                 // obj[2]
    3: 'test',            // obj[3]
    property: 'string value',
    obj: {},
    '{}': [1, 2, 3],
    func: function() {
        return 'hello';
    }
};

console.log(arr);
// 배열 출력 결과:
[
    1,                    // arr[0]
    2,                    // arr[1]
    3,                    // arr[2]
    'test',               // arr[3]
    property: 'string value',
    obj: {},
    '{}': [1, 2, 3],
    func: [Function]
]



console.log(obj);
// 객체 출력 결과:
{
    '0': 1,
    '1': 2,
    '2': 3,
    '3': 'test',
    property: 'string value',
    obj: {},
    '{}': [1, 2, 3],
    func: [Function]
}

위 코드에서 볼 수 있뜻이, 배열과 객체는 매우 유사한 구조를 가지고 있다. 둘 다 키-값 쌍으로 이루어져 있고, 단지 배열은 숫자 인덱스를 자동으로 관리해주는 특별한 객체다. 하지만 이런 특성 때문에 배열을 잘못 사용하면 여러 문제가 발생할 수 있다.

2. 💡배열의 특성과 주의점

2.1 length 속성의 동작

const arr = [1, 2, 3]; 
console.log(arr.length); // 3
arr[3] = 'test';
console.log(arr.length); // 4
arr['property'] = 'string value';
console.log(arr.length); // 4

length 속성은 배열의 길이를 나타내지만, 숫자 인덱스만을 고려한다. arr['property']와 같이 문자열 키를 사용하면 이 값은 length계산에 표함되지 않는다. 이는 배열메서드를 사용할때도 문제를 일으킬 수 있다.

2.2 프로퍼티 접근 방식

// 두 가지 접근 방식
arr[0]; // 숫자 인덱스로 접근
arr['property']; // 문자열 키로 접근

배열에 문자열 키로 접근하면 일반 객체처럼 동작하지만, 이는 배열의 목적에 맞지 않다. 예를 들어 forEach, map, filter 같은 배열 메서드들은 숫자 인덱스의 값만 처리하게 된다.

3. 🎯 왜 용도에 맞는 사용이 중요할까?

// 🚫 잘못된 배열 사용 예시
const userInfo = [];
userInfo[0] = "John";
userInfo["age"] = 30;
userInfo["email"] = "john@email.com";

// 1. length가 실제 데이터를 반영하지 않음
console.log(userInfo.length); // 1 (실제로는 3개의 데이터가 있음)

// 2. 배열 메서드가 의도대로 동작하지 않음
userInfo.forEach(item => {
    console.log(item); // "John"만 출력됨 (age, email은 무시됨)
});

// 3. 데이터 처리가 불가능함
const result = userInfo.map(item => item.toUpperCase()); // age, email 처리 불가
const filtered = userInfo.filter(item => item > 20); // 제대로 된 필터링 불가

// ✅ 올바른 사용 예시
// 1. 순차적인 데이터는 배열로
const userList = ["John", "Jane", "Mike"]; // 이름 목록
const numbers = [1, 2, 3, 4, 5];          // 숫자 목록
const todoList = ["운동", "코딩", "독서"];  // 할일 목록

// 2. 키-값 쌍은 객체로
const userInfo = {
    name: "John",
    age: 30,
    email: "john@email.com"
};

// 3. 복합적인 데이터는 배열과 객체를 조합
const users = [
    {
        name: "John",
        age: 30,
        email: "john@email.com"
    },
    {
        name: "Jane",
        age: 25,
        email: "jane@email.com"
    }
];

// 이제 배열 메서드를 올바르게 사용할 수 있다
users.forEach(user => console.log(user.name));
const adults = users.filter(user => user.age >= 18);
const emails = users.map(user => user.email);

배열에 문자열 키를 사용하면 다음과 같은 문제가 발생한다
1. 배열의 length가 실제 데이터 개수를 반영하지 않음
2. 배열 메서드들이 의도한 대로 동작하지 않음
3. 코드의 예측 가능성이 깨짐
4. 데이터 구조의 일관성이 깨짐

4. 🎯 배열 타입 체크: 클린코드 접근

4.1 ❌ 피해야 할 방법들

// 안티 패턴들
if (arr.length) { ... }              // 문자열도 length 프로퍼티를 가짐
if (typeof arr === 'object') { ... }  // 일반 객체도 'object' 반환
if (arr instanceof Array) { ... }     // 프레임워크 간 호환성 문제
if ('length' in arr) { ... }         // 문자열도 true 반환

4.2 ✅ 권장하는 방법

// 모던 자바스크립트의 표준 방식
if (Array.isArray(arr)) {
    console.log('진짜 배열입니다!');
}

5. 🚀 마치며

자바스크립트 배열의 특별한 성질을 이해하는 것은 매우 중요하다. 배열이 객체의 특성을 가지고 있다는 것을 알면, 더 예측 가능하고 유지보수하기 좋은 코드를 작성할 수 있다.

💡 핵심 포인트

  • 배열 체크는 Array.isArray()를 사용
  • 배열은 순차적인 데이터용으로만 사용
  • 키-값 쌍이 필요하다면 객체를 사용

이러한 원칙들을 지키면서 코딩하면, 더 깔끔하고 유지보수하기 좋은 코드를 작성할 수 있다

profile
Hello

0개의 댓글