처음 참여해본 오픈소스 기여모임 10기 참여 후기

장운서·2026년 2월 8일

프로젝트

목록 보기
9/9

안녕하세요! 서운입니다.
오늘은 오픈소스 기여 모임에 참여하게 된 내용을 여러분들께 공유해보려고 합니다.

프론트엔드 엔지니어로 4년 동안 지내오면서, 제가 쓰는 라이브러리나 프레임워크를 “가져다 쓰기만” 했지, 내부 코드를 제대로 들여다보거나 버그를 찾아 고쳐본 경험은 거의 없었습니다.
그래서 “어차피 백수인 김에 도전해보자”는 마음으로 참가비 3만원을 내고 오픈소스 기여 프로젝트에 참여했습니다.

막상 들어가보니 백엔드/프론트엔드뿐 아니라 C++, C# 등 언어를 가리지 않고 정말 많은 사람들이 참여하고 있더라고요.
‘생각보다 훨씬 많은 엔지니어들이 라이브러리 기여에 관심이 있구나’라는 걸 체감했습니다.

저는 첫 기여였기 때문에, 시작하자마자 무작정 코드부터 고치기보다는 프로젝트의 기여 방법(Contributing Guide)을 먼저 정독했습니다. (이 단계가 생각보다 중요했습니다.)


왜 오픈소스 기여를 하려고 했나

제가 이번에 느낀 오픈소스 기여의 동기는 크게 3가지였습니다.
1. “사용자”에서 “참여자”로 전환하기
매일 쓰는 도구를 조금이라도 이해하고, 문제가 있으면 직접 개선해보고 싶었습니다.
2. 협업 방식이 궁금했다
회사 협업과는 또 다른 방식(이슈 템플릿, 리뷰 문화, 커뮤니케이션 룰)이 궁금했습니다.
3. 작은 성공 경험 만들기
큰 기능 개발보다, 작은 수정이라도 PR을 열고 머지까지 경험해보는 게 목표였습니다.


참여한 모임/프로젝트 소개(여기 채우기)

  • 모임 이름: 오픈소스 기여모임 10기
  • 진행 기간: 2026년 1월 10일 토 ~ 1월 25일 일요일 3주간
  • 방식: 온라인 참여 가능, 오프라인 참여 자율 참여
  • 목표: 특정 레포에 1건 이상 PR

이슈 고르기: “AI가 골랐다”가 아니라, “AI로 후보를 평가했다”

사실 다들 막막한 부분들은 fork → 브랜치 → PR 같은 절차가 아니라 정작 어떤 이슈를 잡고 진행해야 할지가 가장 막막했습니다.

첫 기여에서 제일 무서운 건 "난이도"보다 (1) 재현이 안되거나, (2) 범위가 커지거나, (3) 리뷰가 안 들어오는 상황이라고 생각했어요.

그래서 저는 이슈를 감으로 고르지 않고, 후보군을 넓게 모은 뒤 AI로 1차 평가(리스크/범위/재현 가능성)를 돌리는 방식으로 접근했습니다.

1) 후보 이슈를 "기계적으로" 모으기

GitHub 이슈는 검색/필터 문법이 잘 되어 있어서, 먼저 good first issue, help wanted, no:assignee 같은 조건으로 후보 풀을 만들었습니다.
예를 들면 아래처럼 검색해서 "당장 잡을 수 있는 이슈"만 모았어요.

  • is:issue is:open label:"good first issue"
  • is:issue is:open label:"help wanted" no:assignee
  • is:issue is:open label:"documentation" no:assignee

2) AI에게 "이슈 평가 기준"을 맡기기

그 다음부터는 AI에게 레포 링크/이슈 링크/내 상황을 주고, 아래 항목으로 점수화해서 상위 3개만 뽑게 했습니다.

  • 재현 절차가 명확한가?
  • 변경 범위가 작은가(파일/모듈 단위로 자를 수 있는가)?
  • 트스트/검증이 쉬운가?
  • 유지관리자가 최근에도 반응하는가(리뷰 받을 확률)?
  • UI 변경이라면 Before/After로 증빙 가능한가?

여기서 중요한 건, AI가 “결정”을 한 게 아니라 각 후보의 불확실성(리스크)을 항목별로 드러내준 것이었습니다. 최종 선택은 제가 했습니다.

3) 최종 선택은 "증빙 가능한 작업"위주로

첫 기여는 특히 리뷰 커뮤니케이션 비용이 크기 때문에, 결과를 명확히 보여줄 수 있는 작업이 유리할것같다라는 생각을 했습니다. 예를 들면 UI변경이 있는 경우, RP본문에 스크린샷을 첨부해서 변경점을 바로 이해시키는 방식으로 진행했습니다. GitHub는 이슈/PR 코멘트에 파일을 드래그&드롭으로 첨부할 수 있습니다.

