C++ 오픈소스 기여: 유명 라이브러리 분석부터 첫 Pull Request까지

들어가며: 코드로 커뮤니티에 참여하기

“오픈소스에 기여하고 싶은데, 어디서부터 시작해야 할지 모르겠다”는 고민은 C++ 개발자에게 특히 흔합니다. 오픈소스 기여(공개된 프로젝트에 PR, 즉 Pull Request로 변경을 제안하는 것)는 남의 코드베이스를 읽는 능력, 리뷰를 주고받는 요령, 여러 컴파일러에서 동작하는 코드를 쓰는 감각을 한꺼번에 기를 수 있는 좋은 경험입니다. 그런데 막상 spdlog나 fmt 같은 유명 라이브러리를 열어 보면 빌드부터 막히고, 첫 PR에 코멘트가 수십 개 달려 당황하는 경우가 많습니다.

C++ 프로젝트는 다른 언어보다 진입 장벽이 한 단계 높습니다. 패키지 매니저 하나로 의존성이 해결되는 생태계가 아니라서 CMake 옵션과 컴파일러 버전을 맞춰야 하고, 널리 쓰이는 라이브러리는 GCC·Clang·MSVC의 여러 버전을 동시에 지원하기 때문에 내 컴파일러에서 되는 코드가 CI의 다른 컴파일러에서는 깨지기도 합니다. 헤더 전용 라이브러리라면 헤더 한 줄 변경이 모든 사용자의 빌드 시간과 ABI에 영향을 주므로, 메인테이너가 작은 변경에도 신중한 이유가 있습니다.

이 글은 첫 기여에서 막히는 지점부터 시작해 프로젝트와 이슈 고르기, 코드베이스를 빌드하고 읽는 순서, 포크부터 PR까지의 흐름, 그리고 CI 실패·머지 충돌·DCO 누락처럼 실제로 자주 만나는 문제의 해결법을 차례로 다룹니다. 대상 프로젝트로는 CMake, spdlog, fmt, Catch2, vcpkg처럼 이슈가 잘 정리되어 있고 CONTRIBUTING 문서가 있는 곳을 예로 듭니다. 처음부터 완벽한 코드를 내려고 하기보다 작게 시작해서 피드백을 받는 것이 핵심입니다.


어디서부터 손댈지, 리뷰 폭탄, CLA: 첫 기여에서 막히는 지점

시나리오 1: “첫 기여를 하고 싶은데, 어디서부터 손대야 할지 모르겠어요”

"spdlog·fmt 같은 유명 프로젝트는 코드가 너무 많아요."
"버그 수정은 어려워 보이며, 문서 수정은 사소해 보여요."
"어떤 이슈가 나에게 맞는지 판단이 안 돼요."

원인: 첫 기여자는 진입 장벽이 어느 정도인지, 어떤 이슈가 자기 수준에 맞는지, 메인테이너가 무엇을 기대하는지 모릅니다. good first issue·help wanted 라벨이 있는 이슈부터 시작하고, 문서 수정·오타·테스트 추가부터 손대면 부담이 적습니다. 문서 수정이 사소해 보여도, 포크·브랜치·CI·리뷰라는 기여 절차 전체를 한 번 거쳐 본다는 점에서 가치가 있습니다. 절차에 익숙해진 뒤에 코드 수정으로 넘어가면 기술 문제에만 집중할 수 있습니다.

시나리오 2: “PR을 보냈는데 리뷰가 너무 많아요”

"10줄 수정했는데 20개 코멘트가 달렸습니다."
"스타일·네이밍·테스트까지 다 요구해요."
"다시 수정할까요, 말까요?"

원인: 메인테이너는 머지한 코드를 앞으로 몇 년간 대신 유지보수해야 하는 사람입니다. 그래서 10줄짜리 변경이라도 스타일·네이밍·테스트·다른 플랫폼 영향까지 봅니다. 코멘트가 많다는 것은 대개 거절이 아니라 “이 방향이면 받겠다”는 신호입니다. 정중하게 반영하고, 이해가 안 되면 질문하면 됩니다. 코멘트마다 반영했는지 답을 달아 두면 메인테이너가 다시 검토할 때 시간이 크게 줄어듭니다.

시나리오 3: “빌드가 안 돼요. 환경이 맞지 않는 것 같아요”

