developers · Oct 1, 2019

영웅이 되세요: Quire API로 나만의 앱 만들기

AI 번역
· 영어로 보기

Quire API

최종 업데이트: 2026년 5월 28일

요약: Quire OAuth 2.0 API를 사용하면 사용자의 비밀번호를 저장하지 않고도 앱이 사용자의 Quire 계정에서 작업을 수행할 수 있습니다. 등록된 OAuth 앱(클라이언트 ID, 시크릿, 리디렉션 URL), 4단계 인증 흐름(설정, 리디렉션, 응답 처리, 코드와 토큰 교환), 그리고 액세스 토큰이 1시간 후 만료되므로 토큰 갱신 루프가 필요합니다.

사용자의 Quire 데이터를 읽거나 수정하는 앱을 개발할 때 가장 먼저 결정해야 할 것이 있습니다. 바로 사용자의 비밀번호를 보지 않고 어떻게 인증할 것인가입니다. Quire API는 OAuth 2.0으로 이 문제를 해결합니다. 이 포스트에서는 OAuth 앱 설정, 4단계 인증 흐름, 액세스 토큰과 갱신 루프, 그리고 개발자들이 첫 번째 빌드에서 자주 저지르는 실수를 살펴봅니다.

Quire의 OpenAPI 1.0.0 버전은 2019년 10월에 출시된 이후 안정적으로 유지되고 있습니다. OAuth를 사용하면 사용자가 앱의 Quire 콘텐츠(업무, 프로젝트, 댓글, 담당자, 태그, 마감일) 접근을 승인하며, 개발자는 사용자의 자격 증명을 직접 다루지 않아도 됩니다. 사용자는 언제든지 비밀번호 변경 없이 앱의 접근 권한을 취소할 수 있습니다. 이것이 바로 OAuth가 등장하기 전 비밀번호를 저장하던 방식이 보안상 문제가 있었던 이유입니다.

어떤 Quire 연동 방식이 내 사용 사례에 맞을까요?

OAuth API를 연결하기 전에, API가 실제로 적합한 도구인지 먼저 확인하세요. 2026년 현재 Quire는 네 가지 연동 방식을 지원하며, 각각 다른 문제를 해결합니다.

필요한 기능 사용할 방법 이유
내 앱에서 사용자를 대신해 Quire 데이터 읽기 또는 수정 Quire OAuth API (이 포스트) 사용자 인증, 전체 CRUD 접근, 폴링 불필요
Quire의 이벤트 반응 (업무 생성, 상태 변경, 댓글 추가) Quire 웹훅 푸시 기반, 폴링 오버헤드 없음, 가벼운 설정
Claude 또는 다른 AI 에이전트에 Quire 연결 Quire MCP 서버 LLM 도구를 위한 표준 프로토콜, 사전 구축된 서버 제공
자동화 또는 BI 워크플로우에 Quire 통합 OAuth API와 n8n 또는 Power BI 검증된 파이프라인, 적은 커스텀 코드

모바일 앱, 웹 대시보드, 동기화 서비스와 같은 일반적인 앱 연동을 구축한다면 OAuth API가 적합합니다. 이후 내용은 이 경로를 선택했다고 가정하고 진행합니다.

Quire API를 위한 OAuth 앱은 어떻게 설정하나요?

Quire API를 사용하려면 OAuth 앱을 먼저 만들어야 합니다.

Quire OAuth 앱 만들기

앱을 만들려면 Quire 계정에 로그인되어 있어야 합니다.

  1. Quire 개발자 앱 콘솔로 이동하여 새 앱 만들기 버튼을 클릭합니다. Quire 개발자 앱 콘솔

  2. 앱이 속할 Quire 조직을 선택합니다. 해당 조직의 멤버는 선택된 조직에 속한 모든 앱을 보거나 편집할 수 있습니다. Quire 앱 조직

  3. 애플리케이션 이름과 리디렉션 URL을 입력합니다. 리디렉션 URL의 역할은 나중에 설명하겠습니다. 지금은 아래 URL을 사용해도 됩니다:

    http://localhost:3000/callback

  4. 새 앱 만들기 버튼을 클릭하면, 새로 만든 OAuth 애플리케이션이 개발자 콘솔 페이지에 표시되어 추가 설정을 진행할 수 있습니다. Quire 앱 목록

