코딩/Javascript

[JS-중급편-OOP] 13. JSON 완전 분석

드리프트 2021. 1. 3. 19:00
728x170

 

 

데이터 저장, 검색 또는 전송과 관련하여 사용할 수 있는 파일 형식과 데이터 구조가 많이 있습니다.

 

처리하는 다양한 종류의 데이터를 처리하기 위해 텍스트 파일, Word 문서, Excel 스프레드 시트, zip 파일 등을 사용했을 것입니다.

 

웹 세계에는 다른 모든 것보다 우위를 차지하는 하나의 형식이 있습니다.

 

이 형식은 JSON (JavaScript Object Notation의 약자)으로 알려져 있습니다.

 

이번 편에서는 JSON 객체를 만드는 모든 방법에 대해 알아볼 것입니다.

 

우리는 그 안에 무엇이 들어가는지, 그리고 값을 읽는 방법에 대해 자세히 살펴볼 예정입니다.

 

 

JSON 이란?

JavaScript에서는 "객체 리터럴 문법"을 사용하여 객체를 정의하는 방법이 있습니다.

 

let funnyGuy = {
    firstName: "Conan",
    lastName: "O'Brien",
 
    getName: function () {
        return "Name is: " + this.firstName + " " + this.lastName;
    }
};
 
let theDude = {
    firstName: "Jeffrey",
    lastName: "Lebowski",
 
    getName: function () {
        return "Name is: " + this.firstName + " " + this.lastName;
    }
};
 
let detective = {
    firstName: "Adrian",
    lastName: "Monk",
 
    getName: function () {
        return "Name is: " + this.firstName + " " + this.lastName;
    }
};

 

이 예제는 기존 강의에서 많이 봤던 익숙한 형태입니다.

 

표면적으로 객체 리터럴 문법은 객체의 속성과 값을 정의하는 괄호와 콜론, 이상한 중괄호가 뒤죽박죽 모인 것처럼 보입니다.

 

이상하게 보일지 모르지만, 내부적으로는 상당히 설명적입니다.

 

사용하려는 많은 공통 데이터 타입을 사용할 수 있습니다.

 

속성과 값을 콜론으로 구분된 키/값 쌍으로 깔끔하게 표현할 수 있습니다.

 

방금 언급 한 다른 모든 항목과 마찬가지로  이 방식을 사용하면 구조와 중첩된 값을 가질 수 있습니다.

 

전반적으로 JavaScript 객체를 문자 그대로 표현하는 매우 멋진 방법입니다!

 

JSON 형식은 이 객체 리터럴 문법을 많이 차용합니다.

 

다음은 시애틀의 날씨를 표시하기 위해 WeatherUnderground API에서 반환한 실제 JSON 데이터의 예입니다.

 

