'API'에 해당하는 글 4건

Spring Boot REST API 프로젝트에 API 문서 자동화 툴로 뭘 써야 하나...

 

 

Swagger vs Spring rest docs

 

  • Swagger - 적용 난이도 쉬움, 이쁜 UI, API 테스트 기능, 코드 기반
  • Spring rest docs - 적용 난이도 보통, 단순 UI, 테스트 기반

 

장단점이 분명하지만, 내부용으로 후딱 만들어 쓸 것이라면 Swagger. 외부에 제공해야 한다면 정갈해 보이는 Spring rest docs 이 아닐까 싶다.

 

 

문서화를 위한 gradle 구성

 

  • Step 1. 코드 테스트 -> 에러가 발생하지 않으면 해당 api 내용(snippets: asciidoc 파일) 생성.
  • Step 2. Test 로부터 생성된 snippets 을 import 하도록 api 문서 템플릿(asciidoc 파일) 을 생성하고 빌드하여 API 문서(html) 완성.
  • Step 3. 생성된 html 파일을 외부에 노출하도록 static 디렉토리에 복제.

 

plugins {
    id 'org.springframework.boot' version '2.5.6'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    // gradle 7 이상은 org.asciidoctor.convert 대신 org.asciidoctor.jvm.convert 사용
    id 'org.asciidoctor.jvm.convert' version '3.3.2'  // Step 1
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

bootJar {  // Step 3
    dependsOn asciidoctor
    copy {
        from "${asciidoctor.outputDir}"
        into "${sourceSets.main.output.resourcesDir}/static/docs"
    }
}

asciidoctor {  // Step 2
    sourceDir 'src/main/asciidoc'
    attributes \
        'snippets': file('build/generated-snippets')
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'  // Step 1
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

 

이 build.gradle 파일은 가장 기본적인 세팅이므로 추후 익숙해지면 task 를 통합하거나 build 경로를 수정하여 커스터마이징 해서 편하게 쓰면 되겠다. 예를 들면...

 

asciidoctor {
    dependsOn test
    sourceDir 'src/main/asciidoc'
    outputDir "${sourceSets.main.output.resourcesDir}/static/docs"
    attributes \
        'snippets': file('build/generated-snippets')
}

 

3개의 task (단위 Test - html 생성 - html 복사) 를 하나로 통합한 예...

 

아무튼 build.gradle 파일을 수정했으면 JUnit 와 MockMvc 를 사용하여 Test 를 작성한다. (model, controller 생략)
MockMvc, REST Assured 중 서버 구동없이 컨트롤러 단위 테스트가 쉬운 MockMvc 를 사용한다.

 

@WebMvcTest(TestController.class)
@AutoConfigureRestDocs(outputDir = "build/generated-snippets")
public class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception {

        mockMvc.perform(RestDocumentationRequestBuilders.get("/book/{id}",1).accept(MediaType.APPLICATION_JSON))
                .andDo(print())
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andDo(document("book",
                        pathParameters(
                                parameterWithName("id").description("book unique id")
                        ),
                        responseFields(
                                fieldWithPath("id").description("book unique id"),
                                fieldWithPath("title").description("title")
                        )
                ))
                .andExpect(jsonPath("$.id", is(notNullValue())))
                .andExpect(jsonPath("$.title", is(notNullValue())));
    }
}

 

* 아래 에러 발생시:
urlTemplate not found. If you are using MockMvc did you use RestDocumentationRequestBuilders to build the request?

> pathParameters 을 사용할 때는 MockMvcBuilders.get 대신 RestDocumentationRequestBuilders.get 사용

 

Test 코드에서 document(identifier, ...) 에 기반하여 snippets 의 내용을 구성하게 되며, andExpect 에서 에러가 발생하지 않으면 outputDir 에 snippets 들이 생성된다.

 

curl-request.adoc
http-request.adoc
http-response.adoc
...

 

정상적으로 생성됐다면 이 snippets 들을 불러올 템플릿 asciidoc 파일을 생성한다. (/src/main/asciidoc/)

 

= Document Title
:doctype: book
:icons: font
:source-highlighter: highlightjs
:toc: left
:toc-title: API 명세서
:toclevels: 4

[[api]]

== Book Api
api 에 관련된 설명을 이곳에 적습니다..

include::{snippets}/book/curl-request.adoc[]
include::{snippets}/book/http-request.adoc[]
include::{snippets}/book/path-parameters.adoc[]
include::{snippets}/book/http-response.adoc[]
include::{snippets}/book/response-fields.adoc[]

 

* asciidoc 파일 작성시 참고

https://docs.asciidoctor.org/asciidoc/latest/

https://narusas.github.io/2018/03/21/Asciidoc-basic.html

 

 

Asciidoc 기본 사용법

Asciidoc의 기본 문법을 설명한다

narusas.github.io

 

AsciiDoc Language Documentation :: Asciidoctor Docs

AsciiDoc is a lightweight and semantic markup language primarily designed for writing technical documentation. The language can be used to produce a variety of presentation-rich output formats, all from content encoded in a concise, human-readable, plain t

docs.asciidoctor.org

 

Spring REST Docs는 기본적으로 Asciidoctor 를 사용하지만, Markdown 을 사용할 수도 있다.

간략하게 이런식으로 작성하고 bootJar 를 실행하면 /build/docs/asciidoc/book.html 파일이 생성된 것을 확인할 수 있다.

 

spring-rest-docs

 

bootRun 을 실행하면 해당 파일이 /build/resources/main/static/docs 에 복사되며 http://localhost/docs/book.html 에서 확인 가능.

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

DynamoDB API

Database/DynamoDB 2017. 7. 18. 00:28



DynamoDB 를 어플리케이션에서 사용할 수 있는 몇가지 API 카테고리이다.
심플하게 데이터 올리기, 가져오기, 수정하기 정도가 전부이다.



Control Plane : Table 및 Key, Index 관련.


  • CreateTable
    Table 생성. Secondary Indexes 및 DynamoDB Stream 설정 가능.

  • DescribeTable
    Table 정보 반환 (Primary key 스키마, 처리량 설정, Index 정보)

  • ListTables
    모든 Table 의 이름을 목록으로 반환.

  • UpdateTable
    Table, Index, Stream 수정.

  • DeleteTable
    Table 및 해당 종속적 객체 모두를 삭제.



Data Plane : Table 의 데이터에 대해 생성, 읽기, 업데이트 및 삭제(CRUD) 작업을 수행.


  • PutItem
    단일 Item 생성. primary key 는 반드시 지정.

  • BatchWriteItem
    한번에 최대 25개의 Item 을 생성. PutItem 을 여러 번 호출하는 것보다 이 작업이 효율적.

  • GetItem
    단일 Item 읽기. 원하는 Item 의 primary key 지정. 전체 Items 또는 Attribute 일부를 가져올 수 있다.

  • BatchGetItem
    하나 이상의 Table 에서 최대 100개의 Items 를 가져온다. GetItem 을 여러 번 호출하는 것보다 이 작업이 효율적.

  • DeleteItem
    단일 Item 삭제. 삭제하려는 Item 의 primary key 지정.

  • BatchWriteItem
    하나 이상의 Table 에서 최대 25개의 Items 를 삭제. DeleteItem을 여러 번 호출하는 것보다 이 작업이 효율적.

  • UpdateItem
    Item 에서 하나 이상의 Attribute 수정, 추가, 제거 가능. 수정하려는 Item 의 Primary key 를 지정. 사용자 정의 조건부 업데이트를 수행 가능. 숫자 속성 증감 원자성 카운터를 구현 가능.


  • Query
    Partition key 를 지정하여 해당 Partition key 를 갖는 모든 Item 을 가져온다. 전체 Item 또는 Attribute 일부만 가져올 수 있다. sort key 값에 조건을 적용하여 동일한 Partition key 의 데이터 일부만 검색할 수도 있다. 테이블에 Partition key 와 sort key 가 모두 있는 경우 이러한 작업을 테이블 및 Index 에 사용할 수 있다.

  • Scan
    지정한 Table 또는 Index 의 모든 Items 를 가져온다. 전체 Items 또는 Attributes 일부만 가져올 수 있다. 필터링 조건을 적용하여 필요한 값만 반환할 수 있다. 풀스캔을 하므로 대용량 테이블에 사용하지 않아야 한다. 작은 테이블이나 불가피하게 데이터를 대량으로 내보낼 경우 정도에 사용한다.



DynamoDB Streams : Table에 Stream 설정/해제, Stream 의 데이터 수정 레코드에 액세스 가능.


  • ListStreams
    모든 스트림 목록 또는 특정 테이블의 스트림 반환.

  • DescribeStream
    Amazon 리소스 이름(ARN) 및 애플리케이션이 첫 스트림 레코드를 읽기 시작할 수 있는 위치와 같은 정보를 반환.

  • GetShardIterator
    샤드 반복자(shard iterator) 를 반환. 샤드 반복자는 애플리케이션이 스트림으로부터 레코드를 가져오는 데 사용하는 데이터 구조이다.

  • GetRecords
    지정된 샤드 반복자를 사용하여 하나 이상의 스트림 레코드를 가져온다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

twitter API

Tool/OAuth 2015. 12. 28. 23:52

REST APIs

 

요즘은 웹이든 앱이든 페이스북이나 트위터, 구글 등의 SNS 계정으로 회원가입을 받는 경우가 많다.
따로 회원가입 양식을 요구하지 않으니 사용자 입장에서도 좋고, SNS 연동이나 홍보가 편리하므로 서비스 입장에서도 좋다.
회원가입을 하지 않고도 타 사이트에서 SNS 계정의 권한으로 서비스를 이용하는 것은 각 SNS에서 제공하는 API / SDK 덕분이다.

 

예를 들어, A 쇼핑몰에 트위터 계정으로 로그인 한 후에 마이페이지 등에서 내 트위터 친구 목록 불러오기를 할 수 있다.
트위터에 방문하지 않고 트위터 데이터를 읽어올 수 있는 것은 A 쇼핑몰에서 트위터가 제공하는 API 를 사용하기 때문이다.
twitter API 를 사용하면 새 트윗, 프로필이나 팔로워 등 트위터 상의 데이터들을 읽어오거나 작성할 수 있다.

 

A 쇼핑몰에서 twitter API 를 사용하여 B 사용자의 권한으로 개인정보를 가져올 수 있었던 것은 A 쇼핑몰이 트위터로부터 인증을 받았기 때문이다.
대단한 인증이 아니다. 트위터 개발자 사이트(https://dev.twitter.com/)에 가입을 하고 [Manager Your Apps] 에서 프로젝트(App)를 새로 만들면,
예를 들어, A 쇼핑몰 전용 프로젝트(App)를 만들면 그 프로젝트에 대한 고유 키가 발급된다.


- Consumer Key
- Consumer Secret

그리고 A 쇼핑몰에서 이 키들을 사용하여 API 를 요청하면, 트위터에서 '아~ A 쇼핑몰에서 API 를 요청하는구나~' 라고 인식하고 요청을 허용한다.

 


REQUEST URL

 

twitter API 는 restful 방식이다.
REST API. 즉, URL 과 HTTP 메소드를 이용하여 결과를 얻는 방식이다.
예를 들어, 로그인한 사용자의 친구 목록을 불러오는 API 를 사용해 보면,

 

1
2
3
4
5
6
GET https://api.twitter.com/1.1/friends/list.json
 
"errors": {
    "code"215
    "message""Bad Authentication data."
}
cs


인증 오류이다.
단지 저 URL 을 링크 걸어놓는다고 해서 트위터가 모든 요청을 허용하지는 않는다. API 마다 다르긴 하지만

 

Requires authentication? Yes

 

라고 리소스 정보에 쓰여 있다면 이 API 는 트위터가 인식할 수 있도록 요청 헤더에 인증 정보를 함께 넘겨야 올바른 결과값을 받을 수 있다.
API 로 접근하려는 소비자(Consumer) 가 누구인지, 어떤 사용자의 Token 으로 정보를 얻으려 하는지를 트위터가 정해놓은 방식대로 요청 헤더에 담아 전달해야 한다.

 

이런식의 Flow 가 바로 OAuth 라는 표준 인증 방식이다.
트위터는 이 OAuth  인증 방식으로 Consumer(A 쇼핑몰)들에게 API 를 제공한다.

 

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Facebook ID

Daily/Prog 2015. 9. 9. 01:10

 

 

 

Facebook API 를 사용하여 Token 을 얻어 로그인한 사용자의 정보를 얻어낼 수 있다.

 

https://www.facebook.com/dialog/oauth?client_id={facebook_AppID}&response_type=token&redirect_uri={RedirectUri}

 

위의 URL에 페이스북 개발자 페이지에서 등록한 App ID를 입력하고 토큰을 받을 redirect_uri 를 설정하면 토큰을 얻을 수 있다.
얻어낸 토큰을 이용하여 아래와 같이 필요한 항목들을 나열하면 해당 정보들을 얻을 수 있다.

 

https://graph.facebook.com/me?fields=id,email,name,first_name,last_name,gender,locale,picture&access_token={token}

 

문제는 반환된 id 가 facebook 에서 사용하는 유일한 아이디일 것으로 확신했던 것이 나의 큰 오산이었다.
Facebook API 버전을 v2.0 에서 v2.4 로 업그레이드를 한답시고 app_id 를 신규 발급 했는데 각자 다른 id 가 돌아오는게 아닌가.
기존 회원정보 DB랑 ID가 일치하지 않는다면...ㅋ;
Dash board 에서 세팅을 바꿔봐도 원래 id 는 돌아오지 않았고 API 버전 역시 다운그레이드 되지 않았다.
API 버전문제라 생각하고 구글링만 죽어라 하고...
결국 오랜 삽질 끝에 반환된 id는 Facebook 의 유일한 id가 아닌 등록된 App 의 유일한 id로 검증되었다.

 

https://www.facebook.com/app_scoped_user_id/861203280607126
https://www.facebook.com/app_scoped_user_id/951486641578789

 

두개의 App 에서 반환된 각자 다른 내 ID가, 모두 내 타임라인으로 들어가는 것을 확인.
ㅋㅋ...

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,