오픈소스에 기여한다고 하면 상당히 거창하고 어려운 일처럼 보인다. 나도 그렇게 생각했기 때문이다.
이번에 좋은 기회로 관심 있던 오픈소스 컨트리뷰션 아카데미(OSSCA)에 멘티로 참여하게 되면서 처음으로 오픈소스 문화에 입문하게 되었다.
나처럼 무엇을 기여할지 고민하기 이전에, 어떻게 기여를 시도할 수 있는지조차 어려움을 겪는, 정말 아무것도 모르는(!) 비기너들을 위해 오픈소스 기여 방법을 소개해보고자 한다.
기여할 프로젝트 고르기
먼저 Github에서 기여하고 싶은 오픈소스 프로젝트를 골라야 한다.
나같은 경우에는 아카데미에서 지원하는 여러 오픈소스 프로젝트 중 하나를 골라 그 팀에 합류하였기 때문에 기여할 프로젝트가 정해져 있었지만, 일반적인 경우에는 후보지 없이 자유롭게 고르게 될 것이다.
오픈소스 기여는 무엇보다 재미가 가장 중요하다고 생각한다.
자신이 기여하면서 즐거움을 느낄 수 있는 프로젝트, 이슈를 선정하는 게 좋다.
평소에 자신이 관심 있는 라이브러리, 프로젝트를 진행하면서 사용해 본 오픈소스가 있는지 생각해보길 바란다.
만약 없다면, 다양한 오픈소스 프로젝트를 안내하는 사이트를 참고해도 좋다.
참고할만한 사이트들
https://github.com/explore
https://github.com/topics/open-source
https://www.codetriage.com/
또한 본인에게 익숙한 언어나 프레임워크를 사용하고 있는 프로젝트가 좋을 것이다.
처음 보는 코드 읽기도 벅찬데, 모르는 언어로 작성되었다면... 그때부터는 기여 문제가 아니게 된다.
오픈소스 기여 활동이 활발한 프로젝트를 선정하는 것도 아주 좋은 방법이다.
해당 레포지토리에 이슈나 PR이 활발하게 일어나는지, 기여를 위한 커뮤니티가 잘 조성되어 있는지 확인해보길 바란다.
예컨대 내가 참여 중인 Yorkie 프로젝트에는 소통창구로 Discord 링크가 README에 적혀져 있다.
피드백이 빠르고, 잘 관리되며, 새로운 기여자들에게 우호적인 프로젝트를 선택한다면 기여에 보람을 느끼기 좋기 때문이다!
환경 세팅하기
기여할 프로젝트를 골랐다면, 이제 본인이 개발하는 프로젝트를 다룰 때처럼 코드를 읽고 수정할 수 있어야 한다.
IDE에서 레포지토리를 열어보는 오픈소스 기여 환경을 세팅하기 위해서는 몇가지 절차가 필요하다.
내가 이 글을 포스팅하게 된 이유이다.
fork
가장 먼저 원본 레포지토리를 fork한다.

fork는 해당 레포지토리를 자신의 Github에 복제하는 것이라고 보면 된다. 말 그대로 포크로 떠온다고 한다
그럼 내 깃허브에 있는 레포지토리는 내가 fork한 레포지토리의 복사본이 되고, 원본 레포지토리와의 커넥션을 갖는다.
나는 fork를 어떤 레포지토리 안에서 작업할 브랜치를 만드는 것처럼, 레포지토리 자체를 브랜치로 생성하는 것이라고 이해했다.
fork를 하는 이유는 무엇일까?
어딘가에서 계속 사용될지도 모르는 오픈소스의 원본 레포지토리를 아무나 직접 건들고 수정할 수 있으면 당연히 안 된다.
내가 열심히 개발한 프로젝트의 레포지토리를 누가 클론해서 코드를 삭제하고 push한 게 반영된다면? 끔찍할 것이다.
이를 위해 fork를 하는 것이다.
원본 레포지토리는 권한에 제한을 두어 함부로 망가지지 않게 하고, 기여자들은 fork를 통해 자신의 레포지토리에서 작업 후 원본 레포지토리로 PR을 올려, 권한을 가진 관리자들에게 승인되면 원본 레포지토리에 내 작업물이 반영된다.
이것이 fork의 장점이다. 내가 복사한 레포지토리는 원본 레포지토리와 연결되어 있어, 내 레포지토리에서 수정하게 되면 이 변경사항을 원본 레포지토리에 반영해달라고 요청할 수 있고, 원본 레포지토리의 변경사항도 내 레포지토리로 계속 받아올 수 있다.
또한, 내 fork한 레포지토리에서 작업을 한다면 아무리 코드를 망가뜨리고 바꿔놓아도 원본 레포지토리에 피해가 가지 않게 된다.
그러니 너무 부담갖지 말고 마음 편하게 작업하자!