{
    "response": {
        "version": "0.1",
        "termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
        "features": {
            "conditions": 1
        }
    },
    "current_observation": {
        "image": {
            "url": "http://icons.wxug.com/graphics/wu2/logo_130x80.png",
            "title": "Weather Underground",
            "link": "http://www.wunderground.com"
        },
        "display_location": {
            "full": "Seattle, WA",
            "city": "Seattle",
            "state": "WA",
            "state_name": "Washington",
            "country": "US",
            "country_iso3166": "US",
            "zip": "98101",
            "magic": "1",
            "wmo": "99999",
            "latitude": "47.61167908",
            "longitude": "-122.33325958",
            "elevation": "63.00000000"
        },
        "observation_location": {
            "full": "Herrera, Inc., Seattle, Washington",
            "city": "Herrera, Inc., Seattle",
            "state": "Washington",
            "country": "US",
            "country_iso3166": "US",
            "latitude": "47.616558",
            "longitude": "-122.341240",
            "elevation": "121 ft"
        },
        "estimated": {},
        "station_id": "KWASEATT187",
        "observation_time": "Last Updated on August 28, 9:28 PM PDT",
        "observation_time_rfc822": "Fri, 28 Aug 2015 21:28:12 -0700",
        "observation_epoch": "1440822492",
        "local_time_rfc822": "Fri, 28 Aug 2015 21:28:45 -0700",
        "local_epoch": "1440822525",
        "local_tz_short": "PDT",
        "local_tz_long": "America/Los_Angeles",
        "local_tz_offset": "-0700",
        "weather": "Overcast",
        "temperature_string": "68.0 F (20.0 C)",
        "temp_f": 68.0,
        "temp_c": 20.0,
        "relative_humidity": "71%",
        "wind_string": "Calm",
        "wind_dir": "NNW",
        "wind_degrees": 331,
        "wind_mph": 0.0,
        "wind_gust_mph": "10.0",
        "wind_kph": 0,
        "wind_gust_kph": "16.1",
        "pressure_mb": "1008",
        "pressure_in": "29.78",
        "pressure_trend": "-",
        "dewpoint_string": "58 F (15 C)",
        "dewpoint_f": 58,
        "dewpoint_c": 15,
        "heat_index_string": "NA",
        "heat_index_f": "NA",
        "heat_index_c": "NA",
        "windchill_string": "NA",
        "windchill_f": "NA",
        "windchill_c": "NA",
        "feelslike_string": "68.0 F (20.0 C)",
        "feelslike_f": "68.0",
        "feelslike_c": "20.0",
        "visibility_mi": "10.0",
        "visibility_km": "16.1",
        "solarradiation": "--",
        "UV": "0",
        "precip_1hr_string": "0.00 in ( 0 mm)",
        "precip_1hr_in": "0.00",
        "precip_1hr_metric": " 0",
        "precip_today_string": "0.00 in (0 mm)",
        "precip_today_in": "0.00",
        "precip_today_metric": "0",
        "icon": "cloudy",
        "icon_url": "http://icons.wxug.com/i/c/k/nt_cloudy.gif",
        "nowcast": ""
    }
}

 

반환된 데이터의 크기를 무시하고 일단 앞에서 본 JSON 데이터와 객체 리터럴 문법간에 많은 유사점이 있습니다.

 

당신이 알아야 할 몇 가지 중요한 차이점이 있지만, 우리는 나중에 살펴볼 예정이고, 먼저 JSON 객체를 정확히 구성하는 요소에 대해 자세히 살펴보겠습니다.

 

 

JSON 객체 내부 탐색

JSON 객체는 속성 이름과 해당 값의 조합에 지나지 않습니다.

 

매우 간단해 보이지만 몇 가지 중요한 세부 정보가 있습니다.

 

속성 이름

속성 이름은 값에 액세스 하는 데 사용할 식별자입니다.

 

시각적 보면 콜론 문자 왼쪽에 있는 것입니다.

 

{
    "firstName": "Json",
    "lastName": "Bourne",
    "special": {
        "admin": true,
        "userID": 203
    },
    "devices": [
        {
            "type": "laptop",
            "model": "Macbook Pro 2015"
        },
        {
            "type": "phone",
            "model": "iPhone 6"
        }
    ]
}

 

이 JSON 스니펫(snippet)에서 속성 이름은 firstName, lastName, special, admin, userID, devices, type 및 model입니다.

 

속성 이름이 어떻게 정의되는지 보십시오. 따옴표로 묶인 문자열 값입니다.

 

속성 이름은 객체 리터럴 문법에서 중요한 세부 정보이므로 JSON을 이용해서 작업할 때 절대 따옴표를 포함하는 것을 잊지 마십시오!

 

 

각 속성 이름은 값에 매핑되며 그 값이 될 수 있는 타입(type)은 다음과 같습니다.

 

  • 숫자(Numbers)
  • 문자열(Strings)
  • 불리언(true or false)
  • 객체(Objects)
  • 배열(Arrays)
  • Null

이러한 다양한 타입을 앞서 살펴본 예제에 매핑해 보겠습니다.

 

 

문자열(Strings)

문자열 값은 다음과 같이 표시됩니다.

 

{
    "firstName": "Json",
    "lastName": "Bourne",
    ...
    ...
    "devices": [
        {
            "type": "laptop",
            "model": "Macbook Pro"
        },
        {
            "type": "phone",
            "model": "iPhone XS"
        }
    ]
}

 

큰 따옴표는 값이 문자열이라는 사실을 알려줍니다.

 

일반적인 문자, 숫자 및 기호 외에도 \', \", \\, \와 같은 이스케이프 문자를 포함할 수 있습니다.

 

 

숫자(Numbers)

