GitHub 프로필을 iMessage 대화 메시지로 꾸며보기

GitHub Actions를 십분 활용하여 GitHub 프로필 업데이트를 자동화 해보자

Sigrid Jin
15 min readAug 8, 2021
이렇게 …이 뜨면서 1~2초 정도 딜레이가 있는 애니메이션에 현혹되었다

언제인가 페이스북에서 박찬성님 깃허브를 보게 되었는데, 깃헙 프로필에 아이폰 메시지처럼 대화 형태로 자신을 소개하는 것이 인상적이었다. 1~2초 정도 시간 동안 (…) 구름이 뜨다가 메시지가 뜨는 모습은 아주 놀라웠다. 찬성님 이야기로는 본인은 대화 구름 애니메이션 svg를 하드코딩한 것에 불과하다고 하시더라.

그래서 본인이 직접 원작자를 찾아서 해당 repository를 참고하여 나의 프로필을 꾸며보겠다고 결심했다. 원작자는 GitHub에서 Product Designer로 일한 바 있는 Jason Long씨였다. Jason씨의 메시지에는 오늘 날씨에 따라 본인이 거주하고 있는 오하이오 지역의 날씨를 업데이트해서 보여주고, 오늘이 무슨 요일인지에 따라 인사를 남기도록 자동 업데이트가 설정되어 있었다. 이건 꼭 해봐야지 생각하게 되었다. 그래서 나는 Jason씨의 깃허브를 참고하면서 bubble message를 깃허브 소개에 적용해보는 여정을 시작하게 되었다.

Step 0. 프로젝트 구조 설명

일단 들어가기 전에, 본인의 GitHub 프로필에 소개 화면을 만들고 싶다면 나의 GitHub 아이디와 동일한 이름의 저장소가 생성되어 있어야 한다. 예를 들어, 본인의 GitHub 아이디는 jypthemiracle인데 프로필 소개 화면을 만들고 싶다면 jypthemiracle이라는 이름의 Repository를 생성해야 한다는 것이다. 이것이 먼저 준비된 상태에서 아래 글의 내용을 따라오기 바란다.

본인이 구축한 GitHub 프로필 저장소의 구조를 먼저 설명하고자 한다. 핵심은 build-svg.js와 template.svg라고 할 수 있다. template.svg에는 버블 메시지 형태로 등장하는 메시지가 하드코딩 되어있다. 해당 svg 파일에는 오늘 날짜와 날씨, 온도가 매개변수로 등장한다. build-svg.js는 파일이 실행될 때마다 chat.svg를 생성하는데, template.svg에 매개변수에 들어가야 하는 파라미터를 주입한다. 예를 들어, 나의 깃헙 프로필에 보면 “Have a nice {todayDay}!” 라는 부분이 있다. 자바스크립트 파일에서 오늘 날짜를 계산한 후 이를 요일로 변환하여 {todayDay} 파라미터에 주입하는 것이다.

index.html은 bubble message를 작업하는 기본적인 파일이라고 할 수 있다. 해당 HTML 파일을 다 작성하고 나면 svg 파일로 변환하면 된다. 사실 나는 Jason Long씨의 저장소를 fork받으면서 svg 파일에서 직접 메시지와 width, height을 수정하였다. 원래면 HTML 파일에서 작업한 뒤에 이를 template.svg로 export한 것으로 보인다. 마지막으로 build-svg.js에서 생성한 chat.svg가 GitHub 프로필에 보여지게 되는 최종 아웃풋이라고 할 수 있다.

Step 1. template.svg 만들어보기

index.html에서 작업한 후 이를 template.svg로 저장하면 된다. 기본적인 CSS 스타일링 설정은 모두 index.html나 template.svg에 이미 되어 있다. 나는 HTML, CSS 작업에 둔한지라 바로 svg 파일에서 작업했는데, html을 svg로 변환하는 npm 라이브러리가 몇 가지 있으니 이를 참고해보면 될 듯 하다.

