본문 바로가기

Linux Kernel

[Linux Kernel] 리눅스 커널 개발 가이드: Introduction

반응형
 

A guide to the Kernel Development Process — The Linux Kernel  documentation

© Copyright The kernel development community.

www.kernel.org


Introduction


이 문서는 커널 개발 프로세스와 개발자나, 고용주들이 개발에 참여하면서 겪는 좌절에 대해 다룬다. 커널 코드가 “mainline”에 머지되어야 할 이유는 많다. 코드가 mainline에 머지되어야 사용자들이 편하게 사용할 수 있고, 기여한 코드가 커뮤니티로부터 유지보수 받고, 커널 개발의 방향에 영향을 줄 수 있다. 리눅스 커널에 기여된 코드는 반드시 GPL 호환 라이선스여야 한다.

1.1 Executive summary (링크는 번역 후 추가 예정)


How the development process works에서는 개발 프로세스, 커널 릴리즈 주기, 그리고 머지 윈도우에 대해 다룬다. 또한 패치 개발, 리뷰, 머지 사이클에 대해서도 다룬다. 또한 툴과 메일링 리스트에 관한 내용도 있다. 커널 개발을 시작하고 싶은 개발자들은 연습 삼아 버그 하나를 추적해서 고치는 것을 권장한다.

Early-stage planning에서는 코드를 짜기 전에 초기에 어떻게 커뮤니티와 함께 계획을 세울지에 대해 다룬다.

Getting the code right은 개발 중에 하기 쉬운 실수들를 다룬다. 또한 패치를 작성할 때 유의할 점과 커널 패치를 올바르게 작성했는지 확인하는 툴도 다룬다.

Posting Patches에서는 어떻게 패치를 보내고 리뷰를 받는지를 다룬다. 제대로 기여를 하려면 패치는 적절한 설명이 포함되고, 적절한 포맷으로, 적절한 메일링 리스트에 보내야 한다. 이 파트에선 당신이 작성한 코드가 진지하게 받아들여지는 방법에 대해 논한다.

Followthrough은 패치를 보낸 후의 과정을 다룬다. 리뷰어와 협업하는 것은 개발 프로세스에서 매우 중요한 부분이다. 이 단계에서 생길만한 문제를 피하는 법을 다룬다. 패치를 보내는 개발자들은 패치를 보낸게 개발의 끝이라고 생각해선 안된다.

Advanced Topics는 몇가지 심화 주제를 다룬다. git으로 패치를 관리하고, 다른 사람이 보낸 패치를 리뷰하는 방법을 다룬다.

For more information은 이 문서를 마무리하고, 커널 개발을 참고할만한 다른 문서들을 소개한다.


1.2 What this document is about

리눅스 커널은 약 2,600만 라인의 코드로 구성되었고, 매 릴리즈마다 수천명의 개발자가 기여한다. 리눅스는 세상에서 가장 규모가 크고 활동적인 프로젝트이다. 리눅스는 1991년에 작게 시작했지만 현재는 데스크탑, 스마트폰, 슈퍼컴퓨터 할 것 없이 탑재가 되는 최고의 운영체제가 되었다. 리눅스는 견고하고, 효율적이며 확장성있는 시스템이다.

리눅스가 성장하면서 수많은 개발자가 프로젝트에 참여하게 되었고, 하드웨어 제조사들은 리눅스가 자신의 제품을 지원하길 원했다. 리눅스를 사용하는 임베디드 시스템 제조사도 리눅스가 제품을 만들기 위해 적합한 솔루션이 되기를 원한다. 따라서 이런 제조사와 배포판을 만드는 사람들은 리눅스가 더 나아지는 데에 기여할 것이다.

리눅스의 가장 큰 장점 중 하나는 리눅스가 개발자에게 열려있다는 점이다. 누구든지 실력만 있다면 리눅스를 개선하고, 리눅스의 개발 방향에 영향을 줄 수 있다. 리눅스와 달리 상업적인 제품들(예를 들어 윈도우)은 이런 개방성이 없다. 물론 커널이 다른 자유 소프트웨어 프로젝트보다 더 열려있긴 하다. 리눅스의 전형적인 3개월 주기 개발 사이클은 100개 이상의 회사에서 일하는 (또는 회사에 소속되지 않은 ) 1000명 이상의 개발자들이 참여한다.

리눅스 커널 개발 커뮤니티와 협업하는 것은 그렇게 특별하게 어려운 건 아니다. 하지만 제대로 커뮤니티가 일하는 방식을 이해하지 못하면 어려움을 겪을 수 있다. 커널 커뮤니티는 일하는 방식에 대해 여러가지 시행착오를 겪으며 발전했다. 그리고 마침내 매일 수천줄의 코드가 바뀌면서도 높은 품질을 유지하여 순조롭게 개발이 진행되고 있다.

