• 심플 소프트웨어 : 소프트웨어 이해하기

    2023. 5. 29.

    by. 하루플스토리

    반응형

    6장 소프트웨어 이해하기


    [컴퓨터란 무엇인가?]

    • 소프트웨어를 이해하려면 우선 컴퓨터가 무엇인지 부터 이해해야 한다.
    • 컴퓨터(명사) : 사전 정의된 명령 조합에 따라 정보를 저장하고 처리하는 전자기기
    • 인간이 설정한 목표를 달성하기 위해 일련의 기호 명령을 수행하고 데이터를 비교할 수 있는 모든 물질이 컴퓨터다.
    • 컴퓨터는 데이터를 비교할 수 있다. 이러한 부분이 인간의 입력을 받는 다른 기계와 구분된다.
    • 컴퓨터는 한 가지 명령뿐 아니라 일련의 명령을 받을 수 있다. 단순한 계산기를 딱 한가지 명령만 수행한다는 점에서 컴퓨터와 구분된다.
    • 키보드의 키 입력이나 마우스 클릭도 기호 명령이다. 하지만 프로그래머가 작업할 때 쓰는 주된 기호 명령은 프로그래밍 언어다. 그러므로 작업 품질을 개선할 방법을 이야기 할 때 프로그래머는 프로그램의 구조에 가장 신경쓴다.


    [소프트웨어의 구성 요소 구조, 동작, 결과]

    • 프로그램의 가장 중요한 세 요소가 구조, 동작, 결과라고 생각한다. 구조, 동작, 결과로 현존하는 거의 모든 기계를 묘사할 수 있을 것이다.
    • 소프트웨어를 만들 때 보통 구조부터 만들고 동작과 관련된 부분을 작업한 다음 결과를 표시하는 부분을 만든다.
    • 결과부터 거꾸로 작업하는 사람도 있다. 그래도 상관없다. 단, 구조나 저으이된 결과 없이 동작을 수행하려면 혼란스러울 가능성이 높기 때문에 동작부터 시작하는 방법은 권하지 않는다.


    [소프트웨어 개정판 : ISAR 구별하기]

    • 구조 , 동작, 결과라는 세 요소를 줄여서 SAR 이라고 부르고, 여기에 입력도 포함시킬 경우 ISAR 이라고 부른다.
    • MVC는 소프트웨어를 설계하는 패턴이다. SAR은 모든 소프트웨어에 나타나는 세가지 요소를 가리킨다.

    구조

    • 전체 프로그램의 구조로 볼 수 있는 몇가직 예는 다음과 같다.
      • 코드 디렉터리 레이아웃
      • 모든 클래스와 각 클래스 간의 연결 수조
      • 데이터베이스를 쓰는 프로그램이라면 데이터베이스의 구조 계획 (단, 데이터베이스에 있는 실제 데이터는 구조에 속하지 않는다는 점을 주의해야한다.)
    • 개별 클래스에도 구조가 있다.
      • 클래스 메서드의 이름과 메서드에 전달되는 매개변수의 이름과 저료형
      • 클래스 변수의 이름과 자료형
    • 구조는 프로그램 구성 요소 혹은 프로그램의 일부 조각이라고 볼 수 이싿. 함수 이름이나 자료형, 변수 이름과 자료형 클래스 같은 것은 모두 구조다.

    동작

    • 전체 프로그램의 동작은 매우 이해하기 쉽다. 세무 프로그램은 ‘세금 정산’을 하고 계산기는 ‘계산을 한다’.
    • 동작은 항상 일종의 동사다. 계산하다, 고치다, 더하다, 없애다 이런게 동작이다.
    • 클래스 내부에서 동작은 메서드의 내부 코드를 의미한다.

    결과

    • 모든 프로그램, 함수, 코드는 어떤 영향을 미친다. 즉, 어떤 결과를 생산한다. 결과는 항상 과거시제로 이야기 할 수 있다. 세무 프로그램은 세금 신고서를 제출했다거나 납세 신고서를 작성했다 등의 결과를 낸다.
    • 프로그램의 개별적인 부분에도 결과가 있다. 메서드나 함수를 호출하면 매우 명확한 결과가 나온다. 보통은 데이터를 반환하거나 수정한다.
    • 프로그램이 생산하는 것이라면 모두 결과다.
    • SAR은 거대한 앱부터 한 줄짜리 스크립트까지 어떤 프로그래밍에든 적용할 수 있는 개념이다. 코드를 작성할 때마다 깊게 생각해야하는 개념은 아니지만 프로그램을 분석하고 이해하는데 도움이 된다. 특히 설계 개선 방법을 고민할 때 큰 도움이 될 것이다.


    [지식으로서의 소프트웨어]

    • 소프트웨어는 지식으로 만든 단단한 실체다. 이는 지식의 모든 규칙과 법칙을 따른다. 구체적인 형태를 지니고 있다는 사실만 제외하면 거의 모든 상황에서 지식과 똑같은 양상을 보인다.
    • 나쁜 데이터는 사람의 나쁜 행동을 유발하고, 나쁜 코드는 컴퓨터의 나쁜 행동을 유발한다. 컴퓨터와 사람을 비교하려는게 아니라 소프트웨어와 지식을 비교할 수 있다는 뜻이다.


    [기술의 목적]

    • 일반적으로 물질, 에너지, 시간이나 공간의 문제를 해결하고자 기술을 사용했을 때는 성공적인 결과를 냈다. 하지만 마음, 소통, 능력 등 인간의 문제를 해결하고자 했을 때는 실패하거나 위험한 역효과를 냈다.
    • 소프트웨어의 목적이나 스타트업 아이디어의 성공 가능성을 미리 점칠 때 이 원칙 혹은 법칙을 유용하게 활용할 수 있다.
    • 이 법칙은 기술의 발전이 선인지 악인지를 밝히는 데도 유용하다. 기술의 발전을 생각하면 때로 심경이 엇갈린다. 기술이란 본질적으로 선하거나 악한 것이 아니다. 하지만 인간의 문제를 해결하려고 할 때 악하게 작용하고, 물질 세계의 문제를 해결하려고 할 때 선하게 작용하는 경향이 있다.
    • 기술은 우리를 더 나은 인간으로 만들지는 못하지만 우리가 사는 세상이 조금 더 나아지게 만들 수 있다.


    [단순성과 보안]

    • 소프트웨어의 보안을 보장하는 가장 중요한 요소는 단순성이다.
    • 소프트웨어를 안전하게 지키겠다고 소프트웨어 앞에 소규모 군대를 배치할 필요는 없다. 별도의 보호 장치가 필요 없도록 ‘입구’수를 줄이고, 그 입구를 간결하고 단순하게 만들어 부당하게 악용하지 못하게 하라.


    [테스트 주도 개발과 관찰 주기]

    • 최근에 테스트를 먼저 작성한 뒤에 코드를 작성하는 개발 시스템 TDD의 특성과 작용에 관해 흥미로운 논의가 있었다. 결정을 내리기 전에 관찰부터 해야한다는 것이었다. 소프트웨어 수명 전반에 걸쳐 무언가 관찰해야한다. 이 원칙은 소프트웨어 개발 주기에 광범위하게 적용된다.
      • 관찰 → 결정 → 실행 (이 주기의 반복)
    • ODA 사례 : TDD를 쓸 때는 아래 주기를 따른다
      1. 문제를 본다 (관찰)
      2. 문제를 해결하기로 한다 (결정)
      3. 테스트를 작성한다 (실행)
      4. 테스트를 보고 API가 괜찮은지 확인한다 (관찰)
      5. 괜찮지 않다면 수정 방법을 정하고 (결정) 테스트를 수정한 후 (실행) API가 괜찮아 보일 때까지 관찰 → 결정 → 실행을 반복한다.
      6. API가 괜찮다면 테스트를 실행하고 통과하는지 본다 (관찰)
      7. 코드를 작성한다 (실행)
      8. 테스트를 실행하여 통과하는지 확인한다 (관찰)
      9. 통과하지 못하면 수정 방법을 정하고 (결정) 코드를 작성하고 (실행) 테스트를 통과하는지 확인한다 (관찰)
      10. 이런 방식으로 다음 작업을 이어간다.


    [테스트 철학]

    • 기존의 과학적 방법은 우주를 테스트한 후 테스트 결과를 바탕으로 자신이 세운 가설을 정교하게 다듬는 순서로 진행된다. 어떻게 보면 소프트웨어 테스트는 이와 정반대로 진행된다.
    • 소프트웨어 세계에서는 실험이 가설을 증명하지 못하면 테스트하고 있는 시스템을 수정한다
    • 테스트 가치
      • 테스트의 목적은 시스템에 대한 지식을 전달하는 것이고 각 지식은 다른 가치를 지닌다.
      • 얻고자 하는 지식이 무엇인지 정확히 알아야 효과적이고 유용한 테스트를 만들 수 있다.
    • 테스트 단언문
      • 테스트는 무언가 알기 위해 하는 것이므로 반드시 무언가를 단언해야한다. 그리고 그 단언문은 참인지 거짓인지 확인되어야 한다.
      • 테스트 주체가 인간이라면 매력적이다 처럼 정성적인 단언문으로 써도 된다. 단언문이 없으면 테스트가 아니다.
    • 테스트 범위
      • 실험 한번으로 물리학의 모든 이론과 법칙을 증명할 수 없듯이 복잡한 시스템의 동작 방식을 한 번에 증명하는 테스트를 설계한다는 건 불가능한 일이다.
      • 그러므로 테스트를 설계할 때는 테스트 대상과 테스트에 속하지 안흔 부분을 정확히 구분해야 한다.
    • 테스트 가정
      • 모든 테스트에는 가정이 내재되어야 한다. 해당 테스트의 범위 안에서 유효한 결과를 내는 데 꼭 필요한 전제라고 보면 된다.
      • 모든 테스트는 통과, 실패, 알 수 없음 이 세가지 중 적어도 한 가지 결론을 도출해야한다.
    • 테스트 설계
      • 앞서 살펴본 바와 같이 각 테스트에는 범위와 가정이 존재할 수밖에 없기 때문에 테스트 스위트를 설계해야 한다. 그래야 전체 테스트를 조합했을 대 원하는 지식을 빠짐없이 얻을 수 있다.
    • E2E 테스트
      • E2E 테스트는 시스템 로직을 관통하는 하나의 경로를 완료하는 방식으로 진행하는 테스트다. 전체 시스템을 동작시키고 사용자가 입력하는 시작 지점에서 몇 가지 동작을 실행한 후 시스템이 생산하는 결과를 확인하는 것이다.
      • 이 테스트는 테스트가 많이 부족한 초기에 임시방편으로 쓰기 좋다. 전체 시스템을 조립한 후에 제대로 동작하는지 확인하는 용도로 써도 좋다. 하지만 장기적으로 볼 때 복잡한 시스템에 대해 충분한 지식을 얻을 수 있는 테스트 방식은 아니다.
    • 통합 테스트
      • 두 개 이상의 컴포넌트를 한 시스템에서 조립한 후에 어떻게 작동하는지 보는 것이 통합 테스트이다. 여기서 컴포넌트란 코드 모듈이 될 수도 있고 시스템이 의존하는 라이브러리 , 데이터를 제공하는 원격 서비스가 될 수도 있다.
      • 통합 테스트에서는 컴포넌트의 분리를 중요시 한다.
      • 통합 테스트만으로 시스템을 테스트 하는건 적절하지 않다. 컴포넌트의 인터렉션 만으로 전체 시스템을 분석하려면 시스템 작동 방식 전반에 대해 이해하기까지 엄청난 수의 인터랙션을 테스트해야 하기 때문이다.
    • 단위 테스트
      • 하나의 컴포넌트가 정상 작동하는지 확인하는 테스트가 단위 테스트다.
      • 단위 테스트는 하나의 클래스, 모듈에 있는 한가지 함수의 한 가지 동작을 테스트한다. 컴포넌트의 내부 구현이 아니라 동작을 테스트 해야한다.
      • 이론적으로는 시스템에 있는 모든 컴포넌트의 동작이 문서에 잘 정의되어 있으면 각 컴포넌트가 문서에 나온 대로 동작하는지 테스트하기만 해도 시스템 전체의 동작을 테스트한 셈이 된다.
      • 당연한 말이지만 단위 테스트는 시스템 컴포넌트가 합리적으로 잘 분리 되어있고 각 컴포넌트의 동작을 완전히 정의할 수 있을 정도로 단순할 때 가장 큰 효과를 낸다.
    반응형

    댓글