아래 예에서 userID 속성의 값이 바로 숫자(numbers)입니다.

 

{
...
...
        "userID": 203
...
...
}

소수 값 (예 : 0.204, 1200.23, 45)과 지수 값 (2e16, 3e 4, 1.5e-2)을 모두 지정할 수 있습니다.

 

하지만 알아야 할 몇 가지 단점이 있습니다.

 

숫자 앞에 0과 다른 숫자를 붙일 수 없습니다.

 

예를 들어 03.14 값은 허용되지 않습니다.

 

 

불리언(Booleans)

불리언 값은 쉽습니다.

 

{
...
        "admin": true,
...
}

 

값은 true 또는 false 일 수 있습니다.

 

한 가지 주목할 점은 대소문자가 중요하다는 것입니다.

 

true와 false는 모두 소문자여야 합니다.

 

대소문자 구분 (True 또는 False)을 사용하거나 모두 대문자 (TRUE 또는 FALSE)를 사용하는 것은 금지됩니다.

 

 

객체(Objects)

객체는 약간 흥미롭습니다.

 

{
...
    "special": {
        "admin": true,
        "userID": 203
    },
    "devices": [
        {
            "type": "laptop",
            "model": "Macbook Pro"
        },
        {
            "type": "phone",
            "model": "iPhone XS"
        }
    ]
}

 

객체에는 속성 이름 및 값 모음이 포함되며 중괄호("{ }")로 나머지 콘텐츠와 구분됩니다.

 

 

배열(Arrays)

아래 예를 보면 "devices" 속성 값이 바로 배열입니다.

 

{
...
    "devices": [
        {
            "type": "laptop",
            "model": "Macbook Pro"
        },
        {
            "type": "phone",
            "model": "iPhone XS"
        }
    ]
}

 

배열은 반복할 수 있는 0개 이상의 값의 정렬된 컬렉션을 저장하며 대괄호"[ ]" 표기법으로 구분됩니다.

 

배열 내에서 다른 배열을 포함하여 사용할 수도 있습니다.

 

 

Null

마지막 데이터 타입인 null입니다. 가장 간단합니다.

 

{
    "foo": null
}

 

JSON 값은 null 일 수 있습니다. 

 

이것은 빈 값을 나타냅니다.

 

 

 

 

 

JSON 데이터 읽기

지금까지는 조금 지루한 면이 없진 않았지만 본격적인 JSON 공부에 들어가 보겠습니다.

 

어쨌든 JSON과의 모든 상호 작용은 데이터 읽기를 중심으로 이루어집니다.

 

JSON 데이터를 읽을 때 명심해야 할 점은 일반적인 JavaScript 객체에 저장된 값을 읽는 것과 매우 유사하다는 것입니다.

 

원하는 값 (property.propertyFoo)에 점을 찍거나 배열 접근 방식 (property ["propertyFoo"])을 사용하여 값에 액세스 할 수 있습니다.

 

이 모든 것을 설명하기 위해 다음 예제를 사용하겠습니다.

 

let exampleJSON = {
  "firstName": "Json",
  "lastName": "Bourne",
  "special": {
      "admin": true,
      "userID": 203
  },
  "devices": [
      {
          "type": "laptop",
          "model": "Macbook Pro"
      },
      {
          "type": "phone",
          "model": "iPhone XS"
      }
  ]
};

 

firstName으로 저장된 값을 읽으려면 다음과 같은 방식으로 읽을 수 있습니다.

 

exampleJSON.firstName
exampleJSON["firstName"]

 

위의 두 코드 모두 "Json"이라는 값을 반환합니다.

 

읽어야 하는  값에 접근하기 위해 점 표기법을 사용하든 배열 방법을 사용하든 무엇이 더 좋은 방법인지는 상관없습니다.

 

편한 방식을 사용하면 됩니다.

 

그러나 자바스크립트 세계에서 모두가 선호하는 것은 점 표기법을 사용하는 것입니다.

 

앞에서 본 것과 비슷하게 lastName에 저장된 값에 액세스 하려면 다음과 같이 하면 됩니다.

 

exampleJSON.lastName

 

단순히 값을 저장하는 속성의 경우 사용법은 매우 간단합니다.

 

