Back

GitHub README에서 작동하는 카드를 만든다는 것

mergecard는 오픈소스 기여자의 머지된 PR 이력을 GitHub 프로필에 카드 형태로 보여주는 도구다. README에 한 줄 추가하면 된다.

![mergecard](https://mergecard.vercel.app/api/contrib?user=torvalds)

만들기 전엔 몰랐는데, GitHub README는 꽤 제약이 많은 환경이었다.

GitHub는 SVG를 <img>로 렌더링한다

GitHub README에 이미지를 넣으면 GitHub가 <img> 태그로 처리한다. SVG도 마찬가지다. 이 말은 JavaScript가 동작하지 않고, 외부 CSS도 안 먹히고, 인터랙션이 없다는 뜻이다.

처음에 인터랙티브 요소를 넣으려 했다. hover 효과, 클릭 가능한 링크. 전부 동작하지 않았다. 제약을 파악하고 나서야 “정적 SVG 안에서 어떻게 정보를 잘 보여줄 것인가”로 문제가 바뀌었다.

다크/라이트 모드 대응도 같은 이유로 막혔다. CSS prefers-color-scheme은 SVG 내부에서 쓸 수 있지만, <img> 태그로 렌더링되면 동작하지 않는다. 결국 dark/light 두 버전을 따로 제공하는 방식으로 우회했다.

제약이 아키텍처를 결정했다

GitHub API는 인증 없이 쓰면 rate limit이 빡세다. 처음엔 “그럼 사용자가 토큰을 발급받아서 쓰면 되지 않나”라고 생각했다. github-readme-stats 같은 도구들이 이 방식이다. 레포를 포크하고 Action을 설정하고 토큰을 secrets에 등록하는 과정.

근데 그러면 사용자마다 설정이 필요하다. 내가 원했던 건 README에 한 줄 붙여넣으면 바로 동작하는 경험이었다.

“shields.io는 어떻게 그게 가능한 거야?” 라고 물어보다가 답이 나왔다. shields.io는 자기네 서버에서 rate limit을 관리하고, 사용자는 URL만 쓴다. 같은 구조로 가면 된다. 내 서비스가 shields.io만큼 트래픽이 올 리 없고, Vercel 서버리스면 과금도 트래픽 기반이다. 리스크가 없었다.

SVG 안에서 디자인 이터레이션

정적 SVG라는 제약은 디자인 과정도 어렵게 만들었다. 브라우저에서 보이는 것과 GitHub README에서 보이는 것이 다르다. 렌더링 환경이 다르기 때문이다.

컬러 조합을 여러 번 바꿨다. 검정 배경은 GitHub 다크모드에서 경계가 사라졌다. 폰트 크기는 접근성 기준에 맞추면서 정보 밀도를 유지해야 했다. 긴 레포 이름이 잘리거나 별점이 타임라인에 붙어버리는 문제는 실제 데이터를 넣어봐야만 발견됐다.

?demo=1 파라미터를 만든 것도 이 때문이다. 실제 GitHub API를 거치지 않고 내가 만든 가짜 데이터로 카드를 미리볼 수 있다. 이터레이션 속도가 달라졌다.

결과

https://mergecard.vercel.app/api/contrib?user=USERNAME

제약을 파악하는 게 먼저였다. 인터랙션이 없고, rate limit이 있고, 렌더링 환경이 통제되지 않는다. 그 제약들을 이해하고 나서야 설계 방향이 보였다.