이후 어떠한 방향으로 진행해야 하는지 기여 모임에 인증해야하고 도움도 요청하고 인증도 해야하기 때문에 5개의 후보군중 PR을 진행할 하나를 골라서 아래와 같이 모임 디스코드에 포스트를 남겼습니다.


1) "그래서 내가 고른 이슈는 무엇이었나요?"

제가 첫 기여 대상으로 고른 건 Tiptap 레포의 이슈 #7425였습니다. (2026-02-08 기준으로 이슈 상태는 Open이고, 타입은 Bug이며, Assignee는 없는 상태였습니다.)

이슈를 요약

React NodeView에서 NodeViewContent를 조건부 렌더링할 때, 커서는 들어가는데 입력한 텍스트가 문서(JSON)에 저장되지 않는 문제였습니다. 화면에는 텍스트가 보이지만 editor.getJSON()을 확인하면 해당 텍스트가 들어가지 않는 케이스였습니다.

이슈 설명에 적혀 있던 재현 시나리오
이슈 본문에는 아래처럼 재현 절차가 단계별로 정리되어 있었습니다.

  • content: "inline*"를 가진 커스텀 Image extension을 만들고, showCaption 같은 속성으로 캡션 노출 여부를 제어한다.

  • React NodeView에서 showCaption이 true일 때만 NodeViewContent를 렌더링한다.

  • showCaption: false 상태로 노드를 삽입하고, 화살표/클릭으로 커서를 이미지 옆에 두면 커서가 노드의 content 영역으로 들어간다.

  • 이 상태에서 타이핑하면 화면에는 글자가 보이지만, editor.getJSON()에는 저장되지 않는다.

기대 동작(이슈 작성자가 제안한 방향)

이슈에는 기대 동작이 "셋 중 하나면 된다"는 식으로 명확히 적혀있었습니다.

  1. NodeViewContent가 렌더되지 않으면 커서가 content 영역에 들어가지 못하게 막기
  2. NodeViewContent 렌더 여부와 무관하게 입력 텍스트가 저장되게 만들기
  3. 스키마에 content가 있는데 DOM에 NodeViewContent가 없으면 경고를 제공하기

첫 기여로 이 이슈가 “좋아 보였던” 이유

저는 첫 기여라서 재현이 어려운 환경에 의존하는 리스크가 낮은 이슈를 우선으로 봤고 #7425가 그 조건에 가장 가까웠습니다.


첫 번쨰 목표는 '해결'이 아니라 '재현'

이슈를 고른 다음 제가 먼저 한 건 "바로 고치기"가 아니라 재현 환경을 만드는 것이었습니다.
오픈소스에서는 수정 제안이 아무리 좋아도, 재현이 안 되면 논의가 앞으로 못 나가는 경우가 많아서요.

이슈 #7425는 다해이도 재현 절차와 검증 포인트가 비교적 명확했습니다. 특히 "화면에는 보이는데 editor.getJSON()에는 없다"처럼 결과를 확인할 기준이 분명했어요.


2-1. 이슈 본문을 '체크리스트'로 바꿔 적었다

이슈 설명을 그대로 따라 하되, "내가 확인해야 할 조건"만 남겨서 체크리스트로 만들었습니다.

  • content: "inline*"를 가진 커스텀 Image extension 구성
  • React NodeView에서 showCaption 같은 조건에 따라 NodeViewContent를 조건부 렌더링
  • showCaption: false상태에서 커서가 content 영역으로 들어갈 수 있는지 확인
  • 타이핑 시 화면 표시 vs editor.getJSON()저장 여부 비교

이렇게 바꿔두면, 재현이 되든 안 되든 "어디까지는 맞고 어디서부터 다른지"를 빠르게 분리할 수 있었습니다.


2-2. '최소 재현'으로 먼저 줄였다

처음 기여라서, 레포 전체를 이해하려고 하기보다 이 이슈에 필요한 구성만 남기는 방향으로 갔습니다.

제가 최소 재현을 만들 때 스스로 고정한 규칙은 아래 3가지였습니다.

  1. 변수는 한 번에 하나씩만 바꾼다
    예: 버전/렌더 조건/노드 스키마/NodeView 구성 중 한 가지만 바꾸고, 결과를 기록.

  2. 검증 기준은 이슈 본문과 동일하게 유지한다
    이 이슈는 “입력한 텍스트가 JSON에 들어가느냐”가 핵심이라, 최종 확인은 editor.getJSON()로 통일했습니다.

  3. 증빙 가능한 결과물을 남긴다
    나중에 PR이나 이슈 코멘트로 공유할 때, 말로 설명하는 것보다 스크린샷/GIF/JSON 캡처가 훨씬 빨랐습니다. GitHub는 이슈/PR 코멘트에 파일을 드래그&드롭으로 첨부할 수 있어서 증빙을 올리기 편했습니다.