내가 작업한 template.svg 기준으로 <! — Hi, I’m Sigrid Jin →주석 쪽을 찾아보면 메시지를 하드코딩하는 부분이 나온다. text 태그 내부에 본인이 원하는 메시지를 입력하고, rect 태그의 width와 height을 조정하고, text의 x 좌표와 y 좌표를 조정하여 메시지가 버블 창을 뚫고 나오지 않도록 조정하기를 바란다. <rect width=”153" height=”42" rx=”18.0355" /> 이 쪽 부분이다.

주석 처리된 부분에서 텍스트를 찾아 본인의 입맛에 맞게 수정하면 된다. svg 파일 기준이다.

다 완성이 되었다면 template.svg를 commit 해보면 된다. 브라우저로 확인하면서 본인이 선호하는 메시지로 잘 작업이 되었는 지 확인해보도록 한다.

Step 2. build-svg.js 작업하기

build-svg.js는 template.svg에서 진짜 아웃풋이 될 놈인 chat.svg를 작업하는 부분이다. 전체 코드를 살펴보자.

내가 작업한 원본 파일은 다음의 링크에서 확인할 수 있다. Jason Long씨가 작업한 build-svg.js 파일을 가져오면서 몇 가지 수정사항을 반영했다.

여기서는 npm 라이브러리는 fs와 date-fns, openweather-apis와 js-quantities 라이브러리를 사용했다. fs는 파일의 입출력을 담당하는 라이브러리인데, 여기서는 fs.readFile 함수를 통하여 template.svg를 읽어오면서 매개변수가 들어가야 할 자리를 파라미터로 주입시킨 후에 chat.svg로 파일을 작성하는 것에 사용한다.

date-fns는 자바스크립트에서 시간 계산을 유용하게 할 수 있는 라이브러리이다. 원본 파일에는 {pstime} 이라는 매개변수에 시간 변수를 주입한다고 되어 있으나 이를 활용하는 부분은 없다. date-fns의 formatDistance 함수를 참고하면 특정한 날짜에서 다른 날짜까지 몇 일 차이가 나는 지 계산하는 함수인 것을 보아서 이전에 시간 차이를 보여줘야 하는 메시지를 작성하고자 하셨나보다 생각하게 된다.

내가 작업한 내용에서는 convertTZ라는 함수가 추가로 작성되어 있다. 해당 부분은 추후 GitHub Actions를 돌리게 되는 컴퓨팅 엔진이 UTC 시간으로 되어 있어 today 함수로 오늘을 찍으면 한국 시간 기준으로 만 하루 정도 차이가 나는 것을 알 수 있었다. date-fns 말고 date-fns-tz를 이용하면 time conversion을 할 수 있지만, 나는 그것보다는 직접 함수를 짜서 변환하고자 했다.

function convertTZ(date, tzString) {    
return new Date((typeof date === "string" ? new Date(date) : date).toLocaleString("en-US", {timeZone: tzString})); }
const today = convertTZ(new Date(), "Asia/Seoul");
const todayDay = new Intl.DateTimeFormat('en-US', { weekday: 'long' }).format(today); // 여기서 지정된 todayDay를 svg 파일에다가 주입한다.

날씨의 경우에는 openweather API를 이용했다. process.env에 매개변수를 주입해야 하는데, 우리는 GitHub Action이라는 workflow 자동화 도구를 이용하고 있다. 따라서 깃헙 액션에 매개변수를 주입해야 하는데, 이는 저장소에 가서 Setting > Secrets에 가면 Repository Secrets를 추가하는 부분이 있다. 해당 부분에 API Key를 주입해야 한다. 매개변수 이름은 WEATHER_API_KEY로 해 주면 된다.

저장소 > Settings > Secrets

OpenWeather API Key를 발급받는 방법은 간단하다. openweathermap.org 사이트에 접속해서 API 메뉴를 탭한다. Current Weather API의 Free Plan 정도면 사용하기에 족하니까 무료 버전을 subscribe하고 API Key를 발급받으면 된다. 이후 발급받은 API Key를 깃헙 액션에 Repository Secrets로 매개변수로 주입하면 된다.

Current Weather Data의 무료 버전이면 사용하기에 족하다.

나는 서울 사람이라서 build-svg.js에 서울특별시의 위도와 경도를 넣어주었다. 본인이 희망하는 지역의 위도와 경도를 다음과 같이 설정해주면 되겠다.

