giip
SES Proposal
13 min read

이슈 관리 API 레퍼런스

GIIP 플랫폼에서 발생하는 이슈 및 에러 로그를 프로그래밍 방식으로 조회하고 상태를 업데이트하는 API를 안내합니다.

🔌 이슈 관리 기능 페이지로 이동 →

📋 개요

이 API 모듈은 실시간 이슈 관리 솔루션인 [이슈 관리] 메뉴의 데이터를 외부 시스템과 동기화하거나, 장애 대응 파이프라인(ITSM 등)과 연동하기 위해 사용됩니다.

🔐 인증 (Authentication)

이 API가 받아들이는 키의 종류, 키를 전달하는 방식, 그리고 오류 원인을 실제 서버 코드 (giipfaw/giipIssues/run.ps1, giipfaw/giipIssueComments/run.ps1, 대응 pApiGiipIssue*byAK SP군)와 라이브 API 실측(giipfaw, 2026-08-20) 양쪽으로 확인한 내용을 기준으로 설명합니다. 공통 AK/SK 용어 정의는 API 레퍼런스 개요 → 인증 을 참조하세요.

x-api-key 는 HTTP 헤더의 "이름"이지, 별도의 자격증명 종류가 아닙니다. 유효한 프로젝트 SK, 사용자 고정 키, 로그인 세션 AK 중 하나를 이 헤더의 값으로 바로 넣으세요. 프로젝트 SK 를 쓴다면 별도의 "API 키"를 발급할 필요가 없습니다.

키 전달 방식 — 헤더만 지원 (실측)

전달 방식지원 여부
x-api-key: <key> 헤더✅ 지원(권장)
Authorization: Bearer <key> 헤더✅ 지원(대체 가능)
JSON 바디 { "token": "<key>" }미지원(서버 코드가 읽지 않음. 전달해도 401 Auth required)
쿼리 문자열 ?token=<key>미지원/지원중단(위와 동일. 게다가 키를 쿼리 문자열에 싣는 방식 자체가 서버 로그·브라우저 기록·프록시 로그에 키를 남기므로 보안상 사용해서는 안 됩니다)

이 문서의 이전 버전에는 "Body/Query로도 전달 가능"이라는 내용이 있었지만, giipIssues/giipIssueCommentsrun.ps1$Request.Headers["x-api-key"] → 실패 시 Authorization 헤더, 이 2가지만 읽으며 실제로는 동작하지 않습니다(2026-08-20, 코드 확인 + 라이브 실측으로 삭제 확정). 키는 반드시 헤더로 전달하세요.

키의 종류(3가지, 권한 범위가 다름)

종류실체발급 단위권한 범위발급/확인검증 방법
프로젝트 SK(권장·에이전트용)tSecretKey.SKey프로젝트(csn)당 1개그 csn만. 호출자 개인은 특정되지 않는 공유 키(코멘트 등록 시 author는 클라이언트가 지정한 값이 그대로 사용됨 — 실측 확인)/svclist(서비스 목록) 화면에서 발급/재발급아래 "인증 확인 절차" 참조
사용자 고정 키(tCorpUser.uSecretKey)동일사용자(usn)당 1개해당 사용자 본인이 속한 csn(tUserPerCorp/tCorpUserRel). 관리자 권한(uLevel≥99) 사용자라면 전체 csn관리자가 발급(giipv3 사용자 관리 화면)동일
로그인 세션 AKtUserLogin.AccToken로그인할 때마다 신규 발급, 24시간 후 만료로그인한 사용자 본인과 동일한 권한브라우저 로그인 시 자동 발급(sessionStorage)동일

세 종류 모두 같은 x-api-key 헤더로 전달하면 서버가 자동으로 판별합니다(lwGetUSNbyat → 실패 시 lwGetUSNbysk로 폴백하는 체인). 응답만으로는 호출자가 어떤 종류를 썼는지 구분할 수 없습니다(성공/실패 동작은 동일)만, 권한 범위(어느 csn에 접근 가능한지)는 종류마다 다릅니다.

