ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 티스토리 API 사용하기
    소프트웨어개발 이야기 2020. 3. 5. 15:26

    블로그를 티스토리로 옮긴 이유 중 하나는, API의 제공이었다.

    필요한 정보를 주기적으로 블로그에 자동 업로드하고 싶었는데, 감사하게도 티스토리는 API를 통해서 이런 작업이 가능했다. 요즘같이 클라우드가 보편화된 시기에 누구나 조금의 노력만으로 이런 작업이 가능해졌다. 라떼이즈홀스, 집에 PC 24시간 돌리던 그 시절이 눈물겹다.

    각설하고, 필자의 블로그에 주기적으로 업로드 중인 오늘이야기(오늘의 커뮤니티, 오늘의 유튜브, 오늘의 핫이슈) 경험을 바탕으로 티스토리 API를 사용해서 글을 올리는 내용을 정리한다.


    티스토리 API 앱 등록

    대부분의 오픈 API 사용이 그러하듯, 티스토리 API를 사용하기 위해서는 프로젝트(앱) 등록이 필요하다. 티스토리 API 등록 페이지를 들어가 보자.

     

     

     

    TISTORY

    나를 표현하는 블로그를 만들어보세요.

    www.tistory.com

     

    이용약관을 확인하고, 아래에 입력폼에 있는 서비스명, 설명, 로고, 서비스 URL, 서비스 형태, 서비스 권한, CallBack을 입력한다.

    서비스 URL : API를 사용할 서비스의 URL 이다. 별도 도메인이 없는 경우, 현재 사용 중인 티스토리 블로그의 주소를 입력해도 무관한다.

    서비스 형태 : API를 활용하여 개발하려는 서비스의 종류다. PC Client 나 모바일 SDK를 활용한 앱의 경우 각각에 항목을 선택한다. 필자는 별도의 화면 없이 서버에서 티스토리 글 업로드를 위한 서비스에 사용하기 때문에 웹서비스를 선택했다.

    CallBack : API 사용을 위해서 권한체크가 필요한데, 이때 티스토리에서 호출하는 주소다. 뒤에 설명하겠지만 본글에서 사용하는 Implicit 방식에는 크게 의미가 없다. 임의의 URL값을 설정해 준다.

     

    다른 오픈 API와 마찬가지로, 등록이 완료되면 앱 아이디와 비밀 키를 확인할 수 있다. 

    준비는 끝났으니, 본격적으로 API를 사용해 보자. 


     

    티스토리 API 소개

    티스토리에서는 API 가이드를 제공한다. 구글이나 페이스북 처럼 많은 정보를 제공하는 건 아니지만 그래도 있을 건 다 있다.

     

    소개 · GitBook

    No results matching ""

    tistory.github.io

    API는 REST API 형식이며 아쉽지만 언어별로 SDK를 제공하지는 않는다.(많이 바라지 않는다. 이정도만 해도 감사한다... ㅠㅠ)

    https://www.tistory.com/apis/{RESOURCE}?
      access_token={access-token}
      &output={output-type}
    • access_token: 발급받은 Access Token
    • output: xml, json 두가지 형태의 응답 형식을 지정하며 생략 가능(기본 xml, 생략 시 요청 헤더의 'Content-Type' 값)

    참고로, JSON 형식으로 요청할 경우 EUC-KR로 결과가 반환되기 때문에 인코딩 작업이 필요하다.

    제공하는 기능은 다음과 같다.

     

    보다 자세한 내용은 티스토리 API 가이드를 참고한다. (필자가 제일 싫어하는 표현이다. 뭔가 자세한 건 생략한다는 식의 귀차니즘 같은 표현 말이다. 그런데 티스토리 가이드가 워낙 심플하고 자세히 나와 있어서 서술해봐야 복붙밖에 안된다. 게다가 한글이다. -_ -)

     

    티스토리 API 인증

    유튜브 API 글에서도 언급했지만 API를 사용하기 위해서는 인증이 필요하다. 티스토리는 두 가지 인증방식을 지원하는데, 본 글에서는 간단한 Implicit 방식을 사용한다. 

    • Authentication Code : Server-side 프로그래밍으로 인증을 구현할 경우 사용하기 적합한 인증 방식
    • Implicit : Client-side 프로그래밍으로 인증을 구현할 경우 사용하기 적합한 인증 방식

     

    티스토리 API 관련 글들을 찾아보면 대부분 Implicit 방식으로 소개하고 있고 Authentication Code 방식은 예를 찾아보기 어렵다. 이유인즉슨, Implicit 방식이 쉽고 간단한 데다 Authentication Code 방식이 완벽한 OAuth2를 지원하고 있지 않기 때문에 굳이 이 방식을 써야 할 필요가 없다.(Refresh Token 좀 어떻게 안 되겠니?!...) 

    인증의 최종 목표는 위에서 언급한 다양한 API 사용 시 필요한 Access Token을 얻는 것이다. 지금부터 Implicit 방식을 사용하여 순서대로 진행해 보자.

    1. 인증 요청
    https://www.tistory.com/oauth/authorize?
      client_id={client-id}
      &redirect_uri={redirect-uri}
      &response_type=token
    • client_id : 티스토리 API 앱 등록 시 받은 "APP ID"
    • redirect_uri : 사용자 인증(티스토리 로그인) 후에 리디렉션 할 URL으로 티스토리 API 앱 등록 시 입력한 "CallBcak" 값
    • response_type : "token"

     

    HTTP Request를 통해 인증 요청을 하면 브라우저가 뜨면서 티스토리 로그인 창이 뜬다.(기 로그인 되어있는 상태면 로그인 작업 생략됨) 티스토리 API 앱 등록을 한 계정으로 로그인하면 Redirect 주소 값에 Access Token이 담겨서 반환된다. 

    그런데, 여기서 몇 가지 문제가 생긴다.

    API를 학습하는 차원에서는 최초 한번 Access Token을 얻고 API를 호출하면 그만이지만, 안타깝게도 Access Token은 만료 시간이 정해져 있고 만료 시간이 지난 후에는 위에서 수행한 인증 요청을 다시 거쳐야 한다. 

    필자처럼 API를 통해서 주기적으로 글을 올리는 작업을 자동화하고 싶은 경우에는, 만료시간이 될 때마다 브라우저를 켜서 로그인을 수행해야 한다. 심지어 필자는 GUI도 없는 서버에서 돌려야 하는데.. -_ -;

    OAuth2에서는 이런 문제를 위해 매번 사용자의 인증을 회피할 수 있는 방법을 Refresh Token으로 제공한다. 하지만 위에서 밝혔듯 티스토리가 OAuth2를 완벽히 지원하지 못하는 관계로 ㅠㅠ.... 

     

    자.. 그럼 어떻게 해야 이 문제가 해결될까?! 인증 요청에 앞서 사용자 로그인 요청을 먼저 수행하면 해결된다. 

    0. 로그인 요청
    // 로그인 요청 옵션 정보
    method: 'POST',
    url: 'https://www.tistory.com/auth/login',
    headers: {  
      'Referer': 'https://www.tistory.com'  
    },
    form: {
      'fp': /* 임의값으로 티스토리 로그인 페이지에 있는 fp값 활용 */,
      'loginId': /* 티스토리 아이디 */,
      'password': /* 티스토리 비밀번호 */,
      'redirectUrl': 'https://www.tistory.com'
    }

    POST 방식으로 로그인 정보를 담아서 호출하면 로그인 세션을 받을 수가 있다. 로그인 정보중 'fp'값은 티스토리 로그인 페이지에서 제공하는 임의의 값을 사용하면 된다.

    로그인 요청을 0번으로 인덱싱 한 걸 잊지 말자. 인과 관계를 설명하기 위해 뒤에 작성하기는 했지만, 개발할 때는 반드시 로그인 요청을 먼저 수행하자.

    여기서 반드시 주의해야 할 점!

    필자처럼 Request 라이브러리가 자동으로 redirect를 수행해 버리면 Access Token이 담긴 주소 값을 확인할 방법이 없다. 반드시 redirect 옵션을 해제한 뒤 호출해야 한다. (맞다.. 필자는 개고생했다... =.=)

    반환되는 Access Token은 앵커(#access_token)로 담겨오기 때문에 주소값을 문자열로 파싱 해서 사용해야 한다. 

    Rediection 관련해서 필자가 정리해놓은 글을 참고하자.

     

    티스토리 API 사용

    Access Token을 얻었으면 이제 API를 사용할 일만 남았다. 이때가 제일 행복한 순간이다 ㅎㅎ

    API 가이드에 나와있는 대로 파라미터를 설정해서 호출한다. access_token값은 위에서 인증 요청을 통해 얻은 Access Token을 사용한다. 간단한 REST API 호출이기 때문에 소스코드를 참고하자.

    글 내용 조회
        getPost(blogName, postId) {
            var deferred = Q.defer();
    
            oauth2Service.getAccessToken()
                .then(accessToken => {
    
                    var options = {
                        method: 'GET',
                        url: this.origin + 'post/read',
                        qs: {
                            access_token: accessToken,
                            blogName: blogName,
                            postId: postId
                        }
                    };
    
                    request(options, function (error, response, body) {
                        if (error) {
                            errorHandler.logMessage(error, "글 내용을 조회할 수 없습니다.");
                            deferred.reject(error);
                        } else {
                            deferred.resolve(response.body);
                        }
                    });
                }).catch(err => {
                    reject(err);
                });
    
            return deferred.promise;
        }

     

    글 등록
        registerPost(blogName, contents) {
            var deferred = Q.defer();
    
            oauth2Service.getAccessToken()
                .then(accessToken => {
                    var options = {
                        method: 'POST',
                        url: this.origin + 'post/write',
                        form: {
                            access_token: accessToken,
                            blogName: blogName,
                            title: contents.title,
                            content: contents.content,
                            visibility: contents.visibility,
                            category: contents.categoryId,
                            tag: contents.tag
                        }
                    };
    
                    request(options, function (error, response, body) {
                        if (error) {
                            errorHandler.logMessage(error, "글 내용을 등록할 수 없습니다.");
                            deferred.reject(error);
                        } else {                        
                            deferred.resolve(response.body);
                        }
                    });
                }).catch(err => {
                    reject(err);
                });
    
            return deferred.promise;
        }

     

    댓글

Designed by Joypinkgom.