오픈소스 컨트리뷰톤

오픈소스 컨트리뷰션이란 기여(Contribute)와 마라톤(Marathon)의 합성어로 멘토개발자와 함께 6주간 오픈소스 프로젝트에 참여, 공유, 협업하여 다양한 방식의 기여(Contribute)를 경험해보는 프로그램이다.

 

오픈소스 컨트리뷰션에 대해서 알고는 있었지만 막상 하려고 하니 어떻게 시작을 해야 할지 몰라서 시작을 못하고 있다가 7월 초에 오픈소스 컨트리뷰톤 멘티 모집한다는 글을 보고 좋은 기회다 싶어 신청했는데 운좋게 선발이 되어 참여를 하게 되었다. 많은 프로젝트 중 나는 어떻게 동작하는지 궁금했었던 JavaScript 정적 분석 도구인 EsLint에 신청을 했다.

 

컨트리뷰션 과정은 대략 다음과 같이 진행이 된다.

  1. 이슈 선정
  2. 자신의 Github에 해당 프로젝트 fork, clone 후 브랜치 생성
  3. 프로젝트 구조 파악과 테스트케이스 추가
  4. 코드 수정
  5. Pull Request
  6. merge!

 

이슈 선정

컨트리뷰톤이 시작되고 이슈를 선정해야했다. 처음이라 버그 이슈 위주로 살펴보았는데 EsLint는 이슈가 많이 없고 있어도 이미 PR이 올라온 것이 많아 당장은 기여하기 힘들 것 같았다. 그래서 EsLint의 플러그인 중 하나인 typescript-eslint의 이슈들을 살펴보기 시작했다. EsLint는 확장성이 높아 다양한 플러그인을 제공하는데 그 중 하나가 TypeScript에 대한 정적 분석을 지원하는 typescript-eslint이다.

 

typescript-eslint의 버그 이슈

 

멘토님은 살펴보면서 어떻게 해결하면 좋을지 감이 딱 오는 이슈를 선정하는게 좋다고 하셨는데 나는 감이 오는게 1도 없었다^^ㅎ 우여곡절 끝에 하나를 찾고, 많은 사람들의 관심을 받고 있는 오픈소스인 만큼 경쟁도 있고 선점을 하는게 중요하다고 해서 이 이슈는 내가 해결해보겠다는 코멘트를 달았다. 그래서 컨트리뷰톤에서도 이슈가 겹치지 않게 팀원들끼리도 각자의 이슈를 공유하면서 진행했다.

 

typescript-eslint #2376

선정한 이슈는 typescript-eslint의 규칙 중 naming-convention규칙과 관련된 이슈로서, naming-convention은 프로젝트 내에서 변수의 네이밍을 일관성 있게 설정할 수 있도록하는 규칙이다. 변수 네이밍을 할 때의 규칙은 각Option에 나타낼 수 있으며,Option에는selector, types, format,prefix등 여러 옵션이 있다. 이때 이슈에서의 버그 내용은 아래와 같이 배열 selectortypes를 같이 설정할 경우에 에러가 나는 것이였다.

 

{
  "rules": {
    "@typescript-eslint/naming-convention": [
      "error",
      {
        "selector": ["variable", "parameter", "property", "accessor"],
        "types": ["boolean"],
        "format": ["PascalCase"],
        "prefix": ["is", "should", "has", "can", "did", "will"]
      }
    ]
  }
}

 

해결 과정

위의 예시를 해결하는 것은 생각보다 간단했다. seletor배열을 생성하는 selectorsSchema함수에서 selector배열과 types를 따로 반환을 하고 있어 에러가 난 것이였고, properties속성에서 같이 반환하게끔 옮겨만 주었다.

 

// function selectorsSchema()

...

properties: {
  ...FORMAT_OPTIONS_PROPERTIES,
  ...{
    filter: {
      ...
    },
    selector: {
      ...
    },
    modifiers: {
      ...
    },
    types: {
      ...
    },
  },
},

...

 

이렇게 수정을 한 후 일단 PR을 보냈는데 메인테이너에게 이렇게 하면 이슈에서의 예시는 해결이 되지만 아직 다른 문제가 남아있다는 리뷰를 받았다. 만약 types를 허용하지 않는 selector가 배열에 있을 경우 해당 selector에 대한 검사가 제대로 이루어지지 않는다는 문제였다. 그리고 이러한 문제를 해결하기 위해선 어떤 함수를 수정해야 하는지도 잘 알려주셨다👍

 

 

