Contribution 쉬워요~ 한판 해요.^^

jingjinge·2025년 2월 18일
3

OpenSource

목록 보기
1/9
post-thumbnail

Git stars 8,200개가량의 라이브러리의 컨트리뷰터가 되었따.. 리액트 개발 2달차에 큰 행운을 얻은 것 같고 뜻 깊고 뭐 그렇다..

처음 라이브러리를 뜯어보는거다보니, 시간을 많이 쓰긴 했고, 노가다적인 측면도 있었는데 그 덕에 찾은 것 같다.

나름 대형 라이브러리다 보니, 관리가 잘 되어 있어서 생각보다 금방 찾을 수 있었던 것 같다.

PR링크


발단

프로젝트중 DatePicker를 사용해야해서 라이브러리를 찾아보던중, 가장 유명하고 주에 200만씩 다운로드 되는 라이브러리에 타입 에러가 떴었다.

자세한 사용법은 아래 주소에 있으며, 가장 맨 위의 예시를 적어보았다.

https://reactdatepicker.com/

뭐 엄청난 에러가 뜬다.. 처음엔 뭔가 싶었는데 해석해보면 현재 너가 쓴 속성은 타입이 맞지 않는다는 뜻이다, function의 파라미터 타입이 잘못 됐던가, 필수 속성이 빠졌던가, 쓸 수 없는 프로퍼티가 들어갔던가 했을 때 저런 에러가 뜬다.

분명 가장 맨 위의 예시인데도 오류가 생겼었고, 우리는 다른 라이브러리도 찾아보았지만 난 이 라이브러리가 쓰고 싶었다.

남들은 다 쓰는데 왜 나만 못쓰냐고.. 억울했다

아무 속성 없이 <DatePicker />만 남겨놓아도 빌드는 된다.

타입 에러는 아래와 같이 뜬다.

Type '{}' is not assignable to type 'IntrinsicAttributes & (IntrinsicClassAttributes<DatePicker> & Readonly<DatePickerProps>)'

암튼 정해진 타입에 안맞는다는 뜻이고, 나는 무작정 라이브러리를 뜯어보았다.


라이브러리 뜯어보기

첫 화면은 이렇다.

라이브러리를 들여다 본 경험이 없어서, 보자마자 무서웠다.뭐야 집에 갈래 무서워..

제일 중요한건 23번째 줄이었다. 직접적으로 export되는 CalendearProps이니 저기를 전부 뜯어 보았다.

아래와 같은 타입들이 합쳐진다.

OmitUnion<CalendarProps, "setOpen" | "dateFormat" | ...>

OmitUnion은 라이브러리 제작자가 만든건데, Omit한 타입들을 합쳐준다고 생각하면 된다.

CalendarProps에서 저 뒤에 있는 Property를 제외한 타입들을 가져온다는 것이다.

& Pick<CalendarIconProps, "icon">

CalendarIconProps에서 icon 관련된 타입들을 가져온다. 그리고 합친다.

& OmitUnion<PortalProps, "children" | "portalId">

마찬가지 이하 동문이다.

에러에선 어떤 속성이 필수라고 알려주지도 않았다.. 뭐부터 어떻게 해보지 하다가, 그냥 하나씩 지워봤다. 에러가 없어지는 곳이 문제이지 않을까 생각했다.

(에러가 생겨? 어딘지 모르겠어? 일단 의심 되는거 하나씩 지워봐)

찾았다! 타입 에러가 사라진다. 그럼 이제 문제점을 분석해보자.


문제 해결

// CalendarIconProps에서 'icon' 프로퍼티의 타입만 가져오기
Pick<CalendarIconProps, "icon">
  
// CalendarIconProps는 CalendarIcon 컴포넌트의 props 타입을 상속함
interface CalendarIconProps extends React.ComponentPropsWithoutRef<typeof CalendarIcon> {}

// CalendarIcon 내부

import React from "react";
interface CalendarIconProps {
    icon?: string | React.ReactNode;
    className?: string;
    onClick?: (event: React.MouseEvent) => void;
}
/**
 * `CalendarIcon` is a React component that renders an icon for a calendar.
 * The icon can be a string representing a CSS class, a React node, or a default SVG icon.
 *
 * @component
 * @prop  icon - The icon to be displayed. This can be a string representing a CSS class or a React node.
 * @prop  className - An optional string representing additional CSS classes to be applied to the icon.
 * @prop  onClick - An optional function to be called when the icon is clicked.
 *
 * @example
 * // To use a CSS class as the icon
 * <CalendarIcon icon="my-icon-class" onClick={myClickHandler} />
 *
 * @example
 * // To use a React node as the icon
 * <CalendarIcon icon={<MyIconComponent />} onClick={myClickHandler} />
 *
 * @returns  The `CalendarIcon` component.
 */
