AI Research Engineer이지만 소프트웨어 프로젝트에 있어 소프트웨어 엔지니어링 학문을 굉장히 중요하게 생각하고 팀 컬쳐, 팀 빌딩, 팀 관리에서 중요한 학문이라고 생각하여 제가 읽은 책을 정리하였습니다.
소프트웨어 엔지니어링이란?
프로그래밍과 소프트웨어 엔지니어링의 가장 큰 차이는
- 시간(time)
- 규모∙확장(scale)
- 실전에서의 트레이드오프(trade-offs at play)
라고 합니다.
소프트웨어 엔지니어는 시간의 흐름과 언젠가 변경(change)될 가능성에 더 신경써야 한다고 합니다.
소프트웨어 엔지니어링 조직은 만들어낼 소프트웨어 자체뿐 아니라 제작하는 조직까지 양 측면 모두에서의 확장과 효율에 더 집중해야 합니다.
comments: 좋은 소프트웨어 개발을 위해서는 단순히 개발에서의 기술만 신경 쓸 것이 아니라 전반적인 조건들을 이해하고 집중해야한다고 생각합니다.
구글에서는 소프트웨어 엔지니어링을 정의할 때
‘흐르는 시간 위에서 순간순간의 프로그래밍을 모두 합산한 것이다’ 라고 얘기합니다.
단명하는 시스템 ‘그저’ 프로그래밍 문제와 다를 게 없습니다. 하지만 수명이 길어질수록 변경이라는 요소가 점점 중요해집니다.
소프트웨어 엔지니어링은 ‘소프트웨어의 지속가능성(sustainability)’ 핵심입니다.
소프트웨어 엔지니어링에서의 ‘규모’ 관점.
소프트웨어 엔지니어링은 팀 업무입니다.
초기에는 소프트웨어 엔지니어링을 ‘여러 버전에 프로그램을 여러사람이 참여해 개발하는 것(The multiperson development of multiversion programs)’이라고 정의하곤 합니다.
소프트웨어 엔지니어링의 복잡성에 영향을 미치는 것들
- 소프트웨어 프로젝트의 팀 조직
- 프로젝트 구성
- 정책(Policy)
- 관례(Practice)
소프트웨 엔지니어링에서는
- 주기적으로 여러 선택지 사이의 트레이드오프를 평가해야 합니다.
- 또한 불완전한 지표에 기대어 결과에 커다란 영향을 주는 선택을 해야합니다.
- 소프트웨어 엔지니어 혹은 리더는 지속 가능성을 잃지 않으면서 조직, 제품, 개발 워크플로의 규모를 확장하는 비용을 관리해야 합니다.
이 책을 ‘규모가 커질수록 효과도 커지는 엔지니어링 생태계에 관한 보고서’라고 생각하라고 합니다.
1.1 시간과 변경
초기 프로그래밍을 배우는 과정에서 작성한 코드는 짧은 시간(수일, 수시간)정도 일 것이고 작성된 코드를 리팩터링할 수 없을 것이고 오랜시간의 걸친 유지보수도 어렵다고 합니다. 또한 다시 빌드하는 일도 드물 것입니다.
협업에서도 짧은 생명주기를 다루는 개발자도 찾을 수 있고 의도와 다르게 처음부터 새로 작성하는 비율도 상대적으로 높습니다.
줄곧 초기 스타트업에서만 일해왔다면 10년차 개발자라도 소프트웨어를 1~2년 이상 유지보수 경험이 전무할 수 있는 것이 현실입니다.
소프트웨어 프로젝트의 ‘기대 수명(expected life span)’과 업그레이드 중요도의 관계를 보여줍니다.
소프트웨어 대규모 업그레이드는 엄청난 비용이 발생합니다. 다시 하기 싫을 정도의 고통을 불러일으킬 수도 있습니다. 업그레이드가 좋을지 기회비용을 따져봐야 합니다.
1.1.1 하이럼의 법칙
하이럼의 법칙(Hyrum’s Law): API 사용자가 충분이 많다면 API 명세에 적힌 내용은 중요하지 않습니다. 시스템에서 눈에 보이는 모든 행위(동작)를 누군가는 이용하게 될 것이기 때문입니다.
소프트웨어 유지보수에 하이럼의 법칙이 적용된다고 해서 계획 세우기를 등한시하거나 소프트웨어를 더 잘 이해하려는 노력을 포기하면 안된다고 합니다.
‘하이럼의 법칙’은 최선의 의도, 최고의 엔지니어, 꼼꼼한 코드 리뷰가 뒷받침되더라도 공표한 계약(명세)이나 모범 사례를 완벽하게 구현해냈다고 단정할 수 없다는 현실을 표현한 말이라고 합니다.
comments: 하이럼의 법칙은 개념적으로는 존재하지만 실제 개발에서는 그 법칙을 의존하면 안되고 개발 계획부터 탄탄하게 가져가야한다는 것은 그대로 인 것 같습니다.
1.1.2 사례: 해시 순서
해시 반복 순서(hash iteration ordering) 예에서의 문제점
- 해시 플러딩(hash flooding)공격 때문에 해시 반복 순서가 비결정적이어야 할 필요가 더욱 커졌다고 합니다.
- 개선된 해시 알고리즘과 해시 컨테이너 연구로 얻은 효율 개선 효과를 보려면 해시 반복 순서에 변화를 줘야 합니다.
- 하이럼의 법칙에 따라 (할 수 있다면) 해시 테이블의 순회 순서에 의존하는 프로그램을 작성하는 프로그래머가 나타날 것입니다.
해시 반복 순서를 통한 서비스 거부 공격(Denial-of-Service DoS) 공격하는 경우가 발생한 적이 있습니다.
해시 반복 순서는 ‘동작한다(it works)와 ‘옳다(it is correct)를 보여주는 아주 기초적인 예입니다. 해시 컨테이너의 반속 순서에 의존을 하더라도 프로그램 수명 주기가 짧다면 문제가 되지 않지만 장기적인 관점을 바라보는 소프트웨어 엔지니어링 측면에서는 이런 의존성이 위험하다고 합니다. 효율 개선, 보안 강화, 혹은 앞으로의 변화에 대응하기 위한 미래 지향적 데이터 구조로의 개선 등 여러가지를 고려하여 잘 저울질을 해야 한다고 합니다.
코드 자체를 수명에 대한 요구사항이 다양한 제품으로 생각해보며 프로그래밍 스타일은 두가지로 분류 할 수 있습니다.
- 이용하는 API의 명세에 명시되지 않은, 즉 언제든 변할 수 있는 기능을 사요하는 코드는 ‘임시방편적(hacky)’혹은 ‘기발한(clever)코드입니다.
- 반대로 모범 사례를 따르고 미래에 대비한 코드는 ‘클린하고 ‘유지보수 가능한’ 코드입니다.
1.1.3 ‘변하지 않기’를 목표로 하지 않는 이유
대부분의 프로젝트는 세월이 충분히 흐르면 기반 환경을 모두 교체해야 합니다. 물론 안정성을 목표로 둔 경우 C언어는 상당히 안정적이기 때문에 계속적으로 사용할 수 도 있습니다.
하지만 대부분의 프로젝트는 시간의 흐름에 따라 변화하고 보안 문제는 프로세서, 네트워크 라이브러리, 애플리케이션 할 것없이 모든 기술 제품에서 나타납니다. 그래서 모든 프로젝트에서 보안 취약점이 발생할 수 있습니다. 아무것도 변하지 않으리라 가정하여 하트블리드(Heartbleed) 패치를 적용하지 않거나 멜트다운(Meltdown)과 스펙터(Spectre)같은 추측 실행(speculative execution)문제를 완화해두지 않으면 위험천만한 도박에 뛰어드는 꼴입니다.
구글은 데이터센터를 비용 효율적인 장비들로 꾸리길 원합니다(특히 CPU). 연결 리스트와 이진 검색 트리는 여전히 잘 동작하지만 CPU 클록과 메모리 지연시간의 격차가 점점 벌어지면서 ‘효율적인’코드의 모습이 변하고 있습니다.
comments: 결론적으로 프로젝트에서는 장기적인 변화에 대응이 가능해야 한다는 것입니다. 변경하는 것 자체가 본질적으로는 좋지 않지만 변경이 없는 경우가 나타나기는 어렵기 때문에 미래를 위해서 계획하고 투자하고 복구 등 정확한 대응방법과 비용에 대해서도 알고 있어야 합니다. 반복적인 연습으로 효율과 안정성을 높일 수 있어야 하겠습니다.
References:
- 책: 구글 엔지니어는 이렇게 일한다. link