제14부 시스템 설계·품질·운영
14.7 품질 수준·REP 2004·의존성 위생
14.7.1 이 장에서 배우는 것 / 선수 지식
"이 패키지를 제품에 써도 되는가?" — ROS 2 생태계에는 수천 개의 패키지가 있고, 품질은 천차만별이다. 어떤 것은 여러 회사가 운영에 쓰는 검증된 코드이고, 어떤 것은 대학원생이 논문용으로 만들고 3년째 방치된 것이다. 겉으로는 구분이 안 된다.
REP 2004는 이 문제에 대한 ROS 2의 답이다 — 패키지가 스스로 품질 수준을 선언하고, 그 근거를 문서로 제시하게 한다. 완벽하지는 않지만, 판단의 출발점을 준다.
이 장은 그 체계와, 더 넓게 의존성을 건강하게 관리하는 실무를 다룬다.
배우는 것:
- REP 2004 — 품질 수준의 정의.
- 평가 항목 — 무엇으로 판정하는가.
- 실무적 해석 — 선언을 어디까지 믿는가.
- 의존성 평가 — 도입 전 확인.
- 의존성 위생 — 지속적 관리.
- 자체 패키지의 품질 — 우리가 만들 때.
- 취약점·라이선스 — 놓치기 쉬운 축.
선수 지식: 4.1~4.4(패키지·의존성), 4.9(릴리스), 4.10(CI), 13.4.6(갱신), 14.5·14.6(시험).
정직: REP 2004의 정확한 항목·수준 정의와 각 패키지의 현재 선언 상태는 반드시 원문과 해당 저장소로 확인해야 한다
(확인 필요). 이 장은 개념과 활용 방법을 다루며, 특정 패키지의 품질을 판정하지 않는다. 라이선스 준수 판단은 법무의 영역이며 이 책은 조언을 제공하지 않는다. 이 환경에서 검증하지 않았다(목차 3).검증 상태(추가): 이 장의 서술 가운데 1곳은 이후 회차에서 Jazzy 실물과 대조해 확인했다 — 본문의 (실행 확인) 표기가 그것이다. 표기가 없는 서술은 위 고지가 그대로 적용된다(목차 3의 검증 범위 표).
14.7.2 REP 2004 — 품질 수준
패키지를 다섯 수준으로 분류한다(확인 필요: 정확한 정의).
| 수준 | 대략적 성격 |
|---|---|
| 1 | 가장 높은 요구 — 버전 정책·시험·문서·보안 대응 전부 |
| 2 | 높음 |
| 3 | 중간 — 많은 실무 패키지 |
| 4 | 낮음 |
| 5 | 요구 없음 — 선언만 |
평가 축(확인 필요: 정확한 목록):
| 축 | 내용 |
|---|---|
| 버전 정책 | 안정 버전·호환성 정책 |
| 변경 통제 | 리뷰·CI 요구 |
| 문서화 | 기능·API·라이선스 |
| 시험 | 커버리지·시스템 시험·성능 |
| 의존성 | 하위 의존의 품질 수준 |
| 플랫폼 지원 | Tier 정책(4.4) |
| 보안 | 취약점 대응 정책 |
견해: "의존성의 품질 수준이 평가 축에 있다"는 점이 중요하다. Level 1 패키지가 Level 5 패키지에 의존하면 그 사슬이 약점이 된다. 품질은 전이적이므로, 우리 시스템의 품질도 가장 약한 의존성 수준에 가깝다.
정직: 품질 선언은 자기 선언이며 외부 감사가 아니다
(확인 필요: 검증 절차 유무). 선언한 항목이 실제로 유지되는지는 별개이므로, 선언을 출발점으로 삼되 스스로 확인해야 한다.
14.7.3 실무적 해석
품질 선언을 어떻게 읽을 것인가.
| 상황 | 해석 |
|---|---|
| Level 1·2 선언 + 활발한 저장소 | 신뢰도 높음 |
| 선언 있으나 저장소 정체 | 선언이 낡았을 수 있음 |
| 선언 없음 | 스스로 평가 필요 |
| Level 5 | 정직한 표시 — 그 자체는 문제가 아님 |
견해: Level 5 선언을 부정적으로만 보지 말라. "우리는 품질 보증을 하지 않는다"고 정직히 밝힌 것이며, 실험적 패키지에는 적절하다. 문제는 Level 5 패키지를 운영에 쓰면서 그것을 모르는 것이다.
견해: 선언보다 저장소의 실제 상태가 더 많은 것을 말해 준다. 최근 커밋, 이슈 응답, CI 상태, 릴리스 빈도, 기여자 수 — 이런 것들이 "이 패키지가 유지보수되고 있는가" 를 알려준다. 품질 선언과 함께 봐야 한다.
14.7.4 의존성 평가
새 패키지를 도입하기 전에 확인할 것.
| 항목 | 질문 |
|---|---|
| ① 필요성 | 직접 구현 대비 이득이 큰가 |
| ② 활성도 | 유지되고 있는가·이슈 응답 |
| ③ 라이선스 | 우리 배포 방식과 맞는가 |
| ④ 의존 사슬 | 무엇을 함께 끌고 오는가 |
| ⑤ 이탈 비용 | 나중에 뺄 수 있는가 |
| ⑥ 배포 가능성 | 바이너리 있나·빌드 필요한가 |
| ⑦ 플랫폼 | 대상 아키텍처 지원(4.4) |
| ⑧ 보안 | 취약점 이력·대응 |
# 의존 사슬 확인
rosdep keys --from-paths src --ignore-src
colcon list --topological-order
ros2 pkg xml <package> # 메타데이터 (확인 필요: 명령)
견해: ④(의존 사슬)를 확인하지 않으면 작은 편의를 위해 큰 부담을 진다. 유틸리티 하나를 쓰려고 대규모 프레임워크를 끌고 오면, 빌드 시간·이미지 크기·취약점 표면이 모두 늘어난다. "이 패키지가 데려오는 것"을 먼저 보라.
견해: ⑤(이탈 비용)를 도입 시점에 생각하라. 인터페이스를 우리 코드로 감싸 두면(어댑터) 나중에 교체할 수 있지만, 그 타입이 우리 코드 전체에 퍼지면 뺄 수 없다. 핵심 의존성일수록 경계를 두는 것이 값을 한다(14.1.5).
정직: 라이선스 적합성 판단은 법무의 영역이다. 라이선스 종류를 확인하고 조직의 정책·법무에 확인하는 절차를 두어야 하며, 이 책은 특정 라이선스의 해석이나 준수 방법을 조언하지 않는다.
14.7.5 의존성 위생
도입 후 지속적으로 관리한다.
| 활동 | 주기 |
|---|---|
| 의존성 목록 유지 | 상시 |
| 취약점 확인 | 정기 |
| 버전 갱신 | 계획적(13.4.6) |
| 미사용 의존성 제거 | 정기 |
| 중복 기능 정리 | 정기 |
| 고정(pin) 정책 검토 | 릴리스마다 |
| 라이선스 재확인 | 변경 시 |
흔한 위생 문제:
| 문제 | 결과 |
|---|---|
| 선언되지 않은 의존 | 다른 환경에서 빌드 실패(4.3.6) |
| 과다 선언 | 불필요한 설치 |
| 버전 미고정 | 재현 불가 |
| 과도한 고정 | 보안 패치 못 받음 |
| 방치된 의존성 | 취약점·비호환 |
| 순환 의존 | 빌드 문제 |
<!-- package.xml — 의존 종류를 정확히 (4.3) -->
<depend>rclcpp</depend> <!-- 빌드 + 실행 -->
<build_depend>ament_cmake</build_depend>
<exec_depend>rviz2</exec_depend> <!-- 실행만 -->
<test_depend>ament_lint_auto</test_depend> <!-- 시험만 -->
함정: "내 머신에서는 빌드된다"의 최다 원인이 미선언 의존이다(4.3.6). 시스템에 이미 설치되어 있어 빌드가 되지만, 클린 환경에서는 실패한다. CI를 클린 컨테이너에서 실행하면 이것이 검출된다(4.10).
견해: 버전 고정은 재현성과 보안의 절충이다. 모두 고정하면 재현 가능하지만 패치를 못 받고, 안 하면 어제 되던 빌드가 오늘 깨진다. 릴리스는 고정, 개발은 유연하게 두고, 정기적으로 고정 버전을 갱신하는 절차를 두는 것이 흔한 답이다.
견해: 의존성 목록(SBOM 성격)을 산출물로 남기라(13.4.6). 취약점 공지가 나왔을 때 "우리가 영향받는가"를 즉시 답할 수 있고, 감사·규제 대응에도 쓰인다. 릴리스 시점에 자동 생성하는 것이 현실적이다.
14.7.6 ROS 배포판과 버전
ROS 2 특유의 의존성 문제다.
| 축 | 고려 |
|---|---|
| 배포판 고정 | Jazzy에 맞춘 패키지 버전(4.4) |
| 바이너리 vs 소스 | apt 설치 vs 워크스페이스 빌드 |
| 백포트 | 새 기능이 필요할 때 |
| EOL | 배포판 지원 종료(15.1) |
| 혼합 위험 | 배포판 간 패키지 섞기 |
함정: 다른 배포판용 패키지를 섞으면 ABI·API 불일치가 난다. 빌드는 되는데 실행 시 비정상적으로 종료되는 경우가 있어 진단이 어렵다. 한 배포판으로 통일하고, 필요하면 소스에서 빌드한다.
견해: "바이너리로 되는 것은 바이너리로"가 유지보수에 유리하다. 소스 빌드가 늘수록 빌드 시간과 관리 부담이 는다. 수정이 필요한 것만 소스로 두고, 그것도 upstream에 기여해 되돌리는 것이 장기적으로 낫다.
견해: 포크는 마지막 수단이다. 급한 수정을 위해 포크하면 그 순간부터 upstream 변경을 따라가야 하는 부담이 생긴다. 패치를 upstream에 보내고 기다리는 동안 로컬 패치로 관리하는 편이 부채가 적다.
14.7.7 자체 패키지의 품질
우리가 만드는 것에도 같은 기준을 적용한다.
| 항목 | 실무 조치 |
|---|---|
| README | 무엇·어떻게·인터페이스 |
| 인터페이스 문서 | 토픽·서비스·파라미터(14.1.5) |
| 라이선스 명시 | package.xml·파일 헤더 |
| CI | 빌드·시험·린트(4.10) |
| 시험 | 단위·통합(14.5·14.6) |
| 버전 정책 | 언제 갱신하는가 |
| CHANGELOG | 변경 이력 |
| 이슈 대응 | 내부 팀이라도 |
# 린트 (ament) — 확인 필요: 사용 가능한 린터
colcon test --packages-select my_pkg
# uncrustify · cpplint · flake8 · copyright 등
문서를 생성할 것인가, 쓸 것인가. REP 2004의 상위 품질 수준은 문서를 요구하고(14.7.2), 그 요구는 두 종류로 갈린다.
| 종류 | 만드는 법 | 값어치 |
|---|---|---|
| API 참조(클래스·함수 시그니처) | Doxygen(C++)·Sphinx(Python)로 소스 주석에서 생성. ROS 생태계에서는 rosdoc2가 이 둘을 감싸 패키지 단위로 빌드하며, package.xml의 <rosdoc2> export로 설정을 가리킨다(4.4.6의 export 절) | 생성이 자동이라 낡지 않는다. 다만 "이 함수는 무엇을 하는가"만 답하고 "왜·언제 쓰는가"는 답하지 않는다 |
| 인터페이스·운용 문서(토픽·서비스·파라미터·프레임·단위·QoS) | 사람이 쓴다. 자동 생성 대상이 아니다 | 위 표가 말한 그 문서다. 노드를 쓰는 사람에게 실제로 필요한 것은 이쪽이다 |
정직:
rosdoc2는 Jazzy의 apt 인덱스에 없다(실행 확인 —ros-jazzy-rosdoc2패키지 없음). 소스나 pip로 설치해야 하며, 설치 방법·사용법·지원 범위는 프로젝트 문서가 정본이다(확인 필요). 이 책은 도구 사용법을 다루지 않는다.
견해: 문서 자동 생성은 있으면 좋지만 우선순위가 높지 않다. 로봇 패키지에서 사람이 실제로 찾는 것은 헤더 파일의 함수 목록이 아니라 "이 노드가 무슨 토픽을 어떤 주기·프레임·단위로 내는가" 이고, 그것은 생성되지 않는다. README 한 장 + 인터페이스 표가 Doxygen 사이트보다 값을 한다. 공개 라이브러리를 배포한다면 이야기가 달라진다.
견해: 내부 패키지라도 인터페이스 문서는 반드시 쓰라(14.1.5의 반복). 6개월 뒤의 자신과 새로 온 동료가 그 문서의 독자다. 토픽 이름·타입·주기·프레임·단위·QoS를 적는 데 10분이면 되고, 그것을 안 적어 생기는 손실은 훨씬 크다.
견해: 품질 수준을 내부적으로 등급화하는 것도 유용하다. "이 패키지는 실험용", "이것은 운영 필수"를 명시하면, 어디에 시험과 리뷰를 집중할지 정해진다. 모든 패키지를 같은 기준으로 다루면 자원이 분산된다.
함정: 린트를 나중에 도입하면 대량 수정이 발생한다. 처음부터 켜 두면 점진적으로 유지되지만, 나중에 켜면 수백 개 경고가 대량 출력돼 결국 끈다. 새 패키지는 처음부터 린트를 켜라.
14.7.8 취약점 대응
| 활동 | 설명 |
|---|---|
| 의존성 목록 유지 | 무엇을 쓰는가(14.7.5) |
| 공지 추적 | 배포판·주요 라이브러리 |
| 영향 평가 | 우리가 그 경로를 쓰는가 |
| 패치 적용·검증 | 13.4.6 |
| 기록 | 무엇을 언제 |
견해: "영향 평가"가 실무의 핵심이다. 취약점 공지가 나와도 우리가 그 기능을 안 쓰면 영향이 없을 수 있다. 무조건 갱신"과 "무조건 무시" 사이에서 판단하려면 의존성 목록과 사용 경로를 알아야 한다.
정직: 취약점 대응 절차의 수립은 보안 전문가의 영역이다(13.1.1). 여기서는 개발 실무의 준비(목록·추적·검증 체계)만 다루며, 규제 요구가 있으면 전문가의 설계를 따라야 한다.
14.7.9 함정 카탈로그
| # | 함정 | 증상 | 대처 |
|---|---|---|---|
| 1 | 품질 선언만 믿음 | 낡은 정보 | 저장소 상태 확인 |
| 2 | Level 5를 무조건 배제 | 과도한 제약 | 용도별 판단 |
| 3 | Level 5를 운영에 무자각 사용 | 위험 | 인지·문서화 |
| 4 | 의존 사슬 미확인 | 부담 폭증 | 사전 확인 |
| 5 | 이탈 비용 미고려 | 교체 불가 | 어댑터 경계 |
| 6 | 라이선스 자체 판단 | 법적 위험 | 법무 확인 |
| 7 | 미선언 의존 | 타 환경 빌드 실패 | 클린 CI |
| 8 | 버전 전면 고정 | 패치 못 받음 | 정기 갱신 절차 |
| 9 | 고정 없음 | 재현 불가 | 릴리스 고정 |
| 10 | 배포판 혼합 | ABI 문제 | 통일 |
| 11 | 불필요한 소스 빌드 | 관리 부담 | 바이너리 우선 |
| 12 | 성급한 포크 | 지속 부채 | upstream 기여 |
| 13 | 인터페이스 문서 없음 | 사용·유지 어려움 | 항상 작성 |
| 14 | 린트 늦은 도입 | 대량 경고·포기 | 처음부터 |
| 15 | 의존성 목록 없음 | 취약점 대응 불가 | 자동 생성 |
| 16 | 미사용 의존 방치 | 표면 확대 | 정기 정리 |
14.7.10 체크포인트
- REP 2004의 다섯 수준과 대략적 성격을 말할 수 있는가.
- 평가 축 일곱 가지와, "의존성의 품질 수준"이 축에 있는 의미는?
- 품질 선언을 해석할 때 함께 봐야 할 것은?
- Level 5 선언을 어떻게 받아들여야 하는가.
- 의존성 평가의 여덟 항목을 들 수 있는가.
- 의존 사슬 확인을 강조하는 이유는?
- 이탈 비용을 도입 시점에 고려하는 방법은?
- 의존성 위생의 일곱 활동과 흔한 문제 여섯 가지는?
- "내 머신에서는 빌드된다"의 최다 원인과 예방은?
- 버전 고정의 절충과, 흔한 해법은?
- 의존성 목록을 산출물로 남기는 이유 셋은?
- 배포판 혼합의 위험과, 바이너리·소스 선택 원칙은?
- 포크를 마지막 수단으로 두는 이유는?
- 자체 패키지에서 반드시 할 것 여덟 가지와, 내부 패키지에도 문서가 필요한 이유는?
- 내부 품질 등급화의 이점은?
- 린트를 처음부터 켜라는 조언의 근거는?
- 취약점 대응에서 "영향 평가"가 핵심인 이유는?
다음 장 14.8은 이 모든 것을 로봇에 배포하는 문제 — systemd·컨테이너·OTA 배포를 다룬다.