Jira 커넥터
Jira Cloud 인스턴스를 Brevo에 연결하여 Tajo를 통해 고객 대면 이슈 추적, 지원 티켓 가시성, 프로젝트 마일스톤 알림을 구현하세요.
개요
| 속성 | 값 |
|---|---|
| 플랫폼 | Jira Cloud |
| 카테고리 | Custom |
| 설정 난이도 | 보통 |
| 공식 통합 | 아니오 |
| 동기화되는 데이터 | 이슈, 프로젝트, 사용자, 이벤트 |
| API 유형 | REST API v3 |
| 인증 | OAuth 2.0 (3LO) / API Token (Basic Auth) |
| Base URL | https://your-domain.atlassian.net/rest/api/3/ |
주요 기능
- 이슈 이벤트 동기화 - 이슈 생성, 업데이트, 해결 이벤트를 Brevo 연락처 타임라인으로 전달합니다
- 고객 티켓 추적 - 지원 가시성을 위해 Jira 이슈를 Brevo 연락처에 연결합니다
- 프로젝트 마일스톤 알림 - 버전 릴리스 및 스프린트 완료 시 Brevo 캠페인을 트리거합니다
- 팀 용량 데이터 - 운영 대시보드를 위해 업무량 지표를 동기화합니다
- 상태 변경 이벤트 - 이슈 워크플로우 전환을 Brevo 이벤트로 추적합니다
- 코멘트 동기화 - 고객 대면 코멘트를 Brevo 활동 로그로 전달합니다
사전 준비 사항
시작하기 전에 다음 사항이 준비되어 있어야 합니다.
- Jira Cloud 인스턴스 (Jira Software, Jira Service Management, Jira Work Management)
- OAuth 앱을 생성하거나 API 토큰을 발급할 수 있는 관리자 액세스
- API 토큰과 연결된 Atlassian 계정 이메일
- API 액세스가 활성화된 Brevo 계정
- 활성 구독이 있는 Tajo 계정
인증
Jira Cloud는 여러 인증 방식을 지원합니다.
옵션 1: OAuth 2.0 (3LO) - 권장
- developer.atlassian.com으로 이동합니다
- Create > OAuth 2.0 integration을 클릭합니다
- 콜백 URL을 구성합니다:
https://app.tajo.io/callbacks/jira - 다음 스코프를 추가합니다.
read:jira-workread:jira-userwrite:jira-workread:meOAuth 2.0의 API URL 구조:
https://api.atlassian.com/ex/jira/{cloudId}/rest/api/3/{resource}옵션 2: API Token (Basic Auth)
- id.atlassian.com/manage/api-tokens으로 이동합니다
- Create API token을 클릭합니다
- 이름을 “Tajo Integration”으로 지정합니다
# Basic Auth: email as username, API token as passwordcurl -X GET "https://your-domain.atlassian.net/rest/api/3/myself" \ -H "Accept: application/json"API 토큰 제한
API 토큰은 개별 사용자 계정에 연결됩니다. 사용자가 비활성화되면 통합이 중단됩니다. 프로덕션 배포에는 OAuth 2.0을 사용하세요.
Tajo에 연결
# Using OAuth 2.0tajo connectors install jira \ --client-id $JIRA_CLIENT_ID \ --client-secret $JIRA_CLIENT_SECRET \ --cloud-id $JIRA_CLOUD_ID
# Using API Tokentajo connectors install jira \ --site-url your-domain.atlassian.net \ --api-token $JIRA_API_TOKEN설정
기본 설정
connectors: jira: enabled: true site_url: "your-domain.atlassian.net" auth_type: "oauth2" # or "basic"
sync: issues: true projects: true users: true comments: true worklogs: false
projects: - key: "SUPPORT" sync_to_list: 22 - key: "PRODUCT" sync_to_list: 23
issue_types: - Bug - Story - Task - Support Request필드 매핑
Jira 이슈 및 사용자 필드를 Brevo 속성에 매핑합니다.
field_mapping: # User fields accountId: JIRA_ACCOUNT_ID emailAddress: email displayName: FIRSTNAME
# Issue fields mapped to contact events issue_key: LAST_TICKET_KEY issue_status: LAST_TICKET_STATUS issue_priority: LAST_TICKET_PRIORITY issue_created: LAST_TICKET_DATE resolution: LAST_TICKET_RESOLUTIONAPI 엔드포인트
Tajo는 다음 Jira Cloud REST API v3 엔드포인트와 통합됩니다.
| 엔드포인트 | Method | 용도 |
|---|---|---|
/rest/api/3/search | POST | JQL을 사용한 이슈 검색 |
/rest/api/3/issue/{issueIdOrKey} | GET | 이슈 세부 정보 조회 |
/rest/api/3/issue | POST | 이슈 생성 |
/rest/api/3/project | GET | 모든 프로젝트 목록 |
/rest/api/3/project/{projectIdOrKey} | GET | 프로젝트 세부 정보 조회 |
/rest/api/3/user/search | GET | 사용자 검색 |
/rest/api/3/myself | GET | 현재 사용자 조회 |
/rest/api/3/issue/{issueIdOrKey}/comment | GET | 이슈 코멘트 조회 |
/rest/api/3/webhook | POST | 웹훅 등록 |
/rest/api/3/status | GET | 모든 상태 조회 |
/rest/api/3/priority | GET | 모든 우선순위 조회 |
코드 예제
커넥터 초기화
import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({ apiKey: process.env.TAJO_API_KEY, brevoApiKey: process.env.BREVO_API_KEY});
await tajo.connectors.connect('jira', { clientId: process.env.JIRA_CLIENT_ID, clientSecret: process.env.JIRA_CLIENT_SECRET, cloudId: process.env.JIRA_CLOUD_ID});지원 이슈 동기화
// Sync Jira support issues to Brevo contactsawait tajo.connectors.sync('jira', { type: 'incremental', resources: ['issues'], jql: 'project = SUPPORT AND updated >= -24h', batchSize: 50});
const status = await tajo.connectors.status('jira');console.log(status);// {// connected: true,// lastSync: '2024-03-15T12:00:00Z',// issuesTracked: 4560,// projectsMonitored: 3,// usersLinked: 890// }Jira 웹훅 처리
app.post('/webhooks/jira', async (req, res) => { const event = req.body;
await tajo.connectors.handleWebhook('jira', { event: event.webhookEvent, payload: { issueKey: event.issue?.key, issueType: event.issue?.fields?.issuetype?.name, status: event.issue?.fields?.status?.name, reporter: event.issue?.fields?.reporter?.emailAddress, assignee: event.issue?.fields?.assignee?.emailAddress } });
res.status(200).send('OK');});고객별 이슈 검색
// Find all issues reported by a specific customerconst issues = await tajo.connectors.query('jira', { maxResults: 20, fields: ['summary', 'status', 'priority', 'created']});요청 제한
Jira Cloud는 플랫폼 안정성을 위해 요청 제한을 적용합니다.
| 컨텍스트 | 요청 제한 |
|---|---|
| REST API | 사용자당 10초당 약 100회 |
| 동시 요청 | 장시간 실행 요청 동시 10개 |
| 대량 작업 | 엔드포인트에 따라 다름 |
페이지네이션
Jira는 startAt 및 maxResults 파라미터를 사용한 오프셋 기반 페이지네이션을 사용합니다. 기본 페이지 크기는 50이며 최대 100입니다. Tajo는 페이지네이션을 자동으로 처리합니다.
요청 제한을 초과하면 Jira는 재시도 시점을 나타내는 Retry-After 헤더와 함께 429 Too Many Requests 응답을 반환합니다.
문제 해결
일반적인 문제
| 문제 | 원인 | 해결 방법 |
|---|---|---|
| 401 Unauthorized | 유효하지 않은 토큰 또는 만료된 OAuth | OAuth 토큰을 새로 고치거나 API 토큰을 재생성하세요 |
| 403 Forbidden | 권한 부족 | 사용자가 요청된 프로젝트에 액세스 권한이 있는지 확인하세요 |
| JQL 오류 | 유효하지 않은 쿼리 구문 | 먼저 Jira 이슈 검색에서 JQL을 검증하세요 |
| 웹훅 수신 안 됨 | 방화벽 차단 | 웹훅 URL이 공개적으로 접근 가능한지 확인하세요 |
| 필드 누락 | 응답에 필드가 없음 | fields 파라미터에 필드를 추가하거나 expand를 사용하세요 |
디버그 모드
connectors: jira: debug: true log_level: verbose log_api_calls: true연결 테스트
tajo connectors test jira# ✓ API authentication successful# ✓ Project access verified# ✓ Issue search operational# ✓ User lookup available# ✓ Webhook registration active모범 사례
- 프로덕션에는 OAuth 2.0 사용 - 개별 사용자 계정에 대한 의존성을 피합니다
- JQL로 필터링 - API 호출을 줄이기 위해 관련 이슈만 동기화하세요
- 실시간을 위해 웹훅 사용 - 폴링을 피하고 이슈 변경에 웹훅을 등록하세요
- ADF 형식 준수 - Jira v3는 리치 텍스트 필드에 Atlassian Document Format을 사용합니다
- 프로젝트-리스트 매핑 - Jira 프로젝트별로 별도의 Brevo 리스트를 생성하세요
- 페이지네이션 처리 - 완전한 데이터를 위해 항상 모든 페이지를 순회하세요
보안
- OAuth 2.0 (3LO) - 리프레시 토큰이 포함된 안전한 토큰 기반 인증
- API Token + Basic Auth - HTTPS를 통한 Base64 인코딩된 자격 증명
- HTTPS 전용 - 모든 API 통신은 TLS 1.2+를 통해 암호화됩니다
- 스코프 액세스 - OAuth 스코프는 API 액세스를 필요한 리소스로 제한합니다
- Atlassian Cloud 보안 - SOC 2 Type II 인증 인프라
- 암호화된 저장소 - Tajo의 자격 증명은 저장 시 암호화됩니다