GitHub Issue 기반 피드백 시스템 개선기

sumi-0011·2024년 11월 24일
1

🐱 GitAnimals

목록 보기
2/2
post-thumbnail

발견된 문제점 🐛

GitHub Issue를 활용한 피드백 시스템을 운영하면서 예상치 못한 문제가 발생했습니다. 처음에는 모든 게 잘 돌아가는 것처럼 보였는데, 어느 날 로그를 확인하다가 이상한 점을 발견했죠. 사용자들의 피드백이 GitHub Issue에 등록되지 않는 현상이 있었습니다.

원인을 파악해보니 GitHub API의 권한 체계와 관련이 있었습니다. 기존 구현에서는 Issue를 생성할 때 assignees(담당자)를 지정하도록 되어 있었는데, 이 기능을 사용하려면 해당 레포지토리에 commit 등의 접근 권한이 필요했던 거죠. 결과적으로 권한이 없는 일반 사용자의 피드백은 등록 자체가 실패하고 있었습니다 😱

테스트 할때는 당연히 권한이 있는 제 계정을 사용했기 때문에 문제를 발견하지 못했던 것이죠

문제 해결 과정 💡

1. 권한 문제 해결 방안 모색

첫 번째로 시도한 것은 레포지토리 권한이 없는 사용자도 이슈에서 언급될 수 있도록 하는 방법을 찾는 것이었습니다. GitHub API 문서를 뒤져가며 여러 방법을 시도해봤지만, API를 통해 직접적으로 권한 없는 사용자를 언급하는 것은 불가능했습니다. 이는 GitHub에서 무분별한 할당을 막기 위해 추가한게 아닐까 생각했어요.

하지만 곧 대안을 발견했습니다. GitHub에서는 @사용자이름 형식의 텍스트만으로도 언급 기능이 활성화된다는 점을 생각했죠. 즉, API로 직접 멘션하는 대신 이슈나 댓글의 내용에 사용자 이름을 포함시키면 언급할 수 있는 거예요!

이 방법을 적용하기 위해 팀 내부에서 논의를 진행했고,
이슈 본문은 문제 상황을 명확하게 기술하는 데 집중하고, 사용자와의 커뮤니케이션은 댓글을 통해 하는 것이 더 자연스럽다고 판단해, 이슈 본문에 사용자를 언급하는 것보다는 댓글을 통해 언급하는 것이 더 적절하다는 결론을 내렸습니다.

2. Octokit 도입으로 API 활용 개선

문제 해결에 들어가기 전에, GitHub API를 더 효율적으로 사용할 방법을 찾아보았습니다. 기존에는 일반적인 fetch 요청을 사용했는데, 이는 타입 안정성이나 에러 처리 면에서 아쉬운 점이 있었어요.

Octokit이라는 GitHub의 공식 REST API 클라이언트 라이브러리를 발견 할 수 있었어요.

Octokit은 다음과 같은 장점들을 제공했습니다.

  • TypeScript 지원으로 타입 안정성 확보
  • 자동 인증 처리
  • 레이트 리밋 관리
  • 편리한 에러 핸들링

이를 활용하기 위해 먼저 Octokit을 사용하기 위한 core 로직을 다음과 같이 구성했습니다.

import { Octokit } from '@octokit/core';

const ISSUE_TOKEN = process.env.NEXT_PUBLIC_ISSUE_TOKEN;

const octokit = new Octokit({
  auth: ISSUE_TOKEN,
});

const OCTOKIT_BASE_INFO = {
  owner: 'git-good-w',
  repo: 'gitanimals',
  headers: {
    'X-GitHub-Api-Version': '2022-11-28',
  },
} as const;

export const requestOctokit = async (method: 'GET' | 'POST', url: string, data?: object) => {
  const response = await octokit.request(`${method} ${url}`, {
    ...OCTOKIT_BASE_INFO,
    ...data,
  });

  return response.data;
};

제가 의도한 주요 포인트를 살펴보자면

  • 환경 변수를 통해 GitHub 토큰을 안전하게 관리합니다
  • API 버전을 명시적으로 지정하여 예상치 못한 변경을 방지합니다
  • 공통으로 사용되는 설정을 OCTOKIT_BASE_INFO로 분리했습니다
  • 범용적으로 사용할 수 있는 requestOctokit 함수를 만들어 코드 중복을 줄였습니다

3. Issue 생성 및 댓글 기능 구현

이제 Octokit을 활용하여 실제 피드백 제출 기능을 구현했습니다. 가장 중요한 것은 Issue 생성과 댓글 작성을 안정적으로 처리하는 것이었죠.

export async function postFeedback(request: PostFeedbackRequest): Promise<PostFeedbackResponse> {
  const issueData = await postIssue(request);
  
  if (request.username) {
    const commentBody = `@${request.username}\nThanks for reporting the issue!`;
    await createComment({ issueNumber: issueData.number, body: commentBody });
  }

  return issueData;
}

이 구현에서 중요하게 고려한 점들은 다음과 같습니다.

안정성 확보

  • Issue 생성과 댓글 작성을 분리하여 각각의 작업이 실패했을 때 독립적으로 처리할 수 있도록 했습니다
  • 사용자 이름이 있는 경우에만 멘션 댓글을 추가하여 불필요한 API 호출을 방지했습니다

사용자 경험 개선

  • 피드백 제출 직후 바로 멘션 댓글이 달리도록 하여 사용자가 자신의 피드백이 잘 등록되었음을 즉시 확인할 수 있습니다
  • 친근한 메시지로 사용자와 소통합니다

확장성 고려

  • 추후 피드백 처리 프로세스가 변경되더라도 쉽게 수정할 수 있도록 모듈화된 구조를 유지했습니다
  • TypeScript의 타입 시스템을 활용하여 코드의 안정성을 높였습니다

전체 프로세스 🔄

개선된 피드백 시스템의 전체 동작 흐름을 시퀀스 다이어그램으로 표현하면 다음과 같습니다

이 프로세스를 통해 사용자의 피드백이 안정적으로 GitHub Issue에 등록되고, 사용자는 자신의 피드백 처리 현황을 쉽게 확인할 수 있게 되었습니다.

마무리 🎉

이번 개선 작업을 통해 문제를 해결할 뿐 아니라 피드백 시스템이 한층 더 안정적이게 된것 같아요.
로그를 통해 문제를 발견하고 해결하는 과정을 거치니 로그의 중요성을 더 잘 알게된것 같습니다

개발을 하다 보면 이렇게 예상치 못한 문제들을 마주치게 되는데, 이런 문제들을 해결하면서 시스템도 개선하고 새로운 것을 배울 수 있는 기회가 된 것 같아요 🌱

실제 구현된 코드는 PR #173에서 확인하실 수 있습니다. 코드를 살펴보시면서 더 자세한 구현 내용을 확인해보세요!

profile
안녕하세요 😚

0개의 댓글