기록의 습관화
article thumbnail

웹 개발을 하다 보면 Json을 수도 없이 마주치게 되는데요

요번 글에서는 Json에 대해서 좀 더 깊이 알아보고

이를 파싱할 수 있는 Parser까지 만들어보는 포스트를 1, 2 편에 나눠서 다뤄보려고 합니다.

그럼 일단 Json에 대해서 알아볼까요?

Json 이란?

Json 이란 경량화된 데이터 교환 방식으로 JavaScript Object Notation의 약자입니다.
사람이 읽고 쓰기 쉽고, 기계가 파싱하고 생성하기 편리하다는 장점을 가지고 있죠.

Json은 JS의 언어의 부분적인 서브셋으로 ECMAScript의 표준 사양인 ECMA-262에 정의되어 있습니다.
Json은 2000년대 초반에 개발되었고 XML이나 YAML과 같은 기존의 데이터 표현 방식에 대한 대안으로 제안되었습니다.

XML 태그의 경우 여는 태그와 닫는 태그가 필요하고 속성과 값이 별도로 필요하고
YAML 문법의 경우 들여 쓰기를 사용하여 데이터 구조를 표현하며 문법이 간소하지만 
이 들여쓰기 때문에 몇 번씩 문제를 일으키곤 하죠(Docker 파일을 작성하거나 github action 코드를 작성해 보신 분들은 공감하실 겁니다..)

이 이유 외에도 웹개발에서 많이 사용되는 JS에서 이 JSON 형식을 완벽하게 지원하고
서버 간 네트워크 통신에서도 데이터의 교환에서 직렬화와 역직렬화가 용이합니다.

또한 기본 데이터 유형인 문자열, 숫자, 불리언, 배열 및 객에 대한 지원을 제공하고
필요에 따라 사용자 정의 데이터 유형을 정의도 가능하죠. 이를 통해 복잡한 데이터 구조를 표현하고 다양한 
응용 프로그램에서 사용할 수 있습니다.

특징적으로 key : value의 형태로 이루어져 있으며 값이 될 수 있는 형태는 다음과 같습니다.

  1. Number
  2. String
  3. Boolean
  4. Array
  5. Object
  6. null

가장 많이 사용되는 곳은 아무래도 서버와의 데이터 통신 이겠죠?

{
    "hasNext": false,
    "contents": [
        {
            "bookmarkId": 3,
            "title": "스프링 쌈싸먹기1",
            "url": "https://naver.com1",
            "isUserLike": true
        },
        {
            "bookmarkId": 2,
            "title": "리액트 쌈싸먹기",
            "url": "https://google.com",
            "isUserLike": true
        }
    ]
}

또한 JS를 통해 개발을 하다 보면 다음과 같이 많이 Json을 stringfy 하거나 parse 해서 사용하게 되죠.

 

하지만 개발을 하다 보면 

  1. 객체의 key를 항상 큰따옴표로 감싸야한다.("key")
  2. 객체나 배열 끝에는 콤마를 남길 수 없다.
  3. key와 value는 : 를 이용해서 표현한다. ("key" : "value")

와 같은 제약 조건들이 저희를 귀찮게 만드는 경우가 종종 있죠...