정리하면, 다음 세 가지 정보가 필요합니다:

  • 개발자 클라이언트 아이디: :wJoMEodI4fSSR54pfNwIuIzLnaJ
  • 개발자 클라이언트 보안 키: eb8faf4nyd1wbeconw060e9ejui8zg6w8p1hyoex
  • 콜백 URL: http://localhost:3000/callback

Quire 앱 자격 증명

Quire API를 위한 개발 환경은 어떻게 설정하나요?

1단계. 앱 설정

앱의 설정 정보를 코드에 저장합니다.

const clientId = ':wJoMEodI4fSSR54pfNwIuIzLnaJ';
const clientSecret = 'eb8faf4nyd1wbeconw060e9ejui8zg6w8p1hyoex';
const redirectURI = 'http://localhost:3000/callback';
  
const authorizationUrl = 'https://quire.io/oauth';
const tokenUrl = 'https://quire.io/oauth/token';
const apiUrl = 'https://quire.io/api';

2단계. 사용자를 Quire로 리디렉션하여 앱 인증 받기

사용자를 Quire의 OAuth 엔드포인트 URI로 리디렉션할 인증 URL을 생성합니다. 이 페이지에서 로그인한 Quire 사용자는 앱이 자신의 콘텐츠에 접근하도록 승인할 수 있습니다.

샘플 URL:

https://quire.io/oauth?client_id=your-client-ID&redirect_uri=your-redirect-uri

인증 링크 예시는 다음과 같습니다:

var http = require('http');
var url = require('url');
var server = http.createServer(function (req, res) { 
    var uri = url.parse(req.url, true);
    if (uri.pathname == '/') {        
        //..    
    } else if (uri.pathname == "/install") {
        var authUrl = authorizationUrl 
            + '?client_id=' + clientId 
            + '&redirect_uri=' + encodeURIComponent(redirectURI);
        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write(
             '<html><body>' 
            + '<a href="' + authUrl + '">Connect Quire</a>' 
         + '</body></html>');
        res.end();

    } else if (uri.pathname == "/callback") {
        //...
    }
});
server.listen(3000);

state 파라미터는 CSRF(Cross-Site Request Forgery) 공격을 방지하기 위한 랜덤 문자열입니다. 임의의 문자열을 생성해야 하며, 3단계에서 변경 없이 앱으로 다시 전달됩니다. 애플리케이션은 이 값을 반드시 검증해야 합니다. 선택 사항이지만, 이 파라미터를 포함할 것을 강력히 권장합니다.

샘플 URL:

https://quire.io/oauth?client_id=your-client-ID&redirect_uri=your-redirect-uri&state=lpcl9v94z

3단계. OAuth 2.0 서버 응답 처리

OAuth 2.0 서버는 redirect_uri에 지정된 URL을 통해 앱의 접근 요청에 응답합니다.

사용자가 접근 요청을 승인하면 응답에 인증 코드가 포함됩니다. 사용자가 요청을 거부하면 응답에 오류 메시지가 포함됩니다. 웹 서버로 반환되는 인증 코드 또는 오류 메시지는 아래와 같이 쿼리 문자열에 표시됩니다:

오류 응답:

http://localhost:3000/callback?error=access_denied

인증 코드 응답:

http://localhost:3000/callback?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

콜백 예시:

//...
} else if (uri.pathname == "/callback") {
   var result = uri.query;
   var message = 'Auth fail';
   if (result["error_description"] != null) {
       message = result["error_description"];
       if (result["error"] == 'access_denied') {
           //display reject message
       }
       messageView(res, message);
   } else if (result["code"] != null) {
       return exchangeAccessToken(result["code"])
       .then(function(data) {
            var token = data['access_token'];
            message = token != null ? 'Success': 'Fail';
            messageView(res, message);
        });
   }
}