fork 버튼을 누르면 위와 같은 화면이 보인다.
원본 레포지토리에서 작업 중인 브랜치에서 이어서 작업할 이슈가 있지 않은 이상, 보통은 main 브랜치만 가져오면 된다.
Create fork 버튼을 누르면 내 깃허브에 해당 레포지토리가 복사된다.

'codepair'라는 레포지토리를 fork한 뒤, fork한 레포지토리를 내 깃허브에서 본 화면이다.
어떤 레포지토리를 fork했는지 링크가 걸려 있는 것을 확인할 수 있다.
이때 나만 쓰는 이 복사본을 origin이라 하고, 원본 레포지토리를 upstream이라고 한다.
기여를 하다 보면, 내 복사 시점 이후로 원본 레포지토리가 기여들로 인해 업데이트되어 내 복사본과 달라질 수 있다.
예를 들면 위 이미지에 있는 알림 문구에서는 이 브랜치가 upstream보다 2개의 커밋이 뒤처져있다고 알려주고 있다.
따라서 Sync fork - Update branch를 통해 origin 레포지토리를 계속 갱신(최신화)해주어야 한다.
이를 오랫동안 안 하게 되면 내 새로운 작업물과 원본 레포지토리 간 충돌이 나는 것은 당연한 일이다.
clone
이제 fork한 origin 레포지토리를 내 로컬 환경에 깔아주어야 한다.
clone을 통해 내 컴퓨터의 원하는 곳에 레포지토리를 복제해주면, 자신이 사용하는 IDE 환경에서 코드를 읽고 수정할 수 있게 된다.
즉 fork와 달리, 내 origin 레포지토리를 정말 그대로 사용할 수 있게 가져오는 것이다.
내 레포지토리의 우측 상단에 있는 Code 버튼을 누르면 클론을 위한 URL이 보인다.
해당 URL을 복사하여 터미널에 실행해 원하는 곳에 레포지토리를 깔아주면 된다.
git clone https://github.com/내 ID/레포지토리명.git
그리고 원본 레포지토리도 연결시켜 주어야 한다.
git remote -v
를 실행해보면, origin 태그와 함께 방금 clone한 URL이 보일 것이다.
git remote add upstream https://github.com/원본 레포지토리.git
원본 레포지토리의 URL을 가져와 위 명령어를 실행하여 원본 레포지토리를 추가로 연결하고, 다시 git remote -v를 확인해보면, 아래 사진처럼 보이게 된다.

또한 git status 명령을 통해 내가 어디에 있고 어떤 상태인지 알 수 있다.
우리는 로컬의 origin 레포지토리에서 브랜치를 생성해 작업하면 된다.
이렇게 모든 세팅을 로컬 환경에 완료하면, 다양한 git 명령어를 통해 작업을 진행할 수 있다.
우리는 결국 원격의 원본 레포지토리(upstream), 이를 내 깃허브에 포크한 원격의 복사본 레포지토리(origin), 이를 클론한 로컬 레포지토리로 총 3개의 레포지토리를 다루게 된다고 볼 수 있다.
따라서 깃허브에서 원본 레포지토리와 포크한 내 레포지토리 간 Sync fork를 해주었듯이, 원격 origin 레포지토리와 이를 클론한 로컬과의 동기화도 마찬가지로 진행해주어야 한다. (git pull origin main)
코드 읽기
기여를 시작할 때 가장 먼저 해야할 것은 레포지토리의 README.md와 CONTRIBUTING.md를 읽는 것이다!
README.md에는 보통 해당 프로젝트의 간략한 개요와 개발 환경을 구축하는 가이드라인이 적혀 있다.
설명에 따라 프로젝트를 실행하면 된다.
CONTRIBUTING.md에는 기여자들을 위한 가이드라인이 적혀 있다.
보통 해당 프로젝트의 기여 방법과 규칙이 적혀 있어, 반드시 읽어보고 이를 준수하여 기여 활동을 진행하면 된다.
그 다음으로는 로컬 환경에서 해당 프로젝트의 코드들을 읽어보면 되는데, 대부분 방대한 파일과 코드 양을 자랑할 것이다(...).
나같은 경우에는 적당한 규모의 프로젝트의 frontend 폴더만 열어서 읽었기 때문에 일단 주요 파일들을 다 읽고 시작했지만(물론 그래도 정말 많다), 어렵다면 이슈를 먼저 고르고 그와 관련된 코드들을 찾아가도 된다.
사실 오픈소스 기여는 코드 읽기가 7할이라고 보아도 무방하다.
난생 처음 보는 프로젝트의 엄청난 양의 코드들을 읽어내는 것은 쉽지 않다.
개인적으로 나는 공부할 때 목차부터 보는 스타일이라, 폴더별로 파일 이름들을 적어두고 파일을 하나씩 읽으면서 이 파일이 어떤 행동을 하는 파일인지 적으며 코드 읽기를 진행하였다.
즉 각 파일들이 어떤 파일인지 의도를 먼저 파악하고자 하였다.
프론트엔드를 예로 들어보면, 가장 먼저 route 파일을 확인해 어떤 라우트들이 있는지 보았다.
그리고 pages 폴더에 있는 페이지 파일명들을 적어두고, 한 파일씩 읽으며 이 페이지가 어떤 페이지인지 이해하고, components 폴더에 있는 컴포넌트 이름들을 적어두고 해당 컴포넌트가 어떤 컴포넌트인지 이해하면서 점점 구조화해나갔다.
페이지 내에서 컴포넌트들이 어떻게 쓰이는지 확인하면서 자연스럽게 UI/UX와 관련해 개선할 이슈들을 찾게 되었다.
이슈 선정하기
기여할 준비가 되었으면, 이제 이슈를 할당받아야 한다.
즉 어떤 기여 작업을 할 것인지 결정하는 것이다.
나처럼 코드를 먼저 읽어도 되고, 원본 레포지토리의 Issues 탭에 가서 기여가 필요한 목록들을 먼저 살펴보아도 된다.