만약 위의 JSON의 예제에서 쌍 따옴표 중 하나만 이라도 홀 따옴표로(')로 바꾸게 되면 이는 잘못된 JSON이라고 판단을 하여

오류가 나게 됩니다.

그럼 이들은 어떻게 이루어져 있을까요?

 

JSON에 대해서 좀 더 자세히 알아보기

JSON의 경우 다음의 문서에 잘 설명이 되어 있습니다.

https://www.json.org/json-ko.html

 

JSON

JSON (JavaScript Object Notation)은 경량의 DATA-교환 형식이다. 이 형식은 사람이 읽고 쓰기에 용이하며, 기계가 분석하고 생성함에도 용이하다. JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1

www.json.org

글에 나온 JSON에 대한 특징들을 살펴볼까요?

 

object

  1. object는 name/vlaue의 비순서화된 SET이다.
  2. object는 { 좌 중괄호로 시작하고 } 우 중괄호로 끝이 난다.
  3. 각 name 뒤에는 : (colon)을 붙인다.
  4. , (comma)를 이용해서 name/value를 구분한다.

array

  1. array는 순서화된 collection이다.
  2. array는 [ (left bracket)으로 시작해서 ] (right bracket)로 끝난다.
  3. , (comma)를 이용해서 array의 값들을 구분한다.

value

  1. value는 큰따옴표 안에 string, number, true, false, null, object, array가 올 수 있다.

string

  1. string은 큰따옴표 안에 둘러 싸인 zero 이상의 Unicode 문자들의 조합이다.
  2. 큰따옴표 안에 감싸지며 backslash escape가 적용된다 (\)
  3. 하나의 문자(character)도 하나의 문자열로서 표현된다.
  4. string은 C 또는 Java 문자열과 매우 비슷하다.

number

  1. 8진수와 16진수 형식을 사용하지 않는 것을 제외하면 C와 Java number와 비슷하다.

whitespace

  1. 토큰의 경우 어떤 쌍 사이에 공백을 삽입할 수 있다.

 

json 표기

문서에서 보실 수 있듯이 JSON은 특정한 규칙을 가지고 있습니다.

그리고 우리는 이들을 좀 더 이해하기 쉬운 형태로 가져갈 수 있는데요 여기서 이용할 수 있는 것이 

배커스-나우르 표기법(Backus-Naur Form, BNF)입니다.

 

그렇다면 배커스-나우스 표기법 이란 무엇일까요?

배커스 -나우스 표기법(BNF)

배커스 나우스 표기법 일명 BNF는 컴퓨터 과학에서 사용되는 메타 문법입니다.

프로그래밍 언어의 문법을 정의하는 데 주로 사용되고 이 표기법은 1960년대 존 배커스와 피터 나우르에 의해 개발되었죠.

 

BNF는 언어의 문법을 설명하는 데 사용되는 기호와 규칙들의 집합으로 이루어져 있습니다.

BNF는 문법을 정의하는 데 사용되는 표기법으로, 각 문법 규칙은 일련의 토큰 또는 다른 규칙에 의에 정의된 심볼들을 생성하는 방법을 설명합니다.

 

그렇다면 예시를 한 번 볼까요?

 

<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
<number> ::= <digit> | <digit> <number>

위의 코드를 보면 두 개의 규칙이 있는 걸 알 수 있습니다.

 

  1. <digit>이라는 심볼을 이용해 0 ~ 9까지의 숫자 중 하나로 대체 될 수 있음
  2. <number>라는 심볼이 하나의 <digit> 이거나 <digit> 뒤에 <number>가 따르는 형태를 가질 수 있음

이것을 우리는 JSON을 이해하는 데 사용할 수 있습니다.

 

BNF를 JSON에 이용해 보기

아까 위에서 JSON의 특성과 JSON 문서

에서 보았던 특징들을 BNF로 표현하면 아래와 같습니다.

<JSON> ::= <element>
<value> ::= <string> | <number> | <object> | <array> | "true" | "false" | "null"
<element> ::= <string> ":" <value>
<elements> ::= <element> | <element> "," <elements>
<object> ::= "{" <elements> "}" | "{}"
<array> ::= "[" <values> "]" | "[]"
<values> ::= <value> | <value> "," <values>
  • <JSON>은 하나의 <element>로 시작합니다.
  • <value>는 <string>, <number>, <object>, <array>, "true", "false", "null" 중 하나입니다.
  • <element>는 <string>과 <value>를 콜론(:)으로 연결한 것입니다.
  • <elements>는 하나의 <element>이거나, <element> 뒤에 콤마(,)와 다른 <elements>가 따르는 형태입니다.
  • <object>는 중괄호({}) 안에 <elements>가 들어가거나, 비어있는 중괄호({})입니다.
  • <array>는 대괄호([]) 안에 <values>가 들어가거나, 비어있는 대괄호([])입니다.
  • <values>는 하나의 <value>이거나, <value> 뒤에 콤마(,)와 다른 <values>가 따르는 형태입니다.

저희는 이걸 좀 더 쉬운 이해의 형태로 가져가기 위해 기찻길 다이어그램 형태로 나타낼 수 있습니다.

몇 개를 바꿔서 볼까요?

 

  • value

value에 대한 기찻길 다이어그램

  • object

object 형태의 기찻길 다이어그램

  • array

array 형태의 기찻길 다이어그램

그럼 Js는 이를 어떻게 구현했을까?

저희가 JS 진영에서 흔히 사용하게 되는 

JSON.stringfy, JSON.parse의 경우는 v8 엔진의 c++로 구현이 되어 있습니다.

const json = JSON.stringify({
	name: "ww8007",
	job: "developer",
	hobby: ["coding", "reading", "music"]
});

const parse = JSON.parse(json);

 

 

관심 있는 분들은 아래 링크에서 내용을 확인하실 수 있습니다.

https://github.com/v8/v8/tree/main/src/json

 

GitHub - v8/v8: The official mirror of the V8 Git repository

The official mirror of the V8 Git repository. Contribute to v8/v8 development by creating an account on GitHub.

github.com

 

그럼 저희도 저희만의 Json 파서를 안 만들어 볼 수 없겠죠?

더 나아가 기존의 parse에서 지원해주지 않던 유틸 기능들을 넣어볼 수도 있습니다.

다음 포스트에서는 AST 추상 구문 트리와 저희만의 JSON 파서를 만들어보는 글을 다뤄보겠습니다 😃

profile

기록의 습관화

@ww8007

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!