Tutorial/JavaScript

자바스크립트 기초 마스터

by @webs 2024. 06. 01.
02.

자바스크립트 배우기 : 데이터 불러오기

소개

안녕하세요! 웹스토리보이입니다. 이 강의는 자바스크립트 초급부터 고급까지 아우르는 자바스크립트 핵심 개념을 다루는 기본서 강의입니다. 일반적인 자바스크립트 강의와는 목표와 방식이 다릅니다. 여기에서는 자바스크립트를 어떻게 단순하게 이해하고, 현실적으로 활용할 수 있는지를 고려하여 만들어진 내용입니다.

자바스크립트를 배우면서 때로는 이해하기 어려운 부분이나 무엇을 해야 하는지 혼란스러운 부분이 있을 수 있습니다. 그런 어려움을 극복하고 불필요한 시간 낭비를 줄이기 위해 이 강의는 차별화된 접근 방식을 채택하였습니다. 또한, 개인적으로도 어려움을 겪었던 부분들을 고려하여 설명하였습니다.

이 강의의 주요 목표는 자바스크립트를 학습하면서, 이론 뿐만 아니라 실제로 어떻게 활용할 수 있는지를 강조하는 것입니다. 이를 위해 강의는 크게 네 가지 주요 영역으로 구성되었습니다. 데이터 저장, 데이터 불러오기, 데이터 실행, 그리고 데이터 제어입니다. 이렇게 체계적으로 기초를 다지고 나서 실제 상황에 유용하게 활용할 수 있는 실용적인 예제를 다룰 것입니다. 이를 통해 프로그래밍 실력을 크게 향상시킬 수 있는 기회를 가지게 될 것입니다. 이 강의를 통해 자바스크립트의 세계에 더욱 가깝게 다가갈 수 있길 바랍니다.

인덱스

데이터 불러오기

자바스크립트에서 데이터 저장만큼 중요한 것은 저장된 데이터를 불러오고 활용하는 것입니다. 프로그래밍에서 데이터를 저장하는 것은 시작에 불과하며, 저장된 데이터를 효과적으로 불러오고 그 데이터를 기반으로 다양한 연산을 수행하거나 사용자에게 정보를 제공하는 것이 핵심적인 작업입니다. 자바스크립트는 이러한 작업을 수행할 수 있는 다양한 방법과 도구를 제공합니다.

자바스크립트에서는 배열이나 객체와 같은 복잡한 데이터 구조를 사용하여 여러 개의 데이터를 저장하고 관리할 수 있습니다. 배열은 순서가 있는 데이터 집합을 저장하는데 사용되며, 객체는 키와 값의 쌍으로 데이터를 저장하는데 사용됩니다. 이러한 복잡한 데이터 구조에서도 데이터를 불러오는 방법은 변수에서 데이터를 불러오는 것과 유사합니다. 배열에서는 인덱스를 사용하여 특정 위치의 데이터에 접근할 수 있으며, 객체에서는 키를 사용하여 데이터에 접근할 수 있습니다.

데이터 불러오기는 프로그래밍에서 매우 중요한 작업입니다. 저장된 데이터를 효과적으로 활용하는 것은 웹 페이지의 동적인 요소를 제어하는 것부터, 사용자 입력을 처리하고 데이터를 분석하는 복잡한 서버 측 애플리케이션을 개발하는 것에 이르기까지, 모든 프로그래밍 작업의 핵심적인 부분입니다. 자바스크립트를 통해 이러한 작업을 수행하는 방법을 배우는 것은 프로그래밍 능력을 키우는 데에 있어 매우 중요한 단계입니다.

01. 변수 : 데이터 불러오기

변수에 저장된 데이터를 불러옵니다.

{
        let x = 100, y = 200, z = "javascript";   // 변수를 선언하고 값을 할당

        console.log(x);     // 100 
        console.log(y);     // 200
        console.log(z);     // javascript  
}   

변수에 할당된 값들이 출력됩니다.

  • console.log(x); → 변수에 할당된 숫자 100이 출력됩니다.
  • console.log(y); → 변수에 할당된 숫자 200이 출력됩니다.
  • console.log(z); → 변수에 할당된 문자 javascript가 출력됩니다.
02. 상수 : 데이터 불러오기

상수에 저장된 데이터를 불러옵니다.

{
        const x = 100, y = 200, z = "javascript";   // 상수를 선언하고 값을 할당

        console.log(x);     // 100 
        console.log(y);     // 200
        console.log(z);     // javascript  
}   

상수에 할당된 값들이 출력됩니다.

  • console.log(x); → 변수에 할당된 숫자 100이 출력됩니다.
  • console.log(y); → 변수에 할당된 숫자 200이 출력됩니다.
  • console.log(z); → 변수에 할당된 문자 javascript가 출력됩니다.
03. 배열 : 데이터 불러오기

배열에 저장된 데이터를 불러옵니다.

{
        const arr = [100, 200, "javascript"];       // 배열을 선언하고 초깃값을 할당

        console.log(arr[0]);     // 100 
        console.log(arr[1]);     // 200
        console.log(arr[2]);     // javascript  
}   

배열을 생성하고, 초기 값으로 정수 100, 200 및 문자열 "javascript"를 할당합니다.

  • console.log(arr[0]); → 배열의 첫 번째 요소에 할당된 숫자 100이 출력됩니다.
  • console.log(arr[1]); → 배열의 두 번째 요소에 할당된 숫자 200이 출력됩니다.
  • console.log(arr[2]); → 배열의 세 번째 요소에 할당된 문자 javascript가 출력됩니다.
04. 배열 : 데이터 불러오기 : 갯수

배열에 저장된 데이터의 갯수를 불러옵니다.

{
        const arr = [100, 200, "javascript"];

        console.log(arr.length);    // 3
}   

배열의 length 속성을 사용하여 배열의 길이를 확인하는 방법을 보여줍니다. 배열의 길이란 배열에 저장된 요소의 총 수를 의미합니다. 배열에는 세 개의 요소가 있으므로, 콘솔에는 3이 출력됩니다.

  • console.log(arr.length); → 배열에는 세 개의 요소가 있으므로, 3이 출력됩니다.
05. 배열 : 데이터 불러오기 : for