Issues 탭에서는 사람들이 해당 프로젝트에 대해 개선이 필요한 점들을 찾아 적어둔 내용들을 확인할 수 있다.
bug일 수도 있고, 새로운 기능을 구현하는 것일 수도 있고, 단순한 번역이나 오탈자 수정같은 문서 작업이 필요한 것일 수도 있다.
첫 기여는 언제나 떨린다! 나만 그런걸까
따라서 오픈소스에 처음 기여하게 된다면, 처음에는 아주 사소하고 작은 이슈를 해결하면서 오픈소스 기여 방법을 익히는 발판으로 삼는 것이 좋다. 한 번만 해보면 다음부터는 쉬워지고, 오픈소스 기여의 재미를 느끼게 될 것이다!
정말 별 거 아닌 문제 해결도 누군가는 해야 할 일이기 때문에, 사소하다고 기여를 망설이지 않았으면 좋겠다.
이슈마다 달려 있는 라벨을 통해 이슈를 목적에 따라 분류할 수 있으며, 대부분의 오픈소스 프로젝트에 들어가 보면 위에 내가 올려둔 화면처럼 'good first issue' 라벨을 따로 분류해둔 것을 확인할 수 있다.
이는 오픈소스 기여 비기너들의 기여 독려를 위해 처음 기여해보기 좋은 쉽고 간단한 이슈들을 마련해 둔 라벨이다!
얼마나 따뜻하고 아름다운 세상인가
이를 적극 활용하기 바란다.
나는 코드를 읽으며 import한 라이브러리에서 더 이상 지원하지 않는 컴포넌트를 사용하여 코드 취소선이 그어져 있는 것을 보고, 이를 업데이트하는 것을 첫 기여 대상으로 삼았다.
내가 찾은 이슈는 Issues 탭을 검토했을 때 존재하지 않는 이슈였기 때문에, 새로운 이슈로 작성해 등록하였다.
새로운 이슈를 찾아 등록하여도 되고, 이슈 목록에서 해결하고 싶은 이슈를 찾아도 된다.
새로운 이슈를 찾는 것도 일종의 기여 활동이라고 볼 수 있다.
누군가 올린 이슈를 해결하고 싶다면, 오른쪽 상단의 Assignees를 먼저 확인해보면 된다.
이슈 목록에서도 이슈마다 오른쪽 끝에서 Assignees의 프로필을 확인할 수 있다.

Assignees에 누군가 할당되어 있다면, 그 사람이 해당 이슈를 해결하고 있는 담당자라고 보면 된다.
만약 할당된 사람이 없는 이슈에 기여하고 싶다면 해당 이슈에 기여하고 싶다고 comment를 남기면 된다.
관리자(메인테이너, 커미터)가 확인하고 할당해줄 것이다.
그럼 기여 활동을 시작하면 된다!
그밖에도 만약 이미 할당된 사람이 있는데 오랫동안 작업이 이루어지지 않는 것 같아 이슈를 할당받고 싶거나, 작업하다가 논의할 사항이 생겨도 이 이슈의 comment를 이용하면 된다.
기여 활동
이슈를 할당받았다면 해당 이슈를 해결하기 위한 브랜치를 생성해 개발을 진행하면 된다.
로컬 환경의 내 origin 레포지토리에 브랜치를 생성하고, 브랜치에서 작업을 한 뒤 작업 내용을 커밋하고 원격의 origin 레포지토리에 push한다.
그럼 자동으로 원본 레포지토리인 upstream에 PR이 가능하게 된다.
PR

