[Service] 소프트웨어 엔지니어링


소프트웨어 엔지니어링

  • 소프트웨어 엔지니어링이란?
    • 소프트웨어를 개발하는 과정에서 체계적이고 효율적인 방법을 사용하여 소프트웨어의 품질과 유지보수성을 보장하는 학문 분야

      Untitled

  • 소프트웨어는 다양한 분야가 있고, 집중하는 문제가 다르다.
    • 프론트엔드 : 웹페이지의 앞단
    • 백엔드(서버) : 데이터 처리, 연산, API 등을 진행
    • 풀스택 : 프론트엔드 + 백엔드 등 여러가지 진행
    • 머신러닝, AI
    • 데이터
    • 모바일 앱 : 앱 개발
    • 게임, 보안
    • DevOps, 클라우드 : 클라우드 리소스 효율적인 사용
  • 소프트웨어 엔지니어들은 여러 규칙과 방법론을 사용해서 개발한다.

소프트웨어 개발 라이프사이클

  • Planning(계획) $\rightarrow$ Analysis(요구조건분석) $\rightarrow$ Design(설계) $\rightarrow$ Implementation(구현) $\rightarrow$ Testing & Integration(테스트) $\rightarrow$ Mainenance(유지 보수)
  • 위 단계를 계속해서 반복한다.

소프트웨어 설계

  • 아래는 좋은 소프트웨어 설계를 위해서 알아야 하는 개념이다.

    1. 모듈성
      • 모듈이란 고유한 목적, 기능을 가지는 단위다.
      • 레고 블록과 유사하다. 블록마다 고유한 용도가 존재하며, 쉽게 부착하거나 제거할 수 있다. 또한 나머지 부분에 영향을 주지 않으면서 쉽게 교체가 가능하다.
      • 소프트웨어 개발의 모듈성은 큰 프로그램을 작고 독립적인 부분으로 나누는 것을 의미한다.

        Untitled

      • 예를 들어 계산기를 구현한다면, “입력 모듈 + 연산 모듈 + 출력 모듈 + 메모리 모듈 + 인터페이스 모듈” 로 나눠볼 수 있다.
    2. 응집도(Cohesion)
      • 시스템의 모듈 구성 요소가 목적을 달성하기 위해 관련되어 있는 정도

        Untitled

      • 아래의 Class 는 하나의 모듈이 여러가지 일(기능)을 담당한다. 공동의 목적이 없고, 관련되어 있지 않다.
      • 즉 낮은 응집도를 가진다. 이처럼 낮은 응집도를 가지는 코드는 하나의 클래스에 모든 것이 정의된다.

        Untitled

      • 반면에 아래의 Class 가 높은 응집도를 가지는 코드다. 각각의 모듈이 긴밀하게 엮이고, 각각의 모듈이 하나의 역할을 담당한다.
        • User : 유저의 정보를 만들고 저장하는 역할
        • UserInformation : 유저 정보를 출력하는 역할
        • EmailSender : 이메일을 유저에게 전송하는 역할
        • 이처럼 Class 를 나눠서 각각의 역할을 부여하는 것이 높은 응집도를 가질 수 있다.

        Untitled

      • 높은 응집도의 코드를 짜려면 Class, 객체 지향적 사고가 필요하다. 하나의 Class 에 모든 기능을 구현하는 것이 아닌, 목적에 맞게 나누고 서로 교류하는 인터페이스를 구현하는 것이다.
    3. 결합도(Coupling)
      • 모듈 간 상호 의존성의 정도를 나타낸다.

        Untitled

      • 하나의 클래스에서 수정했을 때 다른 클래스도 수정을 해야 한다면, 높은 결합도를 가지는 코드다. 아래 그림에서 오른쪽이 낮은 결합도를 가지는 코드다.

        Untitled

      • Order 에서 Product 의 메서드를 사용하지 않게 되면, Productself.price 관련 구현 정보와 상관없이 실행이 가능하다. 결합도가 높으면 원하는 결과가 다른 클래스의 수정에 따라 다른 결과로 발생할 수 있다.
      • 즉 다른 클래스 내부의 구현이 바뀌어도 영향을 받지 않는 것이 낮은 결합도이다.
    4. 좋은 소프트웨어 설계 지향점
      • 높은 응집도(모듈 내 교류)와 느슨한 결합도(모듈 끼리는 덜 교류)를 가진 소프트웨어를 지향해야 한다.
      • 소프트웨어 설계 혹은 Pytorch 클래스를 만들 때, 응집도와 결합도를 체크해보자.
      • 블로그에서 설계 용어 측면에서의 응집도와 결합도를 잘 설명하고 있다.

