Study Home

'웹을 지탱하는 기술' 4회차 스터디

JSON

JSON(JavaScript Object Notation)은 데이터를 기술하기 위한 언어다. JavaScript의 기법으로 데이터를 기술할 수 있다. 심플해서 다른 언어로도 라이브러리로써 제공이 되고 많이 활용이 되고 있다.
JSON의 미디어 타입은 application/json입니다.

Content-Type: application/json; charset=utf-8

JSON 파일의 확장자는 .json 이다.

JSON에 6가지의 자료형이 있다.

  • object
  • array
  • string
  • number
  • boolean
  • null

object는 이름과 값의 집합이고 그 집합을 member이라고 한다. member의 이름은 무조건 문자열이고 member의 값은 위 6개 중 아무거나 된다.

{
    name: {
        first: 'gibong'
        last: 'yim'
    }
        age: 30
        isAlive: true
        placeTraveled: [ 'America', 'China', 'SouthEast Asia']
        friends: null
}

등으로 작성을 할 수 있다.

시간을 표현할 때 Unix 시간으로 시간을 표현하는데 이는 UTC(Universal Time Coordinate)인 1970년 1월 1일 시점부터 어느 정도 시간이 지났는지 나타낸다. 나라마다 시간이 다르므로 이것으로 표현하고 나중에 따로 각 국가의 GMT로 설정을 하든가 한다.

Ajax에서 이용하는 XMLHttpRequest라는 JavaScript 모듈은 보안상의 제한으로 인하여 서버와 통신할 때는 하나의 동일한 서버와 통신할 수밖에 없었다. 크로스 도메인 통신이 안되었다. 그래서 보안 제한을 받지 않는 <script> 요소를 써서 이 문제를 대처하였다. 이러한 방법으로 JSONP를 써서 CORS를 형성한다. CORS는 Cross-Origin Resource Sharing의 약자다. 위에 말했듯이 브라우저는 크로스 도메인 통신을 보안상 막는데 CORS 방식으로 헤더에 브라우저에게 다른 도메인의 정보들을 가져오게 한다.

리소스 설계

리소스 설계란 클라이언트와 서버 간 인터페이스의 설계이다. 웹 서비스와 웹 API의 외부설계이다. 어떻게 리소스를 분할하고, URI로 이름을 붙이고, 상호 링크를 가지게 할지가 리소스 설계의 악심이다.

리소스 설계할 때 리소스 지향 아키텍처

  • 웹 서비스에서 제공할 데이터를 특정한다.
  • 데이터를 리소스로 나눈다.
  • 리소스에 URI로 이름을 부여한다.
  • 클라이언트에 제공할 리소스의 표현을 설계한다.
  • 링크와 폼을 이용해 리소스와 리소스를 연결한다.
  • 이벤트의 표준적인 코스를 검토한다.
  • 에러에 대한 검토한다

리소스란 웹상에 존재하는 이름이 부여된 정보이다.
리소스는 URI로 이름을 부여를 할 수 있다.
예를 들어서 정보를 한곳에 저장하고 그 URI를 ”…/data/124125”로 하면 그 정보들은 124125라는 식별 문의 붙여진다, 고로 이름 부여가 된다.

클라이언트에 제공할 리소스의 표현할 때 많은 방법이 있다. 독자 XML, XHTML, Atom, Json, YAML, CSV, multimedia 등이 있다. 하나의 리소스가 복수의 포맷을 지원하면 좋다. XHTML은 XML을 이용하여 HTML 4.0.1을 새로 만든 독립 언어이다. 현제는 HTML5 가 대세이므로 굳이 쓸 필요가 없다. Json은 내용이 함축적으로 최소한의 정보만을 가지고 있다. 그렇기 때문에 XML에 비해 용량이 줄어들고 그만큼 빠른 속도를 가지게 된다. 언어에 독립적이며, 사용하기가 쉽다. YAML은 읽기 쉽고 쓰기도 편하고 한글과 같은 유니코드를 그대로 사용할 수 있다. CSV는 ”,”로 모든 것을 분리하므로 읽기 소프트웨어를 쓸 때 좋다.

링크와 폼을 이용해 리소스와 리소스를 연결할 때는 보통 XML은

<a href= "http://....">...</a>

로 표현하고

JSON 같은 경우에는

"link": "http://..."

로한 다.

이벤트의 표준적인 코스를 검토할 때 폼에 입력값을 입력해서 원하는 리소스를 취득하면 된다. 그리고 에러가 뜰 때를 생각해서 404, 400, 405 등을 에러에 따라 반환하는 작업을 해야 한다.

쓰기 가능한 웹 서비스의 설계

읽기 전용과 달리 쓰기는 조금 더 고려할 사항이 있다. 예를 들어서 동시 수정 같은 것들을 어떻게 처리해야 할지 고민을 해봐야 한다.

리소스 작성할 때 팩토리 리소스에 POST 혹은 PUT이 있다. 팩토리 리소스는 리소스를 작성하기 위한 특별한 리소스이다. 사전 준비된 리소스에 POST로 새로운 리소스를 추가한다. PUT은 새로 작성하고 싶은 리소스의 URU에 직접 요청을 보냅니다. 이러한 방법은 POST를 지원하지 않아도 되고 클라이언트가 작성과 변경을 구별할 필요가 없어서 서버 측의 구현이 간단해진다. 단 클라이언트가 URI 구조를 미리 알아야 하고 신규 작성인지 갱신인지 모른다.

