자바스크립트 변수와 자료형에 대해 공부하고, 개발자로서 "효율"을 따지다보면 누구나 드는 생각이 하나 있을 것이다.
그냥 이거 다 변수 하나에 때려 넣으면 안되나?
개발자로서 매우 위험한 발상이지만, 근본적으로 떠오르는 해결책이긴 하다. 매번 비슷한데 내용만 조금씩 다르다고 별개의 변수를 선언하고 재할당하는 일은 꽤 비효율적이라는 느낌을 받는다. 또한 프로젝트의 규모가 커지면 커질수록 변수가 늘어나고 다양해질텐데, 여러 명이서 같이 하는 작업에서 모든 변수의 이름과 값을 기억하기란 쉽지 않아 걱정도 된다. 이럴 땐 어떻게 해야할까? 답은 배열과 객체에 있다.
배열(Array)이란?
배열은 "순서(index)가 있는 값(value)"으로, 기존에 있었던 자료형을 하나의 변수에 저장하고 조회할 수 있도록 만든 자료형이다. 대괄호[]를 통해 배열을 만들고, 각각의 원소는 쉼표로 구분해 구성한다. 각각의 값은 기존에 지정된 순서(index)를 통해 접근하고 수정할 수 있다. 먼저 전의 예시를 배열로 재구성 해보도록 하자.
이처럼 배열은 각각의 연관성이 있는 자료들을 한 곳에 묶어 보관하는데 유용하다. 덕분에 우리는 각각의 변수를 각각 선언하고 값을 할당하지 않아도 order라는 큰 틀 안에 모든 자료들을 저장할 수 있다. 또, 여러 개의 자료를 한꺼번에 보관하고 있기 때문에 개발자 입장에서 자료에 접근하기 좀 더 용이하고 기억하기도 쉽다. 한 가지 주의할 점은 배열의 순서는 0부터 시작하기 때문에 첫 번째 자료는 [0]번째 인덱스에 저장된다는 사실을 인지하고 있어야 한다.
만약 위의 예시를 각각의 변수값으로 선언하고 할당하려면 10개의 각각 다른 변수 이름을 짓고 각각의 값을 할당해야 한다. 이러한 경우 오타가 생길 확률도 커지고 가독성이 크게 떨어질 것이다. 이 외에도 배열에는 다양한 내장 함수가 있는데, 이를 통해 우리가 구현하고자 하는 기능에 편리성을 더해준다.
배열 메서드
배열은 다양한 메서드를 가지고 있다. 이번 포스팅에서는 간단하게 몇 가지 메서드에 대해서만 설명할 예정인데, 더 자세한 건 MDN문서 등을 참조해 알아보도록 하자.
길이(.length)
.length 메서드는 배열의 길이를 알려준다. 이 때 길이는 해당 배열 안에 원소element의 "개수"로, index와 헷갈리지 않도록 주의하자. (예시의 길이는 4지만, 배열의 마지막 순서는 [3]이다.)
추가(.push / .unshift)
.push() 메서드는 배열의 끝에 항목을 추가하고, .unshift() 메서드는 배열의 앞에 항목을 추가한다. 이 때, return값은 새롭게 항목이 추가된 기존 배열의 "길이"이므로 이 점을 주의하도록 하자.
삭제(.pop / .shift)
앞의 예시와 마찬가지로 배열 끝에서부터 항목을 제거하고 싶으면 .pop() 메서드를, 배열의 앞에서부터 항목을 제거하기 위해서는 .shift() 메서드를 활용해 값을 없애주면 된다. 앞의 항목 추가 메서드와 다르게 삭제 메서드는 삭제된 해당 항목을 return값으로 가지므로 이를 적절히 활용해 어떤 값이 삭제됐는지 확인할 수 있다.
검사(Arrray.isArray)
배열의 경우 현재 자료형이 배열인지 구분하기 위해서는 조금 다른 방법을 활용해야 하는데, Array.isArray() 메서드를 활용해야 확인이 가능하다. 해당 메서드를 통해 현재 자료형이 배열인지 아닌지 확인할 수 있으며 해당 메서드는 전달인자로 받은 값이 배열이 아닐 경우 '거짓false'을 반환하고, 배열이 맞다면 '참true'을 반환한다. 이 때 한 가지 의문점이 든다.
그냥 typeof 쓰면 안되나?
typeof를 썼더니 기대했던 'Array' 대신 'object'가 나왔다. 이건 무슨 소리일까? 말 그대로다. '배열'은 '객체object'의 한 종류다. 다만 배열의 경우 보통의 객체와는 다른 몇 가지 특이점을 가지고 있기 때문에 통상적으로 객체에 포함하지 않고 별개의 존재로서 구분한다. 그렇다고 배열이 객체가 아닌 것은 아니므로 헷갈리지 말자. 우리는 typeof 연산자를 통해 물어봤기 때문에 컴퓨터는 이해한 그대로 '배열'이란 자료형의 구분을 알려준 것이니, 콘솔창의 결과값이 틀린 것이 전혀 아니다. 그렇다면 객체는 무엇일까?
객체(Object)란?
배열이 객체에서 왔기 때문에, 객체 또한 다양한 값들을 한 번에 저장할 수 있다. 또한, 배열을 정확하게 사용하기 위해서는 각 인덱스index가 가지고 있는 정보를 미리 알고 있어야 하기 떄문에 해당 자료에 접근할 때 어려움이 있을 수 있다. 이에 따라 객체Obejct를 사용하면 좀 더 세분화하여 자료들을 구분할 수 있다. 객체를 생성하기 위해서는 중괄호를 이용하고 키와 값을 한 쌍으로 지어 데이터를 저장한다. 이 때 키-값 쌍은 쉼표로 구분한다.
위의 예시처럼 객체는 데이터를 읽는데 있어 (개발자 또는 유저에게) 가독성을 높이는 장점도 있다. 배열의 예시와 다르게 객체의 경우 키key와 값value이 한 쌍을 이루기 때문에 주문번호(orderNumber)가 0이고, 주문자의 이름이 'john'이라는 것을 보다 명확히 이해할 수 있다. 객체의 값에 접근하기 위해서는 두 가지 방법을 사용할 수 있다.
1. Dot Notation(.), 점 표기법
점 표기법은 위처럼 해당 객체에 점(.)을 먼저 입력한 후 키를 입력해 해당 키가 가지고 있는 값에 접근할 수 있다. 이를 통해 접근 중인 키의 값을 변경할 수도 있다.
2. Bracket Notation([ ]), 괄호 표기법
괄호 표기법도 점 표기법과 원리는 같으나, 다른 문법을 사용한다. 괄호 표기법 안에 들어갈 키(속성의 이름)은 문자열('')로 표현되어야 하며, 문법을 지키지 않으면 데이터 값에 접근할 수 없다.
단, 위처럼 별도의 변수를 선언하고 할당해, 변수값과 객체 안의 키가 같다면 이를 활용해 객체 안의 키와 일치하는 값을 불러올 수도 있다.
객체 메서드와 연산자 활용
객체도 배열처럼 메서드를 활용할 수 있다. 하지만 객체는 배열의 메서드를 활용할 수 없으니 주의하자.
키(Object.keys)와 값(Object.values)를 활용한 길이(length)
객체의 길이를 구하고 싶다면 먼저 기존에 객체 안에 포함되어 있던 키와 값을 분리해야 한다. (객체가 성립되기 위해선 키와 값이 쌍을 이루어 있기 때문) 따라서 Object.keys 또는 Object.values를 활용해 해당 객체의 키 또는 값을 배열로 받고 해당 배열의 길이를 구함으로서 객체의 "길이"를 구할 수 있다.
delete 연산자를 활용한 속성 삭제
객체 자체에는 속성을 삭제하는 메서드가 없다. 또한 배열의 메서드를 활용할 수 없기 때문에 위와 같이 delete 연산자를 활용해야 객체의 자료를 삭제할 수 있다.
in 연산자를 활용한 속성 확인
비슷한 방법으로 객체 안에서 찾고자 하는 자료가 있는지 확인할 수 있다. 해당 경우에도 객체의 (키를 통해 값을 불러오므로) 키를 통해 자료가 있는지 확인하고 만약 속성의 이름과 일치할 경우 true를, 일치하지 않을 경우 false를 반환한다.
객체에 in 연산자를 사용하기 위한 경우, 찾고자 하는 속성의 이름을 문자열로 비교해야 한다. 그렇지 않을 경우 위와 같이 오류가 발생한다. 또한 in 연산자의 경우 배열의 인덱스를 통해 해당 배열의 순서에 값이 존재하는지 여부도 확인할 수 있다.
배열 vs 객체
배열도 결국은 객체에 포함이 되지만, 배열만의 특수성 때문에 일반적인 객체 중 하나로 단정하기엔 어렵다. 이에 따라 자바스크립트에서는 배열과 객체를 구분해서 사용한다. 그렇다면 배열은 객체와 무엇이 다를까? 가장 대표적인 특징들은 아래와 같다.
- 배열은 정렬된 값들의 나열(ordered list)이고, 객체는 키(문자열)-값으로 이루어진 정렬되지 않은 값들의 나열(unordered list)이다. 원하는 값을 찾기 위해서 배열에서는 0 이상의 정수를 통해 인덱스(순서)에 저장된 값에 접근하지만 객체는 문자열로 이루어진 임의의 열쇠(이름)을 통해 값을 찾는다. 이 부분에서 배열과 다른 일반적인 객체에서 근본적인 차이가 생긴다.
- 배열은 객체의 한 종류임에도 불구하고 자체적인 메서드가 내장되어 있는 "특별한" 존재다. (배열이 객체는 사용할 수 없는 .length를 사용할 수 있다는 점 등) 이는 배열이 프로토타입Prototype이라는 은닉(private) 속성을 가진 별도의 객체를 가지고 있다는 얘기다. Function, Object, Promise, Array, Number, String 등 모두 프로토타입을 가지고 있기 때문에 Object의 한 종류인 배열이 자체적인 프로토타입을 갖는 것은 꽤 이례적인 일이라고 생각한다.
MDN은 자바스크립트에서의 객체(Object)에 대해 "관련된 데이터와 함수의 집합"이라고 정의한다. 즉, 원시 자료형을 제외한 자바스크립트의 "대부분의 것들"이 객체라고 볼 수 있다. 이 수많은 객체들 중 별개의 독립성을 가진 존재가 배열이라고만 알고 있도록 하자. 그래도 배열이 있기 때문에 일반적인 객체가 해결할 수 없는 부분들도 해결할 수 있기 때문에, 임의의 키를 통해 속성에 접근할 필요가 없다면 (예를 들어 음식 주문 리스트) 배열을 적극 활용하는 것이 좋아 보인다.
참조
'Front-End > 자바스크립트 (JavaScript)' 카테고리의 다른 글
[자바스크립트] 스코프 (Scope) (0) | 2022.09.14 |
---|---|
[자바스크립트] 원시(Primitive) 자료형과 참조(Reference) 자료형 (1) | 2022.09.13 |
[JavaScript] 반복문 (for/while문) (0) | 2022.09.05 |
[JavaScript] 문자열 (String) (0) | 2022.08.30 |
[JavaScript] 조건문 (0) | 2022.08.30 |
댓글