| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
- c#
- 윈도구
- 링크
- 설치
- 애플
- 아이맥
- screen
- Number
- install
- VISTA
- 오브젝티브C
- mac
- 윈도구7
- windows7
- 아이폰
- java
- 볼링
- 형식
- 맥
- ObjectiveC
- WSDL
- iPhone
- windows
- 윈도우즈7
- WebService
- 7932
- Mobile
- 퇴사
- Objective-C
- cagr48com
- Today
- Total
A colossal Dreamer: GR鐵塔-天生我材
[Jira API] v2 평문으로 읽으면 LLM 토큰을 아낄 수 있을까? 본문
v3 ADF가 아무래도 무거워 보여서 v2 평문으로 읽어봤다.
raw 크기는 정말 절반쯤이었다.
그런데 체크박스의 완료 상태까지 같이 사라지고 있었다. 😑

3줄 요약
Jira description을 v2 평문으로 읽으면 v3 ADF보다 raw payload가 대략 절반 정도로 줄어드는 것으로 보인다.
그런데 우리가 쓰는 taskItem의 DONE/TODO 상태도 같이 사라진다.
그래서 지금은 v3를 버리기보다, 필요한 곳에 v2를 섞어 쓰는 쪽이 적당하지 않을까 생각 중.
발단 — ADF가 좀 무겁지 않나?
LLM Agent가 Jira를 제법 많이 읽기 시작했다.
이슈 하나 읽는 정도야 별일 아닌데,
프로젝트 전체를 훑고, description 읽고, 하위 이슈 보고, 다시 comment를 읽다 보면...
결국 이것도 다 토큰이다.
Jira REST API v3의 description은 ADF(Atlassian Document Format) JSON으로 내려온다.
대충 이런 느낌.
{
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "어쩌고 저쩌고..."
}
]
}
]
}
사람 눈에는 그냥 한 줄인데
꽤 많은 구조물이 따라온다.
그러다가 아침 운영 스레드에서 이런 질문이 나왔다.
"ADF를 사용하지 않고 v2 API를 사용하는 것이 토큰과 기능을 아낄 수 있지 않을까?"
음...
그럴 것 같은데?
v2에서는 description이 평문에 가까운 형태로 내려오니
JSON 구조가 왕창 붙는 v3보다 가벼울 가능성이 높아 보였다.
다만 하나가 걸렸다.
우리는 Jira description에서 체크박스를 꽤 많이 쓴다.
그리고 이 체크박스를 단순한 장식이 아니라
Agent의 작업 완료 여부를 판단하는 데에도 쓰고 있다.
그래서 바로 바꿔보기보다는 몇 가지를 먼저 재보기로 했다.
- 체크박스 상태가 v2에서도 살아 있는가?
- v3에서만 볼 수 있는 구조가 실제로 얼마나 있는가?
- 그래서 크기는 진짜 얼마나 차이 나는가?
1. 체크박스부터 확인
같은 이슈를 v2와 v3로 각각 읽어봤다.
결과는 꽤 명확했다.
이슈v3 ADFv2 평문
| MSVC-2 | taskItem 4개, DONE ×4 | 그냥 * 불릿 |
| RCS-19 | taskItem 3개, DONE ×3 | 상태 흔적 없음 |
| HERPIPE-43 | taskItem 5개, TODO ×5 | 상태 흔적 없음 |
ADF에는 이런 정보가 있다.
taskItem
state: DONE
taskItem
state: TODO
그런데 v2로 읽으면 그냥 목록이다.
완료했는지, 아직 안 했는지...
모른다. ㅡㅡ;;
처음에는
뭐... 체크박스 모양 하나 없어지는 거 아닌가?
싶었는데,
우리 쪽에서는 조금 다르다.
워커 규칙 중에 대략 이런 것이 있다.
미완료 체크박스가 남아 있으면
In Review로 넘기지 않는다.
즉, description 안의 DONE/TODO를 읽어서
작업이 인수조건을 만족했는지 확인하는 구조.
그러니까 v2로 전부 바꾸면,
토큰은 좀 줄일 수 있을지 모르지만
완료와 미완료를 구분하던 근거도 같이 없어지는 셈이다.
음...
이건 좀 크다.
2. 그렇다면 이런 ADF 구조를 얼마나 쓰고 있을까?
몇 개 보고 판단하기에는 애매해서
운영 중인 프로젝트 description을 한번 전부 훑어봤다.
대상은
- RCS
- HERPIPE
- MSVC
세 프로젝트.
ADF node를 종류별로 세어보니 대략 이랬다.
| 노드 | 개수 | v2에서 |
| taskItem | 280 | 상태 소실 |
| taskList | 70 | 일반 목록 형태 |
| inlineCard | 298 | URL 문자열로 남음 |
| table | 1곳 / 9 cell | 평문으로 풀림 |
| codeBlock | 3 | 텍스트로 대체로 남음 |
영향받는 이슈는 69건 정도.
생각보다 ADF 구조를 많이 쓰고 있었다.
그런데 하나씩 보니
ADF 구조가 없어지는 것 자체가 모두 문제는 아니었다.
예를 들어 inlineCard.
Jira에서 URL 붙이면 예쁘게 카드처럼 나오는 그것.
v3에서는
{
"type": "inlineCard",
"attrs": {
"url": "https://..."
}
}
이런 구조인데,
v2에서는 대략 wiki 스타일 문자열로 내려온다.
[https://...|https://...|smart-link]
예쁘지는 않지만...
URL은 있다.
codeBlock도 비슷했다.
구조는 없어져도 내용은 대체로 남았다.
table도 평문으로 풀어쓰면
보기는 좀 망가지지만 내용을 못 읽는 수준은 아니었다.
이렇게 놓고 보면,
우리 환경에서는 ADF 구조 중 실제로 신경 쓰이는 것은
아무래도 taskItem의 state 쪽이었다.
3. 그래서 얼마나 작아지는데?
이제 처음 질문으로 돌아갔다.
v2로 읽으면 정말 토큰을 아낄까?
자동링크 inlineCard가 많이 들어 있는 이슈 3개를 골라서
v2/v3 원문 크기를 비교해봤다.
| 이슈 | inlineCard | v2 raw | v3 raw | 비율 |
| 아침 보고 | 77 | 9,997B | 20,006B | 2.0x |
| 이슈 A | 60 | 8,151B | 16,301B | 2.0x |
| 이슈 B | 31 | 4,383B | 9,166B | 2.1x |
오...
정말 두 배네?
처음 직관은 대략 맞아 보였다.
다만 여기서 하나 조심할 것이 있었다.
이 숫자는 LLM tokenizer로 센 token 수가 아니라 raw byte 크기다.
그리고 우리 Agent가 Jira API 응답 JSON을 그대로 LLM에 집어넣는 것도 아니다.
중간에 텍스트를 추출한다.
즉,
Jira API
↓
ADF JSON
↓
text extractor
↓
LLM context
이런 구조.
그러니까
raw JSON이 2배라고 해서 실제 LLM token도 정확히 2배라고 보기는 어렵다.
오히려 우리가 궁금해야 할 것은
API에서 몇 byte 받았나?
보다
최종적으로 LLM에게 몇 글자/토큰을 넘겼나?
쪽에 가까웠다.
처음 질문이 살짝 바뀌었다.
4. 그런데 이상한 숫자 하나
텍스트 추출 결과도 비교해봤다.
어떤 이슈 하나가
v2 추출: 21,605자
v3 추출: 3,764자
...
이건 또 너무 차이가 크다.
ADF가 아무리 구조적이어도
본문 내용 자체가 여섯 배씩 달라질 이유는 없어 보였다.
확인해보니 다른 문제가 있었다.
우리 ADF → text 추출기가 inlineCard의 URL을 버리고 있었다. 😑
즉,
{
"type": "inlineCard",
"attrs": {
"url": "https://..."
}
}
를 만나면
URL을 텍스트 결과에 넣지 않고 그냥 지나가고 있었다.
반면 v2에서는 URL 자체가 문자열이니까
그대로 남는다.
처음에는
v2가 텍스트 보존을 더 잘하네?
라고 생각할 수도 있었는데,
조금 더 까보니 Jira API의 문제가 아니라
우리 코드의 문제에 가까웠다.
이건 v3를 그대로 쓰면서도 고칠 수 있다.
ADF extractor에
inlineCard → attrs.url 포함
정도만 넣어주면 될 듯.
토큰 줄여보겠다고 시작했는데
엉뚱하게 자체 버그 하나를 주웠다. 💪
5. 그래서 v2로 갈아탈까?
여기까지 해보고 나니
처음 질문에 그냥 Yes/No로 답하기가 조금 애매해졌다.
v2가 좋아 보이는 부분
단순 조회라면 아무래도 가볍다.
특히 URL 카드가 많이 들어 있는 description은
raw 기준으로 절반 정도까지 줄어드는 경우가 있었다.
다음 같은 작업이라면 꽤 쓸 만할 것 같다.
- 이슈 목록 읽기
- description 요약
- 링크 수집
- 사람이 보기 위한 리포트
- task 상태와 무관한 검색
이런 경우에는
굳이 ADF 전체 구조를 받을 필요가 있을까?
싶다.
그런데 v3가 필요한 부분
반대로,
- taskItem DONE/TODO 확인
- 인수조건 검사
- 작업 완료 판정
- description 수정
- 구조를 유지해야 하는 작업
같은 경로는 아직 v3 ADF가 필요해 보인다.
우리 쪽에서는 특히
미완료 체크박스 존재
↓
In Review 전이 금지
가 있기 때문에,
taskItem state를 포기하면서까지
v2로 단순화할 이유는 크지 않아 보였다.
지금 생각은 — 전환보다는 병행
그래서 지금 생각은 대략 이쪽이다.
Jira
│
┌────────┴────────┐
│ │
상태 필요 없음 상태 필요
│ │
API v2 API v3
평문 ADF
│ │
가볍게 읽기 구조까지 읽기
SDK에 예를 들어
issue_text_v2(key)
같은 가벼운 helper를 하나 두고,
상태가 필요 없는 읽기에서만 v2를 사용하는 방식.
기존 v3 경로를 없애기보다는
읽는 목적에 따라 하나 더 만들어두는 것이 조금 편하지 않을까 싶다.
아직 실제 전체 Agent workload를 tokenizer 기준으로 비교해본 것은 아니어서
v2 병행의 최종 절감폭이 얼마나 될지는 조금 더 봐야 할 것 같다.
raw에서는 2배 차이가 보였지만,
실제 LLM 앞단에서는 extractor가 있으니까.
이번 삽질에서 얻은 것 몇 가지
1. 가벼운 포맷이 항상 싼 것은 아닌 듯
처음에는 단순했다.
ADF JSON 큼
↓
v2 text 작음
↓
토큰 절약
그런데 중간에 state가 있었다.
ADF JSON 큼
↓
v2 text 작음
↓
task state도 없어짐
↓
우리 Worker는 완료 여부 모름
크기만 보면 v2가 싸다.
그런데 빠지는 정보가
업무 규칙에 쓰이는 값이라면 계산이 달라질 수 있다.
2. raw 크기보다 LLM 직전의 크기를 보는 것이 맞을 듯
이번 실측에서 raw payload는 꽤 예쁘게 2배 차이가 났다.
하지만 우리 구조에서는 API 결과가 바로 LLM으로 가지 않는다.
API → Parser → Extractor → Prompt → LLM
그러니까 토큰 최적화를 하려면
앞단 API보다 Prompt 직전을 재는 것이 조금 더 맞을 듯하다.
이건 다음에 tokenizer까지 붙여서 한번 더 재볼 생각.
3. 상태는 생각보다 비싸다
DONE/TODO라고 해봐야 값 하나다.
그런데 그 한 값이
작업 완료?
검수 가능?
In Review 이동?
을 결정한다.
표현 정보 하나쯤으로 생각했던 것이
우리 파이프라인에서는 사실상 작은 상태 DB 역할을 하고 있었다.
이걸 없애려면 토큰보다 더 많은 것을 다시 만들어야 할 수도 있다.
4. 전수로 세어보니 생각이 좀 편해졌다
처음에는
taskItem 많이 쓰나?
inlineCard가 그렇게 많은가?
정도의 감이었다.
직접 세어보니
taskItem 280
inlineCard 298
영향 이슈 69
정도.
숫자를 보고 나니
뭘 중요하게 봐야 할지가 조금 명확해졌다.
아마 이런 건 몇 건 샘플보다
한번 긁어서 세어보는 게 빠른 듯.
일단 여기까지
처음 질문은 이것이었다.
Jira v2 평문 API로 읽으면 토큰을 아낄 수 있을까?
지금까지 본 것으로는,
아낄 여지는 꽤 있어 보인다.
특히 ADF raw payload 자체는
링크가 많은 이슈에서 v2 대비 약 2배 정도 컸다.
그런데 그것만 보고 전체를 v2로 내리기에는
taskItem 상태가 빠지는 비용도 생각보다 컸다.
그래서 당장은
v3를 유지하면서 v2를 필요한 읽기에만 섞어보는 쪽.
그리고 inlineCard URL을 버리던 우리 extractor부터 고치는 걸로. 😑
한 줄짜리 질문이었는데...
또 파다 보니 API 선택이 아니라
데이터의 어느 상태를 어디까지 보존할 것인가 쪽 이야기까지 왔다.
뭐... 늘 그렇듯.
토큰 조금 아껴보려다가
설계 하나 더 생겼다. 💪
'Development' 카테고리의 다른 글
| nvidia 딥러닝 학습 참조링크 (0) | 2024.10.29 |
|---|---|
| 기존 코드에 새로운 대체모듈 적용과정 (0) | 2023.05.02 |
| 노란소농장 10년 채워가면서... (0) | 2021.03.04 |
| PlantUML 쓸만한 UML도구..! (0) | 2019.12.20 |
| HPBN한 번 읽어 보시죠. 고성능브라우저네트워킹 (0) | 2019.12.10 |