리소스 갱신할 때는 PUT으로 수행하고 일괄 갱신은 POST로 한다. 그러나 요즘은 PATCH로 갱신을 한다.

PUT /999999 HTTP/1.1
Host: ...
Content-Type: application/json

{
    "zipcode":"99999"
    "address":{
        "prefecture":"a",
        "city":"b",
        "town":"c"
    },
    "hhi":{
        "prefecture":"aaa"
        "city":"bbb"
        "town":"ccc"
    }
}

이런 코드에서 한 줄 바꿔서 보내면 벌크 업데이트라고 한다. 아니면 아래처럼 한 줄만 바꿔서 보내는 게 파설 업데이트다

PUT /999999 HTTP/1.1
Host: ...
Content-Type: application/json

    "hhi":{
        "prefecture":"ㅁㅁㅁ"
        "city":"ㅠㅠㅠ"
    }

갱신할 수 없을 때를 고려해서 반환값을 지정해 주는 것도 좋다.

리소스 삭제는 삭제하고 싶은 리소스의 URI에 delete를 보내서 삭제를 하면 된다. 그리고 일반적으로 부모 리소스에 소속된 자식 리소스는 부모 리소스가 삭제되면 따라서 삭제가 된다. 리소스를 일괄 처리할 시에는 post를 쓰고 다 붙여서 쓰면 된다.

PUT /999999 HTTP/1.1
Host: ...
Content-Type: application/json

{
    "zipcode":"99999",
    "address":{
        "prefecture":"a",
        "city":"b",
        "town":"c"
    },
    "hhi":{
        "prefecture":"aaa",
        "city":"bbb",
        "town":"ccc"
    }
},
{
    "zipcode":"99998",
    "address":{
        "prefecture":"a",
        "city":"b",
        "town":"ㅇ"
    },
    "hhi":{
        "prefecture":"aaa",
        "city":"bbb",
        "town":"ㅇㅇㅇ"
    }
}

일괄처리를 transaction 화하여 도중에 처리를 실패할 경우에 아무것도 처리를 안 했다는 보증을 한다.

트랜잭션이란 요청이나 반영한 곳에서 이벤트가 생겼을 시에 양쪽 처리가 모두 성공하거나 실패했을 경우에 둘 다 원래대로 돌아가게끔 보증하는 것이다. 문제가 있을 시에는 rollback를 하고 성공할 시에는 commit을 한다.

요즘은 하나의 클라이언트만 상대하지 않고 다수를 제어를 해야 한다. 이때 들어오는 게 배타 제어이다. 베타 제어는 리소스 편집해 경합이 일어나지 않도록 하나의 클라이언트만 편집 가능하도록 제어 처리하는 개념이다. 이 제어 방법은 비관적 장금과 낙관적 잠금이 있다. 비관적 잠금은 하나의 클라이언트가 사용 중일 시에 다른 클라이언트는 리소스를 불러올 수는 있지만 그 외의 수정 등은 못한다. 수정 중인 클라이언트는 언락을 보내서 다시 다른 사용자가 쓸 수 있게끔 잠금을 푼다. 낙관적 잠금은 ETag를 줘서 먼저 수정 한 사용자는 바로 갱신을 하고 나중에 수정을 요청한 사용자에게 경합을 일으킬 시에 갱신, 삭제, 별도로 리소스 보존, 혹은 병합을 촉구한다.

설계할 때 밸런스를 잘 잡아야 한다. 될 수 있으면 심플하게 만들고 막히면 리소스로 돌아가 생각하자. 검색 기능을 구현한다고 치면 검색 기능을 구현한다고 생각하지 말고 그 리소스를 get 한다는 식으로 사고하자.

리소스의 설계

리소스 설계도 RESTful이 권장된다. 리소스를 설계할 때 웹서비스에서 제공할 데이터를 특정하는 방법과 데이터를 리소스로 나누는 방법을 알 수 없다. 이것을 설계하기 위해서 설계하는 게 리소스 설계이다. 그 방법은 3가지가 있다

  • 관계 모델 ER(Entity Relation) 다이어그램
  • 객체 지향 모델의 클래스 다이어그램
  • 정보 아키텍처

관계 모델 다이어그램은 중심이 되는 데이터에 다른 데이터에 링크 되는 foriegn key를 넣어서 꼬리 연결식으로 데이터들을 링크한다. 이는 데이터의 중복을 생략하기 위해서 한 정규화이다. 그러나 restul 한 아키텍처를 만듦으로써 데이터를 불러올 시에 모든 데이터를 다 다시 불러옴으로써 정규화를 무의미하게 만든다.

객체지향 모델은 설계 대상의 시스템의 분석 모델을 객체지향 언어의 클래스와 인스턴스로 만든다. 클래스로 만들 때 계층별로 만들고 그 계층별 관계를 사용한다.

정보 아키텍처는 웹에서 보이는 정보 구조이다. 웹에서 정보가 어떻게 구성되어 있는지 보여주고 사용자들이 그 구조에 따라 원하는 정보의 구조로 이동할 수 있게끔 만든 것이다.