사용자가 앱의 redirect_uri로 리디렉션되면, 쿼리스트링 파라미터에 code와 state도 함께 포함됩니다. state는 요청을 검증하기 위한 CSRF 방지 토큰입니다.

쿼리스트링 파라미터에서 code와 state를 추출합니다. 이 시점에서 state를 검증할 수 있습니다.

검증 예시:

} else if (result["code"] != null) {
    if (result["state"] != stateFromSession(res))
        return messageView(res, 'invalid state');
            
    return exchangeAccessToken(result["code"])
    .then(function(data) {
         var token = data['access_token'];
         message = token != null ? 'Success': 'Fail';
         messageView(res, message);
     });
}

4단계. 인증 코드를 액세스 토큰으로 교환

추출한 인증 코드와 아래 요청 파라미터를 사용하여 토큰 엔드포인트에 POST 요청을 보내야 합니다.

파라미터
grant_type authorization_code
code {your-authorization-code}
client_id {your-client-ID}
client_secret {your-client-secret}
redirect_uri 2단계에서 redirect_uri를 지정한 경우 필수. 해당 단계에서 사용한 값과 동일해야 합니다.

액세스 토큰 요청 예시:

var request = require('request');
function exchangeAccessToken(code) {
    return new Promise(function(resolve, reject){
        request.post({
            url: tokenUrl,
            form: {
              grant_type: 'authorization_code',
              code: code,
              client_id: clientId,
              client_secret: clientSecret,
              redirect_uri: redirectURI
            }
          },
          function (error, httpResponse, body) {
            if (error) {
              return reject(error);
            }
            resolve(JSON.parse(body))
          });
    });
}

응답으로 받는 액세스 토큰은 JSON 형식입니다.

응답 예시:

{ 
  "access_token":"ACCESS_TOKEN", 
  "token_type": "bearer", 
  "expires_in":2592000, 
  "refresh_token":"REFRESH_TOKEN"
}

이 토큰은 모든 Quire API에 접근하는 데 필요하므로 안전하게 영구 보관해야 합니다.

Quire 액세스 토큰으로 API를 어떻게 호출하나요?

이제 앱에 액세스 토큰이 있으므로, 이를 사용하여 사용자를 대신해 API를 호출할 수 있습니다.

API 호출

요청 헤더에 Bearer 토큰으로 액세스 토큰을 전달하여 API를 호출합니다.

API 호출 예시:

function getCurrentUser(token) {
    return new Promise(function(resolve, reject){
        request.get({
            url: apiUrl + '/user/id/me', 
            headers: {
              "Authorization": "Bearer " + token
            }
          }, 
          function (error, httpResponse, body) {
            if (error) {
              return reject(error);
            }
            resolve(JSON.parse(body))
          });
    });
}

응답 예시:

{
  "email": "john@gmail.cc",
  "website": "https://coolwebsites.com",
  "id": "My_ID",
  "description": "This is *cool*!",
  "url": "https://quire.io/u/My_ID",
  "nameText": "My Name",
  "nameHtml": "My Name",
  "descriptionText": "This is cool!",
  "descriptionHtml": "This is <i>cool</i>!",
  "image": "https://quire.s3.amazonaws.com/oid/image.jpg",
  "iconColor": "37",
  "name": "My Name",
  "oid": "Dyh2YkFcu9uLgLFIeN1kB4Ld"
}

만료된 Quire API 액세스 토큰은 어떻게 갱신하나요?

액세스 토큰은 의도적으로 단기 사용만을 위해 설계되었습니다. 이것은 OAuth 2.0의 중요한 보안 메커니즘입니다. Authorization Code Grant Flow를 사용할 때 액세스 토큰의 기본 유효 시간은 1시간입니다.

액세스 토큰이 만료되면 HTTP 401 오류가 반환됩니다:

{ 
  code: 401, 
  message: 'Invalid or expired token.' 
}

