Auth 검증 구축: 오류 메시지를 실제로 도움이 되게 만드는 5가지 교훈

발행: (2026년 1월 8일 오후 07:51 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

왜 신경 써야 할까

여러 외부 서비스—GitHub, AI 에이전트, 다양한 API—와 연결되는 도구를 만들고 있습니다. 모든 것이 잘 동작합니다… 그런데 문제가 생깁니다.

사용자가 작업을 실행합니다. 실패합니다. 로그를 확인하고 출력을 스크롤한 뒤 30분 후에야 “아, 인증 토큰이 만료됐구나.” 라는 사실을 발견합니다.

저는 DevLoop Runner (AI 에이전트를 사용해 PR을 자동화하는 도구)를 위해 인증 검증 기능을 만들었습니다. 검증을 실제로 유용하게 만들면서 배운 점을 공유합니다.

Lesson 1: 사용자가 볼 필요 없는 것은 숨기기

첫 구현에서는 검증 출력에 JWT 토큰, 이메일 주소, 조직 이름을 평문으로 출력했는데—이건 안 좋은 생각이었습니다.

const isJsonString = authJsonPath.startsWith('{') || authJsonPath.startsWith('[');
const displayValue = isJsonString 
  ? '[JSON content - masked for security]' 
  : authJsonPath;

사용자는 “설정돼 있나요?”“동작하나요?” 만 알면 됩니다. 민감한 자격 증명은 마스킹하세요.

Lesson 2: 실제로 사용되는 것을 검증하기

검증 명령은 환경 변수를 확인했지만 실행 명령은 파일을 사용했습니다. 검증은 통과했지만 실행은 실패해 사용자를 혼란스럽게 만들었습니다.

const homeDir = process.env.HOME || os.homedir();
const authFilePath = path.join(homeDir, '.codex', 'auth.json');

if (fs.existsSync(authFilePath)) {
  // Validate the file, not the env var
}

런타임이 사용하는 환경을 그대로 검증하세요.

Lesson 3: “Failed”가 항상 실패를 의미하는 것은 아니다

제 도구에서는 OpenAI와 Anthropic API 키가 선택 사항입니다. 첫 번째 버전에서는 설정되지 않았을 때 status: failed 로 표시했는데, 이는 오해를 불러일으켰습니다. 이제 status: skipped 로 바꾸었습니다.

if (isBlank(apiKey)) {
  checks.push({
    name: 'OPENAI_API_KEY',
    status: 'skipped',
    message: 'Not configured (optional for follow‑up issue generation)',
  });
  return { status: 'passed', checks };
}
  • 필수 설정 누락 → failed
  • 선택 설정 누락 → skipped

이 구분이 중요합니다.

Lesson 4: 필요 이상으로 요구하지 않기

GitHub 토큰 검증은 원래 repo, workflow, read:org 세 가지 스코프를 요구했습니다. 코드베이스에서는 read:org 를 전혀 사용하지 않았고, GitHub Actions 를 위해서는 workflow 만 필요했습니다.

const REQUIRED_GITHUB_SCOPES = ['repo'];

과도하게 엄격한 검증은 불필요한 오류 메시지를 만들어 사용자를 좌절시킵니다.

Lesson 5: 검증 도구를 디버깅 가능하게 만들기

Jenkins에서 연결 확인이 타임아웃되었지만 로그가 없어 문제를 파악하기 어려웠습니다. 저는 상세 로그를 추가하고 타임아웃을 늘렸습니다.

await codexClient.executeTask({
  prompt: 'ping',
  maxTurns: 1,
  verbose: true,  // Now we can see what's happening
});

// Increased timeout from 10 s to 30 s for Docker environments
setTimeout(() => reject(new Error('Timeout after 30 seconds')), 30000);

검증 도구 자체가 디버깅하기 어렵다면 또 다른 문제를 만든 겁니다.

The pattern

검증을 구축하는 것은 단순히 기술적 정확성만을 의미하는 것이 아니라, 사용자에게 전달하는 메시지와도 관련이 있습니다:

  • 사용자가 볼 필요 없는 것은 마스킹하기
  • 실제로 실행되는 것을 검증하기
  • failedskipped를 구분하기
  • 권한을 과도하게 요구하지 않기
  • 실패 상황을 디버깅 가능하게 만들기

검증 결과는 일종의 커뮤니케이션입니다. 사용자가 다음에 무엇을 해야 할지 이해하도록 돕는 것이 목표이며, 기술적으로는 맞지만 실제로는 오해를 일으키는 메시지로 혼란을 주어서는 안 됩니다.

도구를 만들고 의사 결정을 하는 것에 대한 더 많은 생각은 tielec.blog에서 확인하세요.

Back to Blog

관련 글

더 보기 »

세션 토큰 vs JWT: 잘못된 이분법

JWT와 세션 – 이것이 양자택일이 아닌 이유 논쟁은 끝이 없지만, 어느 쪽을 선택할 필요는 없습니다. 하이브리드 접근 방식이 당신에게 b...