배열에 저장된 데이터의 for문을 통해 불러옵니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        for(let i=0; i<arr.length; i++){     // for 루프를 이용한 배열 순회
                console.log(arr[i]);
        }

        // 100
        // 200
        // 300
        // 400
        // 500
}   

자바스크립트에서 배열의 요소에 접근하고, 반복문을 사용해 배열을 효율적으로 다루는 기본적인 방법입니다. 이 방식은 배열 처리에 매우 일반적으로 사용되며, 다양한 상황에서 배열의 데이터를 처리할 때 기본이 되는 패턴입니다.

  • (let i=0; i<arr.length; i++) → (초깃값 설정; 조건식 설정; 증감값 설정)
  • (초깃값 설정) let i=0; → 시작값 변수를 설정합니다. i는 0에서 시작합니다. 이는 배열의 첫 번째 요소 인덱스를 의미합니다.
  • (조건식 설정) i<arr.length; → 조건을 설정합니다. 루프의 조건은 i가 arr.length (배열의 길이, 즉 5) 미만일 때까지 반복되도록 설정됩니다. 이 조건을 통해 배열의 모든 요소를 순회할 수 있습니다.
  • (증감값 설정) i++ → 증가값을 설정합니다. 각 반복 후에 i는 1씩 증가하여 다음 요소의 인덱스로 이동합니다.
  • console.log(arr[i]); → 현재 인덱스 i에 있는 배열 요소를 콘솔에 출력합니다. 루프가 각 반복을 거치면서, arr 배열의 각 요소 (100, 200, 300, 400, 500)가 순서대로 콘솔에 출력됩니다.
반복문

반복문은 컴퓨터 프로그래밍에서 코드 블록을 조건이 충족될 때까지 반복적으로 실행하기 위해 사용되는 제어 구조입니다. 다양한 종류의 반복문이 있으며, 각각의 사용법과 적용 범위가 조금씩 다릅니다. 자바스크립트에서 가장 흔히 사용되는 세 가지 반복문은 for, while, do...while입니다. 이 부분은 제어하기 파트에서 자세하게 다룹니다.

  • for 문 : for 문은 반복 횟수가 명확할 때 주로 사용됩니다. 초기식, 조건식, 증감식으로 구성되어 있으며, 이러한 세 부분을 통해 반복의 시작, 조건, 그리고 반복 각 사이클 후의 변화를 정의합니다.
  • while 문 : while 문은 특정 조건이 참인 동안 계속해서 코드 블록을 반복 실행합니다. 조건은 반복문 진입 전과 각 반복의 끝에 평가됩니다.
  • do...while 문 : do...while 문은 최소 한 번 코드가 실행된 후에 조건을 평가하는 반복문입니다. 이는 조건이 거짓일지라도 코드 블록이 최소 한 번은 실행된다는 것을 보장합니다.
06. 배열 : 데이터 불러오기 : for of

배열에 저장된 데이터를 for of 루프를 통해 불러옵니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        for(let element of arr){        // for...of 반복문
                console.log(element); 
        } 

        // 100
        // 200
        // 300
        // 400
        // 500
}   

for...of는 JavaScript에서 반복문을 사용하여 배열, 문자열 등과 같은 객체의 요소를 반복적으로 순회할 때 사용하는 루프입니다. for...of 반복문은 자바스크립트에서 데이터의 컬렉션을 처리할 때 매우 유용하며, 배열을 순회하거나 데이터를 가공하는 등의 작업에 자주 사용됩니다.

  • for...of 구문 → 배열의 각 요소를 변수 element에 할당하고, 배열의 끝에 도달할 때까지 이 과정을 반복합니다. element 변수는 반복마다 배열의 다음 요소를 자동으로 참조합니다.
  • console.log(element) → 현재 참조된 배열 요소의 값을 콘솔에 출력합니다. 반복문이 실행될 때마다 배열의 각 요소 (100, 200, 300, 400, 500)가 차례대로 출력됩니다.
for...of를 사용하는 이유는??
  • 간결성 : for...of는 for 반복문의 전통적인 인덱스 접근 방식보다 코드가 더 간결하고 이해하기 쉽습니다.
  • 직관성 : 배열의 요소를 직접적으로 다루므로, 인덱스를 사용하여 요소에 접근하는 것보다 오류를 줄이고 코드의 가독성을 높일 수 있습니다.
  • 범용성 : 모든 종류의 반복 가능한 객체에 사용할 수 있어, 배열뿐만 아니라 문자열, Map, Set 등에도 사용될 수 있습니다.
07. 배열 : 데이터 불러오기 : for in

배열에 저장된 데이터를 for in 루프를 통해 불러옵니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        for(let element in arr){    
                console.log(arr[element]);    // 100 200 300 400 500
        } 

        for(let element in arr){
                console.log(element + " : " + arr[element]);    // 0:100 1:200 2:300 3:400 4:500 
        }        
}   

for...in 반복문을 사용하여 배열을 순회하는 방법입니다. for...in 반복문은 주로 객체의 속성을 순회할 때 사용되지만, 배열의 인덱스를 순회하는 데에도 사용될 수 있습니다.

  • console.log(arr[element]) → 현재 인덱스에 해당하는 배열 요소의 값을 콘솔에 출력합니다. 따라서 출력 결과는 배열의 각 요소인 100, 200, 300, 400, 500입니다.
  • console.log(element + " : " + arr[element]) → 이 구문은 인덱스와 해당 인덱스의 요소 값을 문자열로 연결하여 콘솔에 출력합니다. 출력 결과는 0:100, 1:200, 2:300, 3:400, 4:500으로, 각 인덱스와 그에 해당하는 값이 콜론(:)으로 구분되어 나타납니다.
for...of와 for...in의 차이점

for...of은 배열을 위한 반복문이며, for...in은 객체를 위한 반복문입니다. 하지만 for...in에서도 배열을 사용할 수 있습니다. 만약 배열에서 사용한다면 몇 가지 주의점이 있습니다. 아래와 같은 이유로, 배열을 순회할 때는 보통 for...of 반복문이나 전통적인 for 반복문을 사용하는 것이 더 권장됩니다. for...of 반복문은 배열의 요소에 직접 접근하며, 순서가 보장되고 성능도 더 우수합니다.

  • for...in은 배열의 인덱스를 문자열 형태로 반환합니다.
  • 배열이 아닌 객체의 프로퍼티까지 순회할 수 있으므로, 배열에 추가된 사용자 정의 속성이 있을 경우 그 속성도 순회 대상에 포함될 수 있습니다.
  • 배열의 인덱스가 숫자가 아닌 문자열로 처리되므로, 순서가 보장되지 않을 수 있고 성능이 느릴 수 있습니다.