애플리케이션이 액세스 토큰을 갱신해야 합니다.
function refreshToken(refreshToken) {
    return new Promise(function(resolve, reject){
        request.post({
            url: tokenUrl, 
            form: {
              grant_type: 'refresh_token',
              refresh_token: refreshToken,
              client_id: clientId,
              client_secret: clientSecret
            }
          }, 
          function (error, httpResponse, body) {
            if (error) {
              return reject(error);
            }
            resolve(JSON.parse(body))
          });
    });
}

또는 애플리케이션이 사용자를 인증 흐름으로 리디렉션할 수도 있습니다.

Quire API에서 개발자들이 자주 저지르는 실수는 무엇인가요?

팀들이 Quire API를 기반으로 개발하는 것을 지켜보면서, 동일한 다섯 가지 문제가 반복적으로 발생했습니다. 어느 것도 미묘하지 않으며, 모두 충분히 피할 수 있는 문제입니다.

1. 클라이언트 시크릿을 클라이언트 코드에 저장하기. 클라이언트 시크릿은 말 그대로 비밀입니다. 모바일 앱 바이너리나 브라우저 번들에 포함되면 누구나 추출하여 앱을 사칭할 수 있습니다. 시크릿은 반드시 개발자가 제어하는 서버에만 보관해야 합니다. 앱이 순수하게 클라이언트 사이드(싱글 페이지 앱, 모바일)라면, 시크릿을 삽입하는 대신 OAuth 2.0 PKCE 흐름을 사용하세요.

2. state 파라미터 검증 건너뛰기. state 파라미터는 CSRF 공격을 방지하기 위해 존재합니다. 콜백에서 검증을 건너뛰면, 악의적인 사이트가 Quire 계정을 공격자의 앱 세션과 몰래 연결하는 데 악용할 수 있는 취약점이 생깁니다. 요청마다 state를 새로 생성하고 세션에 저장한 다음, 반환된 state가 일치하지 않는 콜백은 거부하세요.

3. 액세스 토큰을 영구적인 것으로 취급하기. 액세스 토큰은 1시간 후에 만료됩니다. 토큰을 저장하고 갱신하지 않는 앱은 첫날에는 잘 작동하다가 다음 날 아무 경고 없이 작동을 멈춥니다. 출시 전에 토큰 갱신 루프를 먼저 구축하세요. "사용자가 불만을 제기하면 수정하겠다"는 방식은 금물입니다.

4. 변경 사항을 감지하기 위해 API를 폴링하기. 폴링은 속도 제한, 지연 시간, 배터리를 낭비합니다. Quire의 변경에 반응해야 한다면 웹훅을 사용하세요. 웹훅은 이벤트를 즉시 전달하므로, 해당 이벤트를 감지하기 위한 API 호출 자체가 필요 없어집니다.

5. 리디렉션 URL 허용 목록 건너뛰기. 모든 OAuth 앱 등록은 리디렉션 URL 목록을 허용합니다. 와일드카드를 사용하거나 정확하게 설정하지 않으면, 공격자가 자신의 콜백을 리디렉션 대상으로 등록하여 인증 코드를 가로챌 수 있습니다. 앱에서 실제로 사용하는 정확한 URL만 추가하세요.

API를 처음 사용한다면, n8n 커넥터와 같은 기존 연동 사례를 포크하여 인증, 갱신, 오류 처리 방식을 분석하는 것이 가장 빠른 학습 방법입니다.

Quire API가 적합하지 않은 경우는 언제인가요?

다른 연동 방식을 선택해야 하는 세 가지 패턴을 소개합니다.

  • 상태 조회 없이 이벤트에만 반응하면 될 때. 웹훅은 더 간단하고, 푸시 기반이며, 읽기 전용 이벤트 구독에 사용자 인증이 필요하지 않습니다. 앱의 역할이 "무언가 발생했을 때 알림 받기"라면 API가 아닌 웹훅을 사용하세요.
  • Claude 또는 LLM 에이전트 연동을 구축할 때. Quire MCP 서버가 적합한 선택입니다. 인증을 처리하고 표준 스키마를 제공하므로 OAuth 코드를 직접 작성할 필요가 없습니다. MCP는 이 목적을 위해 특별히 설계되었으며, OAuth API로 직접 구현하면 동일한 결과를 위해 더 많은 작업이 필요합니다.
  • 일회성 데이터 내보내기가 필요할 때. 분석이나 백업을 위해 프로젝트 데이터를 한 번만 추출해야 한다면, n8n 연동이나 수동 CSV 내보내기로 개발 시간을 1주일 절약할 수 있습니다.