이제 깃허브로 돌아와 Pull Request을 작성한다.
위 사진과 같이, 내가 fork해서 만든 나의 origin 레포지토리의 한 브랜치(지금은 main이라 적혀 있지만, 특정 브랜치에서 작업한 경우 해당 브랜치의 이름이 오게 된다)에서 원본 레포지토리의 main으로 pull 요청을 보내게 된다.

내가 작성했던 PR이다.
이슈와 마찬가지로 생성된 작성 양식에 따라 내용을 채워 PR을 올렸다.
이슈나 PR을 작성할 때 포맷이 정해져 있지 않다면 메인테이너와 커미터가 이를 이해할 수 있게끔 자세하게 작성하면 된다.
이슈 목록에 있는 이슈를 해결하는 PR이라면 자신이 해결한 이슈 번호를 반드시 태깅해야 한다!
PR을 올리고 나면 해당 프로젝트에 걸려 있는 CI 파이프라인에 따라 1차 검토가 수행된다.
일반적으로는 린트 오류나 빌드 오류가 없는지 기본적인 코드 품질 검사를 거치게 되는데, 이때 오류가 발생한다면 반드시 다시 커밋을 통해 고쳐야 한다.
따라서 작업 내용을 커밋하기 전에 패키징 매니저의 스크립트를 통해 오류가 없는지 확인하고 사전에 수정하는 것이 좋다.
또한 처음 기여하는 프로젝트라면 CLA 사인을 요청받게 된다.
이는 Contributor License Agreement로, 해당 프로젝트에 기여한 코드에 대한 권한에 관한 법적 동의를 구하는 절차이다.
해당 내용에 사인하지 않으면 기여할 수 없게 된다.
CLA에 서명하고 코드 품질 검사도 통과하면 이제 관리자의 리뷰만 기다리면 된다.
관리자가 우리의 PR을 읽어보고 수정 사항이나 의견을 리뷰로 달아주면, 이를 반영하는 커밋을 거듭한다.
실수가 많으면 검토 과정에서 리뷰어도, 계속 수정하는 나도 고통받을 수 있다(...). 나의 능력이 허용하는 선에서 최대한 리뷰하기 쉽도록 가독성 좋고, 실수가 없는지 확인한 뒤 신중하게 PR을 올리도록 하자.
나도 컨트리뷰터!

모든 검토 작업이 성공적으로 끝나면, 관리자가 이를 approve하여 원본 레포지토리에 병합하고 자동으로 PR이 닫힌다.
즉, 오픈소스에 기여하게 된 것이다!
merge가 완료되었으면 작업이 끝난 내 브랜치는 삭제해도 좋다.
PR에 이슈가 연결되어 있었다면, PR과 함께 이슈도 자동으로 함께 닫힌다.
메인테이너의 감사 인사와, 오픈소스에 내 코드가 적혀 있는 것, 컨트리뷰터로 내 프로필이 올라가 있는 것을 보면 오픈소스 기여의 보람과 재미를 비로소 느끼게 될 것이다.


오픈소스에 기여해보기 전에는 '내가 감히 어떻게 그런 걸'이라는 생각에 도전하기를 주저했다.
물론 그 방대한 코드를 읽고, 내가 기여할 부분을 찾고, 개발한다는 것이 간단한 일은 아니다.
아무런 대가 없이 시간을 할애하는 일이기 때문이다.
그러나 어려운 일은 아니라는 생각이 든다.
내가 처음으로 기여한 이슈는 사실 개발 실력이 없어도 가능한 내용이었다.
즉 기여하는 루트만 알면 허들이 높지는 않다는 의미이다. 이 글로 이제 루트도 알지 않았는가
오픈소스에 기여하고자 하는 마음만 있다면, AI와 구글링의 도움을 받아서라도 충분히 할 수 있다고 생각한다.
오픈소스를 운영하는 사람들 입장에서 생각해보면, 대가 없이 프로젝트를 도와주는 컨트리뷰터들은 정말 소중할 수밖에 없다.
개발 활동을 하면서 감사하게 많은 오픈소스를 쓰는 만큼 오픈소스 생태계에도 많은 관심을 가져보길 바란다!