08. 배열 : 데이터 불러오기 : forEach()

배열에 저장된 데이터를 forEach() 메서드를 통해 불러옵니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        // 01. 요소 출력
        arr.forEach(function(element){
                console.log(element);   // 100 200 300 400 500
        }); 

        // 02. 인덱스 출력
        arr.forEach(function(element, index){
                console.log(index);     // 0 1 2 3 4
        });

        // 03. 전체 배열 출력
        arr.forEach(function(element, index, array){
                console.log(array);     // [100, 200, 300, 400, 500] * 5
        });
}   

Array.prototype.forEach() 메서드를 사용하여 배열의 요소를 순회하는 방법입니다. forEach() 메서드는 배열의 각 요소에 대해 제공된 함수를 한 번씩 실행합니다. 이 메서드는 배열을 빠르고 간단하게 반복 처리할 수 있는 방법을 제공하며, 보다 선언적인 접근 방식을 가능하게 합니다. forEach의 ()안에는 요소(element), 인덱스(index), 배열(array) 값을 출력할 수 있습니다.

  • 01. 요소 출력 → 배열의 각 요소를 출력합니다. 100 200 300 400 500
  • 02. 인덱스 출력 → 배열의 각 인덱스를 출력합니다. 0 1 2 3 4
  • 03. 전체 배열 출력 → 배열의 각 요소를 처리할 때마다 전체 배열을 출력합니다. [100, 200, 300, 400, 500] * 5
09. 배열 : 데이터 불러오기 : map()

배열에 저장된 데이터를 map() 메서드를 통해 새로운 배열을 생성합니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        const newArr = arr.map(function(element){       // 각 요소에 대해 콜백 함수를 실행합니다.
            return element + 50;                       // 각 요소에 50을 더하고 새로운 배열에 저장합니다.
        });

        console.log(newArr);  // 새 배열 출력 [150, 250, 350, 450, 550] 
}   

Array.prototype.map() 메서드를 사용하여 배열을 순회하고 각 요소에 대해 함수를 적용하는 방식을 보여줍니다. map() 메서드는 각 요소에 함수를 적용한 결과를 새 배열로 반환합니다. 이 메서드는 원본 배열을 변경하지 않고, 각 요소를 주어진 함수의 반환 값으로 매핑하여 새 배열을 생성하는 데 사용됩니다.

  • 배열 초기화 → arr 변수에는 [100, 200, 300, 400, 500]이라는 초기값이 할당됩니다.
  • map() 메서드 적용 → arr 배열에 .map() 메서드를 적용합니다. 이 메서드는 배열의 각 요소를 차례로 콜백 함수에 전달합니다.
  • 콜백 함수 실행 → 콜백 함수는 각 요소(element)에 50을 더한 값을 반환합니다. 즉, 배열의 각 요소를 가져와 그 값에 50을 더한 후, 그 결과를 새 배열에 저장합니다.
  • 결과 출력 → 최종적으로 console.log(newArr);을 통해 변형된 새로운 배열을 콘솔에 출력합니다. 출력되는 배열은 [150, 250, 350, 450, 550]입니다. 이는 원래 배열 arr의 각 요소에 50을 더한 결과입니다.
콜백함수란?

콜백 함수는 다른 함수에 인수로 전달되는 함수입니다. 이 함수는 외부 함수에 의해 "호출 되돌림(call back)"이라는 이름의 유래대로, 외부 함수의 실행 중 특정 지점에서 호출됩니다.

좀 더 쉽게 설명하면 → 콜백 함수는 한 함수가 실행을 마치고 난 후에 호출되는 또 다른 함수입니다. 더 쉽게 말해 → 콜백 함수는 일종의 순서를 정하는 역할을 합니다. 하나의 작업이 끝나면 그 다음에 무엇을 할지 결정해주는 함수라고 생각할 수 있습니다. 이러한 구조는 일을 차례대로 진행하게 만들어, 한 번에 하나의 작업만 수행되도록 도와줍니다.

콜백함수는 다음의 경우에 많이 사용됩니다.

  • 이벤트 처리 → 특정 이벤트 발생 시 실행될 함수를 지정할 때
  • 배열 메서드 → 다른 함수를 인수로 받거나 함수를 결과로 반환할 때
  • 비동기 실행 → 네트워크 요청이 완료된 후 특정 코드를 실행하려 할 때

이 예제에서 사용된 기능은 고차 함수의 일례입니다. 콜백 함수에 대한 보다 자세한 내용은 다음 섹션 데어터 제어하기에서 자세히 다루게 됩니다. 현재는 기본적인 이해만 갖고 계시면 충분합니다.

10. 배열 : 데이터 불러오기 : filter()

배열에 저장된 데이터를 filter() 메서드를 통해 특정 조건을 만족하는 새로운 배열을 생성합니다.

{
        const arr = [100, 200, 300, 400, 500];      // 배열을 선언하고 초깃값을 할당

        const newArr = arr.filter(function(element){       // 각 요소에 대해 콜백 함수를 실행합니다.
            return element > 200;                       // 각 요소가 200보다 큰지 검사하여 조건에 맞으면 새로운 배열에 저장합니다.
        });

        console.log(newArr);  // 새 배열 출력 [300, 400, 500] 
}   

Array.prototype.filter() 메서드는 배열에서 특정 조건을 만족하는 요소들만 골라내서 새로운 배열을 만듭니다. 원본 배열은 그대로 유지하고, 조건에 맞는 요소들만 모아 새 배열을 생성합니다. 쉽게 말해, 원하는 조건에 맞는 아이템들만 추려내는 역할을 합니다.

  • 배열 초기화 → arr 변수에 [100, 200, 300, 400, 500]라는 값들이 할당되어 있습니다.
  • filter() 메서드 적용 → arr 배열에 .filter() 메서드를 적용합니다. 이 메서드는 배열의 각 요소를 차례로 콜백 함수에 전달합니다.
  • 콜백 함수의 조건 검사 → 콜백 함수는 각 요소(element)가 200보다 큰지를 검사합니다. element > 200 조건을 만족하는 요소만 true를 반환하고, 이 요소들은 새로운 배열 newArr에 포함됩니다.
  • 결과 출력 → 최종적으로 console.log(newArr);을 통해 새로운 배열을 콘솔에 출력합니다. 출력되는 배열은 [300, 400, 500]으로, 이는 원래 배열 arr에서 200을 초과하는 요소들만 모아 만든 새로운 배열입니다.
