주니어 개발자의 첫 오픈소스 기여 경험

이호영·2022년 3월 5일
6
post-thumbnail

깃헙에서 묻혀져 가기 전에 오픈소스 기여 경험을 자랑해보고자 글을 작성한다 :)

오픈소스 Contribution 경험

당근마켓 채용공고

기업들의 채용 공고에서 자주 등장하는 "오픈소스 기여 경험". 오픈소스를 자주 이용하던 입장에서 항상 기여하고 싶은 마음은 굴뚝같았지만 마음 한편에 알 수 없는 두려움이 있었다.

내가 남긴 이슈가 사실 내 버그는 아닐까? 내가 영어로 쓴 글을 다른 사람이 이해할 수 있을까? 내가 고칠 수 있는 버그는 있을까? 등

그러던 와중 Yarn Berry(v2)를 사내에 도입하기 위해 리서치를 하던 중 특정 라이브러리가 잘못 불러와지는 것을 발견했고, npm과 yarn을 크로스 체킹 하면서 npm을 사용할 땐 없던 에러가 yarn을 사용하면 발생하는 것을 확인했다.

에러를 확인해 보니 OTP는 hotp, totp 두 가지 종류가 존재하는데, 그 때문에 라이브러리 내에서 hotp.ts, totp.ts 두 가지가 선언되어 있다. 이를 index.ts 파일에서 export 하는데

export * from './hotp';
export * from './totp';

이렇게 선언되어 있음에도 totp가 hotp 파일을 불러오는 것이었다. 확실한 yarn 문제라고 판단하고 에러도 파악해서 생에 첫 이슈를 남겼다.

간단히 에러가 발생하는 코드와, 내가 분석한 에러 내용, reproducable repository를 올렸다. 이미 보고된 에러였지만 나름 뿌듯했다.

그리고 에러가 수정되었다고 말하고 사내에 Yarn Berry를 도입했다. 그래서 현재는 최근 개발된 프로젝트에는 Yarn Berry가 사용되고 있다.

apidoc 문제 발견

사내에서는 API 문서를 apidoc로 작성해서 프론트로 전달하는데, apidoc에 버그가 존재해서 object에 대해서 선언하면 선언한 순서대로 문서가 작성되지 않았다.

그래서 apidoc을 확인해 보니 0.50.0 버전에서 수정된 버그였다. 하지만 0.50.0으로 업데이트를 하면 정상적으로 동작하지 않았다. 기존 버전에서는 npm에 배포할 때 node_modules를 포함해서 배포하는 바람에 패키지 안에 node_modules가 존재했었다.

그래서 별문제 없이 동작했는데, 버전이 업데이트되면서 그것이 해결되며 발생한 문제였다.

왜냐하면 Yarn v2는 비효율적인 node_modules를 제거하고 Plug n Play라는 개념을 도입했기 때문이다.

// lib/writer.js
/**
   * Find assets from node_modules folder and return its path
   * Argument is the path relative to node_modules folder
   */
  findAsset (assetPath) {
    let nodeModPath = this.path.resolve(this.path.join(__dirname, '..', 'node_modules'));
    if (this.fs.existsSync(this.path.join(nodeModPath, assetPath))) {
      return this.path.join(nodeModPath, assetPath);
    }
    nodeModPath = this.path.resolve(this.path.join(__dirname, '..', '..'));
    if (this.fs.existsSync(this.path.join(nodeModPath, assetPath))) {
      return this.path.join(nodeModPath, assetPath);
    }
    nodeModPath = this.path.resolve(this.path.join(process.cwd(), 'node_modules'));
    if (this.fs.existsSync(this.path.join(nodeModPath, assetPath))) {
      return this.path.join(nodeModPath, assetPath);
    }
    this.log.error('Could not find where dependencies of apidoc live!');
  }

apidoc에는 findAsset 함수가 작성되어 있다. 문서를 빌드 할 때 node_modules 폴더를 찾아서 bootstrap의 css 같은 asset을 찾아서 복사하는 과정을 거친다. 그때 node_modules를 찾아서 bootstrap의 경로를 찾는다.

