레슨 1: 소프트웨어 공학이란 무엇인가
레슨 1: 소프트웨어 공학이란 무엇인가¶
이전: 개요 | 다음: 소프트웨어 개발 생명주기
소프트웨어 공학(Software Engineering)은 소프트웨어의 설계, 개발, 테스트, 배포, 유지보수에 공학적 원리를 체계적으로 적용하는 학문입니다. 단순히 코드를 작성하는 것을 넘어, 대규모로 신뢰할 수 있고 효율적이며 유지보수 가능한 소프트웨어를 생산하는 것을 목표로 하는 지식 체계, 프로세스 집합, 전문 실무입니다.
난이도: ⭐⭐
선수 학습: - 임의의 언어로 된 프로그래밍 경험 - 소프트웨어 프로젝트의 기본 개념에 대한 이해
학습 목표: - 소프트웨어 공학을 정의하고 프로그래밍 및 컴퓨터 과학과 구별하기 - 소프트웨어 위기(Software Crisis)의 기원과 의의 설명하기 - 소프트웨어 공학을 어렵게 만드는 소프트웨어의 본질적 특성 설명하기 - 소프트웨어 시스템의 주요 범주 파악하기 - 소프트웨어 공학 실무를 이끄는 핵심 원리 나열하기 - 소프트웨어 공학 팀에서 발견되는 전문 역할 인식하기
1. 정의와 범위¶
소프트웨어 공학이란 무엇인가?¶
"소프트웨어 공학"이라는 용어는 1968년 독일 가르미슈(Garmisch)에서 열린 NATO 과학위원회 회의에서 처음 공개적으로 사용되었으며, 소프트웨어 개발이 다른 공학 분야와 동일한 수준의 엄격함과 규율을 갖추어야 한다는 의미를 담아 의도적으로 도발적인 표현으로 선택되었습니다.
수십 년에 걸쳐 여러 권위 있는 정의가 제시되었습니다:
IEEE (전기전자공학자협회, Institute of Electrical and Electronics Engineers):
"소프트웨어의 개발, 운용, 유지보수에 대한 체계적이고 규율 있으며 정량화 가능한 접근 방식의 적용; 즉, 소프트웨어에 공학을 적용하는 것." — IEEE Standard 610.12-1990
Sommerville:
"소프트웨어 공학은 초기 시스템 명세 단계부터 사용 후 시스템 유지보수에 이르기까지 소프트웨어 생산의 모든 측면을 다루는 공학적 학문이다."
Pressman:
"소프트웨어 공학은 전문가들이 고품질 컴퓨터 소프트웨어를 구축할 수 있도록 하는 프로세스, 방법(실무)의 집합, 도구 배열을 포괄한다."
이러한 정의들이 공통적으로 강조하는 것은 생산의 모든 측면입니다 — 코딩뿐만 아니라 명세, 설계, 테스트, 유지보수, 그리고 이를 둘러싼 조직적·관리적 관심사들입니다.
소프트웨어 공학 대 프로그래밍¶
프로그래밍은 소프트웨어 공학의 필수적인 구성 요소이지만, 두 가지는 동의어가 아닙니다.
| 차원 | 프로그래밍 | 소프트웨어 공학 |
|---|---|---|
| 범위 | 문제를 해결하는 코드 작성 | 소프트웨어 생산의 전체 생명주기 |
| 시간 지평 | 시간~일 단위 | 월~년 단위 |
| 팀 규모 | 주로 개인 | 대개 5~500명 이상 |
| 주요 관심사 | 작동하게 만들기 | 유지보수 가능하고 신뢰할 수 있게, 일정 내에 작동하게 만들기 |
| 주요 산출물 | 소스 코드 | 코드, 명세, 설계, 테스트, 계획, 문서 |
| 핵심 기술 | 언어 숙련도, 알고리즘 | 프로세스, 커뮤니케이션, 추정, 위험 관리 |
| 성공 지표 | 코드가 올바르게 실행됨 | 요구한 품질로 시간과 예산 내에 프로젝트 납품 |
유용한 비유: 프로그래밍은 소프트웨어 공학에서의 벽돌 쌓기와 같고, 소프트웨어 공학은 토목 공학과 같습니다. 벽돌 쌓기는 필수적인 기술이지만, 토목 공학은 구조 분석, 프로젝트 관리, 재료 과학, 규제 준수, 장기 유지보수 계획도 포함합니다.
소프트웨어 공학 대 컴퓨터 과학¶
컴퓨터 과학(Computer Science)과 소프트웨어 공학은 관련이 있지만 서로 다른 학문입니다:
- 컴퓨터 과학은 주로 계산의 이론에 관심을 가집니다: 알고리즘, 자료구조, 형식 언어, 복잡도 이론, 논리, 컴퓨팅의 수학적 기초.
- 소프트웨어 공학은 주로 소프트웨어 시스템 생산의 실무에 관심을 가집니다: 개발 프로세스를 조직하는 방법, 팀 관리, 품질 보증, 사용자 요구를 충족하는 제품 납품.
실제로 소프트웨어 엔지니어는 컴퓨터 과학 이론을 활용하지만, 궁극적으로는 소프트웨어가 신뢰할 수 있게 구축되고 납품되는지에 따라 평가받습니다.
2. 소프트웨어 위기(The Software Crisis)¶
역사적 배경: 1968 NATO 회의¶
1960년대 후반에 이르러 소프트웨어 산업이 위기에 처했음이 분명해졌습니다. 대형 소프트웨어 프로젝트들은 다음과 같은 문제를 반복적으로 겪었습니다:
- 예산 초과(Over budget): 비용이 추정치를 훨씬 초과
- 일정 지연(Late): 일정이 수개월 또는 수년씩 늦어짐
- 신뢰 불가(Unreliable): 납품된 시스템에 심각한 결함 포함
- 유지보수 불가(Unmaintainable): 코드가 너무 복잡하여 새 기능 추가가 극도로 어려움
- 취소(Cancelled): 상당한 자원을 소비한 후 완전히 폐기된 프로젝트 다수
그 시대의 대표적인 사례로는 IBM OS/360 운영체제 프로젝트가 있으며, Fred Brooks가 1975년 저서 The Mythical Man-Month에서 이를 상세히 기록했습니다. OS/360은 수천 명의 프로그래머를 고용했음에도 불구하고 막대한 예산 초과와 일정 지연이 발생했습니다.
1968 NATO 회의는 이러한 상황을 묘사하기 위해 "소프트웨어 위기"라는 용어를 만들어냈습니다. Edsger Dijkstra, Tony Hoare 등은 소프트웨어 개발이 형식적 방법, 체계적 프로세스, 측정 가능한 결과물을 갖춘 진정한 공학 학문이 되어야 한다고 주장했습니다.
지속되는 도전¶
수십 년이 지난 지금도 많은 원래 문제들이 여전히 존재합니다. Standish Group의 CHAOS 보고서는 1994년부터 소프트웨어 프로젝트 결과를 추적해왔습니다:
CHAOS Report (approximate historical averages):
+------------------+------------------+
| Outcome | % of Projects |
+------------------+------------------+
| Successful | ~30% |
| (on time, budget,| |
| full features) | |
+------------------+------------------+
| Challenged | ~50% |
| (late, over | |
| budget, reduced | |
| features) | |
+------------------+------------------+
| Failed | ~20% |
| (cancelled or | |
| never used) | |
+------------------+------------------+
소프트웨어 공학이라는 학문 분야는 바로 이러한 통계를 개선하기 위해 존재합니다.
3. 소프트웨어가 어려운 이유: Brooks의 네 가지 특성¶
No Silver Bullet(1986)에서 Fred Brooks는 소프트웨어를 본질적으로 공학하기 어렵게 만드는 네 가지 본질적 특성을 제시하며, 소프트웨어 생산성을 극적으로 향상시킬 단일한 기법은 존재하지 않는다고 주장했습니다.
3.1 복잡성(Complexity)¶
소프트웨어 시스템은 비슷한 크기의 다른 어떤 인공물보다 더 많은 상태를 포함합니다. 300개의 불리언 변수를 가진 단순한 프로그램조차 $2^{300}$가지 가능한 상태를 가지는데, 이는 관측 가능한 우주의 원자 수보다 훨씬 많습니다. 이 복잡성은 우연적인 것이 아닌 본질적인 것으로, 소프트웨어가 해결해야 하는 실제 세계 문제의 복잡성을 반영합니다.
이 본질적 복잡성은 다음을 의미합니다: - 가능한 모든 상태를 완전히 테스트할 수 없음 - 시스템의 한 부분에서의 변경이 다른 곳에 예상치 못한 영향을 미칠 수 있음 - 대규모 코드베이스를 이해하는 데 상당한 시간과 노력이 필요함
3.2 순응성(Conformity)¶
소프트웨어가 의존할 수 있는 법칙이 있는 물리학과 달리, 소프트웨어는 인간의 임의적인 결정들 — 규제 요건, 비즈니스 규칙, 하드웨어 인터페이스, 레거시 API, 조직 관행 — 에 순응해야 합니다. 이러한 제약들은 종종 일관성이 없고, 문서화가 미흡하며, 변경될 수 있습니다.
소프트웨어는 자연에 호소할 수 없습니다. 아무리 비논리적이더라도 세상이 요구하는 것에 순응해야 합니다.
3.3 변경 가능성(Changeability)¶
소프트웨어는 지속적으로 변경될 것으로 예상됩니다. 소프트웨어가 "소프트"하다(하드웨어에 비해 변경이 쉽다)고 인식되기 때문에, 이해관계자들은 납품 후에도 수정을 요구하는 경우가 많습니다. 성공적인 모든 소프트웨어 시스템은 변경 압력을 받으며, 모든 변경은 결함을 도입할 위험을 수반합니다.
이는 물리적 공학 산출물과 대조됩니다: 명세에 따라 건설된 다리는 다음 달에 차선을 추가하기 위해 재설계를 요구하지 않습니다.
3.4 비가시성(Invisibility)¶
소프트웨어는 물리적 형태가 없습니다. 건물(구조적 문제를 눈으로 볼 수 있는)이나 기계 장치(허용 오차를 측정할 수 있는)와 달리, 소프트웨어는 보이지 않습니다. 다이어그램과 문서는 불완전한 표현입니다. 이로 인해 시스템의 구조를 시각화하고, 아키텍처를 소통하며, 런타임에서 문제가 나타나기 전에 발견하기 어렵습니다.
4. 소프트웨어의 유형¶
소프트웨어 공학 방법론은 구축하는 소프트웨어의 유형에 맞게 조정되어야 합니다. 주요 범주는 다음과 같습니다:
4.1 시스템 소프트웨어(Systems Software)¶
다른 소프트웨어에 서비스를 제공하는 인프라 수준의 소프트웨어. 예시: 운영체제, 컴파일러, 장치 드라이버, 데이터베이스 엔진, 런타임 환경.
특성: 성능 중심적, 하드웨어와 밀접, 긴 수명, 높은 신뢰성 요건.
4.2 응용 소프트웨어(Application Software)¶
최종 사용자를 위해 직접 작업을 수행하는 소프트웨어. 예시: 워드 프로세서, 스프레드시트, 회계 시스템, ERP 시스템.
특성: 대규모 사용자 기반, 진화하는 요구사항, 사용성(Usability)이 주요 관심사.
4.3 임베디드 소프트웨어(Embedded Software)¶
하드웨어 장치를 제어하는 소프트웨어. 예시: 의료 기기의 펌웨어, 자동차 제어 유닛, 산업 기계, 소비자 전자 제품.
특성: 엄격한 자원 제약(메모리, CPU), 실시간 요건, 안전 중심, 배포 후 업데이트 어려움.
4.4 웹 소프트웨어(Web Software)¶
웹 브라우저를 통해 제공되고 접근되는 소프트웨어. 예시: 전자상거래 플랫폼, 소셜 네트워크, 웹 API, SaaS 애플리케이션.
특성: 빠른 변경 주기, 이기종 클라이언트 환경, 네트워크 및 보안 관심사, 확장성 요건.
4.5 모바일 소프트웨어(Mobile Software)¶
스마트폰 및 태블릿용 애플리케이션. 예시: iOS/Android 앱, 크로스 플랫폼 모바일 앱.
특성: 제한된 자원, 간헐적 연결, 플랫폼 단편화, 잦은 OS 업데이트.
4.6 AI 및 머신러닝 시스템(AI and Machine Learning Systems)¶
명시적으로 프로그래밍되지 않고 데이터로부터 행동을 학습하는 소프트웨어. 예시: 추천 엔진, 이미지 분류기, 언어 모델, 자율 시스템.
특성: 비결정론적 동작, 데이터 의존성, 모델 버전 관리, 설명 가능성(Explainability) 관심사, 다른 테스트 패러다임.
5. 소프트웨어 공학의 핵심 원리¶
수십 년간의 실무와 연구를 통해 특정 방법론에 관계없이 좋은 소프트웨어 공학을 이끄는 지속적인 원리들이 등장했습니다.
5.1 엄격성 및 형식성(Rigor and Formality)¶
소프트웨어는 충분한 엄격성 — 정확한 명세, 체계적인 테스트, 문서화된 설계 — 으로 개발되어야 합니다. 적절한 형식성 수준은 도메인에 따라 다릅니다: 안전 중심 시스템(항공, 의료 기기)은 형식적 수학적 검증이 필요하고, 스타트업 프로토타입은 기본 문서화만 필요할 수 있습니다.
5.2 관심사 분리(Separation of Concerns)¶
복잡한 시스템을 각각 서로 다른 관심사를 다루는 부분들로 분리합니다. 이 원리는 모든 수준에서 나타납니다: - 모듈 수준: 각 모듈은 단일하고 명확하게 정의된 책임을 가짐 - 아키텍처 수준: 표현, 비즈니스 로직, 데이터 계층을 분리 - 프로세스 수준: 요구사항을 설계에서, 설계를 구현에서 분리
관심사 분리는 인지적 부하를 줄이고 팀이 서로 다른 부분에서 동시에 작업할 수 있게 합니다.
5.3 모듈성(Modularity)¶
소프트웨어를 독립적으로 개발, 테스트, 교체 가능한 개별 모듈로 구성합니다. 잘 설계된 모듈은 다음을 가집니다: - 높은 응집도(High cohesion): 관련된 기능이 함께 그룹화됨 - 낮은 결합도(Low coupling): 모듈들이 서로에게 가능한 적게 의존
5.4 추상화(Abstraction)¶
필요한 것만 노출하고 구현 세부 사항을 숨깁니다. 추상화를 통해 엔지니어는 적절한 수준에서 작업할 수 있습니다 — 데이터베이스 드라이버를 사용하는 개발자는 디스크 블록 할당 알고리즘을 이해할 필요가 없습니다.
추상화 계층은 대규모 시스템에서 복잡성을 관리하는 데 근본적입니다.
5.5 변경 예측(Anticipation of Change)¶
소프트웨어는 변경될 것입니다. 좋은 소프트웨어 공학은 다음을 통해 변경을 위해 설계합니다: - 변화 가능성이 높은 소스를 파악하고 인터페이스 뒤에 격리 - 하드코딩된 상수와 매직 넘버 피하기 - 다른 사람이 이해하고 수정할 수 있는 명확하고 문서화된 코드 작성 - 확장성을 위한 데이터베이스와 API 설계
5.6 일반성(Generality)¶
실용적인 경우, 특수 케이스 해결책보다 일반적인 해결책을 선호합니다. 범용 정렬 함수는 특정 자료구조만 정렬하는 함수보다 더 가치 있습니다.
그러나 조기 일반화(Premature Generality)는 과도한 공학(Over-Engineering)으로 이어질 수 있습니다. 이 원리는 단순성과 균형을 이루어야 합니다.
5.7 점진성(Incrementality)¶
전체 시스템을 완성한 후 릴리스하려 하기보다 점진적으로 소프트웨어를 구축하고 납품합니다. 점진적 납품은: - 실제 사용자로부터 조기 피드백 제공 - 잘못된 것을 구축할 위험 감소 - 프로젝트가 "완료"되기 전에 가치를 납품할 수 있음
이 원리는 반복적 개발 모델과 현대 애자일 방법론 모두의 기반이 됩니다.
6. 소프트웨어 공학의 간략한 역사¶
Timeline of Software Engineering
1948-1960s Early programming
├─ Machine code → assembly → high-level languages (FORTRAN 1957, COBOL 1959)
├─ Programs written by mathematicians and scientists
└─ Software "crises" begin to appear as projects grow
1968 NATO Conference, Garmisch
├─ Term "software engineering" coined
├─ Software crisis recognized as a discipline-level problem
└─ Call for systematic, engineered approach
1970s Process models emerge
├─ Royce describes Waterfall model (1970)
├─ Structured programming (Dijkstra, Wirth)
├─ Jackson Structured Design, Yourdon-DeMarco SA/SD
└─ Unix developed at Bell Labs
1980s Maturation
├─ Boehm's Spiral model (1988)
├─ COCOMO estimation model
├─ SEI and CMM (Capability Maturity Model)
├─ IEEE software engineering standards
└─ Object-oriented design (Booch, Rumbaugh, Jacobson)
1990s Objects, patterns, and web
├─ UML standardized (1997)
├─ Design Patterns "Gang of Four" (1994)
├─ World Wide Web transforms software distribution
├─ Extreme Programming (XP) introduced (Beck, 1996)
└─ CMMI released (2000)
2001 Agile Manifesto
├─ Scrum, XP, Kanban gain widespread adoption
├─ Lightweight processes replace heavyweight ones
└─ Iterative, customer-centric development becomes mainstream
2010s DevOps and cloud
├─ DevOps movement formalizes dev-ops collaboration
├─ Continuous integration/continuous delivery (CI/CD)
├─ Microservices architecture
├─ Infrastructure as code
└─ Cloud platforms (AWS, GCP, Azure) change deployment model
2020s AI-assisted engineering
├─ Large language models assist with code generation
├─ AI/ML systems raise new engineering challenges
├─ Platform engineering and developer experience (DevEx)
└─ Software supply chain security as a discipline
7. 소프트웨어 공학의 전문 역할¶
현대 소프트웨어 공학 팀은 다양한 전문 역할을 포함합니다:
| 역할 | 주요 책임 |
|---|---|
| 소프트웨어 엔지니어/개발자(Software Engineer / Developer) | 코드 설계, 구현, 테스트 및 유지보수 |
| 소프트웨어 아키텍트(Software Architect) | 시스템 구조, 주요 기술 선택, 교차 관심사(Cross-Cutting Concerns) 정의 |
| 제품 관리자(Product Manager, PM) | 무엇을 구축할지 정의; 제품 로드맵 소유; 비즈니스 및 사용자 요구 대변 |
| 프로젝트 관리자(Project Manager) | 프로젝트 진행 계획, 일정 수립, 추적; 위험 및 자원 관리 |
| QA 엔지니어/테스트 엔지니어(QA Engineer / Test Engineer) | 테스트 설계 및 실행; 테스트 인프라 유지; 결함 보고 |
| DevOps/플랫폼 엔지니어(DevOps / Platform Engineer) | CI/CD 파이프라인, 인프라, 배포 시스템 구축 및 유지보수 |
| 사이트 신뢰성 엔지니어(Site Reliability Engineer, SRE) | 운영 환경에서 시스템 신뢰성과 가용성 보장; SLO 정의 |
| 기술 작가(Technical Writer) | 개발자와 최종 사용자를 위한 문서 작성 및 유지보수 |
| 비즈니스 분석가(Business Analyst) | 비즈니스 요구와 기술 구현 연결; 요구사항 작성 |
| UX 디자이너(UX Designer) | 사용자 인터페이스 및 사용자 경험 설계 |
| 보안 엔지니어(Security Engineer) | 보안 취약점 식별 및 완화; 보안 코딩 표준 정의 |
| 데이터 엔지니어(Data Engineer) | 데이터 파이프라인 및 인프라 구축; 데이터 품질 관리 |
소규모 조직에서는 한 사람이 여러 역할을 맡을 수 있습니다. 대규모 조직에서는 이러한 역할들이 더 명확하게 구분됩니다. 하나의 역할만 맡더라도 이러한 모든 역할을 이해하면 더 효과적인 협력자가 될 수 있습니다.
8. 요약¶
소프트웨어 공학은 소프트웨어 개발에 체계적이고 규율 있으며 정량화 가능한 접근 방식을 적용하는 것입니다. 1960년대 대형 소프트웨어 프로젝트들이 시간, 예산, 품질 면에서 반복적으로 실패했던 "소프트웨어 위기"에 대응하여 등장했습니다.
핵심 요점: - 소프트웨어 공학은 프로그래밍보다 넓습니다: 전체 생명주기와 모든 조직적 관심사를 포괄합니다 - 소프트웨어는 복잡성, 순응성, 변경 가능성, 비가시성(Brooks)으로 인해 본질적으로 어렵습니다 - 핵심 원리들 — 관심사 분리, 모듈성, 추상화, 점진성 — 은 모든 방법론에 적용됩니다 - 소프트웨어의 유형(임베디드, 웹, AI)에 따라 다른 공학적 접근이 필요합니다 - 이 분야는 1960년대부터 오늘날의 AI 지원 개발 시대까지 지속적으로 진화해왔습니다
연습 문제¶
연습 1: 소프트웨어 공학과 토목 공학을 비교·대조하세요. 세 가지 유사점과 세 가지 근본적인 차이점을 파악하세요. Brooks의 네 가지 특성 중 토목 공학에 직접적인 유사점이 없는 것은 무엇인가요?
연습 2: 당신은 이메일 정렬을 자동화하는 개인 스크립트를 유지보수하는 단독 개발자입니다. 이 규모에서도 적용해야 할 소프트웨어 공학 원리와 덜 중요한 원리를 파악하세요. 이유를 설명하세요.
연습 3: 잘 알려진 소프트웨어 프로젝트 실패 사례(예시: 2013년 HealthCare.gov 출시, Ariane 5 Flight 501, 2012년 Knight Capital 사건)를 하나 찾아보세요. 한 페이지 분석을 작성하세요: 무엇이 잘못되었나요? 어떤 소프트웨어 공학 원리가 위반되었나요? 무엇을 다르게 할 수 있었나요?
연습 4: 당신이 익숙하지 않은 소프트웨어 공학 역할(예: QA 엔지니어, 기술 작가, SRE)에 종사하는 사람을 인터뷰(또는 온라인에서 조사)하세요. 그들의 일상적인 책임과 소프트웨어 개발자와의 업무 교차점을 설명하세요.
연습 5: Brooks는 1986년에 "은탄환은 없다(No Silver Bullet)" — 생산성을 10배 향상시킬 단일한 개발, 기법, 또는 관리 실무는 없다고 주장했습니다. 현대적 발전(AI 코드 어시스턴트, 클라우드 인프라, 성숙한 프레임워크)을 고려하여 이 주장에 대한 찬반 논거를 검토하세요. 동의하나요, 반대하나요? 증거를 제시하세요.
더 읽을거리¶
- Fred Brooks, The Mythical Man-Month: Essays on Software Engineering (Anniversary Edition, 1995) — 소프트웨어 공학의 인적·조직적 측면에 관한 기초적인 저작
- Fred Brooks, "No Silver Bullet: Essence and Accident in Software Engineering" (1986) — IEEE Computer, Vol. 20, No. 4
- Ian Sommerville, Software Engineering (10th ed., 2015) — 포괄적인 학술 교재
- Roger Pressman, Software Engineering: A Practitioner's Approach (8th ed., 2014) — 실무 중심의 포괄적 내용
- NATO 1968 Conference Report: http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF 에서 열람 가능
- ACM/IEEE-CS Software Engineering Body of Knowledge (SWEBOK): https://www.computer.org/education/bodies-of-knowledge/software-engineering
이전: 개요 | 다음: 소프트웨어 개발 생명주기