고차함수란?

고차 함수(Higher-Order Function)는 다른 함수를 인수로 받거나 함수를 결과로 반환하는 함수를 말합니다. 이 개념은 함수형 프로그래밍 패러다임에서 중요한 역할을 합니다. 고차 함수를 사용함으로써 코드의 재사용성을 높이고, 모듈성을 개선하며, 복잡한 작업을 더 간단하게 처리할 수 있습니다.

좀 더 쉽게 설명하면 → 자바스크립트 메서드 안에 들어있는 또 다른 함수라고 보면 됩니다. 콜백 함수에서 많이 쓰이는 유형중에 하나입니다. 사실 이름이 어려울 뿐 예시를 보면 전혀 어럽지 않습니다. 그냥 누군가가 이름만 고차원적으로 만들었다고 보면 됩니다.

자바스크립트에서는 다음과 같은 고차 함수들이 흔히 사용됩니다.

  • Array.prototype.map(): 배열의 각 요소에 주어진 함수를 적용하고, 결과로 새 배열을 반환합니다.
  • Array.prototype.filter(): 주어진 판별 함수를 만족하는 모든 요소로 새 배열을 생성하여 반환합니다.
  • Array.prototype.reduce(): 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
11. 배열 : 데이터 불러오기 : 배열 펄침 연산자

배열에 저장된 데이터를 펼침 연산자(Spread Operator)를 통해 불러옵니다.

{
        // 01 복사
        const arr = [100, 200, 300];   
        const copy = [...arr];          // 펼침 연산자를 사용하여 배열의 모든 요소를 복사하여 새 배열을 생성
        
        console.log(arr);       // 원본 배열 출력: [100, 200, 300]
        console.log(...arr);    // 원본 배열의 요소를 개별적으로 출력: 100, 200, 300
        console.log(copy);      // 복사된 배열 출력: [100, 200, 300]

        // 02 합치기
        const arr1 = [100, 200];         
        const arr2 = [300, 400];      
        const merged1 = [...arr1, ...arr2];     // 두 배열의 요소를 합쳐 새로운 배열을 생성
        const merged2 = [...arr1, 250, ...arr2, 450]; // 새로운 속성을 추가

        console.log(merged1);   // [100, 200, 300, 400]
        console.log(merged2);   // [100, 200, 250, 300, 400, 450]

        // 03 함수 인자로 사용
        function numbers(a, b, c) {     // 세 개의 매개변수를 받는 함수를 정의
            return a + b + c;       // 세 매개변수의 합을 반환
        }
        
        const nums = [100, 200, 300];       // 매개변수로 사용할 배열을 선언
        console.log(numbers(...nums));      // 펼침 연산자를 사용하여 nums 배열의 각 요소를 개별 매개변수로 함수에 전달하고 결과를 출력 : 600
}   

배열 펼침 연산자(Spread operator)는 JavaScript에서 ... 세 개의 점으로 표현되며, 배열이나 객체의 요소들을 개별 요소로 펼치는데 사용됩니다. 이 연산자는 ES6에서 도입되었으며, 배열 또는 함수 호출에서 인자 리스트를 간편하게 사용하거나 객체 리터럴에서 속성을 복사할 때 유용하게 사용됩니다.

  • 01 배열 복사 → 배열을 복사할 때 사용합니다.
  • 02 배열 합치기 → 배열을 합칠 때 사용할 수 있으며, 속성을 추가할 수 있습니다.
  • 03 함수 인자로 사용 → 함수가 여러 개의 인자를 받을 때, 배열을 인자로 쉽게 넘길 수 있습니다.
배열 펼침 연산자를 사용하는 이유는?

펼침연산자는 ES6(ECMAScript 2015)에 도입된 자바스크립트의 중요한 기능 중 하나입니다. 최신 자바스크립트 문법을 사용함으로써, 코드를 보다 간결하고, 읽기 쉽게 만들며, 다양한 작업을 효율적으로 처리할 수 있게 해줍니다.

  • 가독성과 간결성 향상 : 펼침연산자를 사용하면 복잡한 표현식이나 메서드 호출 대신 간단한 문법으로 배열이나 객체의 요소를 처리할 수 있습니다. 코드의 양을 줄이고, 의도를 더 명확하게 전달할 수 있습니다.
  • 배열 병합과 복사 : 펼침연산자는 배열을 병합하거나 복사할 때 concat() 함수나 반복문 없이 간단히 할 수 있도록 해줍니다. 이는 코드를 단순화시키며, 실수할 여지를 줄여줍니다.
  • 함수 인자 처리 : 함수에 배열을 인자로 전달할 때, 배열의 각 요소를 개별 인자로 쉽게 분리할 수 있습니다. 이는 함수가 가변적인 수의 인자를 받아야 할 때 매우 유용합니다.
  • 불변성 유지 : 자바스크립트에서는 불변성(Immutability)이 중요한 개념 중 하나입니다. 객체나 배열을 직접 변경하지 않고, 새로운 객체나 배열을 생성하여 상태를 관리하는 것이 좋습니다. 펼침연산자를 사용하면 기존의 배열을 변경하지 않고 새로운 배열을 생성할 수 있어, 불변성을 유지하는 데 도움이 됩니다.
  • 동적 요소 추가 : 펼침연산자를 이용하면 배열이나 객체에 동적으로 요소를 추가하는 작업을 매우 간편하게 할 수 있습니다. 이는 코드를 동적으로 구성할 필요가 있을 때 유용합니다.
  • 문자열을 배열로 변환 : 문자열을 배열로 쉽게 변환할 수 있습니다. 문자열의 각 문자를 배열의 요소로 분리할 때 유용하게 사용됩니다.
12. 배열 : 데이터 불러오기 : 배열 구조 분해 할당

배열에 저장된 데이터를 배열 구조 분해 할당(Array Destructuring)을 통해 불러옵니다.