2-3. 재현 과정에서 "원인 후보"를 좁히는 힌트

재현을 하다 보니, 이 이슈의 구조가 이렇게 정리되더라고요.

  • 스키마상으로는 content가 있는데(inline*)
  • DOM에는 NodeViewContent가 없거나(조건부 렌더링)
  • 그 상태에서 커서가 content 영역으로 들어가면
  • “보이는 입력”과 “저장되는 입력”이 어긋날 수 있다

실제로 Tiptap 문서에서도, NodeView 안에 non-editable 요소가 섞여 있으면 커서가 예상치 않게 이동할 수 있고, contenteditable="false" 같은 처리가 도움이 될 수 있다고 언급합니다. (이건 “해결책 확정”이 아니라, 커서/편집 가능 영역이 핵심 축이라는 힌트로만 참고했습니다.)


2-4. 모임 인증/도움 요청을 위해 “현재 상태”를 먼저 공유했다

기여 모임은 진행 상황 공유가 중요해서, 저는 재현 진행도를 아래처럼 정리해 디스코드에 남겼습니다.

이번에 오픈소스 첫 기여로 Tiptap을 선정했습니다.
선정 이유는 실무에서 자주 사용했었고…ㅎㅎ 개인적으로도 많이 써봤던 플러그인이라, 이번 기회에 관련 이슈를 직접 해결해보고 싶었습니다.

제가 고른 이슈는 아래입니다.

Tiptap #7425: https://github.com/ueberdosis/tiptap/issues/7425

이슈 내용(요약)

React NodeView에서 NodeViewContent를 조건부 렌더링하는 경우, 에디터에서 커서는 들어가고 화면에 입력은 되는 것처럼 보이는데, editor.getJSON() 결과에는 반영되지 않아 입력 내용이 문서에 저장되지 않는(유실되는) 문제가 발생합니다.

제가 생각한 접근 방식

이 이슈는 현재 본문에 재현 코드 링크가 없어 보이기 때문에, 저는 아래 순서로 진행하려고 합니다.

최소 재현 레포/샌드박스를 먼저 만들어 이슈에 공유

기대 동작을 정리(예: NodeViewContent가 비활성일 땐 입력 차단 vs 조건부여도 저장 보장 등)

Tiptap 내부에서 NodeViewContent mount/unmount 시점에 selection/transaction 반영 흐름을 추적

회귀 테스트 추가 후 수정 PR

질문(피드백 요청)

이 이슈를 기존 #7425에서 그대로 진행하면서 재현 레포 + PR까지 이어가는 게 좋을까요?
아니면 재현이 확보되면 새 이슈로 “재현 케이스 전용” 이슈를 따로 파는 방식이 더 적절할까요?

접근 방식/순서에서 더 좋은 방법이나 주의할 점이 있다면 피드백 부탁드립니다.

아래는 위 내용의 사진입니다.
장운서_오픈소스코드기여


3) 어디서 저장이 끊기는 걸까?

재현까지 만들고 나니, 다음 질문은 하나였습니다.

화면에는 입력이 보이는데, 왜 문서(JSON)에 반영이 안될까?

