developers · Oct 1, 2019

히어로가 되어 보세요: Quire API로 나만의 앱 만들기

✦
AI 번역
· 영어로 보기

Quire OAuth 2.0 API 앱 개발 인증 흐름

최종 업데이트: 2026년 7월 20일

TL;DR

Quire OAuth 2.0 API를 사용하면 앱이 사용자의 비밀번호를 저장하지 않고도 Quire 계정에서 작업할 수 있습니다. 등록된 OAuth 앱(클라이언트 아이디, 보안 키, 리디렉션 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 웹훅 푸시 방식, 폴링 부담 없음, 간단한 설정
Quire를 Claude 또는 다른 AI 에이전트에 연결 Quire MCP 서버 LLM 도구용 표준 프로토콜, 사전 구축된 서버 제공
Quire를 자동화 또는 BI 워크플로에 연결 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

클라이언트 아이디, 클라이언트 보안 키, 콜백 URL이 표시된 Quire OAuth 앱 설정 화면

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(사이트 간 요청 위조) 공격을 막기 위한 무작위 문자열입니다. 문자열을 무작위로 생성하세요. 이 값은 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를 지정했다면 필수입니다. 값은 2단계에서 사용한 값과 같아야 합니다.

액세스 토큰 요청 예제:

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 내보내기로 개발 시간을 일주일쯤 아낄 수 있습니다.

이 중 어디에도 해당하지 않는다면 OAuth API가 알맞은 도구입니다.

Quire 대시보드 뷰: 프로젝트 전체를 한눈에 보여 주는 하나의 뷰

자주 묻는 질문

Quire API를 사용하려면 유료 Quire 요금제가 필요한가요?

아니요. Quire API는 무료 요금제를 포함한 모든 요금제에서 사용할 수 있습니다. 모든 요금제에 요청 제한이 적용되며, 앱별 현재 제한은 API 문서에서 확인하세요.

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

API는 HTTP 기반이며 요청과 응답 본문이 JSON이므로, HTTP 클라이언트와 JSON 파서가 있는 언어라면 무엇이든 사용할 수 있습니다.

이 글의 예제는 JavaScript이지만, 같은 흐름이 Python, Go, Ruby, PHP 등 다른 언어에서도 똑같이 동작합니다. 공식 클라이언트 라이브러리는 없습니다. API 규모가 작아서 사용하는 언어의 HTTP 클라이언트를 가볍게 감싼 래퍼를 쓰는 것이 일반적입니다.

Quire 액세스 토큰은 얼마나 오래 유지되나요?

액세스 토큰은 기본적으로 1시간 후 만료됩니다. 리프레시 토큰은 더 오래 유지되며, 사용자에게 다시 묻지 않고도 새 액세스 토큰을 받는 데 쓸 수 있습니다. 리프레시 토큰 루프는 첫날부터 앱에 구현하세요.

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

네. OAuth 범위(scope)를 지정하면 앱에 필요한 권한만 요청할 수 있습니다. 앱이 업무를 읽기만 한다면 읽기 범위만 요청하세요. 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를 연동하는 분들이 흔히 택하는 폴링 방식보다 웹훅이 대체로 더 알맞습니다. OAuth 앱을 만들지 않고 빠른 변경만 스크립트로 처리하고 싶다면 Quire CLI로 터미널에서 바로 프로젝트 관리 명령을 실행할 수 있습니다.

Jimmy Shiau
Software Engineer