# Table of Contents

# 소프트웨어 공학

  • 최소 비용, 시간으로 최대 품질의 소프트웨어를 개발, 운영, 유지보수하기 위한 방법론

# 좋은 소프트웨어란?

  1. 사용자 요구가 정확히 반영된 소프트웨어
  2. 에러가 적은 소프트웨어
  3. 유지보수가 쉬운 소프트웨어
  4. 변경에 대응하기 쉬운 소프트웨어

# 소프트웨어 위기

  • 소프트웨어 규모가 커지고 복잡해 질수록 유지보수 비용이 기하급수적으로 증가하는 현상
  • 소프트웨어 수명 전체를 고려하면 유지보수 비용이 개발 비용을 초과한다.

# 왜 유지보수가 필요할까?

  1. 시스템에 남아있는 오류를 제거하기 위해
  2. 요구사항의 변경
  3. 비즈니스의 변경

# 소프트웨어의 생명주기

프로젝트 계획 > 요구분석 > 아키텍처 설계 > 상세 설계 > 구현 > 테스트 > 유지보수

# 소프트웨어 개발 방법론

  • 폭포수 방법론
  • 애자일 방법론

# 폭포수 방법론

  • 계획, 요구분석, 아키텍처 설계, 상세 설계, 구현, 테스트 등 각 단계를 순서대로 진행하는 방법론
  • 한 단계의 결과가 확인된 후에 다음 단계로 넘어간다.
  • 구현, 테스트 등 뒷 단계가 지연될 가능성이 있다.
  • 변경에 유연하게 반응하기 힘들다.

# 애자일 방법론

  • 처음부터 끝까지 계획하고 개발하는 폭포수 방법론과는 달리 피드백을 받아서 유연하게 개발하는 방법
  • 개발해야 할 기능이 100가지라면 중요한 1~2가지 기능을 짧은 단위로 먼저 개발하고, 사용자로부터 피드백을 받아 보안하는 주기를 반복하는 것이 포인트
  • Jira처럼 Scrum, Kanvan Borad 같은 애자일을 지원하는 프로젝트 관리도구와 전문적인 QA 인력이 필요
  • 애자일 방법론에도 다양한 방법이 있다.

# Scrum

  • 1년 정도의 단기 계획인 로드맵으로 Product Backlog 작성
  • 2~3주 단위의 Spring Planing Meeting으로 Sprint Backlog 작성
  • 2~3주 단위의 Sprint와 매일 진행하는 Daily Scrum Meeting 수행

# Kanvan Board

해야할 작업, 진행 중인 작업, 완료된 작업 등 작업을 시각화하는데 사용한다.

# 간트 차트

일정 관리에 사용된다.

# Pair Programming

  • 두 사람이 짝이 되어 한사람은 코딩, 다른 사람은 코드 리뷰를 하는 방법론
  • 두 사람이 함께 성장할 수 있고, 코드의 일관성이 유지

# Test Driven Development

  • 테스트 케이스를 먼저 작성하고 이를 통과하는 코드를 개발하는 방법론

# Feature Driven Development

  • 기능 단위로 개발하는 방법론

# XP(Extreme Programming)

  • 문서화를 줄이고 조금씩 자주 개발하고 릴리즈하는 방법론

# Lean

  • 한국말로 군살이 없다는 의미
  • 낭비를 줄이는데 포커스를 둔 방법론

# 프로젝트 계획

  • 개발 범위를 한정한다.
  • 일정을 계획한다.
  • 비용을 추정한다.
  • 구성원에 작업을 할당한다.
  • 위험 요소를 관리한다.

# SOLID 원칙

객체지향 프로그래밍에서 유지보수가 쉽고 변경에 유연하게 대응할 수 있도록 적용하는 원칙

# SRP

  • 단일 책임 원칙(Single Responsibility Priciple)
  • 한 클래스는 하나의 책임만 가져야한다.
  • 즉 하나의 클래스는 해당 클래스와 연관된 기능들만 가져야하며, 모듈 하나의 응집도를 높이고 모듈 사이의 결합도를 낮추는 것과 관련된다.
  • 예를 들어 계산기 클래스는 덧셈, 뺄셈, 곱셈, 나눗셈 기능만을 포함해야한다.