수정해야할 함수는 normalizeOption였다. 이 함수에서 Option들을 반환하는데, selector가 배열일 경우 Binary OR을 통해 하나로 합쳐서 반환하여 각각의 selector에 대한 타입 검사를 할 수 없었던 것이다.

 

   return { 
     selector: selectors 
       .map(selector => 
         isMetaSelector(selector) 
           ? MetaSelectors[selector] 
           : Selectors[selector], 
       ) 
       .reduce((accumulator, selector) => accumulator | selector), 
     ...normalizedOption, 
   }; 

 

그래서 이 로직을 각 selector마다 Option을 반환하도록 수정해야했다. 나는 직관적으로 생각하고 따로 configs라는 배열을 만들어 각 selector마다 Option들을 생성해 configs에 push한 후 반환하도록 수정을 했다. 또한 각 Option을 생성할 때 타입을 허용하는 selector가 5개 밖에 없어 따로 selectorsAllowedToHaveTypes배열로 선언하여 해당 배열 안에 없는 selector일 경우 types를 null로 설정하였다.

 

const selectorsAllowedToHaveTypes: (Selectors | MetaSelectors)[] = [
  Selectors.variable,
  Selectors.parameter,
  Selectors.property,
  Selectors.parameterProperty,
  Selectors.accessor,
];

const config: NormalizedSelector[] = [];
selectors
  .map(selector =>
    isMetaSelector(selector) ? MetaSelectors[selector] : Selectors[selector],
  )
  .forEach(selector =>
    selectorsAllowedToHaveTypes.includes(selector)
      ? config.push({ selector: selector, ...normalizedOption })
      : config.push({
          selector: selector,
          ...normalizedOption,
          types: null,
        }),
  );

 

selectorsAllowedToHaveTypes배열을 처음 만들 때 enum인 Selectors에 있는 각 selector의 값(number)로 했었는데 멘토님과 메인테이너분이 '무슨 의미인지 알기 어렵기 때문에 수정을 하는게 좋을 것 같다' 라고 알려주셔서 위와 같이 수정을 했다👶

 

결과

어제까지가 컨트리뷰션 기간이였는데 아직 merge가 되지 않아 좀 더 기다려야 될 것 같다고 아쉬워 하고 있었는데, 어제 딱 merge가 되었다🙇‍♂️

 

 

컨트리뷰톤을 시작하기 전에는 Git을 통한 협업 경험이 없어서 초반에 코드 수정을 하고 처음 PR을 보낼 때 내 master 브랜치로 보내는 실수를 하거나 처음으로 테스트 코드를 작성하는 등 사실 컨트리뷰션 과정은 낯설고 쉽지 않았다. 하지만 그럴때마다 멘토님이 바쁘신데도 불구하고 이것저것 알려주시고 도와 주셔서 많이 배우기도 하고 감사했다. 컨트리뷰톤 시작하면서 oss관계자 분이 멘토님을 많이 많이 괴롭히라고 하셨는데 어느정도 달성한거 같다ㅎ 감사합니다. 사실 멘토님 말고도 같은 팀원 분들이 굉장히 잘하셔서 진행 상황 공유 하시는거 보면서 동기부여도 되고 도움이 많이 되었다.

 

Chrome으로 Node 디버깅 하는 법, Git 사용법 그리고 컨트리뷰션 하는 방법 등 많은 것을 배울 수 있었던 좋은 시간이였던 것 같다. 멘토님의 노력이 헛되지 않도록 까먹지 않게 시간을 내서 배운 것들 포스팅을 해야겠다. 또한 진행을 하면서 스스로 부족한 것이 많이 보이고 해서 훨씬 더 열심히 해야겠다는 생각을 많이 했다. 이 기회를 통해 앞으로도 컨트리뷰션을 계속 이어가도록 노력해야겠다🦾

 

나처럼 오픈소스에 관심은 있지만 어떻게 시작 해야될지 모르겠는 분들이 참여하시면 실력에 상관없이 여러모로 굉장히 많은 것들을 얻어갈 수 있는 좋은 프로그램인 것 같다. 

 

 

 

 


생강강

,