위의 경우에 해당하지 않는다면, OAuth API가 적합한 도구입니다.

자주 묻는 질문

Quire API를 사용하려면 유료 Quire 플랜이 필요한가요?

아니요. Quire API는 무료 티어를 포함한 모든 플랜에서 사용할 수 있습니다. 모든 플랜에 속도 제한이 적용되며, 현재 앱별 제한은 API 문서에서 확인할 수 있습니다.

Quire API는 어떤 프로그래밍 언어를 지원하나요?

API는 JSON 요청 및 응답 본문을 사용하는 HTTP 기반이므로, HTTP 클라이언트와 JSON 파서를 지원하는 모든 언어에서 사용할 수 있습니다. 이 포스트의 예제는 JavaScript로 작성되었지만, Python, Go, Ruby, PHP 등 다른 언어에서도 동일한 흐름이 적용됩니다. 공식 클라이언트 라이브러리는 없으며, API 표면이 작아 언어의 HTTP 클라이언트를 얇게 래핑하는 것이 일반적인 패턴입니다.

Quire 액세스 토큰의 유효 기간은 얼마나 되나요?

액세스 토큰은 기본적으로 1시간 후에 만료됩니다. 리프레시 토큰은 더 오래 유지되며, 사용자에게 다시 인증을 요청하지 않고도 새 액세스 토큰을 발급받는 데 사용할 수 있습니다. 처음부터 앱에 토큰 갱신 루프를 구현해 두세요.

Quire API를 읽기 전용으로만 사용할 수 있나요?

네. OAuth 스코프를 통해 앱에 필요한 권한만 요청할 수 있습니다. 앱이 업무를 읽기만 한다면 읽기 스코프만 요청하면 됩니다. Quire 사용자는 인증 페이지에서 요청된 스코프를 확인하고, 요청이 과도하다고 느끼면 거부할 수 있으므로 필요 이상의 권한을 요청하면 전환율이 낮아집니다.

Quire API와 Quire MCP 서버의 차이점은 무엇인가요?

API는 사용자를 대신하여 Quire 데이터를 읽거나 수정하려는 모든 앱을 위한 범용 REST 인터페이스입니다. MCP 서버는 Claude 및 기타 LLM 에이전트를 위해 특별히 설계된 것으로, 인증을 처리하고 표준 도구 스키마를 제공하므로 OAuth 코드를 직접 작성할 필요가 없습니다. 전통적인 앱 연동에는 API를, LLM 에이전트 연동에는 MCP를 사용하세요.

다음 단계는 무엇인가요?

지금까지 Quire API의 전체 OAuth 2.0 흐름, 즉 OAuth 앱 설정, 4단계 인증, 액세스 토큰 사용, 그리고 갱신 루프를 살펴보았습니다. 개발자들이 잘 작동하는 연동을 구현했다가 이틀 후 문제가 생기는 가장 흔한 이유는, 토큰 갱신 루프를 나중에 수정할 사항으로 미루고 처음부터 구현하지 않기 때문입니다.

Quire 개발자 앱 콘솔에서 시작하거나 전체 API 참고 문서를 확인하세요. OAuth 코드를 직접 작성하고 싶지 않다면, Quire MCP 서버가 인증을 대신 처리해 주며 LLM 에이전트 연동에 적합한 선택입니다. 이벤트 기반 연동의 경우, 대부분의 첫 번째 API 연동이 결국 사용하게 되는 폴링 패턴보다 웹훅이 더 나은 선택입니다.

Jimmy Shiau
Software Engineer