테스트

  • 유저에게 우리가 제공하는 기능을 제공하기 전에 사전 테스트를 진행해야 한다.
  • 소프트웨어 개발의 테스트는 프로그램이 예상대로 작동하고 문제가 없는지 확인하는 과정이다. 유저에게 공개하기 전에 프로그램이 잘 작동하는지 확인하는 과정이 없으면 장애를 경험하기 쉽다.
  • 테스트를 통해 기대되는 결과(현상)와 실제 나온 결과를 비교한다. 즉 사용자들에게 안정적으로 소프트웨어를 사용할 수 있도록 기능이 추가될 때 기존 시스템에서 오류가 생기는지 버그가 있는지 등을 확인한다.

    Untitled

  • 개발 과정에서 모두 테스트를 할 수 있다. 코드만 확인하는 것이 아닌 전체 시스템에 대한 확인도 할 수 있다.
  • 요구 조건 확인, 아키텍처 디자인 설계 확인, 서버 정상 확인, 데이터베이스 연결 확인, 서버 부하 테스트 등이 가능하다.

테스트의 종류

  • Unit Test : 개별 단위 테스트를 말한다. 함수를 테스트 할 때도 Unit test 라고 볼 수 있다. pytest 라는 라이브러리로 가능하다.
  • Integration Test : 다른 단위, 구성요소의 동작을 테스트한다. 즉 여러가지 함수를 같이 사용하는 경우에 해당한다.
  • End to End Test : 처음부터 끝까지 모두 테스트한다. 서버가 올라가는지, API 요청이 되는지, 어떻게 동작하는지 등을 확인한다.
  • Performance Test : 성능, 부하 테스트
  • 딥러닝 프레임워크에서의 테스트는 잘 발전되지 않은 부분이 있다. 딥러닝에서는 데이터와 코드로 같이 테스트를 해야 하기 떄문이다.
  • 그러나 소프트웨어 설계에서는 코드 단위 테스트를 쉽게 할 수 있다.

문서화

  • 소프트웨어를 이용하기 위한 README, API 문서, 아키텍쳐 문서 등을 작성하는 것이 좋다. Pytorch 깃허브의 README.md 가 매우 올바른 예시다.
  • Pytorch 공식문서에는 API 설명서, 사용 가이드, Ecosystem(관련된 다른 라이브러리), Blog, Tutorial 등이 모두 있다. 즉 좋은 소프트웨어는 좋은 문서가 같이 존재한다.
  • 따라서 개인 프로젝트도 문서화를 신경쓰면 좋다.

소프트웨어 엔지니어링을 배워야 하는 이유

  • 아래는 Hidden Technical Debt in Machine Learning Systems 논문의 그림이다. 여기서 알 수 있는 것은, 코드(검은 부분)는 매우 작은 일부에 불과하다는 것이다.

    Untitled

  • 예시로 트위터의 아키텍쳐를 보자.

    Untitled

  • Prediction Service(home score 예측) 와 Candidate Source(Feature 를 뽑아 Scoring) 가 AI 와 관련된 아키텍처다.
  • 모델보다 크고 복잡한 시스템에서 제 역할을 하기 위해 소프트웨어 엔지니어링을 이해해야 한다.
  • 큰 아키텍처 안에 AI 가 들어가 있다는 것을 알고 있는 것이 핵심이다. 유튜브 추천 알고리즘 또한 큰 아키텍처 안에 들어가 있다.
  • AI 모델을 개발하고 서비스에 녹이기 위한 과정을 위해 소프트웨어 엔지니어링(소프트웨어 개발, 프론트엔드 & 백엔드)을 학습하는 것이 필요하다.
  • 프로덕트 프로토타이핑, 변환 품질, 인퍼런스 속도에 대해서도 생각해보자.
  • 정리하면, 서비스에 ML/AI 기술들을 적용하기 위해서는 서비스와 그를 만들어 내는 소프트웨어 엔지니어링을 이해해야 한다.
맨 위로 이동 ↑

댓글 남기기