"README대로 했는데 CMake가 실패해요."
"컴파일러 버전·의존성·OS가 다르면 빌드가 안 돼요."

원인: C++ 프로젝트는 컴파일러·버전·플랫폼 조합이 다양합니다. README는 오래되기 쉽지만 CI 설정 파일(.github/workflows/*.yml)은 매일 실행되므로 가장 정확한 빌드 문서입니다. CI가 쓰는 컴파일러 버전, CMake 옵션, 설치하는 패키지를 그대로 따라 하거나, Docker로 같은 이미지를 띄워 환경을 맞추면 됩니다.

시나리오 4: “라이선스·CLA가 뭔지 모르겠어요”

"Contributor License Agreement가 뭐예요?"
"MIT·Apache·BSD가 뭐가 다른가요?"

원인: 기여할 때의 권리·의무가 프로젝트마다 다릅니다. CLA(Contributor License Agreement)는 기여물에 대한 권리를 프로젝트(또는 재단·회사)에 부여하는 별도 계약이고, DCO(Developer Certificate of Origin)는 “이 코드를 기여할 권리가 내게 있다”는 선언을 커밋의 Signed-off-by 줄로 남기는 가벼운 방식입니다. 둘 다 없는 프로젝트는 보통 기여물이 프로젝트 라이선스(MIT·Apache-2.0·BSD 등)로 배포되는 것으로 간주합니다(GitHub 이용약관의 “inbound=outbound” 원칙). CLA 봇이 서명을 요구하면 서명 전에는 PR이 머지되지 않는 경우가 많습니다. 회사 업무 시간이나 회사 장비로 작성한 코드는 권리가 회사에 있을 수 있으므로, CLA에 서명하거나 DCO를 달기 전에 사내 오픈소스 기여 규정을 먼저 확인해야 합니다.

시나리오 5: “PR이 머지되지 않고 계속 대기 중이에요”

"2주 전에 PR 보냈는데 아무 응답이 없습니다."
"메인테이너가 바쁜가요?"

원인: 많은 오픈소스 프로젝트는 한두 명의 메인테이너가 여가 시간에 운영합니다. 알림이 묻혔거나, 이슈의 우선순위가 낮을 수 있습니다. 1~2주가 지나면 “리뷰 가능할 때 봐 주시면 감사하겠다, 추가로 필요한 것이 있으면 알려 달라” 정도의 짧은 리마인더를 한 번 남기는 것이 적당합니다. 그사이 CI가 모두 통과하도록 해 두면, 메인테이너가 들어왔을 때 바로 머지할 수 있는 상태가 됩니다.

시나리오 6: “머지 충돌이 났습니다. 어떻게 해결하나요?”

"main 브랜치가 업데이트됐는데, 제 PR이 충돌해요."
"git rebase가 뭔지 모르겠습니다."

원인: main이 먼저 진행되어 같은 줄이 바뀌면 PR 브랜치와 충돌합니다. git rebase 또는 git merge로 main을 가져와서 충돌을 해결하면 됩니다. 어느 쪽을 쓸지는 프로젝트가 정합니다. 히스토리를 깔끔하게 유지하려는 프로젝트는 rebase를, 리뷰 중 강제 푸시로 코멘트 위치가 흐트러지는 것을 싫어하는 프로젝트는 merge를 선호하므로 CONTRIBUTING을 먼저 확인합니다.


1단계: 기여할 프로젝트 고르기

기여하기 좋은 프로젝트

  • 라이선스: MIT, Apache-2.0, BSD 등 기여 시 권리·의무가 명확한 프로젝트가 좋습니다. CONTRIBUTING.md·CODE_OF_CONDUCT가 있으면 분위기를 파악하기 쉽습니다.
  • 이슈: good first issue·help wanted 라벨이 있으면 진입 장벽이 낮습니다. 문서 수정·오타·테스트 추가부터 시작할 수 있습니다.
  • 규모: 너무 크면 빌드·테스트가 부담되므로, 단일 라이브러리·명확한 모듈이 있는 프로젝트가 첫 기여에 적합합니다.

C++ 오픈소스 프로젝트 추천

프로젝트설명첫 기여 난이도참고
spdlog로깅 라이브러리중테스트는 Catch2
fmt포맷 문자열 라이브러리중테스트는 GoogleTest, 구형 컴파일러 지원 범위가 넓음
Catch2테스트 프레임워크중매크로·템플릿 비중이 큼
vcpkgC++ 패키지 매니저중~상포트(port) 추가·업데이트 PR이 입문용으로 많음
CMake빌드 시스템상GitLab(Kitware)에서 MR로 기여
nlohmann/jsonJSON 파싱중단일 헤더 생성 스크립트 규칙 확인 필요

라벨 운영은 프로젝트마다 달라서 good first issue 라벨이 거의 없는 곳도 있습니다. 라벨이 없다면 최근 닫힌 PR 몇 개를 열어 보고, 외부 기여자의 작은 PR이 어떻게 리뷰되고 머지되는지를 보는 것이 가장 좋은 판단 기준입니다.

이슈 선택 가이드

첫 기여자에게 적합한 이슈:

✅ good first issue - 메인테이너가 선별한 난이도 낮은 이슈
✅ help wanted - 도움이 필요한 이슈
✅ documentation - 문서 관련 (빌드 불필요)
✅ bug + 재현 방법 명시 - 원인 파악이 쉬움

피하는 것이 좋은 이슈:

❌ 논의 중인 설계 이슈 (결론 없이 오래 끌 수 있음)
❌ "큰 리팩토링" - 범위가 넓어 리뷰가 길어짐
❌ 1년 이상 방치된 이슈 - 메인테이너 관심 낮을 수 있음
❌ 재현 불가능한 버그 - 원인 파악이 어려움

이슈 선점 팁: good first issue는 빨리 사라집니다. “I’d like to work on this” 댓글을 남기면 다른 기여자와 중복을 줄일 수 있습니다. 다만 선점만 해 두고 몇 주씩 소식이 없으면 다른 사람의 기회를 막는 셈이라, 메인테이너가 가장 곤란해하는 패턴이기도 합니다. 그래서 댓글을 남기기 전에 먼저 로컬에서 재현과 빌드까지 해 보고, 며칠 안에 초안 PR을 올릴 수 있겠다는 확신이 들 때 선점 댓글을 다는 편이 좋습니다. 진행이 막히면 막혔다고 남기고 이슈를 놓아 주는 것도 좋은 매너입니다.


2단계: 코드베이스 분석

빌드·테스트·읽기

  • 빌드: README·CONTRIBUTING에 따라 CMake·vcpkg 등으로 빌드합니다. 컴파일러·버전을 맞추고 경고 제로로 빌드되는지 확인합니다. 많은 C++ 프로젝트가 CI에서 -Werror를 켜기 때문에, 내 컴파일러에서 경고 하나가 CI에서는 빌드 실패가 됩니다.
  • 테스트: ctest·pytest 등으로 테스트를 돌리고, 기존 테스트 추가 위치·스타일을 파악합니다. 수정 후 반드시 테스트를 돌려 회귀가 없도록 합니다.
  • 코드 읽기: 이슈와 연결된 파일·함수부터 읽습니다. 코딩 스타일·네이밍·주석 규칙을 지키면 리뷰가 수월해집니다.

빌드 예제 (spdlog)

# spdlog 클론 및 빌드
git clone https://github.com/gabime/spdlog.git
cd spdlog
mkdir build && cd build
cmake .. -DSPDLOG_BUILD_TESTS=ON   # 테스트는 기본값이 OFF
cmake --build .
ctest --output-on-failure

spdlog의 테스트 타깃은 기본으로 꺼져 있어서, 옵션 없이 빌드하고 ctest를 돌리면 No tests were found!!!만 출력되고 끝납니다. 이런 옵션 이름은 최상위 CMakeLists.txt의 option(...) 줄을 보면 가장 빨리 확인할 수 있습니다.

코드 분석 흐름

flowchart TD
    A[이슈 선택] --> B[관련 파일 찾기]
    B --> C[코드 읽기]
    C --> D[빌드·테스트]
    D --> E[수정·테스트 추가]
    E --> F[PR 작성]
    F --> G[리뷰 대응]
    G --> H[머지]

테스트 실행 예제

# fmt 프로젝트 테스트
git clone https://github.com/fmtlib/fmt.git
cd fmt
mkdir build && cd build
cmake .. -DFMT_DOC=OFF -DFMT_TEST=ON
cmake --build .
ctest -C Debug --output-on-failure

fmt는 최상위 프로젝트로 빌드하면 테스트가 기본으로 켜져 있고, 테스트 프레임워크로 GoogleTest를 씁니다. -C Debug는 Visual Studio처럼 여러 구성을 한 번에 만드는 멀티 구성 생성기에서만 의미가 있고, Linux의 Makefile/Ninja 생성기에서는 무시됩니다.

코드 읽기 순서

1. 이슈에서 언급된 파일·함수부터
2. 해당 모듈의 테스트 코드 (동작 이해)
3. 헤더 파일 (API·인터페이스)
4. 구현 파일 (내부 로직)
5. CONTRIBUTING·.clang-format (스타일)

테스트 코드를 헤더보다 먼저 읽는 이유는 테스트가 “이 함수가 어떤 입력에 무엇을 약속하는지”를 가장 짧게 보여 주는 문서이기 때문입니다. 특히 fmt나 spdlog처럼 템플릿이 깊게 얽힌 라이브러리는 구현부터 따라가면 메타프로그래밍 계층에서 길을 잃기 쉽습니다. 수정하려는 동작의 테스트를 먼저 찾고, 그 테스트가 호출하는 공개 API에서 구현으로 내려가는 순서가 효율적입니다.

버그 수정 시 디버깅 팁

// 이슈에 재현 코드가 있으면 그대로 빌드해서 확인
// 예: fmt 포맷 버그 재현
#include <fmt/core.h>
int main() {
    // 경계 조건에서 잘못된 출력
    fmt::print("{}\n", fmt::format("{}", problematic_value));
    return 0;
}
# GDB로 원인 추적
gdb ./repro
(gdb) break fmt::format
(gdb) run
(gdb) bt  # 백트레이스

3단계: 포크부터 PR까지

포크·클론·브랜치

# 1. GitHub에서 프로젝트 포크 (웹 UI)
# 2. 포크한 저장소 클론
git clone https://github.com/YOUR_USERNAME/spdlog.git
cd spdlog
# 3. upstream 저장소 추가 (원본)
git remote add upstream https://github.com/gabime/spdlog.git
# 4. 이슈 번호에 맞는 브랜치 생성 (예: fix-1234)
git checkout -b fix-typo-in-readme

수정·커밋

# 1. 파일 수정
# ... (에디터에서 수정)
# 2. 변경 사항 확인
git status
git diff
# 3. 스테이징
git add README.md
# 4. 커밋 (Conventional Commits 형식)
git commit -m "docs: fix typo in README (fixes #1234)"

Conventional Commits 예시

feat: add support for custom format
fix: resolve memory leak in async logger
docs: fix typo in README
test: add unit test for format
style: apply clang-format
refactor: simplify buffer allocation

PR 보내기

# 1. upstream main 최신화
git fetch upstream
git rebase upstream/main
# 2. 포크 저장소로 푸시
git push origin fix-typo-in-readme
# 3. GitHub에서 "Compare & pull request" 클릭

PR 설명 템플릿

## 변경 사항

- README의 "recieve" → "receive" 오타 수정
## 관련 이슈

Fixes #1234
## 테스트 방법

- [ ] 문서만 수정이므로 별도 테스트 없음
- [ ] 또는: `ctest` 실행 후 통과 확인
## 체크리스트

- [x] CONTRIBUTING 가이드 확인
- [x] 커밋 메시지 규칙 준수
- [x] 이슈 번호 연결

리뷰 대응

# 리뷰 코멘트 반영 후 (변경한 파일만 명시적으로 스테이징)
git add README.md
git commit -m "docs: apply review feedback"
git push origin fix-typo-in-readme

리뷰 반영 커밋을 추가로 쌓을지, 기존 커밋을 고쳐 강제 푸시할지는 프로젝트마다 다릅니다. 머지 시 squash하는 프로젝트라면 커밋을 쌓는 편이 리뷰어가 “무엇이 바뀌었는지”를 보기 쉽고, 커밋 히스토리를 그대로 남기는 프로젝트라면 git commit --fixup과 git rebase -i --autosquash로 정리해 달라는 요청을 받기도 합니다. git add .는 빌드 디렉터리나 에디터 설정 파일을 실수로 포함하기 쉬우므로 파일을 명시하는 습관이 안전합니다.

기여 유형별 상세 가이드

문서 수정 (가장 쉬운 첫 기여)

1. README, CONTRIBUTING, 주석의 오타·문법 수정
2. 번역 개선 (영문 → 한글 등)
3. 예제 코드 업데이트 (deprecated API 수정)
4. 설치 가이드 보완 (새 OS·컴파일러 추가)

장점: 빌드·테스트 없이도 기여 가능. 첫 PR에 최적.

테스트 추가

// fmt는 GoogleTest를 사용 (test/format-test.cc 스타일)
TEST(format_test, handles_edge_case) {
    EXPECT_EQ(fmt::format("{}", 0), "0");
    EXPECT_EQ(fmt::format("{}", -1), "-1");
    // 경계 조건 테스트
}

장점: 버그 수정보다 난이도 낮음. 기존 테스트 스타일만 따르면 됨. 같은 저장소 안에서도 파일마다 테스트 이름 규칙이 조금씩 다르므로, 추가하려는 파일의 기존 테스트를 그대로 흉내 내는 것이 가장 안전합니다. spdlog처럼 Catch2를 쓰는 프로젝트라면 TEST_CASE/REQUIRE 형태가 됩니다.

버그 수정

1. good first issue / help wanted 이슈 선택
2. 재현 방법 확인 (이슈에 재현 코드 있는지)
3. 원인 분석 (디버거·로그)
4. 최소 수정으로 해결
5. 회귀 방지 테스트 추가

기능 추가

1. 이슈에서 먼저 "이 기능 추가해도 될까요?" 논의
2. API 설계·네이밍 합의
3. 구현 후 테스트·문서 추가
4. 리뷰 대응 (기능 추가는 리뷰가 길어질 수 있음)

실전 연습: 처음부터 끝까지

시나리오: spdlog README에 “recieve” → “receive” 오타를 수정하는 PR을 보냅니다.

flowchart TD
    A[1. GitHub에서 spdlog 포크] --> B[2. 로컬 클론]
    B --> C[3. upstream 추가]
    C --> D[4. fix-readme-typo 브랜치 생성]
    D --> E[5. README.md 수정]
    E --> F[6. git add, commit -s]
    F --> G[7. push origin]
    G --> H[8. GitHub에서 PR 생성]
    H --> I[9. CI 통과 대기]
    I --> J[10. 리뷰 반영 또는 머지]

처음 이 절차를 밟을 때 가장 흔한 실수는 포크의 main 브랜치에서 바로 수정하고 PR을 여는 것입니다. 그러면 두 번째 PR을 준비할 때 첫 PR의 커밋이 섞여 들어가고, 포크의 main을 upstream과 동기화하기도 어려워집니다. 포크의 main은 upstream을 따라가는 용도로만 두고, 작업은 항상 새 브랜치에서 하는 것이 좋습니다.

프로젝트별 실전 예제

spdlog 기여 예시

# spdlog good first issue: 문서 오타 수정
git clone https://github.com/YOUR_USERNAME/spdlog.git
cd spdlog
git checkout -b docs/fix-readme-typo
# README.md 수정
git add README.md
git commit -s -m "docs: fix typo in README (fixes #XXXX)"
git push origin docs/fix-readme-typo

fmt 기여 예시

# fmt: 테스트 케이스 추가
git clone https://github.com/YOUR_USERNAME/fmt.git
cd fmt
git checkout -b test/add-format-edge-case
# test/format-test.cc에 테스트 추가
mkdir build && cd build
cmake .. -DFMT_TEST=ON
cmake --build . && ctest --output-on-failure
git add test/format-test.cc
git commit -s -m "test: add edge case for format (fixes #XXXX)"
git push origin test/add-format-edge-case

기여 전체 흐름 다이어그램

sequenceDiagram
    participant Dev as 기여자
    participant Fork as 포크
    participant Upstream as 원본
    participant CI as CI
    Dev->>Fork: 1. 포크
    Dev->>Fork: 2. 클론·브랜치
    Dev->>Fork: 3. 수정·커밋
    Dev->>Fork: 4. 푸시
    Dev->>Upstream: 5. PR 생성
    Upstream->>CI: 6. CI 실행
    CI->>Upstream: 빌드·테스트 결과
    Upstream->>Dev: 7. 리뷰
    Dev->>Fork: 8. 수정 반영
    Dev->>Upstream: 9. 리뷰 대응
    Upstream->>Upstream: 10. 머지

CMake 빌드 실패, CI 실패, 머지 충돌, CLA 누락 같은 문제

에러 1: CMake 빌드 실패

증상:

CMake Error: Could not find a package configuration file provided by "spdlog"

원인: 의존성 패키지가 설치되지 않았거나, CMAKE_PREFIX_PATH가 설정되지 않음. 해결법:

# vcpkg 사용 시
vcpkg install spdlog
cmake .. -DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake
# 또는 시스템 패키지 매니저
# Ubuntu: sudo apt install libspdlog-dev
# macOS: brew install spdlog

에러 2: CI에서 실패

증상:

clang-tidy: warning: ... [readability-*]
cppcheck: error: ...

원인: 로컬에서는 통과했지만, CI에서 정적 분석·포맷 검사가 실패함. 또는 CI 매트릭스의 다른 컴파일러(MSVC, 오래된 GCC)에서만 실패함. 예를 들어 최신 GCC에서는 되던 C++20 기능이 프로젝트가 지원하는 오래된 GCC에는 없거나, MSVC에서만 warning C4244: conversion from 'int64_t' to 'int', possible loss of data가 /WX 때문에 에러가 되는 식입니다. 해결법:

# 변경한 파일에만 프로젝트 .clang-format 적용 (전체 파일을 돌리면 diff가 폭증)
git diff --name-only upstream/main -- '*.cpp' '*.h' | xargs clang-format -i
# clang-tidy 실행 (프로젝트 스크립트 확인)
# .github/workflows/ 또는 scripts/ 확인

저장소 전체에 clang-format -i를 돌리면, 로컬 clang-format 버전이 프로젝트가 쓰는 버전과 다를 때 수백 개 파일이 바뀌어 PR이 리뷰 불가능해집니다. clang-format은 메이저 버전마다 출력이 조금씩 달라지므로, CI가 쓰는 버전을 확인하고 변경한 파일에만 적용하는 것이 안전합니다. 포크에서도 GitHub Actions를 활성화해 두면, PR을 열기 전에 자기 포크에서 CI 전체 매트릭스를 먼저 돌려 볼 수 있습니다.

에러 3: 리뷰에서 “스타일이 맞지 않아요”

증상: 메인테이너가 들여쓰기·네이밍·주석을 요구함. 해결법:

// ❌ 잘못된 스타일 (예: 프로젝트가 snake_case 사용)
void processData()
// ✅ 올바른 스타일
void process_data()
// CONTRIBUTING.md, .clang-format, 기존 코드 스타일 확인

에러 4: 머지 충돌

증상:

This branch has conflicts that must be resolved

해결법:

# upstream main 최신화
git fetch upstream
git rebase upstream/main
# 충돌 발생 시
# 1. 충돌 파일 수동 수정
# 2. git add <충돌해결된파일>
# 3. git rebase --continue

에러 5: CLA/DCO 서명 누락

증상:

All commits need to be signed off (DCO)

해결법:

# 커밋에 Signed-off-by 추가
git commit -s -m "docs: fix typo in README (fixes #1234)"
# 또는 이전 커밋 수정
git commit --amend -s --no-edit
git push --force-with-lease origin fix-typo-in-readme
# 커밋이 여러 개라면 한 번에 서명 추가
git rebase --signoff upstream/main
git push --force-with-lease origin fix-typo-in-readme

--amend는 마지막 커밋 하나만 고치므로, 커밋이 여러 개인 PR에서는 DCO 봇이 계속 실패로 표시합니다. 또 Signed-off-by의 이메일이 커밋 작성자(author) 이메일과 다르면 DCO 검사가 실패하므로, git config user.email이 GitHub 계정에 등록된 주소인지 확인해야 합니다.

에러 6: 커밋 메시지 규칙 위반

증상:

Commit message does not follow Conventional Commits

해결법:

# 커밋 메시지 수정
git commit --amend -m "docs: fix typo in README (fixes #1234)"
git push --force-with-lease origin fix-typo-in-readme

에러 7: 테스트 실패

증상:

The following tests FAILED:
  42 - format_test (Failed)

원인: 수정한 코드가 기존 동작을 바꿔서 회귀가 발생함. 해결법:

# 로컬에서 전체 테스트 실행
cd build
ctest --output-on-failure -C Debug
# 실패한 테스트만 실행 (ctest 정규식 필터)
ctest -R format-test --output-on-failure
# GoogleTest 바이너리를 직접 실행해 특정 케이스만
./bin/format-test --gtest_filter='format_test.*edge*'

주의: 버그 수정 시 회귀 방지 테스트를 반드시 추가합니다.

에러 8: 포크와 원본 동기화 실패

증상:

! [rejected] main -> main (non-fast-forward)

원인: 포크가 원본보다 뒤처져 있어서 푸시가 거부됩니다. 해결법:

# upstream 최신화
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
# PR 브랜치도 rebase
git checkout fix-typo-in-readme
git rebase upstream/main
git push --force-with-lease origin fix-typo-in-readme

에러 9: C++ 컴파일러 버전 불일치

증상:

error: 'optional' is not a member of 'std'

원인: 프로젝트가 C++17 이상을 요구하는데, 로컬 컴파일러가 구버전임. 해결법:

# GCC 버전 확인
g++ --version
# CMake에서 C++ 표준 지정
cmake .. -DCMAKE_CXX_STANDARD=17
# 또는 Docker로 CI와 동일 환경 구성
docker run -v $(pwd):/src -w /src ubuntu:22.04 bash -c "apt update && apt install -y build-essential cmake && ..."

에러 10: PR이 닫히거나 엉뚱한 커밋이 섞임

증상: PR이 갑자기 닫혀 있거나, diff에 내가 만들지 않은 커밋이 수십 개 보입니다. 원인: PR의 base 브랜치가 삭제되면(예: 릴리스 브랜치 정리) GitHub는 그 브랜치를 향한 PR을 닫습니다. 또 기본 브랜치가 바뀐 상태(master에서 main으로 이름 변경 등)에서 옛 base 기준으로 작업하면, 다른 사람의 커밋이 PR diff에 섞여 보입니다. 해결법:

# 현재 기본 브랜치 기준으로 다시 정렬 후 푸시
git fetch upstream
git rebase upstream/main
git push --force-with-lease origin fix-typo-in-readme
# 닫힌 PR은 GitHub에서 올바른 base로 새 PR을 열고, 이전 PR 링크를 설명에 남김

작게 시작하고 이슈에서 먼저 논의하기

작게 시작하기

  • 문서 수정·오타·테스트 추가로 첫 PR을 보내고, 점차 버그 수정·작은 기능으로 확장합니다.
  • 한 PR = 한 가지 변경으로 두면 리뷰가 수월합니다.

이슈 먼저 논의하기

# 큰 변경 전 이슈에서 먼저 논의
"이 기능을 추가하려고 하는데, 이런 방향이 맞을까요?"
"이 버그를 수정하려면 A/B 방법이 있는데, 어떤 게 선호되나요?"

커밋 메시지 규칙

<type>: <description> [optional: (fixes #123)]
type: feat, fix, docs, test, style, refactor

Conventional Commits는 널리 쓰이지만 모든 프로젝트의 규칙은 아닙니다. 짧은 명령형 문장(“Fix typo in README”)만 쓰는 프로젝트도 많으므로, git log --oneline -20으로 최근 커밋 형식을 보고 그대로 맞추는 것이 가장 확실합니다.

리뷰어와 소통하기

리뷰 코멘트에는 가능한 한 빨리, 정중하게 응답합니다. 이해가 안 되는 피드백은 “왜 이렇게 바꾸는 게 좋은가요?”처럼 구체적으로 되물어보고, 반영했다면 “Updated per your suggestion”처럼 커밋 메시지나 댓글로 명시합니다. 의견이 갈리는 경우에는 근거(벤치마크, 기존 코드 스타일, 관련 이슈 링크)를 들어 설명하되, 최종 결정은 메인테이너에게 맡기는 편이 관계 유지에 도움이 됩니다.

지속적인 기여로 이어가기

첫 PR이 머지되면 같은 프로젝트의 다른 good first issue를 이어서 처리하며 코드베이스 이해를 넓혀갑니다. 몇 차례 기여가 쌓이면 이슈 트리아지(라벨링, 재현 확인)나 다른 초보 기여자의 PR 리뷰처럼 코드 작성 이외의 역할로 확장할 수도 있습니다. 꾸준히 참여하다 보면 프로젝트에 따라 리뷰나 머지 권한을 위임받기도 합니다.


같이 보면 좋은 글