리눅스 커널의 개발 프로세스는 새로 참여하는 개발자한테 강압적이고 이상해보일 수 있지만, 이러한 개발 프로세스에는 분명한 이유와 시행착오가 녹아있다. 커널 커뮤니티의 방식을 이해하지 못하는 개발자는 좌절을 하게 될 것이다. 커널 커뮤니티는 개발 프로세스를 지키지 않는 사람들에게 투자할 시간이 없다.

이 문서를 읽는 당신은 이런 좌절을 피했으면 한다. 이 문서는 다양한 주제를 다루고 있지만, 이걸 읽고 나면 빠른 시간 안에 제 값을 할 것이다.  리눅스는 커널을 더 좋게 만들어줄 개발자가 항상 필요하다. 이 문서는 당신과 당신의 동료들이 이 커뮤니티에 참여하는 것을 도와줄 것이다.

1.3 Credits

이 문서는 Jonathan Corbet (corbet@lwn.net)이 작성했다. 그리고 다음의 사람들이 조언을 해주었다: Johannes Berg, James Berry, Alex Chiang, Roland Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh, Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and Jochen Voß.

이 작업은 Linux Foundation이 후원해주었다. 특별히 이 문서의 가치를 알고 지원해준 Amanda McPherson에게 감사를 표한다.

1.4 The importance of getting code into the mainline

일부 개발자와 회사는 커널 커뮤니티와의 협업 방식을 익히고, 코드를 mainline에 기여하느라 고생할 필요가 있는지 궁금해할 것이다. (“mainline“ Linus Torvalds가 관리하며 리눅스 배포판의 기반이 된다.) 짧게 보면 코드를 mainline에 기여하는게 불필요한 시간 낭비라고 생각할 수 있다. 하지만 mainline와 별도로 개별적으로 코드를 관리하는 것(out-of-tree)은 단기적으로는 효율적인 것 같지만 장기적인 관점에서는 손해이다.

- mainline에 머지된 코드는, 배포판의 버전이 올라가면서 자동으로 모든 리눅스 사용자에게 적용된다.
- 커널 개발자들은 사용자 공간에 대해 안정적인 API를 제공하려고 노력하는 반면, 커널 내부에서 사용하는 API는 주기적으로 바뀐다. 커널 내에 안정적인 API를 제공하지 않는 것은 충분한 심사숙고 후에 결정된 것이다. 그렇게 함으로써 API의 설계에 문제가 있을 때 언제든지 문제를 고치고, 코드의 품질을 관리할 수 있다. 하지만 이러한 특징은 out-of-tree 코드가 이런 API 변경을 끊임없이 따라가야 한다는 것을 의미한다. out-of-tree 코드를 관리하는 것은 그저 그 코드를 유지하는 것만으로도 수많은 작업을 해야한다.

하지만 mainline에 존재하는 코드는 간단한 규칙으로 이 문제를 해결할 수 있다. 바로 API를 바꾸는 개발자가 바뀐 API로 인해 문제가 생기는 (API를 호출하는) 코드를 모두 고치게 하는 것이다. 이렇게 함으로써 mainline에 머지된 코드는 적은 비용으로 관리가 된다.
- 그리고 그걸 넘어서, mainline에 있는 코드는 다른 개발자들이 그걸 보고 개선할 수 있다. 당신의 제품의 사용자가 코드까지 개선한다면 제품에 놀라운 효과가 생길 것이다.
- 커널 코드는 mainline에 머지되기 전과 후에 리뷰를 거친다. 아무리 개발자가 코드를 잘 짜도 리뷰 과정에서 코드를 개선할 방법을 찾게 된다. 그리고 종종 리뷰 과정에서 보안 관련 문제를 찾기도 한다. 특히 단절된 환경에서 개발되었던 코드에서 이런 보안 문제가 많이 발견된다. 이런 단절된 코드는 외부의 다른 개발자들이 보면서 개선된다. out-of-tree 코드는 이러한 개선 과정을 거치지 않기 때문에 저품질 코드이다.

- 코드가 따로 관리되면 제 3자가 유사한 기능을 서로 다른 방식으로 구현하는 일이 항상 생긴다. 그러면 시간이 지날수록 mainline에 머지하는 것이 불가능할 정도로 어려워진다. 결국에는 (1) 비표준 기능을 별도의 트리에서 영원히 관리하거나 (2) 코드를 포기하고 사용자를 mainline 트리 버전으로 사용자를 마이그레이션 해야하는 상황이 발생하게 된다.