이번 세션의 실측은 주로 프로젝트 SK(giip-accounts.json에 등록된 실운영 SK)로 진행했습니다. 사용자 고정 키·로그인 세션 AK는 이 세션에서 브라우저 로그인으로 신규 발급할 수 없어 소스 코드 분석으로만 확인했습니다(lwGetUSNbyat.sql의 3단계 폴백 로직에서 존재를 확인함. 라이브 신규 발급·실측은 수행하지 않음 — 솔직히 밝힙니다).

SK의 조건(전부 실측+코드 확인)

  • 발급 위치: giipv3의 /svclist(서비스 목록) 화면. 프로젝트(csn)당 1개.
  • 활성화 확인: tSecretKey.SKStatus = 1일 때만 유효합니다. 재발급/회전하면 이전 SK는 즉시 SKStatus = 0이 되고, 이후 401 Invalid session을 반환합니다(giip #1265에서 실측: 활성 SK→200, 비활성화된 SK→401 둘 다 확인).
  • 연결 csn: tSecretKey.CSn에 1:1로 고정됩니다. (관리자 권한이 아닌 한) 다른 csn에는 접근할 수 없습니다 (아래 "csn 권한 불일치 시 동작" 참조).
  • 필요 권한: SK 자체가 해당 csn 접근 권한을 나타내므로 추가 권한 설정이 필요 없습니다.
  • 만료 여부: 시간 경과로 자동 만료되지 않습니다(로그인 세션 AK와 달리 24시간 제한 없음). 비활성화되는 경우는 재발급/회전 시뿐입니다.
  • 허용 엔드포인트: GET/POST/PUT /api/giipIssues, GET/POST /api/giipIssueComments 전부에서 사용 가능(실측 확인). 단 giipApiSk2 경유 GiipIssuePut 커맨드는 전체 덮어쓰기 SP라 별개이므로 쓰기에는 쓰지 마세요(아래 "방법 2" 참조).
  • 키 검증용 읽기 API: 쓰기(POST/PUT) API를 호출하기 전, 부작용 없는 GET /api/giipIssues로 먼저 키가 유효한지 안전하게 확인할 수 있습니다(아래 "인증 확인 절차" 참조).
  • 재발급 방법: /svclist 화면에서 대상 csn의 SK를 재생성합니다(이전 SK는 즉시 무효화되므로, 이 키에 의존하는 자동화가 있다면 함께 갱신하세요).

인증 확인 절차(쓰기 전 안전하게 검증)

쓰기 API(POST/PUT)를 호출하기 전에, 부작용 없는 GET으로 키의 유효성을 먼저 확인하세요.

curl -s -o /dev/null -w "%{http_code}\n" \
  "https://giipfaw.azurewebsites.net/api/giipIssues?csn=47" \
  -H "x-api-key: ${GIIP_API_KEY}"
  • 성공 시(200): {"issues":[...]} — 이 키를 그대로 생성/상태변경 API에 사용할 수 있습니다.
  • 실패 시(401): {"error":"Auth required"}(헤더 자체가 없거나 읽히지 않음) 또는 {"error":"Invalid session"}(키는 있지만 무효 — 자세한 내용은 아래 "401 Invalid session 원인 분류" 참조). 이 경우 생성 API를 실행하지 마세요.

🚀 주요 API 엔드포인트 (실제 구현 기준)

이슈 API는 두 경로 모두 정상 동작합니다. 신규 등록·코멘트 등 CRUD는 전용 REST 엔드포인트(giipv3 어드민 UI가 실제 사용하는 경로)를, SP 직접 호출은 giipApiSk2 래퍼를 사용합니다.

1. 이슈 전용 엔드포인트 (REST API)

가장 직관적인 호출 방식이며, giipv3 어드민 UI가 실제 사용하는 경로입니다. 인증은 x-api-key 헤더, Content-Type은 application/json. 키는 환경변수로 전달하고 하드코딩하지 마세요.

  • 신규 등록: POST /api/giipIssuesisn을 생략(또는 0)하면 신규 이슈가 INSERT되고 새 isn을 반환합니다.
curl -s -X POST "https://giipfaw.azurewebsites.net/api/giipIssues" \
  -H "x-api-key: ${GIIP_API_KEY}" -H "Content-Type: application/json" \
  -d '{ "title":"제목(필수)", "content":"본문", "status":"PENDING",
        "csn":47, "target_lssn":null, "agent_workflow":null }'
  • 성공: { "isn":577, "message":"Issue created", "success":true } (실측: 2026-08-20, isn 1282로 확인 후 삭제)
  • 목록 조회: GET /api/giipIssues?status=READY&csn=47(csn 지정 권장 — 생략하면 키 권한 범위 내 전체 csn 반환)
  • 상세 조회: GET /api/giipIssues?isn=7890
  • 상태 업데이트/완료: PUT /api/giipIssues
    • Body: { "isn":7890, "status":"DONE" }{ "success":true }
  • 코멘트 등록: POST /api/giipIssueComments
    • Body: { "isn":7890, "content":"처리 완료", "author":"api-tester", "issuetype":"comment" }{ "success":true }
    • 코멘트 조회: GET /api/giipIssueComments?isn=7890{ "comments":[...] }