declare const CalendarIcon: React.FC<CalendarIconProps>;
export default CalendarIcon;

음.. 뭐가 문제지? 들어가보니 전부 optional이고, 안쓴다고 해서 문제될 부분이 없는 것 같다.

그래도 icon만 가져오니 컴포넌트에 icon 프로퍼티를 추가해봤다.

optional인 icon property를 가져오는데 뭔가 문제가 있나보다. required 처리가 되어있다.

지금은 이렇게 평안하게 정리하지만 여기까지 오는데 반나절 넘게 소요되었다.

내가 생각한 해결 방안은 두 가지였다.

1. propetry에 icon을 적기

당장 사용하려면 이렇게 해야할 것 같다. 배포시에도 타입 에러로 빌드가 되지 않는 상황이며, icon을 따로 사용하지 않지만 null이나 ''를 기재해두면 될 것 같다.

2. 라이브러리 타입 수정하기

Partial 유틸리티 클래스는 가져오는 속성을 Optional처리하는 효과가 있다.

Pick<CalendarIconProps, "icon">
// ->
Partial<Pick<CalendarIconProps, "icon">>

로 수정하면 된다. 2번은 문제점이 node_moduels를 .gitignore에 추가해놓아서 프로젝트 진행하는 모든 사람들이 라이브러리의 index.d.ts를 수정해야한다는 점이다.

1번으로 우리 문제는 해결했는데, 오픈소스에 PR을 날려보고 싶었다.

이건 기회야.. 오픈소스 형님들에게 강한 인상을 안겨주는 거야

문제를 해결함에 있어 너무 신나서 high가 온 상태라 이슈 확인하고 이런건 못했었는데, 원래 과정은 아래와 같다


Opensource PR 보내기

1. Opensource의 issue를 확인한다.

누군가 이미 Issue를 적어두고 해결하고 있을 수 있다. 같은 작업을 동시에 하는 것 만큼 개발자로서 모난게 있을까?

2. PR 내역 확인하기

open 상태인 PR과, Closed인 상태의 PR을 확인한다. 나랑 같은게 거부 되었을 수도 있다.

3. Fork하기

Fork를 눌러서 내 레포로 옮긴다

4. 오픈 소스의 Contributiong 문서를 확인한다

각 오픈 소스마다 contribute하는 양식이 따로 존재한다.
내 경우에는 약간의 제약만 있는 양식이 있었다.

4. 수정하기

git clone <내가 포크한 레포의 주소>

에서 수정한 후 커밋을 단다.

난 위와 같이 달았다.

5. PR을 보낸다.

보통 main이나 develop등에 보낸다.

실수한 점

  1. test 코드를 추가한 것 처럼 썼는데, 그런거 없었다. yarn test를 돌려본게 끝인데 high가 온 나머지 멋들어지게 쓰려고 이것저것 쓰다보니 저렇게 됐다.
  2. 처음이라고 언급했는데, 메인테이너 입장에서는 뉴비의 PR을 쉽사리 merge하긴 힘들기 때문에, 이것저것 검사를 본인이 많이 해볼 것 같다. 조금 짜친다

6. 코멘트 혹은 결과를 기다린다.

난 테스트 코드 어디있냐고 하길래 그런거 없다고 미안하다고 했다.

오픈 소스가 회사에서 관리되는 경우도 있지만, 보통 개인이나 팀 단위로 업무 외 일과로 하기 때문에 빠른 PR을 기다리지는 말자.

7. Contributor 달성

이렇게 하여 8,200 stars인 오픈 소스의 contributor가 되었다.. 허허


느낀점

  1. 메인테이너는 면접관이 아니더라!
    본인의 코드를 주의깊게 봐주는 사람들을 좋아한다고 한다.

  2. PR 보내놓고 맘 편하게 있는게 좋을 것 같다..
    사실 나는 하루에도 몇 번씩 들여다보고 했었는데, 기다리다보면 알아서 온다.

  3. 생각보다 별거 없네??
    라이브러리를 단순히 커스텀 훅이라고 생각하면, 내 코드 개선하는 것과 다르지 않더라

  4. 책임감이 든다.
    만약 내가 이거 바꿔서 잘 쓰고 있던 사람들이 오류가 나면 어떻게하지? 라는 생각에 PR 날리기 전에 수십번 들여다 봤던 것 같다.

  5. 재밌다.
    다른 나라의 개발자와 소통하는 느낌은 생소하지만 기분 좋았으며, 재밌었다.

이번 경험으로 오픈 소스에 관심이 더 생겨서 지속적으로 도전해보려고 한다. 화이팅!

2개의 댓글

comment-user-thumbnail
2025년 2월 18일

대단해요! 멋집니다!

1개의 답글