솔루션 - REST API 연동을 위한 정리

BBang·2022년 7월 19일
1

솔루션 연동

목록 보기
1/2

링크 작성한 원문

1. REST API 개요

➡️ 목차

자료 작성간 참고한, 읽어보면 좋은 글

1. REST API란? - REpresentational State Transfer

( 표현적인 API )

  • 탄생: Roy Thomas Fielding은 HTTP의 주요 저자 중 한 사람으로, 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표
  • 구성: URI ( 자원 ) , 행위 ( HTTP Method ), 표현 ( Representations )
  • 특징: 유니폼 인터페이스 (URI) , 무상태성 (Stateless), Cacheable (캐시 가능), Self-descriptiveness (자체 표현 구조), Client-Server 구조, 계층형 구조
  • REST 의 특징
    • Uniform (유니폼 인터페이스) HTTP 표준에만 따른다면, 안드로이드/IOS 플랫폼이든, 특정 언어나 기술에 종속되지 않고 모든 플랫폼에 사용할 수 있으며, URI로 지정한 리소스에 대한 조작이 가능한 아키텍처 스타일을 의미한다.
    • Stateless (무상태성) REST는 무상태성 성격을 가진다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다. 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 그래서 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.
    • Cacheable (캐시 가능) REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹 표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용할 수 있다. 따라서 HTTP가 가진 캐싱 기능이 적용할 수 있다. HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.
    • Self-descriptiveness (자체 표현 구조) REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어 있다는 것이다.
    • Client - Server 구조 REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로 간 의존성이 줄어들게 된다.
    • 계층형 구조 REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.

1-1. REST API 디자인 가이드

1) 자원에 대한 행위는 HTTP Method로 표현

HTTP Method 중 대표적인 4가지 ( POST - 생성, GET - 조회, PUT - 수정, DELETE - 삭제) 를 사용한다.

2) URI는 정보의 자원을 표현

  • 회원 삭제 URI 예시 ( 1번 member를 삭제 )

GET /members/delete/1  (x) ( 'delete' 라는 행위에 대한 표현이 들어간 URI )

DELETE /members/1             (o)

  • 회원 조회 URI 예시

GET /members/show/1        (x)

GET /members/1                   (o)

  • 회원 추가 URI 예시

GET /members/insert/2        (x)

POST /members/2                 (o)

3) URI는 자원을 표현하는 Colllection과 Document 로 구성

  • Collection : 문서나 객체들의 집합
  • Docuemnt : 문서나 객체
	http:// restapi.example.com/sports/soccer/players/13
* sports , players 라는 Collection. (복수형 사용됨)
* Collection 안에, soccer, 13 이라는 Document

1-2. REST API 설계 시 주의점

1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용

    http://restapi.example.com/houses/apartments ( 집 -> 아파트 )
    http://restapi.example.com/animals/mammals/whales ( 동물 -> 포유류 -> 고래 )

2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다.

    http://restapi.example.com/houses/apartments/ (X)
    http://restapi.example.com/houses/apartments  (0)

3) 가독성을 위해서,

 https://www.destiny.com/books/my-service
  • 하이픈(-)을 사용
  • 소문자를 사용
  • 파일 확장자는 포함 X ( /users/2/profile/ thumbnail.jpg (x) → thumbnail (o) )

1-3. HTTP 응답 상태 코드

잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것까지 포함되어야 함.

  • 200 ( 요청 정상 수행함 ) , 201 ( 생성 요청 리소스 성공적 생성함 )
  • 301 ( 요청한 리소스의 URI가 변경 되었음 → Location Header에 변경된 URI 리턴 )
  • 400 ( 요청이 부적절함 ) , 401 ( 클라이언트 인증되지 않았는데 보호된 리소스 요청함 )
    405 ( 요청한 리소스에 사용 불가한 Method를 이용하여 요청함 )

등등, 성공/실패 여부에 맞는 적절한 Response status code 및 메세지를 응답!