{
        // 01: 기본 구조 분해 할당
        let arr = [100, 200, 300];  
        let [a, b, c] = arr;        // 배열 arr의 요소를 각각 변수 a, b, c에 할당합니다.

        console.log(a);     // 100
        console.log(b);     // 200
        console.log(c);     // 300 

        // 02: 배열 리터럴을 사용한 구조 분해
        let [a2, b2, c2] = [100, 200, 300];     // 배열 리터럴의 요소를 직접 변수 a2, b2, c2에 할당합니다.

        console.log(a2);     // 100
        console.log(b2);     // 200
        console.log(c2);     // 300

        // 03: 기본값 설정
        let [a3, b3, c3 = 300] = [100, 200];    // 변수 c3에 기본값 300을 설정하며, 할당된 배열에 세 번째 요소가 없으므로 기본값 사용

        console.log(a3);     // 100
        console.log(b3);     // 200
        console.log(c3);     // 300

        // 04: 특정 요소 무시
        let [a4, , c4] = [100, 200, 300];    // 두 번째 요소는 무시하고, 첫 번째와 세 번째 요소만 변수 a4와 c4에 할당  

        console.log(a4);    // 100
        console.log(c4);    // 300

        // 05: 나머지 요소 수집(+펼침연산자)
        let [a5, b5, ...rest] = [100, 200, 300, 400];   // 처음 두 요소는 각각 a5, b5에 할당하고, 나머지 요소를 배열 rest에 할당

        console.log(a5);        // 100 
        console.log(b5);        // 200
        console.log(...rest);   // 300, 400

        // 06: 변수의 값 교환
        let a6 = 100, b6 = 200;   // 배열 구조 분해를 사용하여 변수 a6과 b6의 값을 서로 교환
        [a6, b6] = [b6, a6];        

        console.log(a6);    // 200
        console.log(b6);    // 100

        // 07: 중첩 배열 구조 분해
        let [a7, [b7, c7]] = [100, [200, 300]];    // 중첩 배열에서 첫 번째 요소를 a7에, 두 번째 배열의 요소를 b7과 c7에 할당 

        console.log(a7);     // 100
        console.log(b7);     // 200
        console.log(c7);     // 300
}   

배열 구조 분해 할당은 JavaScript의 강력한 기능 중 하나로, 배열의 요소들을 변수에 쉽고 직관적으로 할당할 수 있게 해줍니다. ES6에서 도입된 이 기능은 코드를 더 깔끔하고 읽기 쉽게 만들어 줍니다. 각 예제는 배열 구조 분해 할당을 통해 배열의 요소들을 변수에 할당하는 다양한 방식을 보여줍니다. 이를 통해 코드의 유연성과 가독성을 높일 수 있습니다

배열 구조 분해 할당을 사용하는 이유는?

배열 구조 분해 할당(Destructuring assignment)은 자바스크립트에서 데이터를 다루는 데 있어 매우 유용합니다. 이를 통해 코드의 복잡성을 줄이고, 유지 관리를 용이하게 할 수 있습니다.

  • 가독성 향상: 코드가 간결해지고 읽기 쉬워져, 어떤 데이터가 어떻게 사용되는지 쉽게 파악할 수 있습니다.
  • 코드 단순화: 여러 값을 한 번에 변수에 할당할 수 있어, 반복적인 코드를 줄일 수 있습니다.
  • 유연성: 필요한 데이터만 쉽게 선택하여 추출할 수 있고, 함수에서 여러 값을 반환할 때도 유용합니다.
  • 기본값 설정: 존재하지 않는 데이터에 대해 기본값을 설정할 수 있어, 오류를 방지하고 코드를 안정적으로 만듭니다.
  • 나머지 요소 활용: 배열의 일부만 변수에 저장하고 나머지를 다른 변수에 쉽게 담을 수 있습니다.
13. 객체 : 데이터 불러오기 : 기본

객체에 저장된 데이터를 불러옵니다.

{
        const obj = {       // 객체 obj를 선언하고 초기화합니다.
                a: 100,
                b: 200,
                c:"javascript"
        }
                
        console.log(obj.a);     // 100
        console.log(obj.b);     // 200
        console.log(obj.c);     // javascript   

        // 대괄호 표기법을 사용
        console.log(obj["a"]);      // 100  
        console.log(obj["b"]);      // 200
        console.log(obj["c"]);      // javascript
}   

이 코드는 자바스크립트에서 객체를 선언하고 데이터에 접근하는 가장 기본적인 예시를 보여줍니다. 객체에는 점 표기법이 가장 자주 사용되며, 이를 통해 객체의 속성 값을 쉽게 읽을 수 있습니다. 대괄호 표기법은 상황에 따라 유용할 수 있지만, 일반적으로는 점 표기법이 더 흔히 사용됩니다. 대괄호 표기법에 대해서는 필요할 때 사용할 수 있다는 정도로 이해하시면 좋을 것 같습니다.

14. 객체 : 데이터 불러오기 : Object.keys()

객체에 저장된 데이터의 키 값을 배열로 불러옵니다.

{
        const obj = {       // 객체 obj를 선언하고 초기화합니다.
                a: 100,
                b: 200,
                c:"javascript"
        }
        console.log(Object.keys(obj));      // ["a", "b", "c"]     
}   

Object.keys() 메서드는 객체의 모든 열거 가능한 속성 이름들을 문자열의 배열로 반환합니다. 이 배열을 console.log()를 통해 콘솔에 출력함으로써, 우리는 객체의 모든 키를 쉽게 볼 수 있습니다. 이 방식은 객체의 구조를 파악하거나, 특정 프로세스를 실행하기 전에 필요한 속성을 확인할 때 특히 유용합니다.

15. 객체 : 데이터 불러오기 : Object.values()

객체에 저장된 데이터의 속성 값을 배열로 불러옵니다.

{
        const obj = {       // 객체 obj를 선언하고 초기화합니다.
                a: 100,
                b: 200,
                c:"javascript"
        }
        console.log(Object.values(obj));    // ["100", "200", "javascript"]    
}   

Object.values() 메서드는 객체의 모든 값들을 배열로 반환합니다. Object.values() 메서드를 사용하면 객체 내의 모든 값을 쉽게 추출할 수 있어, 데이터 처리나 검증 작업에 유용하게 사용될 수 있습니다.

16. 객체 : 데이터 불러오기 : Object.entries()

