React 공식 문서에 기여하게 된 썰

React 공식 문서에 기여하게 된 저의 신비한 사연을 소개합니다.

2023-03-24

위풍당당

개요

네 React 공식 문서에서 코드 에러 잡은 사람이 바로 접니다.

코드 에러를 찾게된 전말

때는 3월 22일 새벽 2시경이었습니다. React의 컴포넌트 라이프 사이클을 새로운 공식 문서를 통해 공부하던 중 ESlint를 활용하면 re-synchronize에 필요한 reactive value를 찾아준다는 부분의 코드 예시에서 에러를 찾게 되었습니다. 에러 코드는 다음과 같습니다.

수정되기 전 코드

⁉️ 잠깐 혹시 이상한 점을 발견하셨나요?

이상한 점은 바로, 코드 예시 ChatRoom 컴포넌트의 propsserverUrlconst로 선언된 useState의 첫 번째 반환 값 serverUrl이 재할당 됐으며 이미 선언되었다는 것입니다!

function ChatRoom({ roomId, serverUrl }) {
  const [serverUrl, setServerUrl] = useState("https://localhost:1234"); // serverUrl is reactive
 
  // ...
}

처음 코드 에러를 찾아내고 뭔가 알 수 없는 두근거림을 느꼈습니다. 두근거림 이후 제 눈을 의심했고 const로 선언된 변수의 경우 재할당이 불가능 한데, Dan Abramov가 설마 실수를?이라는 생각이 들었습니다.

에러를 찾았다는 것을 빨리 React 팀에 알리기 위해 바로 Pull Request를 생성하자는 생각을 하였는데, 잠시 숨을 가다듬었습니다. 그 후 저는 만약 내가 틀린 것이라면?이라는 생각이 들었고, 사실 90% 정도 에러다라고 확신은 했습니다(진짜). 그래도 에러라는 확신을 얻기 위해 테스트 작업을 해보았습니다.

✨ 절대 제가 틀린 것 같아서 테스트를 진행한 것이 아니라는 점을 밝힙니다. 😆

코드 에러 테스트 과정

총 6 가지 경우에서 에러 테스트를 진행하였습니다.

  1. JavaScript 환경

    js

    IDE 상으로 JavaScript 환경에서는 어떤 에러도 발생하지 않습니다. 하지만, 런타임에서는 어떻게 동작할까요?

    코드를 실행시키면 바로 아래와 같은 Syntax 에러가 발생됩니다.

    const [serverUrl, setServerUrl] = [];
          ^^^^^^^^^
     
    SyntaxError: Identifier 'serverUrl' has already been declared

    즉 식별자 serverUrl이 이미 선언되었다는 에러입니다. JavaScript 환경에서는 확실한 에러라는 것이 증명되었습니다. ✔️

  2. TypeScript 환경

    ts

    코드 작성과 동시에 Duplicate identifier 'serverUrl' 에러를 보여줍니다.
    런타임이 아닌 컴파일 시 에러를 보여주는 TypeScript의 특징을 확인해 볼 수 있습니다.
    위 과정을 통해 TypeScript 환경에서도 확실한 에러라는 것이 증명되었습니다. ✔️