2. 범용적으로 사용되는 REST API 분석

  • Naver네이버 오픈API 종류 영화 SearchAPI 예제
    // 요청
    
    > GET /v1/search/movie.xml?query=%EC%A3%BC%EC%8B%9D&display=10&start=1&genre=1 HTTP/1.1
    > Host: openapi.naver.com
    > User-Agent: curl/7.49.1
    > Accept: */*
    > X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 client id 값}
    > X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 client secret 값}
    
    
    // 응답 ( XML )
    < HTTP/1.1 200 OK
    < Server: nginx
    < Date: Wed, 28 Sep 2016 07:40:17 GMT
    < Content-Type: text/xml;charset=utf-8
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < Keep-Alive: timeout=5
    < Vary: Accept-Encoding
    < X-Powered-By: Naver
    < Cache-Control: no-cache, no-store, must-revalidate
    < Pragma: no-cache
    <
    <?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0">
        <channel>
            <title>Naver Open API - movie ::'주식'</title>
            <link>http://search.naver.com</link>
            <description>Naver Search Result</description>
            <lastBuildDate>Wed, 28 Sep 2016 16:40:17 +0900</lastBuildDate>
            <total>2</total>
            <start>1</start>
            <display>2</display>
            <item>
                <title>주마등&lt;b&gt;주식&lt;/b&gt;회사</title>
                <link>http://openapi.naver.com/l?AAADWLQQvCIBzFP83f48h0zh08uK1B0S2IOm7mUEIts0F9+vQQPN77vQfv+dbxI2DXgyTQ9QV4B+2ATNSLMCk9gEjYjlkurFZXflp1rFRw/yXnbEspNk8vqypvPJBRhZsGMrSMY4ySwLSpN5RT3NSYIScO5nxhdzc18cjq0958w8LneKUy8fz6AdRxjD6YAAAA</link><image>http://imgmovie.naver.com/mdi/mit110/0968/96811_P01_142155.jpg</image>
                <subtitle>走馬&amp;amp;#28783;株式&amp;amp;#20250;社</subtitle>
                <pubDate>2012</pubDate>
                <director>미키 코이치로|</director>
                <actor>카시이 유우|쿠보타 마사타카|카지와라 히카리|치요 쇼타|요코야마 메구미|카시와바라 슈지|</actor>
                <userRating>4.50</userRating>
            </item>
            ...
        </channel>
    </rss>
    

    기타

    • GET/POST https://nid.naver.com/oauth2.0/authorize - 네이버 로그인 인증을 요청합니다.

    • GET https://openapi.naver.com/v1/search/news - JSON, XML응답 : 네이버 검색의 뉴스 검색 결과를 반환합니다.

    • POST [https://openapi.naver.com/v1/papago/n2mt](https://openapi.naver.com/v1/papago/n2mt) - JSON응답 : 인공 신경망 기반의 기계 번역 결과(영어, 중국어(간체))를 반환합니다.

      /v1/papago/n2mt API의 요청 예시
      -H : 헤더
      -d : 파라미터
      curl "https://openapi.naver.com/v1/papago/n2mt" \
          -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
          -H "X-Naver-Client-Id: {애플리케이션 등록 시 발급받은 클라이언트 아이디 값}" \
          -H "X-Naver-Client-Secret: {애플리케이션 등록 시 발급받은 클라이언트 시크릿 값}" \
          -d "source=ko&target=en&text=만나서 반갑습니다." -v
      
    • 비로그인 방식 오픈 API 호출 예 (JAVA) https://github.com/naver/naver-openapi-guide/blob/draft/sample/java/APIExamTranslateNMT.java

  • Kakao지도 Open API 개발 가이드
    • 주소 검색하기 예시

      // 요청
      curl -v -X GET "https://dapi.kakao.com/v2/local/search/address.json" \
        -H "Authorization: KakaoAK ${REST_API_KEY}" \
        --data-urlencode "query=전북 삼성동 100"
      // 응답
      HTTP/1.1 200 OK
      Content-Type: application/json;charset=UTF-8
      {
        "meta": {
          "total_count": 4,
          "pageable_count": 4,
          "is_end": true
        },
        "documents": [
          {
            "address_name": "전북 익산시 부송동 100",
            "y": "35.97664845766847",
            "x": "126.99597295767953",
            "address_type": "REGION_ADDR",
            "address": {
              "address_name": "전북 익산시 부송동 100",
              "region_1depth_name": "전북",
              "region_2depth_name": "익산시",
              "region_3depth_name": "부송동",
              "region_3depth_h_name": "삼성동",
              "h_code": "4514069000",
              "b_code": "4514013400",
              "mountain_yn": "N",
              "main_address_no": "100",
              "sub_address_no": "",
              "x": "126.99597295767953",
              "y": "35.97664845766847"
            },
            "road_address": {
              "address_name": "전북 익산시 망산길 11-17",
              "region_1depth_name": "전북",
              "region_2depth_name": "익산시",
              "region_3depth_name": "부송동",
              "road_name": "망산길",
              "underground_yn": "N",
              "main_building_no": "11",
              "sub_building_no": "17",
              "building_name": "",
              "zone_no": "54547",
              "y": "35.976749396987046",
              "x": "126.99599512792346"
            }
          },
          ...
        ]
      }
      

      Java로 REST API 호출 샘플 코드

➡️ 범용적인 API의 구성 요약
  • 사용자는 OAuth 2.0 토큰 기반 인증을 통해 인증 과정을 거침.
  • 클라이언트가 서버인 경우, 애플리케이션을 등록 하고, 발급 받은 Client-ID와 SecretKey를 통해 인증 과정을 거침.
  • 각 서비스/도메인에 맞는 URI와 파라미터가 있으며, API 명세를 통해 요청과 응답을 정의함.
  • JSON / XML 방식의 응답을 지원함. ( JSON / XML로 파싱해 응답하는 Java 라이브러리가 있음 )
  • URI의 경로 버저닝 전략을 이용하여 API의 버전 관리를 함. ( /…/v1/search )

3. ECM 연동에 적합한 REST API

// ECM - APIController 의 주요 메서드 일부
createDummySession[-ByUserCode] (HttpServletRequest, String) : boolean
logout(HttpServletRequest, HttpServletResponse) : void
getServerStatus(HttpServletRequest, HttpServletResponse) : ModelAndView 
getRootOID(HttpServletRequest, HttpServletResponse) : ModelAndView 
getFolderList(HttpServletRequest, HttpServletResponse) : ModelAndView 
getDocumentList(HttpServletRequest, HttpServletResponse) : ModelAndView 
downloadFile(HttpServletRequest, HttpServletResponse) : ModelAndView 
createDownloadFileUrl(HttpServletRequest, HttpServletResponse) : ModelAndView 
uploadFile(HttpServletRequest, HttpServletResponse) : ModelAndView 

3-1. 현재 구현 되어 있는 컨트롤러 코드 분석

  • ECM 연동 API Controller에서는 [ 로그인(세션 생성), 로그아웃, 서버 상태, Root 정보, 폴더나 문서 정보, 문서(파일)의 업/다운로드 ] 등의 기능을 제공함.
    • 로그인/로그아웃은 요청 헤더의 “Authorization”의 값과, 서버에 있는 평문을 비교 후, Account와 IP를 이용해 Dummy Session을 생성하고 삭제하는 역할만 함.
    • downloadFile() 의 경우, 위의 과정 수행 후 전달 받은 fileOID를 이용해 바로 response에 OutputStream을 전달한다

3-2. REST API로 전환 시 필요한 내용

3-3. 고민이 더 필요한 부분

💡 결론
현대의 HTTP를 사용하는 API는 대부분 RESTful하다고 봐도 무방할 정도로, 사실상 HTTP의 표준처럼 사용되고 있습니다.
모든 상황과 애플리케이션에서 완벽한 아키텍처라는 뜻이 아니며 반드시 완전하게 설계 규칙을 준수해야만 하는 것이 아닙니다. (HATEOAS 구현 등)
위와 같은 설계 규칙을 준수하는 것은 내가 이해하고 다른 사람이 이해하는데 효율적이기 때문에 융통성을 갖고, 도구로써 적절히 잘 사용하는것이 중요할 듯 합니다.

profile
Java

1개의 댓글

comment-user-thumbnail
2023년 9월 17일

좋은포스팅 감사합니다 :)

답글 달기