객체에 저장된 데이터의 속성들을 키와 값으로 불러옵니다.

{
        const obj = {       // 객체 obj를 선언하고 초기화합니다.
                a: 100,
                b: 200,
                c:"javascript"
        }
        console.log(Object.entries(obj));   // [["a", 100],["b", 200],["c", "javascript"]]
}   

Object.entries() 메서드는 객체의 모든 속성과 그 값들을 [키, 값] 쌍의 배열로 반환합니다. Object.entries() 메서드는 데이터를 키-값 쌍으로 쉽게 처리하고 싶을 때 특히 유용하며, 이 메서드를 사용하면 객체를 배열로 변환하여 for...of와 같은 반복문으로 쉽게 순회하거나 다른 형태의 데이터 구조로 재구성할 수 있습니다.

17. 객체 : 데이터 불러오기 : Object.assign()

객체에 저장된 여러개의 데이터를 병합하고 수정된 객체를 반환합니다.

{
        const obj1 = {
                a: 100,
                b: 200,
        };
        const obj2 = {
                b: 300,
                c: 400,
        };
        const result = Object.assign(obj1, obj2);

        console.log(result);      // {a: 100, b: 300, c: 400}
        console.log(obj1);      // obj1도 변경되어 {a: 100, b: 300, c: 400}이 됩니다.
        console.log(obj2);      // {b: 300, c: 400}
}   

Object.assign() 메서드를 사용하면 간단하게 여러 객체의 속성을 하나의 객체로 합칠 수 있으며, 특히 설정 객체를 합칠 때 유용합니다. 이 방법은 객체의 깊은 복사(deep copy)를 제공하지 않는다는 점에 주의해야 합니다. 속성 값이 객체인 경우 참조가 복사되기 때문에, 복사된 객체와 원본 객체가 같은 객체를 참조하게 됩니다.

Object.assign()은 객체를 간편하게 병합하고 수정하는 작업을 지원하지만, 깊은 복사나 불변성을 보장하기 위해서는 추가적인 조치가 필요합니다.

얕은 복사? 깊은 복사?

얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)는 프로그래밍에서 객체를 복제할 때 사용되는 두 가지 주요 방법입니다. 이 두 방법은 복제된 객체와 원본 객체 간의 참조 관계와 복제의 범위에 따라 구분됩니다.

얕은 복사 (Shallow Copy) → 얕은 복사는 객체의 최상위 속성만 복사합니다. 즉, 복사된 객체의 최상위 속성은 원본 객체의 해당 속성과 동일한 값을 가지지만, 이 속성이 참조형 데이터(예: 다른 객체, 배열 등)를 가리킬 경우, 복사된 객체와 원본 객체는 그 참조형 데이터를 공유합니다. 이 때문에 한 객체에서 참조형 데이터를 수정하면 다른 객체에도 영향을 미칩니다.

let original = {
        a: 1,
        b: { c: 2 }
};
let shallowCopy = Object.assign({}, original);

shallowCopy.b.c = 3; // 원본 객체의 b.c도 3으로 변경됩니다.
console.log(original.b.c); // 출력: 3

깊은 복사 (Deep Copy) → 깊은 복사는 객체의 모든 계층을 재귀적으로 복사하여, 복사된 객체와 원본 객체 간의 완전히 독립적인 복제본을 만듭니다. 이 방식에서는 원본 객체의 참조형 데이터도 새로운 메모리 위치에 복제되므로, 한 객체에서 참조형 데이터를 수정해도 다른 객체에는 영향을 주지 않습니다.

let original = {
        a: 1,
        b: { c: 2 }
};
let deepCopy = JSON.parse(JSON.stringify(original));

deepCopy.b.c = 3; // 원본 객체의 b.c는 변경되지 않습니다.
console.log(original.b.c); // 출력: 2
  • 얕은 복사 → 데이터 구조가 간단하거나, 참조된 객체를 공유해도 문제가 없을 때 사용합니다.
  • 깊은 복사 → 원본 객체와 완전히 독립적인 복사본이 필요할 때 사용합니다, 예를 들어 복잡한 객체 구조에서 독립적인 수정이 필요할 경우에 적합합니다.
18. 객체 : 데이터 불러오기 : hasOwnProperty()

객체에 저장된 데이터의 존재 여부를 확인합니다.

{
        const obj = {
                a: 100,
                b: 200,
                c:"javascript"
        }
        console.log(obj.hasOwnProperty("a"));       // true
        console.log(obj.hasOwnProperty("b"));       // true
        console.log(obj.hasOwnProperty("c"));       // true
        console.log(obj.hasOwnProperty("d"));       // false

        // in 연산자
        console.log("a" in obj);    // true
        console.log("b" in obj);    // true
        console.log("c" in obj);    // true
        console.log("d" in obj);    // false
}   

hasOwnProperty() 메서드는 JavaScript에서 객체가 특정 속성을 자신의 속성으로 가지고 있는지를 확인하는 데 사용됩니다. 이 메서드는 객체가 상속받은 속성이 아닌, 직접 정의된 속성을 확인할 때 유용합니다. hasOwnProperty() 메서드와 in 연산자 두 방법 모두 객체에 특정 속성이 있는지 확인하는 데 사용되지만, hasOwnProperty()는 객체의 직접 속성만 검사하고, in 연산자는 객체의 프로토타입 체인에 있는 속성도 검사합니다. 이 차이점을 이해하면 두 방법을 적절히 사용할 수 있습니다.

19. 객체 : 데이터 불러오기 : for in

객체에 저장된 데이터를 for in 루프를 통해 불러옵니다.

{
        const obj = {
                a: 100,
                b: 200,
                c: "javascript"
        }
        for(let el in obj){     // obj 객체의 모든 열거 가능한 속성을 순회합니다.
                console.log(el + " : " + obj[el]);      // 각 속성의 이름과 값을 콘솔에 출력합니다.
        }

        // a: 100
        // b: 200
        // c: "javascript"
}   

"for...in" 반복문을 사용하여 객체(obj)의 속성을 순회하면서 각 속성의 이름과 값을 출력하는 것을 확인할 수 있습니다. 이를 통해 객체의 속성을 동적으로 처리하거나 객체의 내용을 탐색할 때 유용하게 사용할 수 있습니다.

