우리의 Jira 플러그인인 Timesheets by Appforest는 Testlify의 근무시간 관리를 중앙화했지만, 개발자들은 여전히 시간을 수동으로 기록하려면 작업을 멈추고 다른 도구로 전환해야 했다. Appforest Timetracker는 이 간극을 메운다. 이것은 에디터 안에서 바로 코딩 활동을 추적하고 근무시간 기록을 빠른 작업으로 바꿔주는 VS Code 확장으로, 엔지니어들이 IDE를 벗어나지 않고도 Timesheets에 기록할 수 있게 해준다. 나는 콘셉트부터 Visual Studio Marketplace 패키징까지 이 확장을 처음부터 끝까지 소유했다.
내가 만든 것
- 확장 코어: 공식 VS Code Extension API 위에 구축. 문서 변경, 저장, 선택 리스너가 활동 타임스탬프를 재설정하며, 이는 창 포커스 상태를 1초 간격으로 폴링하는 것과 대조하여 확인되고, 개발자를 방해하지 않으면서 조용히 활성/유휴 시간을 추적한다.
- Git 인식 근무시간 기록: 확장은 현재 Git 브랜치를 읽어 Jira 티켓 ID를 자동으로 추출해, 수동으로 티켓을 검색하거나 다시 입력할 필요 없이 기록된 시간이 올바른 이슈에 연결되도록 한다.
- 전체 라이프사이클: VS Code의 SecretStorage API를 통한 안전한 토큰 저장, 패키징, 그리고 Visual Studio Marketplace로의 수동 배포를 처리했다.
왜 중요했는가
Git 브랜치 컨텍스트로부터 티켓 매칭을 자동화함으로써 수동 타임시트 기록 단계를 없애고, 보고 오류를 줄이며, 스프린트 계획과 고객 청구를 위한 더 깨끗한 데이터를 경영진에게 제공했다.
혼자, 작게, 실제로
나는 유일한 기여자로, 2025년 4월 이후 32건의 커밋을 남겼다. 이것은 특정 일상적 불편함을 해결하기 위해 만든 소규모의 개인 규모 사내 도구이지, 대형 제품이 아니다.
기록된 시간이 실제로 어디로 가는가
이 확장은 Jira의 REST API를 직접 호출하지 않는다. Timesheets by Appforest 자체 백엔드로 전송하며, 이는 Forge 앱이 매니페스트에 선언한 것과 같은 원격 서비스로, 그 앱이 Jira 쪽 처리를 대신 담당한다. 이 두 프로젝트는 각자 독립적으로 Jira와 통신하는 것이 아니라 서로 대화하도록 만들어졌으며, 이것이 바로 Forge 앱의 리졸버가 VS Code에서 온 제안이 기록되고 나면 그것을 지우는 전용 함수를 포함하는 이유이기도 하다.
활동 및 티켓 감지가 실제로 작동하는 방식
Git 브랜치 감지는 git 라이브러리를 도입하는 대신 git rev-parse --abbrev-ref HEAD를 직접 셸 아웃하는데, 값 하나를 읽기 위해 라이브러리의 전체 API 표면을 떠안는 것보다 합리적인 선택이다. 브랜치 이름은 동기화되기 전에 /^[A-Z]+-\d+$/에 대해 검증되므로, 티켓과 매칭되지 않는 피처 브랜치(예: ABC-123이 아닌 것)는 잘못된 이슈에 기록되거나 에러를 내는 대신 조용히 건너뛰어진다. 활동 추적은 파일 전환 단위의 세밀함이 아니라, 문서 변경 및 저장 리스너와 함께 창 포커스 상태를 1초 간격으로 폴링하는 것이며, 10초의 유휴 임계값과 세션이 일시정지된 것으로 간주되기 전 60초의 유예 기간을 둔다. 진행 상황은 매초 VS Code의 globalState에 저장되고 재시작 시 복원되며, 자가 복구 검사가 있다: 마지막 동기화 카운트가 복원 시 추적된 카운트보다 앞서 있다면(동기화가 쓰는 도중에 중단되었다는 신호), 더 어긋나게 두는 대신 다시 맞춰 고정한다.
인증은 설정 기반이 아니라 명령 기반이다: 전용 명령들(authenticateToken, deleteToken, updateToken, syncNow, resetTime)이 입력 프롬프트를 통해 토큰 생명주기를 처리하며, 이것이 애초에 설정 UI가 없는 이유이기도 하다. 이는 빠진 기능이 아니라 의도적인 선택이다.
데이터 모델과 규모
여기에는 한 개발자의 에디터 세션을 넘어 확장될 필요가 있는 것이 없다: 하나의 상태 표시줄(티켓 시간과 일일 합계), 하나의 유휴/활성 상태 머신, 자정마다 실행되는 하나의 일일 리셋 작업. 이 규모에서 더 무거운 데이터 모델이 필요한 경우는 없으며, 그런 모델을 만드는 것은 이 도구가 갖고 있지 않은 문제를 해결하려는 것이다.
Build vs. Buy
simple-git이나 isomorphic-git 같은 라이브러리 대신 git 바이너리를 셸 아웃: 하나의 값(현재 브랜치)을 읽는 것은 전체 Git 작업을 위해 만들어진 의존성을 정당화하지 못한다. 커스텀 암호화 파일 토큰 저장소 대신 VS Code 자체의 SecretStorage API: 플랫폼이 바로 이 경우를 위한 안전한 자격 증명 저장을 이미 해결해 놓았다.
Stack
VS Code Extension API, TypeScript, Git 접근을 위한 Node의 내장 child_process, 토큰 저장을 위한 VS Code의 SecretStorage API, Visual Studio Marketplace에 게시.