- 코드를 기여하는 것은, 리눅스의 개발 프로세스 자체가 돌아가게 하는 원초적인 행동이다. 코드를 기여함으로써 커널에 새로운 기능을 추가하고, 다른 개발자들이 이를 참고할 수 있게 된다. 만약 당신이 리눅스 커널의 코드를 수정했다면 리눅스가 계속 성공하길 빌 것이다. 그러려면 코드를 기여해야 한다.

이 모든 사항은 모든 out-of-tree 커널 코드에 적용된다.  (바이너리 형태로 배포하든, 사유적인 형태로 배포하든) 하지만 바이너리 형태로 커널 코드를 배포할 때 고려할 사항이 있다:
-  사유적인 커널 모듈의 배포는 법적으로 안전하다고 할 수 없다. 몇몇 저작권자들은 바이너리 형태로 모듈을 배포하는 건 (모듈은 커널에 직접적으로 포함되지 않기 때문에) 괜찮다고 생각하지만, 사실상 GPL 라이선스 위반이다. 하지만 이 문서를 작성하는 저자가 변호사가 아닌 점을 유의하자. 나는 법적인 조언을 해줄 수는 없다. 결국에 진짜 법적으로 어떻게 처리될지는 법정에 가봐야 안다. 하지만 이런 법적인 문제의 가능성을 열어두는 건 좋지 않다.
- 또한 바이너리 형태로만 배포하는 배포자 스스로도 힘들다. 배포자들은 모든 배포판의 모든 버전에 대해 모듈을 지원해야 하는데, 같은 모듈을 수십번 빌드하는 것도 쉽지 않고, 사용자들도 커널 버전을 업그레이드 할 때마다 모듈을 따로 업그레이드 해야한다.
- 위에서 언급한 코드 리뷰에 관한 모든 것은 비공개 소스 코드에는 두배로 적용된다. 애초에 소스코드가 접근이 불가능하므로, 리뷰를 받을 수 없고, 커뮤니티는 문제가 있을 것이라고 의심할 수 밖에 없다.  

특히, 임베디드 시스템 개발자들은 더더욱 이 문서에서 권장하는 사항들을 무시하고 싶은 욕구가 들 것이다. 왜냐하면 임베디드 시스템은 제품 안에 모든 것이 들어있고, 고정된 커널 버전만을 사용하고, 배포 후에는 유지보수할 필요가 없기 때문이다.

하지만 이러한 주장은 코드 리뷰와 사용자가 주는 가치를 놓치게 된다. 또한, 이러한 임베디드 제품들도 한정된 수명이 존재하고, 그 다음에는 새로운 버전을 만들어야 한다. 반면에 코드가 mainline에 머지된 제조사들의 코드는 잘 관리되므로 더 빠르게 제품을 만들 수 있다.

1.5 Licensing

리눅스 커널에 코드는 몇가지 라이선스하에 기여된다. 코드의 라이선스는 반드시 리눅스의 라이선스인 GPLv2와 호환되어야 한다. 호환되지 않는 라이선스의 코드는 커널이 받아들일 수 없다.

커널에 기여한다고 해서 저작권을 양도할 필요는 없다. mainline에 머지된 각각의 코드는 기여한 사람의 것이다. 따라서 커널은 수천명의 저작권 소유자가 존재한다.

이렇게 저작권 소유를 서로 나눠서 함으로써, 커널 전체의 라이선스를 누군가 바꾸는 것이 거의 불가능하다. 물론 모두의 동의를 받고 라이선스를 바꾼다던지 동의하지 않는 사람의 코드를 지워버릴 수도 있겠지만… 힘들 것이다. 그리고 이런 이유로 당분간의 미래에 GPLv3으로 라이선스를 이전하는 일도 없을 것이다.

커널에 기여되는 코드는 법적으로 자유 소프트웨어가 되는 것을 피할 수 없다. 이러한 이유로, 익명의 누군가가 보내는 코드는 기여가 될 수 없는데, 모든 기여자들은 자신의 코드에 “서명”을 해서 자신이 보낸 코드가 GPL 하에 배포될 수 있다는 것을 명시해야 한다. 자유 소프트웨어로 라이선스되지 않거나, 저작권 관련 문제를 일으킬 수 있는 코드(예를 들어 리버스 엔지니어링으로 얻은 코드)는 기여가 불가능하다.

저작권 관련 문제에 관한 질문은 리눅스 개발 메일링 리스트에 종종 올라온다. 그러면 사람들이 답변은 해주겠지만 질문자는 답변을 하는 사람들이 변호사가 아니라는 점을 명심해야 한다. 따라서 법적인 조언을 해줄 수는 없다. 그러므로 리눅스 소스 코드와 관련된 법적인 질문이 있다면 메일링 리스트가 아니라 변호사를 찾아가자.