20. 객체 : 데이터 불러오기 : 객체 펼침 연산자

객체에 저장된 데이터를 펼침 연산자 통해 불러옵니다.

{
        // 01 복사
        const obj = { a: 100, b: 200 };
        const copy = { ...obj };

        console.log(copy);      // { a: 100, b: 200 }

        // 02 합치기
        const obj1 = { a: 100, b: 200 };
        const obj2 = { c: 300, d: 400 };
        const merged = { ...obj1, ...obj2 };

        console.log(merged);    // {a: 100, b: 200, c: 300, d: 400}

        // 03 속성 추가
        const obj3 = { a: 100, b: 200 };
        const merged2 = { ...obj3, c: 300 };

        console.log(merged2);    // {a: 100, b: 200, c: 300}

        // 04 속성 덮어쓰기
        const obj4 = { a: 100, b: 200 };
        const merged3 = { ...obj4, b: 300 };

        console.log(merged2);    // {a: 100, b: 300}
}   

객체 펼침 연산자를 사용하여 객체를 복사하고 병합하며, 속성을 추가하거나 덮어쓰는 방법입니다.

  • 객체 복사: 객체의 모든 속성을 새로운 객체에 복사.
  • 객체 합치기: 여러 객체의 속성을 하나의 객체로 병합.
  • 속성 추가: 기존 객체에 새로운 속성을 추가하여 새로운 객체 생성.
  • 속성 덮어쓰기: 기존 객체의 특정 속성을 덮어써서 새로운 객체 생성.
배열 펼침 연산자 vs 객체 펼침 연산자

배열 펼침 연산자와 객체 펼침 연산자는 JavaScript에서 배열과 객체를 다루는 작업을 더 간편하게 만들기 위해 도입된 기능입니다. 두 연산자는 모두 ... 세 개의 점으로 표현되며, 배열 또는 객체의 요소를 개별적으로 펼치는데 사용됩니다. 두 연산자는 JavaScript의 데이터 구조를 더 유연하고 직관적으로 다룰 수 있게 해주며, 코드의 가독성과 유지보수성을 향상시킵니다.

  • 배열 펼침 연산자 → 배열의 요소를 개별적으로 분리하여 다른 배열이나 함수의 인자로 전달할 수 있습니다. 이는 배열을 복사하거나 합치고, 함수 호출 시 여러 인자를 편리하게 전달할 때 유용합니다.
  • 객체 펼침 연산자 → 객체의 속성을 다른 객체로 복사하거나 병합할 때 사용됩니다. 이를 통해 객체를 간편하게 복사하거나 병합하고, 새로운 속성을 추가하거나 기존 속성을 덮어쓸 수 있습니다.
21. 객체 : 데이터 불러오기 : 객체 구조 분해 할당

객체에 저장된 데이터를 구조 분해 할당을 통해 불러옵니다.

{
        // 01 기본
        const obj1 = {
                a: 100,
                b: 200,
        }
        const { a, b } = obj1;

        console.log(a);     // 100
        console.log(b);     // 200

        // 02 변수 이름 변경하기
        const obj2 = {
                a: 100,
                b: 200,
        }
        const { a: name1, b: name2 } = obj2;

        console.log(name1);     // 100
        console.log(name2);     // 200

        // 03 기본값 설정 
        const obj3 = {
                a: 100,
                b: 200,
        }
        const { a, b, c = 300 } = obj3;

        console.log(a);     // 100
        console.log(b);     // 200
        console.log(c);     // 300

        // 04 중첩 객체 분해 
        const obj3 = {
                a: 100,
                b: {
                        c: 200,
                        d: 300
                }
        }
        const { a, b: { c, d } } = obj3;

        console.log(a);     // 100
        console.log(c);     // 200
        console.log(d);     // 300

        // 05 함수 매개변수에서 사용
        function func({ a, b }) {
                console.log(a, b);
        }

        const obj4 = {
                a: 100,
                b: 200,
        }

        func(obj4);     // 100 200
}   

객체 구조 분해 할당은 객체의 속성을 개별 변수에 쉽게 할당할 수 있게 하여 코드를 더 간결하고 읽기 쉽게 만들어줍니다. 이를 통해 변수를 빠르게 초기화하고, 함수 매개변수로 객체를 다룰 때 더욱 유용하게 사용할 수 있습니다. 또한, 기본값 설정과 변수 이름 변경, 중첩 객체 분해 등의 다양한 기능을 제공합니다.

  • 01 기본 사용법 → 기본 사용 방법입니다.
  • 02 변수 이름 바꾸기 → 객체의 속성을 다른 이름의 변수로 할당할 수 있습니다.
  • 03 기본값 설정 → 객체에 속성이 없을 때 기본값을 설정할 수 있습니다.
  • 04 중첩 객체 분해 → 객체의 속성이 또 다른 객체일 때 중첩 구조 분해를 사용할 수 있습니다.
  • 05 함수 매개변수에서 사용 → 함수의 매개변수로 객체 구조 분해 할당을 사용할 수 있습니다.
배열 구조 분해 할당 vs 객체 구조 분해 할당

배열 구조 분해 할당과 객체 구조 분해 할당은 모두 JavaScript에서 데이터 구조를 다루는 데 유용한 도구입니다. 두 방식 모두 데이터를 더 쉽게 추출하고, 코드를 간결하고 명확하게 만들어줍니다. 하지만, 그 사용 방법과 적용되는 데이터 구조는 다릅니다.

  • 배열 구조 분해 할당 → 배열의 요소를 개별 변수에 할당하며, 기본값 설정과 나머지 요소 수집, 값 교환 등의 다양한 기능을 제공합니다.
  • 객체 구조 분해 할당 → 객체의 속성을 개별 변수에 할당하며, 변수 이름 변경, 기본값 설정, 중첩 객체 분해 등의 다양한 기능을 제공합니다.
비교 항목 배열 구조 분해 할당 객체 구조 분해 할당
데이터 구조 순서가 있는 배열 키-값 쌍으로 이루어진 객체
할당 방식 인덱스 순서에 따라 할당 속성 이름에 따라 할당
변수 이름 지정 순서에 따라 임의로 지정 가능 속성 이름과 동일하거나 이름 변경 가능
기본값 설정 가능 가능
나머지 요소 수집 가능 (...rest 문법 사용) 가능 (...rest 문법 사용)
중첩된 구조 분해 불가능 가능
사용 예 배열에서 특정 요소 추출 객체에서 특정 속성 추출
복잡한 데이터 구조 다루기 비교적 간단한 구조에서 유용 복잡한 객체 구조를 쉽게 다룰 수 있음
22. 파일 : 데이터 불러오기 : JSON