전달 방식 요약 (실측, 2026-08-20)

엔드포인트x-api-key 헤더Authorization: Bearer 헤더JSON 바디 token쿼리 ?token=
GET /api/giipIssues✅ 실측 200✅ 실측 200❌ 미지원(401)❌ 실측 401
POST /api/giipIssues(생성)✅ 실측 200코드 동일(미실측·고신뢰)❌ 실측 401❌ 실측 401
PUT /api/giipIssues(상태변경)✅ 실측 200코드 동일(미실측·고신뢰)❌ 실측 401코드 동일(미실측·고신뢰)
POST /api/giipIssueComments✅ 실측 200코드 동일(미실측·고신뢰)❌ 실측 401❌ 실측 401
GET /api/giipIssueComments✅ 실측 200코드 동일(미실측·고신뢰)❌ 미지원❌ 미지원(미실측·고신뢰)

"코드 동일(미실측·고신뢰)"은 4개 엔드포인트 모두의 인증 추출 코드($Request.Headers["x-api-key"] → 실패 시 Authorization 헤더, 이 2가지뿐)가 giipfaw/giipIssues/run.ps1·giipIssueComments/run.ps1에서 완전히 동일함을 소스로 확인한 뒤의 추정입니다(전체 20칸을 매번 실행하지는 않았고, 주요 칸을 실측하고 나머지는 코드 리뷰로 대체했습니다).