# OCP

  • 개방 폐쇠 원칙(Open Closed Priciple)
  • 변경에는 닫혀있으나 확장에는 열려있다.
  • 요구사항이 변경되었을 때 기존 코드를 수정하지 않고도 확장의 형태로 재사용할 수 있어야한다.
  • 요구사항이 변경될 수도 있는 부분을 인터페이스로 정의하고, 변경된 요구사항은 새로운 구현체로 구현한다.
  • Spring 에서는 JDBC나 JPA를 사용할 때 인터페이스 형태로 Driver에 접근하고, 이 인터페이스를 따르는 MySQL, Oracle, H2 등의 Driver를 사용하여 쉽게 변경에 대응할 수 있다.
  • 변경될 부분과 절대 변경되지 않을 부분을 구분하는게 핵심이다.

# LSP

  • 리스코프 치환 원칙(Liskov Substitution Principle)
  • 잘못된 상속을 피하기 위한 원칙으로 부모 클래스 타입의 변수에 자식 클래스의 인스턴스를 넣어도 잘 작동해야한다.
  • 자식 클래스는 부모 클래스의 기능을 오버라이딩하기보단 새롭게 메소드를 정의하는 형태로 구현해야한다.

# ISP

  • 인터페이스 분리 원칙(Interface Segregation Principle)
  • 클래스는 자신이 사용하지 않는 인터페이스를 implements 하지 말아야한다.
  • 또한 하나의 인터페이스에 선언을 몰아넣는 것보다 연관된 작은 단위로 인터페이스에 분리하여 필요한 인터페이스만 구현하는 것이 낫다.

# DIP

  • 의존관계 역전 원칙(Dependency Inversion Principle)
  • 의존하는 객체를 직접 만들고 관리하는 것이 아니라 외부에서 주입받는 원칙으로 의존성 주입의 기반이 된다.

# 클린 아키텍처

  • 핵심은 계층을 분리하고, 계층의 기능을 명확하게 정의하는 것
  • Layered Architecture라는 용어를 쓰기도 한다.
  • 예를 들어 웹 프론트나 모바일 앱은 UI와 관련된 계층, 비즈니스 로직과 관련된 계층, 캐싱과 관련된 리포지토리 계층, 데이터베이스에 접근하거나 네트워크 통신하는 계층으로 계층을 나눌 수 있다.
  • 서버 어플리케이션의 경우 요청을 받거나 뷰를 보여주는 컨트롤러 계층, 비즈니스 로직을 수행하는 계층, 트랜잭션을 관리하는 계층, 데이터베이스에 접근하는 계층 등으로 나눌 수 있다.
  • 각 계층은 인접한 계층에만 접근할 수 있으며, 계층 간에 데이터가 이동할 때 적절한 Mapper가 필요하기도 하다.
  • 또한 인터페이스와 다형성, 추상화를 적용하여 의존하는 계층과의 결합도를 낮출 수 있다.
  • 마지막으로 의존성 주입 프레임워크와 함께 사용될 때 계층 분리와 효용성이 극대화된다.
  • 파일과 코드가 많아진다는 단점이 있다.
  • 그러나 작업중인 계층, 그리고 인접한 계층만 고려하여 개발하기 때문에 분업화 측면에 큰 장점이 있다.
  • 유지보수, 기능 추가가 쉬워진다.
  • 인접한 계층만 고려하면 되기 때문에 단위테스트가 쉬워지며, Mockup 라이브러리와 함께 사용하면 큰 시너지를 만들어낸다.

# 스케일 업 vs. 스케일 아웃

  • 스케일 업: 더 좋은 컴퓨터를 배치하는 것.
  • 스케일 아웃: 비슷한 성능의 컴퓨터를 수직적으로 배치하는 것. Kubernetes 같은 오케스트레이션 도구가 필요하다.