그러나 객체와 배열로 구성된 더 복잡한 값으로 작업할 때 약간 어려울 수 있습니다.

 

Object 내부에 저장된 값을 읽으려면 그 값을 저장하는 속성에 도달할 때까지 각 속성에 계속 점을 찍으십시오.

 

userID 속성에 저장된 값에 액세스 하려는 시도는 다음과 같습니다.

 

exampleJSON.special.userID

 

배열도 다르지 않지만 배열 값을 저장하는 속성에 도달하면 결국 배열 표기법으로 전환해야 합니다.

 

"devices" 배열에 있는 첫 번째 장치의 모델 값에 액세스 하려면 다음과 같이 입력할 수 있습니다.

 

exampleJSON.devices[0].model

 

devices 속성은 배열을 참조하기 때문에 다음과 같은 전형적인 배열 작업을 수행할 수도 있습니다.

 

let devicesArray = exampleJSON.devices;

for (let i = 0; i < devicesArray.length; i++) {
  let type = devicesArray[i].type;
  let model = devicesArray[i].model;

  // do something interesting with this data!
}

 

지금까지 배운 것을 되돌아보면 JSON 값은 문자열, 숫자, 객체, 배열, 부울린 또는 null 일 수 있습니다.

 

JSON 객체 내에서는 주어진 데이터 타입에 대해 JavaScript가 지원하는 모든 것을 쉽게 활용할 수 있습니다.

 

 

JSON 같이 생긴 데이터를 진정한 JSON 값으로 파싱 하기

위에서는 JSON 데이터는 exampleJSON 변수 내에 깔끔하게 정의되었습니다.

 

우리가 다루는 것이 JSON 문법을 따르는 실제 JS 객체라는 사실은 의심할 여지가 없습니다.

 

실제 프로젝트를 할 때는 항상 그런 것만은 아닙니다.

 

JSON 데이터는 다양한 소스에서 올 수 있으며 모든 소스가 JSON 데이터를 우리가 본 실행 가능한 형식으로 반환하지는 않습니다.

 

많은 사람들이 JSON 데이터를 원시 텍스트로 반환합니다.

 

JSON 객체처럼 보이지만 실제 JSON 객체로 작업할 때처럼 데이터와 상호 작용할 수 없습니다.

 

이를 처리하기 위해 "가짜" JSON 데이터를 인수로 사용하는 JSON.parse 메서드가 있습니다.

 

function processRequest(e) {
    if (xhr.readyState == 4 && xhr.status == 200) {
        let response = JSON.parse(xhr.responseText);
        selectInitialState(response.region);
    }
}

 

위 코드 세 번째 줄에서 볼 수 있듯이 JSON.parse 메서드는 우리가 다양한 소스에서 얻은 JSON 모양같이 생긴 데이터(xhr.responseText)를 실제 JSON 객체(response)로 변환합니다.

 

외부 소스에서 데이터를 가져올 때는 안전을 위해 항상 JSON.parse 메서드를 사용해야 합니다.

 

 

JSON 데이터로 저장하기

JSON 데이터를 파일에 저장하거나 웹 서비스로 작업을 수행할 때 JSON 데이터를 저장해야 하는 경우가 생깁니다.

 

이러한 작업 은 아마 당신이 Node에서 개발하거나 JavaScript 이외의 프로그래밍 언어로 코드를 작성할 때입니다.

 

Node 작업은 향후 강좌에서 다루도록 하겠습니다.

 

 

결론

JSON이 유명해지기 전에 인터넷에서는 XML을 주로 사용했었습니다.

 

오늘날에도 XML은 정보를 저장하거나 전달하기 위한 파일 형식으로 널리 사용되고 있습니다.

 

웹 브라우저가 왕인 세상(우리가 살고 있는 세상)에서만 JSON이 매우 인기가 있습니다.

 

그렇다고 다른 상황에서 JSON이 존재하지 않는다는 의미는 아닙니다.

 

웹 및 비 웹 상황 모두에 대한 앱 구성은 데이터를 나타내는 방식으로 JSON을 점점 더 많이 사용하고 있습니다.

 

이제는 웹 브라우저에서 모든 걸 다 하는 세상이니까요.

 

다음 편에서는 "Set" 타입에 대해 간단히 알아보겠습니다.

 

 

그리드형