1. 무료로 설치할 수 있다는 말과 자유롭게 사용할 수 있다는 말은 다르다
Python의 pip, Java의 Maven이나 Gradle, JavaScript의 npm을 사용하면 다른 사람이 만든 기능을 몇 줄의 설정으로 가져올 수 있습니다. 다운로드 비용이 없더라도 그 코드는 저작권이 있는 창작물이며, 오픈소스 라이선스는 사용·수정·배포를 허용하는 조건을 정합니다. 저작권 고지를 유지해야 하는지, 수정한 소스를 공개해야 하는지, 같은 라이선스를 적용해야 하는지는 라이선스와 배포 방식에 따라 달라질 수 있습니다.
따라서 ‘오픈소스’와 ‘아무 조건 없음’을 같은 뜻으로 이해하면 안 됩니다. 패키지를 개인 컴퓨터에서 학습하는 상황과 수정한 프로그램을 고객에게 배포하는 상황도 검토할 조건이 다를 수 있습니다. 개발자는 라이선스를 임의로 법률 해석하기보다 프로젝트가 사용하는 패키지와 라이선스 정보를 정확히 수집하고, 조직의 정책과 검토 절차에 연결해야 합니다.
GitHub는 2026년 10월 16일 GitHub Enterprise Cloud와 GitHub Code Security를 사용하는 조직을 대상으로 오픈소스 라이선스 준수 기능의 정식 제공을 발표했습니다. 핵심은 라이선스 이름을 보여 주는 데서 끝나지 않고, 조직 정책에 맞지 않는 의존성 변경을 풀 리퀘스트 단계에서 발견하고 병합 규칙과 연결하는 것입니다. 특정 제품 기능을 쓰지 않더라도 이 흐름은 소프트웨어 공급망을 공부하는 좋은 설계 사례입니다.
근거 자료 · GitHub Changelog · Open source license compliance generally available · GitHub Docs · Open source license compliance
2. 의존성 그래프는 내가 고른 패키지 뒤의 패키지까지 펼쳐 보인다
프로젝트 설정 파일에 직접 적은 라이브러리를 직접 의존성이라고 합니다. 그 라이브러리가 다시 요구하는 라이브러리는 전이 의존성입니다. 예를 들어 애플리케이션이 A를 직접 설치하고 A가 B와 C를 필요로 한다면, 개발자가 B와 C의 이름을 입력하지 않았어도 최종 프로그램에는 영향을 줄 수 있습니다. 라이선스 검토가 package.json이나 requirements.txt의 첫 줄만 읽어서는 끝나지 않는 이유입니다.
GitHub 문서에 따르면 의존성 그래프는 지원되는 패키지 생태계의 매니페스트와 잠금 파일을 분석해 직접 및 전이 의존성을 식별합니다. 잠금 파일은 실제 선택된 버전을 고정하므로 ‘어떤 버전이 배포됐는가’를 재현하는 데 특히 중요합니다. 분석 결과는 소프트웨어 자재 명세서인 SBOM으로 내보낼 수 있습니다. SBOM은 제품 속 재료표처럼 구성요소, 버전, 패키지 관계를 추적하는 자료입니다.
라이선스 이름은 SPDX 식별자로 표준화할 수 있습니다. MIT, Apache-2.0처럼 일정한 식별자를 쓰면 띄어쓰기나 약칭 때문에 같은 라이선스를 다르게 처리하는 문제를 줄일 수 있습니다. 그러나 파일에 라이선스가 없거나 여러 조건이 결합된 표현도 있으므로 ‘알 수 없음’을 정상적인 상태로 모델링하고 사람의 검토로 보내야 합니다.
| 구분 | 확인할 질문 | 남길 데이터 |
|---|---|---|
| 직접 의존성 | 개발자가 명시적으로 추가했는가 | 패키지·버전·선택 목적 |
| 전이 의존성 | 어떤 패키지를 통해 들어왔는가 | 상위 패키지와 경로 |
| 라이선스 | 표준 식별자와 원문이 무엇인가 | SPDX 식별자·근거 URL |
| 정책 결과 | 허용·거부·검토 중 어느 상태인가 | 규칙 버전·판정 시각 |
| 예외 | 누가 어떤 범위와 기간을 승인했는가 | 사유·승인자·만료일 |
3. 정책 검사는 발견, 판단, 적용의 세 단계로 나뉜다
첫 단계는 발견입니다. 매니페스트와 잠금 파일에서 패키지와 버전을 찾고, 의존성 관계와 라이선스 정보를 수집합니다. 두 번째는 판단입니다. 수집한 SPDX 식별자를 조직의 허용·거부·검토 정책과 비교합니다. 세 번째는 적용입니다. 결과를 개발자에게 설명하고, 병합을 허용하거나 막거나 담당자 검토로 보냅니다. 이 세 단계를 분리하면 라이선스 정보가 바뀐 것인지 정책이 바뀐 것인지 추적하기 쉽습니다.
GitHub 문서의 Evaluate 모드는 정책 위반 가능성을 풀 리퀘스트에 표시하지만 병합은 막지 않습니다. Active 모드는 규칙과 연결될 때 정책에 맞지 않는 변경의 병합을 차단할 수 있습니다. 처음부터 차단하면 기존 프로젝트의 미분류 패키지 때문에 개발이 멈출 수 있으므로, 문서는 먼저 비활성 상태에서 정책을 만들고 Evaluate로 영향을 관찰한 뒤 Active로 전환하는 단계적 도입을 설명합니다.
이 방식은 보안 취약점 검사와 닮았지만 질문은 다릅니다. 취약점 검사는 알려진 공격 가능성과 영향 버전을 묻고, 라이선스 검사는 사용·수정·배포 조건이 조직 정책과 맞는지 묻습니다. 안전한 버전이라도 정책에 맞지 않을 수 있고, 허용된 라이선스라도 보안 취약점이 있을 수 있으므로 두 검사를 하나의 통과 표시로 합치지 않는 편이 좋습니다.
| 검사 | 주요 입력 | 주요 결과 | 개발자의 다음 행동 |
|---|---|---|---|
| 취약점 | 패키지·버전·보안 권고 | 영향 여부와 심각도 | 업데이트·완화·위험 검토 |
| 라이선스 | 패키지·라이선스·조직 정책 | 허용·거부·검토 | 교체·정책 검토·예외 신청 |
| Evaluate | 정책과 변경된 의존성 | 주석과 관찰 결과 | 오탐·영향 범위 확인 |
| Active | 검증된 정책과 병합 규칙 | 통과 또는 차단 | 위반 해결 뒤 다시 검사 |
4. 풀 리퀘스트에서는 결과보다 설명 가능한 경로가 중요하다
새 패키지를 추가한 풀 리퀘스트가 열리면 검사기는 변경 전후의 의존성을 비교해야 합니다. 기존에 있던 문제와 이번 변경으로 새로 들어온 문제를 구분해야 작성자가 자신이 해결할 범위를 이해할 수 있습니다. 결과에는 패키지 이름만 적기보다 직접 또는 전이 의존성인지, 어떤 경로로 들어왔는지, 어떤 정책 규칙과 충돌했는지를 보여 주는 편이 유용합니다.
공식 발표는 위반을 해결하는 방법으로 의존성 제거 또는 교체, 정책 수정, 특정 패키지 예외를 설명합니다. 예외는 경고를 지우는 버튼이 아닙니다. 패키지와 버전 범위, 적용 저장소, 승인 사유, 검토자와 만료 시점을 남겨야 다음 버전에서도 같은 판단이 유효한지 확인할 수 있습니다. 정책 변경과 패키지 예외에는 감사 로그가 필요합니다.
GitHub는 정식 제공 과정에서 라이선스 정책 및 예외 감사 이벤트, 정책 API와 패키지 준수 확인 API를 제공한다고 발표했습니다. 코딩 에이전트가 패키지를 추천하기 전에 준수 여부를 확인하는 사용 예도 제시했습니다. 여기서 AI의 역할은 후보 탐색과 확인 요청을 자동화하는 것이며, 불명확한 라이선스의 법률 판단이나 조직 승인까지 대신하는 것은 아닙니다.
# 교육용 의사코드: 패키지 추가 전 정책 확인
candidate = ai_agent.suggest_package(requirement)
metadata = dependency_service.lookup(candidate.name, candidate.version)
result = policy_engine.evaluate(metadata.licenses, policy_version)
if result.status == "allowed":
open_pull_request(candidate, evidence=result)
elif result.status == "denied":
search_for_alternative(requirement)
else:
request_human_review(candidate, evidence=result)근거 자료 · GitHub Changelog · Open source license compliance generally available
5. Python·SQL·Java로 작은 정책 검사기를 설계해 본다
다음 내용은 공식 제품을 재현했다는 주장이 아니라 원리를 이해하기 위한 수업 프로젝트 제안입니다. 먼저 20개 정도의 가상 패키지 데이터를 JSON으로 만듭니다. 각 항목에는 패키지 이름, 버전, 직접 또는 전이 구분, 상위 패키지, SPDX 식별자와 근거 URL을 넣습니다. 실제 프로젝트의 라이선스 적법성을 판정하는 자료가 아니라 데이터 흐름을 시험하는 학습용 표본임을 표시합니다.
Python 프로그램은 JSON을 읽어 식별자 표기를 정규화하고, 정책 파일의 allowed, denied, review 목록과 비교합니다. AND와 OR이 포함된 복합 SPDX 표현은 문자열 포함 검사로 처리하지 말고 별도의 파서가 필요하다는 한계를 보고서에 적습니다. 처음 구현에서는 단일 식별자만 지원하고 복합 표현을 review로 보내는 것이 잘못된 허용보다 설명하기 쉽습니다.
SQL에는 검사 실행, 패키지 결과, 정책 버전, 예외와 감사 이벤트를 서로 다른 테이블로 저장합니다. 같은 패키지도 정책 버전에 따라 결과가 달라질 수 있으므로 현재 결과만 덮어쓰지 않습니다. Java API는 검사 요청을 받고 실행 번호를 반환하며, 결과 조회와 예외 신청을 분리합니다. 승인 권한이 없는 사용자가 예외 상태를 바꾸지 못하도록 역할을 확인합니다.
- 입력 데이터의 출처와 수집 시각을 함께 저장한다.
- unknown과 review를 오류가 아닌 정상적인 업무 상태로 다룬다.
- 정책 버전과 검사 결과를 묶어 과거 결정을 재현한다.
- 예외 승인과 변경 기록을 일반 검사 로그와 분리한다.
-- 교육용 스키마 예시
CREATE TABLE scan_run (
run_id BIGINT PRIMARY KEY, commit_sha VARCHAR(40),
policy_version VARCHAR(30), started_at TIMESTAMP
);
CREATE TABLE package_result (
run_id BIGINT, package_name VARCHAR(200), version VARCHAR(80),
dependency_path TEXT, spdx_id VARCHAR(120), status VARCHAR(20),
reason TEXT, PRIMARY KEY (run_id, package_name, version)
);
CREATE TABLE policy_exception (
exception_id BIGINT PRIMARY KEY, package_name VARCHAR(200),
version_range VARCHAR(100), reason TEXT, approved_by VARCHAR(100),
expires_at TIMESTAMP
);6. 클라우드 파이프라인에서는 재현성, 권한, 실패 처리를 확인한다
검사기를 클라우드 CI에 연결하면 매니페스트나 잠금 파일이 바뀐 풀 리퀘스트에서만 실행하도록 구성할 수 있습니다. 실행 환경은 동일한 정책 버전과 파서 버전을 사용해야 합니다. 네트워크 조회가 실패했을 때 허용으로 처리하면 검사가 조용히 무력화되므로, 재시도 후 ‘판정 불가’로 표시하고 병합 정책에 따라 사람이 결정하도록 설계합니다.
패키지 메타데이터 서비스의 토큰은 저장소 코드에 넣지 않고 비밀 저장소에서 주입합니다. 정책 편집자, 예외 승인자, 일반 개발자의 권한을 나누고 모든 변경을 기록합니다. 검사 결과에는 필요한 근거만 남기며, 토큰과 내부 저장소 주소 같은 비밀이 로그나 생성형 AI 프롬프트에 포함되지 않도록 필터링합니다.
AI 도구가 새 패키지를 제안하는 경우에도 같은 관문을 통과시킵니다. 에이전트가 만든 코드라는 이유로 더 엄격하거나 느슨한 별도 규칙을 만드는 대신, 사람이 추가한 의존성과 같은 SBOM·정책·보안 검사를 적용하면 책임 경로가 단순해집니다. AI가 제안한 후보, 실제 선택한 후보, 거절 사유를 기록하면 추천 품질도 나중에 평가할 수 있습니다.
풀 리퀘스트의 잠금 파일 변경
→ 의존성 그래프 생성
→ 패키지·버전·라이선스 근거 수집
→ 정책 버전으로 평가
→ 취약점 검사와 라이선스 검사를 각각 표시
→ 통과·교체·검토·기간 있는 예외
→ 병합 후 SBOM과 감사 이력 보관7. 결과를 평가할 때는 차단 횟수보다 근거와 복구 가능성을 본다
실습 평가는 얼마나 많은 패키지를 차단했는지로 결정하지 않습니다. 입력에서 전이 의존성까지 추적했는지, 같은 입력과 정책 버전으로 같은 결과가 나오는지, 허용·거부·검토의 이유를 사람이 이해할 수 있는지 확인합니다. 알 수 없는 라이선스를 억지로 허용하거나 거부하지 않고 검토 상태로 남기는 것도 올바른 결과가 될 수 있습니다.
고장 실험도 필요합니다. 잠금 파일이 없을 때, SPDX 값이 비어 있을 때, 메타데이터 서비스가 응답하지 않을 때, 예외가 만료됐을 때를 시험합니다. 각 상황에서 파이프라인이 어떤 상태와 메시지를 반환하는지 기록합니다. 정책을 Evaluate에서 Active로 바꾸기 전에는 기존 저장소에서 발생할 영향과 담당자가 처리할 수 있는 검토량을 먼저 측정합니다.
라이선스 분류 화면의 위험 범주나 자동 판정은 법률 자문을 대신하지 않습니다. GitHub 문서도 라이선스 위험 분류가 정보 제공 목적이라고 설명합니다. 실제 배포 프로젝트에서는 라이선스 원문, 사용·수정·배포 방식과 조직 정책을 함께 확인하고, 불명확한 사안은 권한 있는 담당자에게 검토를 요청해야 합니다.
- 직접·전이 의존성과 유입 경로를 모두 표시했는가
- SPDX 식별자의 근거 URL과 수집 시각을 남겼는가
- 정책 버전별 결과와 예외의 만료를 재현할 수 있는가
- 네트워크 실패와 미분류 상태를 허용으로 오인하지 않는가
- Python 처리, SQL 이력, Java 권한, CI 실행을 하나의 흐름으로 설명했는가
- 자동 결과와 사람의 정책·법률 판단 경계를 명확히 했는가
근거 자료 · GitHub Docs · Open source license compliance · GitHub Docs · Configuring license policies
8. 2주 프로젝트는 작은 데이터와 명확한 정책에서 시작한다
첫 주에는 가상 패키지 20개의 직접·전이 관계를 만들고 Python 정규화기와 정책 평가기를 구현합니다. SQL에 실행 이력을 저장하고 같은 입력을 두 번 검사했을 때 결과가 같은지 확인합니다. 두 번째 주에는 Java API와 간단한 풀 리퀘스트 모의 화면을 붙이고, Evaluate 모드에서 발생한 결과를 검토한 뒤 Active 전환 조건을 팀 문서로 작성합니다.
발표에서는 성공 화면보다 하나의 패키지가 어떤 경로로 발견되고 어떤 근거와 정책 버전으로 판정됐는지 보여 줍니다. 라이선스가 불명확한 항목, 서비스 장애, 만료된 예외를 어떻게 처리했는지도 시연합니다. 마지막에는 현재 구현이 지원하지 않는 생태계, 복합 SPDX 표현, 법률 판단의 한계를 적습니다.
이 프로젝트를 완성하면 오픈소스를 피하는 방법이 아니라 더 투명하게 사용하는 방법을 배우게 됩니다. 라이브러리를 빠르게 가져오는 능력과 그 구성요소를 설명하고 관리하는 능력이 함께 있을 때, AI가 코드와 패키지를 더 많이 제안하는 개발 환경에서도 프로젝트의 출처와 책임을 잃지 않을 수 있습니다.
학생이 이 이슈에서 확인할 것
- 직접 의존성과 전이 의존성의 경로를 설명할 수 있나요?
- 취약점 검사와 라이선스 정책 검사의 질문을 구분했나요?
- Evaluate와 Active 모드를 단계적으로 적용하는 이유를 설명할 수 있나요?
- 정책 버전, 판정 근거, 기간이 있는 예외를 재현 가능하게 기록했나요?
- AI 추천과 자동 판정을 사람의 정책·법률 판단과 구분했나요?
가상 패키지 20개의 직접·전이 의존성 데이터로 교육용 라이선스 정책 검사기를 만드세요. Python 평가기, SQL 감사 이력, Java 조회·예외 신청 API와 CI 모의 흐름을 연결하고, Evaluate에서 Active로 전환할 조건과 자동 판단의 한계를 보고서로 작성하세요.
관심 기술을 대학의 프로젝트로 연결하세요.
전공의 학습 흐름을 이해하고 학생이 직접 만든 결과를 확인한 뒤, 자신에게 맞는 입학 계획을 세워 보세요.