I Turned My GitHub Profile Into a Cyberpunk Console With a City Built From My Contributions
GitHub 프로필을 사이버펑크 콘솔로 바꾸고 기여 기록으로 도시를 만들었습니다
GitHub README의 제약을 SVG 이미지로 우회해 애니메이션이 있는 사이버펑크 콘솔과 기여 기록 기반 3D 도시를 만들었습니다. Python 스크립트와 GitHub Actions로 데이터를 갱신하며, 그래프 렌더링부터 API 수집과 실패 대응까지 구현 과정을 소개합니다.
- 주제
AI 요약
개발자는 GitHub 프로필을 꾸미려다 기여 그래프를 3D 도시로 바꾸고, 프로필 전체를 네온빛 사이버펑크 콘솔처럼 구성했습니다. README에서 스크립트와 스타일을 실행할 수 없는 제약을 SVG 이미지로 풀었습니다. SVG 안에 CSS 애니메이션을 넣고, 각 UI 요소를 이미지로 그려 README에 쌓았습니다.
README 제약을 SVG로 우회
GitHub README에서는 <script>, <style>, 인라인 스타일을 사용할 수 없습니다. 대신 <img>로 삽입한 SVG 안에서는 CSS와 애니메이션을 쓸 수 있습니다. 작성자는 이 방식으로 깜박이는 커서, 글리치 효과가 있는 이름, 네온 UI를 구현했습니다. SVG는 외부 리소스를 불러오지 못하므로 폰트를 이미지에 필요한 글자만 남겨 삽입했습니다. 이미지에는 마우스 오버나 클릭을 붙일 수 없고 링크는 이미지 전체에 연결해야 합니다. 그래서 프로젝트 카드와 링크 버튼도 각각 별도 이미지로 만들었습니다. GitHub 이미지 캐시는 몇 분간 유지되므로 수정 사항이 바로 보이지 않는 경우도 겪었습니다.
프로필을 여러 패널로 나누면 조각난 터미널처럼 보였습니다. 이를 해결하려고 콘솔 프레임을 가로로 잘라 이미지 23장에 나눠 그렸습니다. 헤더는 위쪽 테두리와 제목 표시줄을 맡고, 푸터는 아래쪽 테두리를 그립니다. 중간 이미지는 좌우 테두리만 그려 세로 레일이 이어지게 했습니다. 조각마다 높이를 40픽셀 단위로 맞춰 배경 격자가 어긋나지 않도록 했고, 네온 광선은 이미지 경계 바깥까지 이어 그렸습니다. 이미지 아래에 생기는 기본 여백은 align="top"으로 없앴습니다.
기여 기록을 등각 투영 도시로
도시는 GitHub 기여 그래프와 같은 53주 열, 7일 행을 바탕으로 만듭니다. 각 날짜를 등각 투영으로 그린 뒤 기여가 없는 날은 빈 땅으로, 기여가 있는 날은 건물로 표현합니다. 건물은 지붕과 양쪽 벽, 세 도형으로 구성합니다. 뒤쪽 건물부터 앞쪽 순서로 그려 앞 건물이 뒤 건물을 가리키게 하므로 별도의 3D 엔진은 필요하지 않습니다.
높이를 기여 수에 정비례시키면 바쁜 날 하나만 지나치게 높아지고 나머지는 낮은 판처럼 보였습니다. 그래서 제곱근을 적용했습니다. 계산식은 height = 8 + 110 * math.sqrt(count / busiest_day)입니다. 이 방식에서는 기여 1건인 날 높이가 11픽셀에서 25픽셀로 올라가고, 10건인 날은 34픽셀에서 61픽셀로 올라갑니다. 최다 기록인 43건은 두 방식 모두 118픽셀입니다. 건물 창문은 시드가 고정된 난수로 배치합니다. 데이터가 바뀌지 않으면 그림도 그대로여서 매일 의미 없는 커밋을 만들지 않습니다. 창문 불빛과 별, 달, 점멸하는 비행기도 더했습니다.
데이터 수집과 자동 갱신
갱신 과정은 네 단계입니다. fetch.py가 GitHub와 DEV에서 데이터를 가져와 JSON으로 저장하고, render.py가 SVG를 다시 그립니다. readme.py는 README에서 표시한 구역만 갱신하고, 마지막으로 변경 사항이 있을 때만 커밋합니다. GitHub Actions가 매일 뉴욕 시간 12시 17분에 실행하며, 필요하면 수동으로 실행할 수도 있습니다. 정각에 예약 작업이 몰리는 일을 피하려고 실행 시각을 17분으로 정했습니다.
GitHub 데이터는 REST API 대신 GraphQL API로 한 번에 가져옵니다. 팔로워, PR 수, 가입 날짜와 저장소별 별 수·포크 수·언어별 코드 크기를 조회합니다. 기여 내역은 요청 하나로 최대 1년치만 받을 수 있어, 먼저 활동 연도를 가져온 뒤 각 연도에 별칭을 붙인 필드를 만들어 한 번의 후속 요청으로 여러 해의 달력을 조회합니다. 이렇게 얻은 날짜별 기여 수로 연간·전체 기여 수와 연속 기록을 계산합니다. 작업이 정오에 돌아도 당일 기여가 아직 없으면 전날까지의 연속 기록을 유지하도록 처리했습니다.
DEV 데이터는 Forem API에서 가져옵니다. 공개 데이터로 글 수, 반응 수, 댓글 수를 집계하고, API 키가 있으면 조회 수와 팔로워 수도 더합니다. 페이지를 순회해 응답이 비어 있을 때까지 데이터를 모으며 최신 글 다섯 개도 프로필에 표시합니다.
실패 대응과 저장소 보안
API 호출이 실패하면 기존 JSON을 먼저 읽고 성공한 데이터만 갱신합니다. GitHub 조회가 실패해도 DEV 데이터는 갱신하며, 반대 상황도 같습니다. 둘 다 실패하면 스크립트가 오류로 종료하고 파일을 건드리지 않아 프로필에 0만 표시되는 일을 막습니다. 데이터 JSON도 이미지와 함께 저장소에 커밋하므로 Git 기록에서 통계 변화를 확인할 수 있습니다.
README 전체를 템플릿으로 덮어쓰지 않고 HTML 주석으로 표시한 글 목록 구역만 바꿉니다. 시작·끝 표시가 정확히 하나씩 없으면 스크립트가 실패하도록 해 README를 조용히 망가뜨리지 않습니다. 워크플로에는 GitHub 토큰과 DEV API 키를 저장소 비밀 값으로 전달합니다. 작성자는 읽기 전용 권한만 가진 fine-grained personal access token을 사용했고, 비밀 값이 없으면 내장 GITHUB_TOKEN과 공개 데이터만으로 실행하도록 구성했습니다.
dev.to 반응
- @kyisaiah47 — 매일 바뀌는 SVG라면 GitHub 이미지 캐시가 걱정됩니다. 워크플로에서 자산 URL을 바꾸나요, 아니면 캐시 무효화 없이도 프로필이 안정적으로 갱신되나요?
- @georgekobaidze — URL은 그대로 둡니다. 캐시는 몇 분 지나면 저절로 풀립니다.
- @sylwia-lask — 와, 정말 부럽습니다!!!! 😅💖
- @georgekobaidze — 이 활동 그래프는 가능성이 많으니 더 좋은 아이디어도 분명 찾으실 겁니다.😄
- @sinarezaei — GitHub 프로필을 다시 생각하게 만드는 정말 좋은 방법입니다. README를 사이버펑크처럼 꾸미는 데 그치지 않고 GitHub 기여 데이터를 실제 시각 시스템으로 만들었다는 점이 특히 좋습니다. 기여 강도는 건물 높이가 되고, 배치는 도시가 되며, 생성된 SVG는 인터페이스가 됩니다. 결정론적으로 생성하는 기술적 선택도 좋습니다. 데이터가 바뀔 때만 시각 결과가 달라지고, 나머지 시간에는 일관성을 유지합니다. 이 방식을 프로필 밖에도 적용할 수 있을 것 같습니다. CI/CD 활동은 배포 도시로, 이슈 활동은 지원 지도나 저장소 활동은 프로젝트 풍경으로 표현할 수 있습니다. 플랫폼 제약을 단순히 피해 가는 대신 디자인의 일부로 만든 점이 정말 영리합니다. 개발자 정체성을 표현하는 참신한 접근입니다.
- @georgekobaidze — 감사합니다! 말씀하신 대로 제약이 있어서 이 프로젝트를 작업하는 일이 정말 흥미로웠습니다. 너무 재미있었습니다.😄
- @effessdev — 정말 정말 좋습니다 😮😮😮
- @georgekobaidze — 감사합니다! 그렇게 말해주시니 좋습니다. 최근에 떠올린 아이디어 중 가장 창의적인 것 같습니다.
- @yashksaini — 다른 사람도 활용하고 수정할 수 있도록 자세히 설명한 점이 정말 좋습니다.
- @georgekobaidze — 감사합니다! 깊이 파고들기 전에는 저도 이런 게 가능한지 몰랐습니다.
원문: dev.to / 번역·요약: Trawling