JSON은 데이터 교환 형식의 파일입니다.

{
        // 01 JSON 데이터 --> 객체 변환
        const jsonString = '{ "name": "Hwang", "age": 30}';
        const jsonObject = JSON.parse(jsonString);

        console.log(jsonObject.name);   // Hwang
        console.log(jsonObject.age);    // 30
    
    
        // 02 객체 파일 --> JSON 데이터
        const person = { name: "Hwang", age: 30 }
        const jsonString = JSON.stringify(person);

        console.log(jsonString);    // {"name":"Hwang","age":30}                    
}   

JSON (JavaScript Object Notation)은 경량 데이터 교환 형식으로, 사람이 읽고 쓰기 쉽고 기계가 해석하고 생성하기 쉬운 구조를 가지고 있습니다. JSON은 자바스크립트 객체 표기법을 기반으로 하지만, 프로그래밍 언어에 독립적이며 대부분의 현대 언어에서 지원됩니다.

  • 간단한 문법: JSON은 키-값 쌍으로 데이터를 표현합니다. 키는 항상 문자열로, 값은 문자열, 숫자, 객체, 배열, 불리언 또는 null일 수 있습니다.
  • 경량: 간결한 형식으로 인해 데이터 전송 시 부담이 적습니다.
  • 언어 독립적: 대부분의 프로그래밍 언어에서 쉽게 파싱하고 생성할 수 있습니다.
  • 자바스크립트와의 호환성: 자바스크립트 객체 표기법을 기반으로 하여 자바스크립트 환경에서 특히 유리합니다.
23. 서버 : 데이터 불러오기 : XMLHttpRequest

서버에 저장된 데이터를 XMLHttpRequest 객체를 통해 가져옵니다.

{
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "https://webstoryboy.github.io/webs2024/json/gineungsaJC2011_05.json", true);
        
        xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                        var responseData = xhr.responseText;
                        var jsonData = JSON.parse(responseData);
    
                        console.log(jsonData);
                } else if (xhr.readyState === 4) {
                        console.error("데이터 불러오기 오류: " + xhr.status);
                }
        };
        
        xhr.send();      
}   

웹에서 JSON 데이터를 비동기적으로 가져오는 XMLHttpRequest 객체를 사용하는 예제입니다.

  • XMLHttpRequest 객체 생성 → XMLHttpRequest 객체를 생성합니다. 이 객체를 사용하여 웹 리소스와 상호작용할 수 있습니다.
  • XMLHttpRequest 객체 설정 → "GET": HTTP 요청 방식을 지정합니다. 이 경우 GET 요청을 사용합니다. URL: 데이터를 가져올 웹 리소스의 URL을 지정합니다. true: 비동기적 요청을 사용하도록 지정합니다. 즉, 요청이 백그라운드에서 실행되고 응답을 기다리지 않습니다.
  • XMLHttpRequest 이벤트 리스너 설정 → onreadystatechange 이벤트 핸들러를 설정합니다. 이 핸들러는 XMLHttpRequest 객체의 상태가 변경될 때마다 호출됩니다. 상태가 변경될 때마다 이벤트 핸들러 함수가 실행됩니다.
  • 상태 변경 감지 → xhr.readyState 속성을 사용하여 XMLHttpRequest 객체의 현재 상태를 확인합니다. xhr.status 속성을 사용하여 HTTP 상태 코드를 확인합니다. xhr.readyState === 4: 상태 4는 요청이 완료되었음을 나타냅니다. xhr.status === 200: HTTP 상태 코드 200은 요청이 성공적으로 처리되었음을 나타냅니다.
  • 성공적인 응답 처리 → 요청이 성공하면, xhr.responseText를 사용하여 서버로부터 받은 JSON 문자열 데이터를 가져와 JSON.parse()를 사용하여 JavaScript 객체로 파싱합니다. 그리고 파싱된 데이터를 콘솔에 출력합니다.
  • 오류 처리 → 요청이 실패하면, 콘솔에 오류 메시지를 출력합니다. 오류 메시지에는 HTTP 상태 코드도 포함됩니다.
24. 서버 : 데이터 불러오기 : fetch API

서버에 저장된 데이터를 fetch API를 통해 가져옵니다.

{
        fetch("https://webstoryboy.github.io/webs2024/json/gineungsaJC2011_05.json")
                .then(response => {
                        return response.json();
                })
                .then(data => {
                        console.log(data);
                })
                .catch(error => {
                        console.error("데이터 불러오기 오류: ", error);
                });
}   

비동기적으로 원격 서버에서 JSON 데이터를 가져오고, 성공 또는 실패에 따라 적절한 처리를 수행합니다. Fetch API는 간결하고 더 간편한 구문을 제공하여 데이터를 가져오는 프로세스를 단순화하므로 많은 개발자에게 선호되는 방법 중 하나입니다.

  • fetch 함수 호출 → fetch 함수를 호출하여 지정된 URL에서 데이터를 가져오기 위한 요청을 시작합니다. 이 URL은 JSON 데이터가 있는 웹 리소스를 가리킵니다.
  • Promise 체이닝 → .then() 함수를 사용하여 Promise 체이닝을 구성합니다. fetch 함수는 Promise를 반환하며, 요청이 완료되면 then 블록이 실행됩니다.
  • 첫 번째 then 블록 → 첫 번째 then 블록에서는 서버로부터의 응답을 처리합니다. response 객체를 받아와서 response.json()을 호출하여 JSON 데이터를 추출하고 JavaScript 객체로 변환합니다. 이 부분은 response.json()이 반환하는 Promise를 반환합니다.
  • 두 번째 then 블록 → 두 번째 then 블록에서는 JSON 데이터가 JavaScript 객체로 성공적으로 변환된 경우, 이 데이터를 콘솔에 출력합니다.
  • catch 블록 → catch 블록은 Promise 체인 중 어떤 위치에서든 오류가 발생하면 실행됩니다. 이 블록에서는 오류 메시지와 함께 오류를 콘솔에 출력합니다.