위 두 과정을 거치며 에러라는 것을 확신하였습니다. 그런데 저는 viteCRA 같은 툴체인으로 만든 프로젝트의 경우 어떤 에러를 발생할지 의문을 갖게 되었습니다. 그래서 직접 에러를 검증해 봤습니다.

  1. viteJavaScript 환경

    vite-js

    분명한 에러임에도 어떠한 에러도 확인할 수 없습니다. 하지만, 개발 서버를 실행해 로컬 호스트로 접속을 하면 바로 아래와 같은 에러들을 발생시킵니다.

    // 번째 에러
    × cannot reassign to a variable declared with `const`
     function ChatRoom({ roomId, serverUrl }) {
    ·                             ────┬────
    ·                                 ╰── cannot reassign
     const [serverUrl, setServerUrl] = useState("https://localhost:1234"); // serverUrl is reactive
    ·          ────┬────
    ·              ╰── const variable was declared here
     
    // 번째 에러
    × the name `serverUrl` is defined multiple times
     function ChatRoom({ roomId, serverUrl }) {
    ·                             ────┬────
    ·                                 ╰── previous definition of `serverUrl` here
       const [serverUrl, setServerUrl] = useState("https://localhost:1234"); // serverUrl is reactive
    ·          ────┬────
    ·              ╰── `serverUrl` redefined here

    두 가지 에러는 다음과 같습니다.

    • cannot reassign to a variable declared with const
      • const로 선언한 변수는 재할당을 할 수 없습니다.
    • the name serverUrl is defined multiple times
      • serverUrl이 여러 번 정의되었습니다.

    vite-JavaScript 환경에서도 역시 에러라는 것이 증명되었습니다. ✔️

  2. viteTypeScript 환경

    vite-ts

    어디서 본 에러 메시지가 보입니다. 바로 2번 경우와 똑같은 에러입니다. 만약 개발 서버를 실행시키면 어떻게 될지 궁금해졌습니다.

    X [ERROR] The symbol "serverUrl" has already been declared

    3번 경우와 다르게 서버를 실행하는 명령어를 입력하자마자 터미널에 serverUrl이 이미 선언되었다는 에러가 발생됩니다. vite-TypeScript 환경에서도 역시 에러라는 것이 증명되었습니다. ✔️

  3. CRAJavaScript 환경

    cra-js

    기존의 JavaScript 환경들과 차이점을 발견하셨나요? 바로 ESlint입니다. ESlint는 문법 및 규칙을 검증해 주는 정적 코드 분석 도구입니다. 그렇다면 vite 환경에서는 왜 ESlint가 문법 오류를 잡아내지 못한 걸까요? 그 이유는 vite은 내부적으로 ESlint가 설치되지 않았기 때문입니다.

    CRA로 초기화된 React 프로젝트는 기본적으로 React에 맞는 ESlint가 설치되어 있습니다. 설치 목록을 보려면, 터미널에 npm ls eslint를 입력합니다. 그럼 다음과 같은 결과를 볼 수 있습니다.

    npm ls eslint
    cra@0.1.0
    └─┬ react-scripts@5.0.1
    ├─┬ eslint-config-react-app@7.0.1
     ├─┬ @babel/eslint-parser@7.21.3
     └── eslint@8.36.0 deduped
    // ...
     ├─┬ eslint-plugin-jsx-a11y@6.7.1
     └── eslint@8.36.0 deduped
     ├─┬ eslint-plugin-react-hooks@4.6.0
     └── eslint@8.36.0 deduped
     ├─┬ eslint-plugin-react@7.32.2
     └── eslint@8.36.0 deduped
    // ...

    1번의 경우와 마찬가지로 Identifier 'serverUrl' has already been declared라는 오류를 발생합니다. CRA와 JavaScript 환경에서도 에러라는 것이 증명되었습니다. ✔️

  4. CRATypeScript 환경

    cra-ts

    TypeScript로 테스트를 진행한 이전 경우들과 마찬가지로 Duplicate identifier 'serverUrl'라는 에러를 발생합니다.
    이때 ESlint의 'serverUrl' is already defined 에러 메시지가 보입니다.

즉 모든 테스트 과정을 진행하였을 때, React 공식 문서의 코드는 문법적으로 오류라는 것이 확실해졌습니다.

테스트를 다 끝낸 후 제가 본 예시가 잘못된 것이라는 확신을 갖게 되었습니다. 이제 공식적으로 Pull Request를 생성할 때가 온 것입니다.

사상 첫 오픈 소스에 Pull Request를 생성하다.

Pull Request의 경우 프로젝트들을 진행하며 생성해 본 적은 있었지만, 오픈 소스에 생성하는 것은 처음이었습니다. 처음 하는 일이다 보니 제법 긴장이 됐습니다. 더군다나 그냥 오픈 소스도 아닌 React의 공식 문서라니! 😵
제가 지금껏 GitHub를 사용한 방식을 되짚으며 Pull Request을 생성하였습니다.

순서는 다음과 같습니다.

1.React.dev Fork

우선 공식 문서 레포를 제 개인 레포로 Fork 해옵니다.

fork

2. Commit과 Push

commit-push

먼저 제 개인 레포에 수정 사항을 커밋하고 푸시 합니다. 이때 커밋 메시지의 경우 최대한 Conventional Commits 를 지키며 작성하였습니다.

3. Pull Request 생성

제 개인 레포에만 수정 사항이 있으면 안 되기에 원본 저장소에 PR을 생성합니다.

저는 다음과 같은 내용으로 PR을 생성하였습니다.

Pull Request

✨ PR의 경우 제 나름대로 정중하게 작성하려고 노력했습니다.

두근두근 이제 제 PR이 리뷰되고 머지 되기만을 기다리면 되는 줄 알았습니다. 하지만 또 다른 절차가 존재합니다.

4. Contributor License Agreement

facebook-github-bot이 모든 컨트리뷰터는 Contributor License Agreement에 동의해야 하며, 1시간 뒤에 검증을 통해 CLA 태깅을 해주겠다고 댓글을 달아줍니다.

Contributor License Agreements

5. Merged

시간이 많이 늦어, 자고 일어나 확인해야지 하는 마음을 갖고 침대에 누웠는데 도저히 잠이 오지 않았습니다. 그러던 중 핸드폰에 알림이 울렸습니다. 그래서 저는 설마? 하는 마음으로 알림을 확인해 보았는데 다른 유저의 댓글이었습니다. 이때의 실망감이란, 그 유저의 질문은 의도된 에러가 아니냐는 것이었습니다.

comments

일어나서 대답을 하기로 하고 우선 잠을 청했습니다. 어릴 때 소풍을 가는 날이면 눈이 빨리 떠지는 것처럼 유난히 일찍 눈이 떠졌습니다.

그런데 이게 웬걸! 그 Dan Abramov가 제 PR에 다른 유저의 질문에 대한 댓글과 함께 thanks라는 댓글을 남겨주었습니다. 물론 제 PR의 머지와 함께 말이죠!!

Dan Abramov

그 후 바로 공식 문서에 반영이 되었습니다. 😆

코드 수정 후

머지 된 PR은 이곳에서 확인하실 수 있습니다!

후기

일련의 기여 과정을 거치며, 몇 가지 느낀 점이 있습니다. 우선 코드를 읽고 문제점을 찾을 수 있게 되었다는 것입니다. 내가 작성한 코드뿐 아니라 타인이 작성한 코드를 읽고 이해할 수 있게 됐다는 점이 저에게 있어 큰 의미를 갖습니다. 깃에 관해서도 이제 제법 익숙해졌다는 생각이 들었습니다. 또, 사람은 누구나 실수할 수 있다는 것을 알게 되었고 실수하는 것에 대해서 낙담하지 말자는 것입니다. 완벽한 결과물을 한 번에 내놓는 건 어려우며, 여러 사람의 의견을 받아들여 더 좋은 결과물을 만드는 것이 더 좋은 방식이라는 것을 이번 과정을 통해 몸소 느끼게 되었습니다.

무엇보다 저에게 가장 의미 있었고 좋았던 부분은 제가 좋아하는 개발자 Dan Abramov에게 thanks라는 댓글을 받게 된 것과 저의 코드가 공식 문서에 반영이 되었다는 것 아닐까 합니다. 정말 감회가 새롭습니다!

단발성에 그치지 않고 앞으로도 가능하면 여러 오픈 소스에 기여하고 싶다는 생각이 들었습니다. 저 스스로를 위한 프로젝트를 진행하는 것도 좋지만, 기여라는 것은 정말 또 다른 세상인 것 같습니다.

이번 기여를 통해 단순히 코드를 작성하는 것 외에도 다른 방식으로 성장하고 시야를 넓힐 수 있다는 것을 알게 된 아주 귀중한 경험입니다. 정말 뿌듯하고 이 경험을 토대로 더욱 앞으로 나아가고 싶습니다.

✨ PR 링크를 북마크 해놓고 하루에도 몇 번씩 보는 것은 비밀입니다. 🤫