이렇기 때문에 패키지 내부에 node_modules가 없는 Yarn v2에서는 node_modules를 찾을 수 없다.

그래서 해당 오류에 대한 이슈를 남기고 해결하는 코드를 작성해 PR을 날렸다.

단순히 node_modules를 찾고 그다음에 .yarn/cache를 찾는 코드를 작성했다.

하지만 pnpapi를 사용해 달라는 리뷰를 받았고 내가 아는 한 pnpapi는 npm에서 설치해 사용하는 것이 아니라 Yarn v2를 사용하는 프로젝트에서 injection 하는 방식으로 호출해서 사용하는 것이었다.

https://www.npmjs.com/package/pnpapi 를 확인해 보면 아무런 코드가 작성되어 있지 않은 것을 확인할 수 있습니다. Yarn v2로 설정하면 설치되는 .pnp.cjs에서 pnpapi의 패키지가 있는 것처럼 동작하게 만들어주기 때문에 injection 한다고 표현했습니다.

즉 apidoc 코드 안에서 const pnpapi = require('pnpapi') 했지만 apidoc 프로젝트에 yarn을 사용하지 않기 때문에 apidoc을 설치한 우리 프로젝트에서 .pnp.cjs 가 호출된다.

그래서 apidoc의 dependency인 bootstrap에는 우리 프로젝트는 접근할 수 없었다. pnpapi로 여러 가지 테스트를 해봤지만 해결책을 찾을 수 없었다. 그래서 해당 PR은 머지되지 않고 닫혔다.

그래서 해결할 수 있는 방법을 Yarn 커뮤니티에 물어보았고, 의외로 쉽게 해결할 수 있는 문제라는 것을 알 수 있었다.

packages-are-stored-inside-zip-archives-how-can-i-access-their-files

그래서 바로 새 PR을 올렸다.

노드 문서를 확인해 보니 require.resolve는 0.3.0부터 추가되어 있어서 하위호환성 및 npm 과의 호환성에 대한 걱정 없이 작동할 거라고 판단했다.

워낙 간단히 해결했기 때문인지 코드에 대한 리뷰는 없이 테스트를 어떻게 해야 하는지 물어보는 코멘트가 달렸다.

내 빈약한 영어로 설명하기 힘들었지만 이 PR에 대한 설명, 어떻게 테스트해야 하는지 작성했다. (고마워요 구글! 파파고!)

그래서 현재는 dev 브랜치에 merge 되었고 master에 머지되어 릴리즈 되기를 기다리고 있다.

마치며

처음에 PR을 올렸을 때 머지되지 않고 닫혔을 때 실망했다.
apidoc에서 object 순서가 맞지 않는 것은 response example를 추가해주기 때문에 프론트엔드 측에서 크게 불편함을 느끼지 않았다.
그래서 그냥 업데이트 하지 않고 사용할까도 생각했다.

하지만 해결하고 싶었다. 이전에 Yarn Berry 레포에 이슈를 작성하며 앞에 말한 두려움은 극복했지만 단 한가지가 남았다.

내가 고칠 수 있는 버그는 있을까?

여기서 이 두려움을 떨쳐낼 수 있는 기회라고 생각했다. 문제가 발생한 코드도 간단했고 문제점도 찾았기에 해결할 수 있을 것 같았기 때문이다.

그리고 도전했고 이렇게 성공적으로 첫 삽을 떴다. 이제는 오픈소스에 기여할 또 다른 기회가 있다면 주저하지 않고 도전할 것이다.

우리 회사뿐만 아니라 Yarn v2를 도입한 곳에서 apidoc을 잘 쓰게 된다면 너무 뿌듯할 것 같다.

profile
안녕하세요!

3개의 댓글

comment-user-thumbnail
2022년 3월 11일

재미있게 봤습니다! 불편함에서 멈추시지 않고 PR까지 남기신게 정말 대단한 거 같아요.

1개의 답글
comment-user-thumbnail
2022년 10월 22일

멋지십니다!!

답글 달기