인증 오류 시 동작(2026-08-24 라이브 실측): 이 문서의 이전 버전에는 GET /api/giipIssueComments가 무효한 키에도 HTTP 200을 반환하는 알려진 버그가 있다는 기록이 있었지만, 이는 수정되었습니다(giip #1285). 현재는 GET /api/giipIssues와 동일하게 동작하며, 무효한 키에는 HTTP 401 {"error":"Invalid session"}을 반환합니다(2026-08-24, giipfaw API에 대해 라이브 실측으로 확인). 인증 성공/실패는 HTTP 상태 코드로 판정하면 됩니다.

csn 권한 불일치 시 동작 (401 아님)

키는 유효하지만 대상 csn에 접근 권한이 없는 경우, 401이 되지 않습니다(실측 확인, 2026-08-20).

호출실측 결과
GET /api/giipIssues?csn=<권한없음>200 {"issues":[]}(빈 배열. 오류 아님)
POST /api/giipIssues에서 csn에 권한 없는 값을 지정200으로 성공하지만, 지정한 csn은 무시되고 키 자신의 홈 csn으로 조용히 클램프(clamp)됨(실측: csn70335의 SK로 csn:47 지정 → 실제로는 cSn:70335로 생성됨)
특정 isn의 GET/PUT/코멘트 등록에서 대상 이슈의 csn에 권한이 없음404 {"error":"Issue not found or no permission"}

지원 상태값과 다중 상태 조회 패턴

지원 상태값 (실측 확인, 2026-08-27):

상태값의미
PENDING등록됨, 미처리
READY처리 준비 완료
IN_PROGRESS처리 중
REVIEW사람 검토 대기
TESTED테스트 완료, 최종 검수 대기
WARN경고·조건부 완료
DONE완료

다중 상태 조회 — 단일 필터 완전일치만 지원 (중요):

GET /api/giipIssues?status=TESTED,REVIEW 또는 status=TESTED|REVIEW 형태의 OR 조회는 지원하지 않습니다. 쉼표·파이프·파라미터 반복은 모두 단일 완전일치 문자열로 인식되어 의도대로 동작하지 않습니다.

대량 처리 워크플로우(예: /gissue-final-review)에서 TESTEDREVIEW를 모두 처리해야 할 때는 각 상태를 개별적으로 조회한 뒤 클라이언트에서 순서대로 결합합니다:

# 1. TESTED 먼저 조회
TESTED_ISSUES=$(curl -s "https://giipfaw.azurewebsites.net/api/giipIssues?status=TESTED&csn=47" \
  -H "x-api-key: ${GIIP_API_KEY}")

# 2. REVIEW 조회
REVIEW_ISSUES=$(curl -s "https://giipfaw.azurewebsites.net/api/giipIssues?status=REVIEW&csn=47" \
  -H "x-api-key: ${GIIP_API_KEY}")

# 3. 클라이언트에서 TESTED → REVIEW 순서로 결합
# (jq, Python, JS 등 사용)

주의: 조회 시점 기준 큐 스냅샷이므로, TESTED 처리 중에 새로운 REVIEW가 들어올 수 있습니다. 워크플로우의 "최초 스냅샷" 기준을 지키려면 두 쿼리를 동시에 실행하고, 이후 추가된 이슈는 다음 실행 주기에 처리 대상으로 둡니다.

코멘트 전량 조회:

GET /api/giipIssueComments?isn=<isn>는 대상 이슈의 전체 코멘트를 시간순으로 반환합니다. AI 에이전트의 최종 검수 워크플로우(/gissue-final-review)에서는 작업자의 완료 보고나 Actionflow SUCCESS 코멘트를 검증할 주장이지 합격 증거로 취급하지 않습니다 — repo·PR·화면·DB를 직접 대조해 독립 증거를 확보해야 합니다.

🤖 AI 에이전트용 전체 절차(등록 → 확인 → 부분 업데이트 → 코멘트)

ChatGPT/Codex 등의 AI 에이전트가 이슈 신규 등록·부분 업데이트·코멘트 추가를 안전하게 실행하기 위한 일련의 절차입니다. 모든 쓰기 전후에 GET으로 확인합니다. 비밀 정보는 x-api-key 헤더에만 넣고, body/query에는 넣지 마세요.

부분 업데이트(title/content/status) — 전체 덮어쓰기가 아님

전용 REST PUT /api/giipIssues부분 업데이트입니다. 내부 SP pApiGiipIssuePutbyAK가 각 필드를 ISNULL(@value, existing)로 갱신하므로, JSON에 포함하지 않은 필드는 기존 값을 유지합니다(2026-08-24, SP 소스 확인). 갱신 가능 필드: title / content / status / target_lssn / agent_workflow(그리고 권한이 있으면 csn).

# title과 content만 갱신(status나 다른 필드는 기존 값 그대로)
curl -sS -X PUT "https://giipfaw.azurewebsites.net/api/giipIssues" \
  -H "x-api-key: ${GIIP_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"isn":1474,"title":"Revised title","content":"Revised body"}'
  • 변경하지 않을 필드는 JSON에 포함하지 마세요(포함하면 덮어써집니다).
  • 빈 문자열은 "미지정"이 아닙니다. "title":""를 보내면 제목이 빈 값으로 덮어써집니다. 비울 의도가 아니라면 보내지 마세요.
  • Sk2의 GiipIssuePut은 전체 덮어쓰기 SP(pApiGiipIssuePutbySK)이므로 편집에는 사용 금지입니다(제목·본문이 파괴됩니다. 방법 2 참조). 전용 REST PUT을 쓰세요.

긴 content(4,000자 초과도 가능)

content는 SP 쪽에서 OPENJSON ... NVARCHAR(MAX)로 읽으므로, 4,000자를 넘는 Markdown 본문도 등록·갱신할 수 있습니다(2026-08-24, SP 소스 확인). 긴 작업 지시서를 그대로 이슈화할 수 있습니다.

  • UTF-8 JSON으로 전송합니다.
  • 셸에 긴 문장을 직접 넣지 말고, 파일에서 JSON으로 만들어 보내는 것이 안전합니다:
# body.json 에 {"isn":1474,"content":"...(긴 문장)..."} 를 준비
curl -sS -X PUT "https://giipfaw.azurewebsites.net/api/giipIssues" \
  -H "x-api-key: ${GIIP_API_KEY}" -H "Content-Type: application/json" \
  --data-binary @body.json
  • 등록 후, GET /api/giipIssues?isn=<isn>으로 본문 길이나 해시(예: sha256)를 대조해 전체 문장이 저장됐는지 확인합니다.

코멘트 추가(필수 항목과 저장 후 확인)

{ "isn": 1474, "content": "Comment body", "author": "ChatGPT Work", "issuetype": "comment" }
  • 필수: isn, content.
  • 기본값: author=Agent, issuetype=comment.
  • 저장 author 정규화 주의: 자격증명 종류와 서버 측 identity 해석에 따라, 보낸 author저장 시 사용자 이름으로 정규화될 수 있습니다(2026-08-24 실측: author="ChatGPT Work"로 보낸 코멘트가 author="Lowy Shin"으로 저장됨). 보낸 author가 그대로 저장된다고 전제하지 말고, 추가 후 GET /api/giipIssueComments?isn=<isn>으로 content와 실제 저장된 author를 확인하세요.
  • 코멘트 전에도 GET /api/giipIssues?isn=<isn>으로 대상 CSN을 확인하세요.

End-to-End 예시(등록 → 확인 → 부분 업데이트 → 재확인 → 코멘트 → 확인)

# 1. 인증·CSN scope 확인(read-only preflight)
curl -sS "https://giipfaw.azurewebsites.net/api/giipIssues?csn=47" -H "x-api-key: ${GIIP_API_KEY}"

# 2. 신규 등록(반환값의 isn 취득)
curl -sS -X POST "https://giipfaw.azurewebsites.net/api/giipIssues" \
  -H "x-api-key: ${GIIP_API_KEY}" -H "Content-Type: application/json" \
  -d '{"title":"AI test issue","content":"initial body","csn":47}'

# 3. 실제 cSn 확인(CSN 불일치는 조용히 홈 CSN으로 clamp되므로 필수)
curl -sS "https://giipfaw.azurewebsites.net/api/giipIssues?isn=<isn>" -H "x-api-key: ${GIIP_API_KEY}"

# 4. 부분 업데이트(title만. content는 ISNULL로 보존됨)
curl -sS -X PUT "https://giipfaw.azurewebsites.net/api/giipIssues" \
  -H "x-api-key: ${GIIP_API_KEY}" -H "Content-Type: application/json" \
  -d '{"isn":<isn>,"title":"AI test issue (edited)"}'

# 5. 재GET으로 미지정 필드(content)가 보존됐는지 확인
curl -sS "https://giipfaw.azurewebsites.net/api/giipIssues?isn=<isn>" -H "x-api-key: ${GIIP_API_KEY}"

# 6. 코멘트 추가
curl -sS -X POST "https://giipfaw.azurewebsites.net/api/giipIssueComments" \
  -H "x-api-key: ${GIIP_API_KEY}" -H "Content-Type: application/json" \
  -d '{"isn":<isn>,"content":"done","author":"ChatGPT Work","issuetype":"comment"}'

# 7. 코멘트 확인(저장 author와 content를 GET으로 대조)
curl -sS "https://giipfaw.azurewebsites.net/api/giipIssueComments?isn=<isn>" -H "x-api-key: ${GIIP_API_KEY}"

CSN silent clamp 탐지: POST에서 지정한 csn이 권한 밖이면 오류가 나지 않고 키의 홈 CSN으로 조용히 클램프됩니다. 절차 3의 재GET에서 cSn이 의도대로인지 반드시 확인하세요.

2. 범용 API 래퍼 (giipApiSk2)

GIIP의 Stored Procedure를 직접 호출하는 sk 기반 방식이며, 조회(List/Get)와 에이전트 액션(Dispatch/ReadinessCheck) 에 사용합니다. 생성·상태변경·코멘트 등 쓰기(write)는 이 경로로 하지 말고 위 §1 전용 REST 엔드포인트를 사용하세요(이유는 아래 🚫 참고).

  • URL: POST /api/giipApiSk2
  • Content-Type: application/x-www-form-urlencoded
  • 필드:
    • token: [Your_SK] — SK는 반드시 이 필드로만 전달
    • text: [Command] [파라미터...]
    • jsondata: 값 매핑용 JSON(선택). 예: {} 또는 {"lssn":101}

⚠️ text 작성 규칙(엄수): text에는 해당 SP가 받는 정확한 파라미터만 순서대로 나열합니다. 인증(@sk)과 jsondata는 엔진(run.ps1)이 자동 처리하므로 절대 나열하지 마세요. 파라미터를 과다 나열하면 SP 인자 개수를 초과해 has too many arguments specified 오류가 납니다.

명령(안전)SP 파라미터(=text에 나열)text 예시성공 응답
목록 조회statusGiipIssueList READYdata(이슈 배열)
상세 조회isnGiipIssueGet 7890data[0](이슈 1건)
원격 실행isnGiipIssueDispatch 7890data[0].RstVal = 200

🚫 GiipIssuePut을 Sk2로 상태변경에 쓰지 마세요 (데이터 파괴 위험). Sk2 GiipIssuePut은 내부 SP pApiGiipIssuePutbySK(@sk, @isn, @title, @content, @status, @csn)에 매핑되는 전체 덮어쓰기(full overwrite) 입니다(coalesce 없음). GiipIssuePut 7890 DONE로 부르면 두 번째 값 DONE@title로, 세 번째(jsondata)가 @content로 들어가 제목·본문이 파괴됩니다. 응답은 RstVal:200(가짜 성공)으로 나오지만 실제로는 오손된 것입니다(실측: 2026-07-09, task 20260708183049). 상태만 안전하게 바꾸려면 전용 REST PUT /api/giipIssues {isn, status}를 쓰세요. 내부 pApiGiipIssuePutbyAKISNULL(@title, title)로 기존 제목·본문을 보존합니다(=giipv3 프론트가 실제 쓰는 경로).

🔍 응답 데이터 예시

giipApiSk2 (SP 래퍼) 응답 — 조회는 data 배열에 레코드, SP 액션(Dispatch 등)은 성공 시 RstVal = 200:

{ "data": [ { "RstVal": 200, "Proc_MSG": "Dispatched", "isn": 7890 } ] }

조회 명령(GiipIssueList/GiipIssueGet)은 data 배열에 이슈 레코드가 담깁니다.

전용 REST 엔드포인트 응답 — 성공 시 success: true (응답 본문에 RstVal 없음):

{ "isn": 7890, "message": "Issue updated", "success": true }

ℹ️ 성공 판정 주의: SP 성공 코드는 RstVal = 200이며 0이 아닙니다. 실패 시 400/401/403/404를 반환합니다(K-Layer CLAIM-006). 전용 엔드포인트는 RstVal 대신 success 불리언을 반환합니다.

💡 활용 사례

  • 슬랙 알림 봇: API를 주기적으로 호출하여 신규 Critical 이슈 발생 시 즉시 개발팀 채널에 메시지를 보냅니다.
  • 자동 복구 스크립트: 특정 유형의 이슈(예: 프로세스 다운) 탐지 시 API로 이슈를 확인하고, 원격 명령 API(api-system)를 호출하여 해당 서비스를 재시작합니다.

🛡️ Sk3(고성능 로깅) 활용

장애 대응 시스템이나 외부 티켓팅 도구와의 연동 시, 업데이트 무결성 보장과 상세한 호출 이력 추적을 위해 giipApiSk3 엔드포인트를 권장합니다.

  • 엔드포인트: https://giipfaw.azurewebsites.net/api/giipApiSk3
  • 장점: 이슈 상태 업데이트(Done 처리 등) 실패 시 호출자의 상세 환경 정보(IP, UA)와 StackTrace를 즉시 tErrorLogs에 기록하여 장애 대응 프로세스의 신뢰성을 높여줍니다.
  • 활용 팁: jsondata 치환 기능을 사용하여 이슈 내의 특정 변수값이나 긴 에러 메시지를 파라미터 유실 없이 안전하게 전송할 수 있습니다.

401 "Invalid session" 원인 분류

401에는 서로 다른 의미의 메시지 2가지가 있습니다(실측 확인, 2026-08-20).

응답원인
{"error":"Auth required"}키가 서버까지 도달하지 못함x-api-key/Authorization 헤더가 없거나, 지원되지 않는 전달 방식(JSON 바디 token, 쿼리 ?token=, 잘못된 헤더 이름 등)을 사용함
{"error":"Invalid session"}키는 도달했지만 무효 — 아래 원인 중 하나

Invalid session이 되는 구체적 원인:

  1. 키 값에 오타가 있거나 존재하지 않음(어떤 AK/SK 테이블에도 매칭되지 않음)
  2. 유효했던 프로젝트 SK가 재발급/회전으로 비활성화됨(SKStatus=0) — giip #1265에서 실측
  3. 로그인 세션 AK가 24시간 유효기간을 초과함(tUserLogin.AccToken, 코드 확인만·미실측)

해당하지 않는 경우(오해하기 쉬운 지점):

  • AK 전용 엔드포인트에 SK를 쓴 경우/그 반대 → 해당 없음. giipIssues/giipIssueComments는 AK·SK 어느 쪽으로도 동작하도록 구현돼 있으며, 종류별 전용 엔드포인트 구분이 없습니다(실측+코드 확인).
  • 대상 csn에 권한이 없는 경우 → 401이 아니라 위 "csn 권한 불일치 시 동작"대로 200(빈 배열)/200(조용한 클램프)/404가 됩니다.

문제 해결

증상원인해결
{"error":"Auth required"} (401)헤더에 키가 없거나, 바디/쿼리 등 미지원 방식으로 전달함x-api-key: <key> 헤더(또는 Authorization: Bearer <key>)로 전달. 바디 token·쿼리 ?token=은 사용 불가
{"error":"Invalid session"} (401)키 오타, 비활성화(재발급/회전), 세션 만료 중 하나위 "인증 확인 절차"의 GET으로 키를 재검증. /svclist에서 대상 csn의 현재 유효한 SK 확인
프로젝트 이슈가 [](빈 배열)로 반환됨키는 유효하지만 대상 csn에 권한이 없음(401이 되지 않음)대상 csn용 키를 사용하거나 관리자에게 권한 부여를 요청
POST에서 csn을 지정했는데 다른 csn에 생성됨권한 없는 csn을 지정하면 키의 홈 csn으로 조용히 클램프됨(실측: 위 참조)생성 후 GET /api/giipIssues?isn=<isn>으로 실제 cSn을 확인. 다른 csn 생성이 필요하면 관리자에게 tUserPerCorp 권한 부여 요청
명령이 실행되지 않거나 빈 결과 반환(Sk2)text 파라미터 형식 오류(명령·파라미터 구분 누락)GiipIssueList READY처럼 [명령] [파라미터] 형식 준수
... has too many arguments specified 오류(Sk2)text에 SP 파라미터를 과다 나열SP의 정확한 파라미터만 나열. @sk·jsondata는 엔진이 자동 추가하므로 나열 금지
상태변경 했더니 제목·본문이 DONE/{} 등으로 파괴됨(Sk2)Sk2 GiipIssuePut(전체 덮어쓰기 SP)로 상태변경 시도상태변경은 전용 REST PUT /api/giipIssues {isn,status} 사용(§1). Sk2 GiipIssuePut은 write에 쓰지 말 것
응답 data[0].RstVal200이 아님(Sk2)Stored Procedure 실행 오류 또는 잘못된 isnProc_MSG 확인 후 API 결과 코드 가이드 참조 (성공은 0이 아니라 200)
긴 에러 메시지·특수문자 전송 시 값 유실JSON 값 이스케이프 처리 누락giipApiSk3jsondata 치환 기능으로 안전하게 전송

버전: 1.7 최종 업데이트: 2026-08-27(테스트 대상 API: giipfaw 프로덕션, pApiGiipIssue*byAK SP군 — 위에 명시한 각 실측은 이 날짜에 라이브 API로 수행) 소스 파일: giipv3/public/help/giip-issue-api.ko.md

v1.7 변경 이력 (2026-08-27, giip #1484): 이슈 처리 워크플로우(/gissue-final-review) 완료를 위해 다음 항목을 추가. ① 지원 상태값 표(TESTED/WARN 포함, 7가지 상태). ② 다중 상태 조회 — 운영 API는 단일 완전일치 필터만 지원 (TESTED,REVIEW/TESTED|REVIEW 등 형식은 동작하지 않음)하여 각각 조회 후 클라이언트에서 결합하는 패턴. ③ 코멘트 전량 조회 시간순 설명과 FINAL-REVIEW 워크플로우에서 작업자 완료 보고를 "주장"으로, repo/PR/화면/DB를 직접 대조한 독립 증거만 합격으로 인정하는 검증 원칙.

v1.6 변경 이력 (2026-08-24, giip #1475): AI 에이전트용 전체 절차 섹션 추가(부분 업데이트/긴 content/ 코멘트 author 정규화/등록→확인→부분 업데이트→코멘트 End-to-End 예시). x-api-key가 헤더 이름이지 별도의 자격증명 종류가 아님을 명시. GET /api/giipIssueComments가 HTTP 200을 반환한다는 옛 "알려진 버그" 기록을, 수정됨(giip #1285, 2026-08-24 라이브 실측으로 HTTP 401 확인)으로 삭제.

v1.5 변경 이력 (2026-08-20, giip #1280): 인증 관련 내용을 대폭 보강. ① JSON 바디 token·쿼리 ?token=giipIssues/giipIssueComments에서 실제로는 동작하지 않음을 코드 확인+라이브 실측(4개 엔드포인트)으로 확정하고 잘못된 서술(x-giip-sk 헤더·?token= 지원 언급 포함)을 삭제(쿼리 문자열 방식은 보안상으로도 지원 중단 명시). ② SK/사용자 고정 키/로그인 세션 AK 3종류를 발급 테이블 기준으로 정리 (tSecretKey/tCorpUser.uSecretKey/tUserLogin.AccToken). ③ 쓰기 전 키를 안전하게 검증하는 절차 추가. ④ 401의 원인을 "Auth required(키 미도달)"와 "Invalid session(키 무효)"로 분류하고, csn 권한 불일치는 401이 되지 않음(빈 배열/404/조용한 클램프)을 실측으로 명시. ⑤ GET /api/giipIssueComments가 무효한 키에도 HTTP 200을 반환하는 알려진 버그를 발견·기록(후속 이슈 등록). ⑥ 생성 예제를 하드코딩된 키에서 환경변수(${GIIP_API_KEY})로 변경.

v1.4 변경 이력 (2026-08-20, giip #1265): SK로 POST /api/giipIssues 호출 시 401 Invalid session을 받는다는 제보를 실측 검증. 라이브 Azure SQL에 배포된 pApiGiipIssuePutbyAK 정의는 레포 소스와 완전히 동일하며 SK 폴백 인증(lwGetUSNbyat 실패 시 lwGetUSNbysk)이 이미 정상 배포돼 있음을 확인(배포 갭 아님). 실제로 활성 SK로 호출하면 200 Issue created, 비활성화(재발급/회전)된 옛 SK로 호출하면 401 Invalid session이 재현됨(2026-08-20 실측: giipfaw 라이브 API에 두 케이스 모두 직접 호출해 확인). 즉 코드 결함이 아니라 문서가 "어떤 SK가 유효한지"를 설명하지 않은 것이 원인 — §인증 및 문제 해결 표에 SK 활성 상태 요건과 재확인 경로(/svclist)를 추가.

v1.3 변경 이력 (2026-07-09, task 20260708183049): 실제 프로덕션 API(giipv3 프론트·giipApiSk2·SP 소스)와 대조하여 정합화. ① Sk2 쓰기 경로 위험 경고 추가: Sk2 GiipIssuePut은 내부 pApiGiipIssuePutbySK(@sk,@isn,@title,@content,@status,@csn) 전체 덮어쓰기 SP라 GiipIssuePut 7890 DONE이 제목·본문을 파괴함(응답은 가짜 RstVal:200). 실측 확인(577·578 오손 후 복구). 생성·상태변경·코멘트는 전용 REST 엔드포인트로, Sk2는 조회·액션 전용으로 안내. (과거 보고서의 "too many arguments 비호환" 진단은 부분적 관찰이었고, 실제로는 SP가 full-overwrite여서 위험한 것.) ② 성공 코드는 RstVal = 200(0 아님) — 응답 예시·문제 해결 표 정정. ③ 이슈 신규 등록 절차(POST /api/giipIssues, isn 생략 시 신규) 및 안전한 상태변경(PUT /api/giipIssues {isn,status}, ISNULL 보존) 추가.


관련 문서: