소프트웨어 시스템
관심사
- 신뢰성 : 예측 가능한 방법으로 동작하고, 장애 발생 시에도 복구되거나 서비스가 지속되는 능력이다. (신뢰성이 높은 시스템은 장애나 성능 저하에도 사용자의 기대에 부응할 수 있다. 비즈니스 중단을 방지함)
- 중요성
- 신뢰성 보장 방법
- 장애 대응 계획
- 장애 대응 프로세스 구축
- 실시간 모니터링, 알림 시스템 구축
- 무중단 운영
- 다중 데이터 센터 운영( 멀티 리전, 멀티 AZ )
- 로드 밸런싱 : 트래픽을 여러 서버에 분산시켜 특정 서버에 과부하가 걸리지 않도록 하고, 다운되면 살아있는 곳으로 던지는
- Active-Active/ Active-Passive
- Active-Active : 모든 서버가 동시에 동작, 한 서버가 장애 상태라고 다른 하나가 이를 처리
- Active-Passive : 하나의 서버가 동작하고 하나는 대기, (Passive 살리는데 시간이 걸려서 잘 안씀)
- failOver시스템 : 장애시 시스템이 자동으로 백업을 활성화하여 서비스 중단 없이 운영 지속 -> 대체 시스템
- 데이터 복제 및 백업 전략 -> 데이터 유실 방지
- 다중 리전 데이터 복제
- 주기적인 백업 및 복구 테스트
- 자동 복구(Self-Healing System) -> 시스템이 스스로
- 시스템이 장애를 스스로 감지하고, 자동으로 복구하는 기능을 도입
- 서버 인스턴스가 다운되면 자동으로 새로운 인스턴스를 생성하거나, 장애가 발생하면 대체 경로를 찾는 식으로 복구
- 모니터링 및 장애 탐지
- 실시간 모니터링: 임계치를 초과하면 알림을 발송해서 대응하도록 함
- 메트릭 기반 모니터링 도구(Prometheus)
- 장애 대응 계획
- 신뢰성 높이기 위한 팁
- 다중 가용성 존
- 자동 복구 기능
- 장애 복구 훈련
- 확장성 : 트래픽 증가, 자원 요구 증가할 때 성능 저하 없이 이를 처리할 수 있는 능력이다.
- 확장성의 중요성
- 비즈니스 성장 대응: 스타트업 -> 대규모 엔터프라이즈까지 성장에따라
- 비용 효율성: 필요할 때문 자원을 늘리고, 트래픽이 줄면 자동으로 줄여 비용 절감
- 안정적인 사용자 경험: 트래픽이 늘어도 성능 저하 없이 경험을 제공할 수 있음
- 확장성의 종류
- 수직 확장: 기존 서버나 시스템 자원을 업그래이드하여 트래픽을 처리
- 장점:
- 기존 시스템 구조를 유지하면서 간단하게 성능 향상
- 기존 인프라 구조 변경이 필요가 없음 - 단점:
- 물리적 하계에 도달하면 더 이상 높일 수 없음
- 성능 향상에 따라 비용이 기하급수적으로 증가
- 수평 확장: 여러 대의 서버를 추가하여 트래픽을 분산 처리
- 장점:
- 자원을 물리적으로 제한 없이 확장 가능
- 트래픽 증가에 따라 서버를 추가하면 쉽게 성능을 향상시킬 수 있다.
- 장애 발생시 특정 서버에만 영향을 미치므로 높은 가용성을 제공
- 단점
- 시스템이 분산되어 있으므로 인프라 설정과 관리를 더 복잡하게 해야 한다.
- 데이터 일관성을 유지하기 위한 설계가 필요
- 데이터 싱크 맞추는 데 작업이 추가적으로 필요
- 장점:
- 하이브리드: 수펑 + 수직을 결합한 방식
- 장점:
- 각각 시스템에 맞춤 맞춤형 확장을 할 수 있다.
- 확장성뿐만 아니라 성능도 최적화할 수 있다.
- 단점:
- 설계가 복잡하고, 관리 비용이 증가함
- 장점:
- 수직 확장: 기존 서버나 시스템 자원을 업그래이드하여 트래픽을 처리
- 확장성 보장
- AutoScaling: 클라우드 환경에서 트래픽이나 부하에 맞춰서 인스턴스를 자동으로 추가하거나 축소하는 기능임
- 장점:
- 트래픽 상황에 따라 자원을 자동으로 조정할 수 있어서 운영 비용을 최적화할 수 있다.
- 수요에 따라 시스템이 자동으로 확장되므로, 운영자가 수동으로 서버를 관리할 필요가 없음
- 단점:
- 설정 및 운영 과정에서 복잡성이 있을 수 있으며, 자원 조정 시 지연이 발생할 수 있음
- 장점:
- loadBalancing:
- 장점:
- 특정 서버에 과부하가 걸리지 않도록 트래픽을 분산하여 성능을 안정적으로 유지
- 서버 장애 시에도 나머지 서버로 트래픽을 자동으로 전환하여 가용성을 높임
- 단점:
- 트래픽 분산을 위한 로드 밸런서 설정이 복잡할 수 있으며, 네트워크 레벨에서 문제를 추가적으로 고려해야 함
- 장점:
- Sharding: 대규모 데이터를 처리하기 위해서 데이터를 여러 개의 작은 DB로 분할하는 방법이다. 수평 확장 중 하나
- 장점
- DB부하를 분산시켜 읽기 및 쓰기 성능을 크게 향상시킬 수 있음
- 대규모 데이터를 효율적으로 처리할 수 있음
- 단점
- 데이터 일관성을 유지하는 것이 복잡하며, 샤딩된 데이터베이스 간의 동기화 이슈가 발생할 수 있다.
- 장점
- Caching
- 장점
- 응답 속도를 크게 향상시킬 수 있다
- 데이터베이스 부하를 줄여 시스템 성능을 최적화한다.
- 단점
- 오래된 캐시에 대한 무효과 전략이 필요하다.
- 장점
- AutoScaling: 클라우드 환경에서 트래픽이나 부하에 맞춰서 인스턴스를 자동으로 추가하거나 축소하는 기능임
- 확장성 테스트
- 부하 테스트(LoadTesting) : 시스템이 예상 트래픽 수준에서 얼마나 안정적으로 동작하는지 확인하는 테스트 방법이다. 시스템이 얼마나 많은 요청을 처리할 수 있는지 파악하고, 부하가 증가함에 따라 성능 저하가 발생하는지 확인
- 도구: JMeter, Gatling, k6등
- 스트레스 테스트(StressTesting) : 정상적인 운영 범위를 초과하는 부하를 가해서 시스템이 언제 성능이 저하되거나 장애가 발생하는지 확인하는 테스트다. 한계점을 파악하고, 비정상적인 트래픽 상황에 대한 대응력을 확인함
- 도구: Locust, Artillery
- 스파이크 테스트(SpikeTesting) : 짧은 시간 내에 급격히 증하는 트래픽에 시스템이 어떻게 반응하는지 확인하는 테스트( 급작스런 트래픽 폭증에 시스템이 견딜 수 있는지 검증)
- 팁
- AutoScaling
- 부하 및 스트레스 테스트 주기적으로 실행
- 로드밸런서 구성, 최적화
- 캐시 사용 및 최적화
- 데이터베이스 샤딩 고려
- 부하 테스트(LoadTesting) : 시스템이 예상 트래픽 수준에서 얼마나 안정적으로 동작하는지 확인하는 테스트 방법이다. 시스템이 얼마나 많은 요청을 처리할 수 있는지 파악하고, 부하가 증가함에 따라 성능 저하가 발생하는지 확인
- 확장성의 중요성
- 유지보수성 :
- 시스템이 시간이 지나면서 새로운 기능을 추가하거나 버그를 수정할 때, 얼마나 쉽게 관리하고 수정할 수 있는지를 나타내는 능력
- 개발 부채를 줄여서 개발 속도를 높이고, 장기적인 시스템 운영 비용을 줄일 수 있다.
- 코드의 가독성, 시스템의 모듈화, 자동화된 테스트 등이 유지보수성을 높이는 핵심요소다.
- 유지보수성의 중요성
- 장기적 비용 절감: 유지보수성이 낮은 시스템은 시간이 지나면서 기술부채로 쌓이고, 새로운 기능 추가나 버그 수정을 할 때마다 점점 더 많은 시간이 소요됨. 반대로 유지보수성이 높은 시스템은 수정이 간단하고, 적은 비용으로 안정적인 운영이 가능
- 개발 생산성 향상 : 유지보수성이 높은 시스템은 새로운 팀원이 빠르게 적응할 수 있도록 돕고, 개발자들이 복잡한 시스템을 이해하거나 기존 코드와 씨름하지 않을 수 있음
- 기능 확장 용이: 비즈니스가 성장하면서 새로운 요구 사항이 발생할 떄, 쉽게 확장가능함
- 신속한 문제 해결 : 코드와 시스템이 잘 구조화도어 있고, 문서화, 주석이 잘되어 있을 떄, 장애나 문제가 발생했을 때 빠르게 원인을 파악하고 수정할 수 있다.
- 유지보수성을 보장하는 방법
- 모듈화: 시스템을 기능별로 나눠서 독립적으로 관리할 수 있도록 설계하는 방법이다. 각 모듈은 고유한 역할을 담당하고, 다른 모듈과의 의족선을 최소화하여 변경 역시 용이
- 장점:
- 각 모듈이 독립적으로 유지보수 될 수 있어서 전체 시스템을 변경하지 않고 특정 기능을 수정하거나 추가할 수 있다
- 모듈 간 의존성이 낮으면 사이드 이펙트가 줄어든다.
- 장점:
- 코드 품질 관리: 유지보수성을 높이기 위해서는 코드가 가독성 있게 작성되고, 코드 스타일이 일관되기 유지되어야 함. 코드 품질이 높을수록 이해하기 쉽고, 수정하기가 간단해짐
- 코드리뷰: 코드 리뷰는 코드가 시스템 요구사항에 맞게 작성되었는지, 성능 및 보안 문제가 없는지 검토하는 과정
- 코드 컨벤션: 팀 내에서 일관된 코드 스타일 가이드를 정의하고 모두 준수하도록함
- 문서화 및 주석: 시스템의 설계 구조와 코드에 대한 명확한 문서화를 통해 새로운 개발자가 쉽게 시스템을 이해하고 유지 보수할 수 있게 함. 또한, 코드 내에 주석을 추가해서 각 부분이 어떤 역할을 하는지 설명한다.
- 문서화의 중요성
- 복잡한 시스템일수록 시스템 설계화 흐름을 문서화하여 누구나 쉽게 시스템을 이해하고 유지보수 할 수 있도록 해야한다.
- 주요 API나 데이터 흐름, 시스템 설계 철학 등을 명확히 문서화해서 새로운 개발자나 유지보수 담당자가 빠르게 적응할 수 있음
- 문서화의 중요성
- 자동화된 테스트:
- 시스템 변경이 생겼을 때 기존 기능이 정상적으로 동작하는지 자동으로 검증하는 테스트를 의미
- 유지보수성 높은 시스템은 변화가 있을 때마다 테스트를 수동으로 실행하지 않고, 자동화된 테스트로 시스템 안정성을 확인
- 장점:
- 개발자가 새로운 기능을 추가하거나 버그를 수정할 때, 자동화된 테스트가 기존 기능에 미치는 영향을 빠르게 확인할 수 있다.
- 테스트 커버리지를 높여 예상치 못한 오류를 미리 발견해서 유지 보수 비용을 낮출 수 있다.
- 단위 테스트: 코드의 작은 단위가 예상대로 동작하는 테스트하는 방식이다. 특정 모듈이나 함수가 올바르게 작동하는지를 보장한다.
- 통합테스트: 여러 모듈이 함께 작동할 때 예상대로 동작하는지 테스트한다. 시스템 간 상호작용에 문제가 없는지 확인한다.
- CI/CD: 코드 변경사항이 있으면 자동으로 테스트하고, 이상이 없으면 배포까지 자동화하는 프로세스를 의미한다.
- CI: 커밋할 때마다 자동으로 빌드, 테스트가 실행되어, 코드가 기존 기능과 잘 통합되는지를 확인한다.
- CD: CI를 통화하느 코드를 자동으로 프로덕션에 배포하여, 새로운 기능이나 수정 사항이 사용자에게 빠르게 전달되도록 함
- 장점
- 배포 주기를 단축하고, 새로운 기능을 신속하게 제공할 수 있음
- 배포 과정에서 실수를 줄이고, 자동화된 테스트를 통해 안정성을 높일 수 있음
- 기술 부채 관리 : 기술부채는 일시적인 해결책이나 나쁜 설계로 인해 발생하는 유지 보수 비용을 의미한다. 시간이 지날수록 시스템이 복잡해지고, 유지보수에 더 많은 시간이 필요하겐 된다. 또한 새로운 기능 추가에 장애물이 될 수 있다.
- 기술부채 해결방법
- 장기적인 리팩토링: 코드가 복잡해지거나, 기술부채가 쌓인 부분은 주기적으로 리팩토링을 통해서 해결한다. 이는 장기적으로 유지보수 비용 절감에 도움이 된다.
- 문제 우선순위 설정: 모든 기술 부채를 한 번에 해결하는 것이 아니라 비즈니스에 가장 중요한 부분을 우선적으로 해결해야 함
- 기술부채 해결방법
- 버전 관리: 유지 보수성을 높이기 위해서 코드 버전 관리 시스템을 사용하여, 각 코드 변경 사항을 기록하고 추적할 수 있어야 한다. 이를 통해 이전 버전으로 쉽게 롤백하거나 특정 시점에서 발생한 문제를 빠르게 해결할 수 있다.
- 장점
- 코드 변경 사항을 추적하고, 문제가 발생했을 때 이전 버전으로 쉽게 되돌 릴 수 있다.
- 여러 개발자가 코드를 수정할 때 충돍을 방지하고, 각 변격 사항을 쉽게 통합할 수 있다.
- 유지보수성을 높이기 위한 팁
- 장점
- 장기적인 코드 리팩토링
- 테스트 커버리지 확대
- 지속적인 코드리뷰
- 문서화 및 주식 철저
- CI/CD 파이프라인 도입
- 결론
- 유지보수성은 소프트웨어 시스템이 시간이 지남에 따라 얼마나 쉽게 관리, 수정, 확장될 수 있는지를 결정하는 중요한 요소임.
- 이를 위해 모듈화된 설계, 코드 품질 관리, 자동화된 테스트, CI/CD 파이프라인, 기술 부채 관리 등이 필수적으로 고려되어야 함.
- 유지보수성이 높은 시스템은 개발 속도를 높이고, 장기적인 운영 비용을 절감하며, 시스템이 안정적으로 운영되도록 보장함.
software 개발 프로세스
- 컨테이너는 어플리케이션을 가볍고 독립적인 환경에서 실행할 수 있게 해준다.
- CI/CD는 애플리케이션을 지속적으로 테스트하고 자동 배포하여 개발 주기를 빠르게 만듦
- 컨테이너 오케스트레이션은 여러 컨테이너를 관리하고, CI/CD 파이프라인에서 자동으로 빌드된 컨테이너 이미지를 다양한 환경에 배포하고 운영을 자동화하는 데 사용함
Container
- 애플리케이션, 그 종속성, 라이브러리를 패키징하여 OS와 결리된 가상화된 환경에서 실행하는 기술
- 컨테이너는 경량화된 가상화 기술이다.
CI/CD
- 지속적 통합
- 지속적 배포
- 컨테이너와 CI/CD는 긴밀하게 연계되어 있음. 애플리케이션을 격리된 환경에서 쉽게 테스트하고 배포할 수 있게 CI/CD 파이프라인에서 자주 사용함
Container Orchestration
- 여러 컨테이너를 배포, 관리, 확장하는 작업을 자동화하는 기술이다.
- 컨테이너 오케스트레이션은 컨테이너의 수평확장, 서비스 복구, 로드 밸런싱을 자동으로 처리하여 대규모 컨테이너 환경에서 운영을 단순화함
- CI/CD 와 컨테이너 오케스트레이션은 긴밀히 연결되어 있다.
기술 도입?
사용자 요구사항, 시스템 요구사항을 기반으로 설계한다.
배포
- 배포란 소프트웨어 개발의 마지막 단계에서 애플리케이션을 실제 사용자에게 제공하기 위한 일련의 프로세스를 의미
- 개발 완료 후 사용자가 애플리케이션을 사용할 수 있게하는 과정. 신뢰성, 확장성, 유지보수성과 밀접하게 연관됨
배포의 중요성
- 단순히 사용 가능 상태로 만드는 것이 아니라, 시스템의 안정성, 성능 그리고 확장성을 보장해야하는 절차
- 배포 과정에서 적절한 계획과 검증이 이뤄지지 않으면 서비스 중단, 성능 저하, 데이터 손실 등의 문제가 발생할 수 있다.
1. 배포와 신뢰성
- 신뢰성을 보장하는데 핵심적인 역할을 한다. 배포 프로세스에서 장애가 발생하지 않도록해야하고, 일어나더라도 신속하게 복구하는 전략이 필요함
- 장애 대응 계획
- 무중단 운영
- failOver
- 데이터 복제 및 백업 전략
- self-Healing
2. 배포와 확장성
- 시스템의 확장성을 보장하기 위한 필수 절차다. 배포 후 트래픽이 급증할 수 있기에, 시스템이 이를 수용할 수 있도록 확장 가능한 구조로 배포해야 한다.
- 수평 확장
- autoScaling
- loadBalancing
- db sharding
3. 배포와 유지보수성
- 유지보수성에도 영향을 준다. 배포된 소프트웨어가 장기적으로 쉽게 관리되고, 수정 및 업데이트가 용이하도록 설계되어야 한다. 배포 후에도 새로운 기능을 추가하거나 문제를 수정할 때 쉽게 배포할 수 있어야 한다.
- modularization
- 코드 품질관리
- CI/CD
- Version Control