이 이슈(#7425)는 구조적으로 “스키마에는 content가 있는데, DOM에는 NodeViewContent가 없는 상태(조건부 렌더링)”가 핵심 조건으로 걸려 있었습니다.


3-1. 스키마(content) vs DOM(contentDOM) 불일치

ProseMirror(NodeView) 관점에서 contentDOM은 “자식 노드가 렌더링될 자리”입니다. contentDOM이 있으면 ProseMirror가 자식 렌더링을 맡고, 없으면 NodeView가 자식 렌더링(혹은 렌더링하지 않음)을 책임지는 구조입니다.

Tiptap React NodeView에서는 그 contentDOM 역할을 보통 NodeViewContent가 담당합니다(문서에서도 NodeViewContent를 “editable content”를 추가하는 컴포넌트로 설명).

그래서 이 이슈는 “커서가 들어갈 수 있는 ‘content 영역’은 스키마상 존재하는데, DOM에는 그 영역이 없거나(조건부 렌더링) 비정상 상태인 것”으로 볼 수 있었습니다.

“내 재현 코드에서는 showCaption=false일 때 NodeViewContent가 다른 DOM으로 대체돼서 contentDOM이 비는 상태였다.”


3-2. 커서가 "이상한 곳"으로 튀는 문제는 문서에도 힌트가 있었다

Tiptap NodeView 문서에서도 non-editable 요소가 섞이면 커서가 예상치 않게 이동할 수 있고, 특정 요소에 contenteditable="false"를 명시해서 개선할 수 있다고 언급합니다.

이건 곧바로 “정답”이라기보다는, 커서/selection 경로가 문제의 축일 수 있다는 힌트로만 가져갔습니다.

3-3. 해결 방향을 3개로 쪼개서 "첫 PR 범위"를 결정했다

이슈 작성자가 제안한 기대 동작은 크게 3가지였습니다.

  1. NodeViewContent가 없으면 커서가 content 영역에 들어가지 못하게 막기
  2. NodeViewContent 렌더 여부와 무관하게 입력 텍스트가 저장되게 만들기
  3. 스키마에 content가 있는데 DOM에 NodeViewContent가 없으면 경고 제공

첫 기여에서는 (2)처럼 근본 수정은 범위가 커질 수 있어서, 저는 “논의를 진전시키는 최소 변경”을 목표로 잡는 편이 안정적이었습니다

아래 중 네가 실제로 선택한 1개를 골라서 문장만 확정하면, 다음 섹션(PR 작성)까지 자연스럽게 이어집니다.

  • 내가 택한 1차 접근은 (1 / 2 / 3) 이었다. 이유는 (범위/리스크/검증 난이도) 때문이다.

4) 첫 PR은 ‘정답’보다 ‘재현 가능한 최소 변경’으로 만들었다

이슈(#7425)는 “해결책 하나”보다도, 재현 조건과 검증 기준이 명확한 문제였습니다. 그래서 첫 기여에서는 욕심내서 근본 해결을 한 번에 끝내기보다, 리뷰어가 바로 확인할 수 있는 최소 변경을 목표로 잡았습니다. #7425

그리고 여기부터는 정말 대부분을 AI에게 맡겼습니다.
제가 직접 한 일은 “AI가 헛소리하지 않게” 기준을 고정해주는 정도였고, AI가 제안한 선택지/초안을 바탕으로 제가 확인하고 정리하는 흐름이었습니다.

AI에게 맡긴 것

  • 이 이슈를 “기술 문제”로 다시 정리(조건부 NodeViewContent / 커서 진입 / getJSON() 불일치 관점)
  • 가능한 해결 방향을 여러 개로 나누고저장 정상화, 각 안의 리스크·범위를 비교
  • PR 본문 초안 작성(재현 steps, 검증 기준, 변경 의도, 증빙 요구사항)

내가 고정한 것(사람이 잡아야 했던 기준)

  • 검증 기준은 editor.getJSON()으로 유지 (이슈 본문에서도 핵심 검증 포인트) (github.com
    )
  • 증빙 가능한 결과물을 남기기(스크린샷/GIF/JSON 캡처 등)
    GitHub는 이슈/PR 코멘트에 파일을 드래그&드롭으로 첨부할 수 있어, “설명”보다 “증빙”이 훨씬 효율적이었습니다. (docs.github.com
    )

현재 PR은 아직 머지되지는 않았지만, 첫 기여에서 제가 얻은 가장 큰 수확은 “정답을 맞혔다”가 아니라, 오픈소스에서 중요한 재현 → 증빙 → 커뮤니케이션 흐름을 한 번 끝까지 밟아봤다는 점이었습니다.


다음 기여를 위한 체크리스트

이번 경험을 통해 “다음에는 이 순서로 하면 덜 헤맨다”라는 체크리스트가 생겼습니다.

  1. 이슈 선정: 재현 steps/기대·실제가 명확한 이슈 + assignee 없는 상태를 우선 고려

  2. 재현 먼저: 해결 시도보다 “내 로컬에서 재현된다”를 먼저 확보

  3. 검증 기준 고정: 이번처럼 getJSON()처럼 한 가지 기준으로 Before/After를 비교

  4. 증빙 준비: 스크린샷/GIF/로그/JSON 캡처를 PR 본문에 같이 제공

  5. PR은 작게: “논의를 앞으로 보내는 최소 변경”을 먼저 만들고, 필요하면 다음 PR로 쪼개기
    (다음 목표는, 이번에 만든 재현/정리 흐름을 그대로 재사용해서 작은 PR을 하나 더 올려보는 것입니다.)

profile
성공을 위해선 과정만 있을 뿐이다

0개의 댓글