weather.setLang('en')
weather.setCoordinate(37.517235, 127.047325) // 여기서 설정하면 된다.
weather.setUnits('imperial')
weather.setAPPID(WEATHER_API_KEY)

js-quantities 라이브러리는 화씨를 섭씨로 변경해주는 데 사용한다. OpenWeatherAPI는 화씨를 기준으로 데이터를 내려주기 때문에, 라이브러리의 섭씨 변경 함수를 이용하면 된다. 날씨 아이콘도 사전에 지정되어 있는데, API에서 내려오는 날씨 코드값을 바탕으로 이모티콘을 js 파일에 지정해주어서 날씨 별로 icon이 설정되어 svg 파일에 매개변수로 내릴 수 있도록 되어 있다.

const emojis = {  '01d': '☀️',  '02d': '⛅️',  '03d': '☁️',  '04d': '☁️',  '09d': '🌧',  '10d': '🌦',  '11d': '🌩',  '13d': '❄️',  '50d': '🌫'}weather.getWeatherOneCall(function (err, data) {  
if (err) console.log(err)
const degF = Math.round(data.daily[0].temp.max)
const degC = Math.round(qty(`${degF} tempF`).to('tempC').scalar)
const icon = data.daily[0].weather[0].icon
...

Step 3. GitHub Action으로 자동커밋 설정하기

깃헙 액션을 이용해서 하루에 한 번씩 build-svg.js가 실행되도록 하여서 chat.svg를 업데이트하도록 설정해보자. 이렇게 된다면 매일매일 날씨와 오늘의 요일이 버블 메시지에 업데이트 될 것이다.

readme2.yml 파일을 작성해보자. 해당 YAML 파일에는 workflow의 내용이 상세하게 지정될 것이다. 폴더 위치는 /.github/workflows이다.

readme2.yml

GitHub Actions의 workflow를 처음 접하는 사람들을 위해 간단하게 설명해보도록 하겠다. 먼저 GitHub Action에는 Workflow라는 개념이 있다. 워크플로우 안에는 여러 Job이 구성되어 있고, 이는 특정한 Event에 의해 트리거될 수 있는 프로세스다. name은 workflow 하나를 통틀어 부르는 이름이다. 위의 파일을 보면 여러 가지 job, 즉 일이 지정되어 있다. 그것들을 하나로 묶는 것이다 라고 생각하면 된다.

Event는 특정한 Workflow를 Trigger하는 활동이나 규칙이다. 특정 브랜치로 push가 들어오거나, pull request가 들어올 때 자동으로 실행되도록 규칙을 지정할 수 있다. 여기서는 Cron을 사용했는데, 특정 시간대에 반복하도록 하는 것이다. 이는 on 탭에서 schedule로 지정되어 있다. “0 4 * * *” 라고 되어 있는데, 이는 매일 새벽 4시에 실행하라는 의미가 된다. GitHub Actions는 UTC 시간을 기준으로 하므로, UTC 시간 기준 새벽 4시에 실행될 것이다. Cron 표현식을 더욱 이해하고 싶으면 다음의 링크를 참고하면 좋겠다.

Step는 Job에서 해야 하는 특정한 Actions를 실행하는 각각의 개별적인 단위라고 생각하면 된다. 액션은 GitHub Marketplace에 올라와 있는 것들을 주로 사용하는데, 나는 GitHub Actions 컴퓨팅 엔진에 Node.js를 설치하고 node 파일을 실행하도록 하는 Action과 자동 커밋을 수행하는 Action을 받아서 사용했다. actions/setup-node를 통하여 build-svg.js를 자동으로 실행하도록 하고, add-and-commit 액션을 통하여 생성된 svg 파일을 잡아서 자동으로 commit하도록 한 것이다.

자동 커밋을 할 때에는 GitHub Token이라는 것을 발급받아야 한다. GitHub Token은 깃헙 저장소를 관리할 수 있는 API Key로서, 굳이 저장소에 별도로 주입할 필요 없이 한 번 발급받으면 GitHub Token이 Workflow에서 실행될 때 GitHub Action이 자동으로 주입해준다. GitHub Token은 다음의 설정 사이트에 들어가면 발급받을 수 있다.

처음 yaml 파일을 올려두고 난 후에는 Run workflow를 눌러서 임의로 한 번 실행하도록 하자. 이후에는 계속 자동으로 GitHub Actions가 Workflow를 잡아서 자동으로 지정한 시간에 따라 cron 실행을 할 것이다. svg 파일을 새로 만들고 이를 새롭게 commit하는 것을 보면 참 신기하다고 할 수 있다.

Step 4. GitHub Profile 업데이트하기

위의 단계까지 정상적으로 거쳐왔다면 저장소 최상단 폴더에 chat.svg 파일이 자동으로 생성되어 있을 것이다. 본인이 yaml 파일에서 Auto updating my readme 라고 커밋 메시지를 작성해두었으므로 해당 커밋 메시지에 따라 chat.svg 파일이 생성되었다면 의도대로 workflow가 잘 작동한 것이다.

나의 저장소에 들어가서 README.md 파일을 작업해준다. 마크다운 파일이므로 다음과 같이 사진이 나타나도록 지정해주면 된다. 반드시 blob/master가 path로 지정되어 있어야 commit이 바뀌어서 파일이 업데이트 되더라도 이전 commit의 svg 파일을 따라가지 않는다.

본인이 실수로 특정한 커밋의 svg 파일의 링크를 복사해서 README.md에 설정해주는 바람에 chat.svg 파일이 정상적으로 갱신 되었는데도 불구하고 이전 커밋의 svg 파일이 떠 있어서 당황했던 적이 있다. 사실 당연한게 Git은 변경 사항을 업데이트할 때 모든 파일을 다 올려버리기 때문에 나타나는 현상이기는 하다. 아무튼 이 지점에 유의하기 바란다.

// README.md
...
![message_svg](https://github.com/나의 깃헙 아이디 /나의 깃헙 아이디/blob/master/chat.svg)

여기까지 작업했다면 다음과 같이 뜰 것이다.

Bonus. Commit Contribution Snakes 만들기

찬성님 깃허브에서 또 커밋 기여 항목을 뱀이 잡아먹고 있는 모습을 보았다. 의 커밋 기여 항목을 보여준 후, 뱀이 돌아다니면서 커밋 항목을 하나씩 먹는 것이다. 아주 귀여워서 꼭 적용해야지 생각했다.

위에서 버블 메시지를 적용한 것과 유사하게 작업하면 되므로 보너스로 설명해보도록 하겠다.

먼저 동일한 폴더 .github/workflows에 가서 다음과 같은 yaml 파일을 만든다.

본인의 파일 링크는 다음을 참조하라. 별 차이는 없고 github_user_name을 본인의 깃헙 아이디로 바꾸면 된다. 여기에서는 본인의 github commit contribution을 매번 workflow를 작동할 때마다 갱신하는데, 이 때 그림 파일을 output이라고 하는 새로운 브랜치에다가 매번 push한다. Actions는 snk@master 라는 액션을 사용했다. workflow가 정상적으로 실행되었다면 output 브랜치에 새롭게 제작된 gif와 svg파일이 있을 것이다. 해당 svg 파일의 링크를 복사해서 README.md에 다음과 같이 지정해두면 된다.

// README.md
...
![snake svg](https://github.com/본인 깃헙 아이디/본인 깃헙 아이디/blob/output/github-contribution-grid-snake.svg)

나가며

GitHub Actions를 활용하여 프로필을 꾸미는 것에 대해 설명해보았다. 이번 작업을 통하여 GitHub Actions가 얼마나 강력한 툴인지 사뭇 깨닫게 되었다. CI/CD를 도구를 활용한 자동 커밋이 세상 유용하다는 생각을 하게 되었다. 개발자는 귀찮음을 싫어하는 사람들이라서 자동화를 그렇게나 좋아한다고 하더라. 자동화를 해가는 삽질을 통해 개발 능력을 상승시키는 것 같기는 하다. 마지막으로, 훌륭한 리소스를 작업해주신 Jason Long씨에게 다시 한번 감사의 말씀을 드리고 싶다.

--

--