🏠 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 어플리케이션
오늘날 많은 어플리케이션은 계산 중심에서 데이터 중심적으로 변했다. 더이상 CPU 성능이 아닌 데이터의 양, 복잡도, 변화 속도에 어플리케이션이 영향을 받는다는 뜻이다. 때문에 이제부터 개발자는 어플리케이션 개발자 뿐만 아니라 설계자여야 한다.
엔지니어링 관점에서 소프트웨어 시스템에서 중요하게 여기는 3가지를 자세하게 살펴보자
- 신뢰성
- 확장성
- 유지보수성
🔥 신뢰성
하드웨어나 소프트웨어 결험, 인적 오류같은 역경에 직면하더라도 시스템은 지속적으로 올바르게 동작해야한다.
즉, 무엇가 잘못되더라도 지속적으로 올바르게 동작함을 신뢰성의 의미로 이해할 수 있다.
소프트웨어 관점에서 잘못될 수 있는 일을 결함이라고 부르며, 결함을 예측하고 대처할 수 있는 시스템을 내결함성, 탄력성을 지녔다고 할 수 있다.
결함은 장애와 구별된다. 장애는 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우를 의미한다. 따라서 결함으로 인해 장애가 발생하지 않도록 결함성 구조를 설계하는 것이 좋다. 결함 유형으로는 다음과 같이 3가지로 정의할 수 있다.
- 하드웨어 결함
- 소프트웨어 결함
- 인적 오류
🌈 하드웨어 결함
하드디스크가 고장나고, 램에 결함이 생기고, 대규모 정전사태가 일어나는 것과 같은 결함을 의미한다.
실제로 데이터센터에서 일하는 경우 늘상 일어난다고 말한다.
보통 대응으로는 각 하드웨어 구성 요소에 중복을 추가해서 해결한다고 한다. 백업 장비를 사용한다고 생각해도 좋다.
🌈 소프트웨어 결함
하드웨어 결함과 독립적이지 않고 약하게 상관관계가 있을 수도 있다.
소프트웨어 결함을 예상하기 어렵고 노드간 상관관계가 있을 수도 있다. 예를 들면 리눅스 커널 버그 혹은 공유 자원을 과도하게 사용하는 프로세스, 시스템 속도가 느려져 잘못된 응답을 반환하는 서비스 등이 있을 수 있다.
이는 예측하고 해결하기 어렵다. 시스템의 상호작용에 대해 주의깊게 생각하고 빈틈없게 테스트코드를 작성하고, 모니터링 등 여러 작은 일들이 해당 결함 예방에 도움을 줄 수 있다
🌈 인적 결함
말 그대로 운영 중 사람에게 나오는 결함이다.
저자는 5가지 원칙을 지켜 인적 결함에 대해 대비하라고 권고한다.
- 오류의 가능성을 최소화하는 방향으로 시스템을 설계해라. (추상화)
- 사람이 많이 실수하는 장소에서 장애가 발생할 수 있는 부분을 분리하라.
- 단위테스트부터 통합테스트, 수동테스트까지 모든 수준에서 철저하게 테스트하라.
- 장애 발생의 영향을 최소화하기 위해 인적 오류를 빠르게 쉽게 복구할 수 있게하라.
- 성능 지표와 오류율 같은 상세하고 명확환 모니터링을 제공하라.
🔥 확장성
현재 시스템이 안정적으로 동작한다고 해서 미래에도 안정적으로 동작한다는 보장은 없다.
가장 일반적인 이유는 부하 증가 때문이다. 트래픽이 증가했을 때 어플리케이션이 정상적으로 동작하게끔 설계해야한다.
현재 부하를 간결하게 기술해야한다. 부하는 부하 매개변수로 나타낼 수 있다.
부하 매개변수로는 웹서버의 초당 요청 수, DB의 읽기 대 쓰기 비율, 채팅방의 동시 활성 사용자 수, 캐시 적중률 등이 될 수 있다.
책에서는 트위터 어플리케이션을 예시로 두었다.
기본적으로 트위터 어플리케이션의 동작은 두가지 동작으로 이루어진다.
- 새 트윗 올리기
- 홈 타임라인 불러오기
일반적으로 1번 작업보다는 2번 작업의 수가 수백배 많다고 분석하였다. 때문에 2번 작업의 부하를 줄이는게 핵심이다.
때문에 트위터 개발자들은 새 트윗을 올릴 때 캐시를 업데이트해, 홈 타임라인을 불러올 때에 대한 리소스를 줄였다.
즉 비교적 작업 수가 적은 1번 작업에 리소스를 증가시켜, 비교적 작업 수가 많은 2번 작업에 리소스를 줄인 샘이다.
하지만 새 트윗을 올릴 때에는 해당 팔로워의 타임라인 캐시를 모두 업데이트 해야하는데, 팔로우 수가 엄청 많은 유저가 새 트윗을 올릴 때에는 해당 방법에 대한 리소스가 너무 커지는 문제점을 발견했다.
트위터 개발자들은 예외적으로 유명인의 트윗은 별도로 가져와 읽는 시점에 사용자의 홈 타임라인에 합치는 혼합적 방법으로 서비스를 구현하였다.
이처럼 해당 어플리케이션의 부하 매개변수를 적절히 구분하고 분석하여 서비스에 적용할 줄 알아야한다.
🌈 성능 기술하기
시스템의 부하를 기술하면 부하가 증가할 때 어떤 일이 일어나는지 조사할 수 있다.
시스템의 성능을 분석할 때에는 보통 응답시간을 비교한다. 즉 클라이언트가 요청을 보내고 응답을 받는 사이의 시간이다.
응답시간은 지연시간과는 조금 다르다. 응답시간은 클라이언트 관점에서 보는 시간으로, 네트워크 지연과 큐 지연을 모두 포함한다.
같은 요청이라도 응답시간은 다를 수 있기 때문에, 평균적으로 볼지, 중앙값으로 볼지, 꼬리 지연 시간으로 볼지, 백분위로 볼지 해당 어플리케이션의 특성을 분석해 성능을 기술해야한다.
🌈 부하 대응 접근 방식
부하 매개변수가 증가하더라도 좋은 성능을 유지하려면 어떻게 하면 좋을까 ?
보통 확장성과 관련해서는 스케일 업과 스케일 아웃을 많이 고려한다.
단일 장비에서 고사양 장비는 매우 비싸기 때문에 실용적인 접근 방식의 조합이 필요하다.
일부 시스템은 탄력적이다. 즉 부하를 감지하고 자동으로 컴퓨팅 자원을 추가해준다.
이는 예측할 수 없이 부하가 증가할 때에는 유용하지만, 수동으로 확장하는 시스템이 더 간단하고 운영상 예상치 못한 일이 더 적다고 한다.
즉 부하 매개변수에 대한 가정과 측정을 올바르게 해야하낟.
특히 스타트업 같은 경우는 초기 단계에서 검증되지 않은 제품에 대해 부하를 대비하기 보다는, 빠르게 반복해서 제품 기능을 개선하는 작업이 필요하다고 말한다.
🔥 유지보수성
소프트웨어 개발비용은 사실 초기 개발이 아닌 유지보수에서 일어난다.
우리는 유지보수의 고통을 최소화하고 레거시 소프트웨어를 직접 만들지 않도록 유의해서 설계해야한다.
그러기 위해 지켜야할 소프트웨어 설계 원칙 3가지가 있다.
- 운영성
- 단순성
- 발전성
🌈 운영성
운영 중 일부 측면은 자동화 할 수 있고, 자동화 해야한다고 말한다.
좋은 운영성이란 동일하게 반복되는 테스크를 쉽게 수행하게끔 만들어 운영팀이 고부가가치 활동에 집중할 수 있게 만드는 것을 의미한다.
- 좋은 모니터링으로 런타임 동작과 내부에 대한 가시성 제공
- 좋은 문서와 이해하기 쉬운 운영 모델 제공
- 예측 가능하게 동작하고 예기치 않은 상황을 최소화
- 표준 도구를 이용해 자동화와 통합을 위한 우수한 자원을 제공 등
🌈 단순성
시스템의 복잡도는 다양한 증상으로 나타난다. 모듈 간 강한 커플링, 복잡한 의존성, 일관성 없는 명명과 용어 등등
복잡도 때문에 시스템 유지보수가 어려울 때 예산과 일정은 증가한다.
복잡도를 줄이라는 것이 반드시 기능을 줄이라는 의미는 아니다. 복잡도를 제거하기 위한 최상의 도구는 추상화이다.
좋은 추상화는 깔끔하고 직관적인 외관 아래로 많은 세부 구현을 숨길 수 있다. 또한 다양한 어플리케이션에서 재사용 가능하다.
책 전반에 걸쳐 좋은 추상화를 눈여겨 본다고 하니 기대된다.
현재 필자가 하고있는 추상화는 SQL 처리, DB 작업은 Repository 단에서 처리하고, 핵심 로직은 Service 단에서 Repository 객체를 주입받아 사용하여 서비스에서는 DB 처리에 대해 내부 동작은 알 필요가 없게 처리하고 있다.
🌈 발전성
시스템의 요구사항이 영원히 바뀌지 않을 가능성은 매우 적다. 우리는 변화하는 요구사항에 맞게 시스템을 발전시켜야 한다.
데이터 시스템의 변경을 쉽게하는 방법은 시스템의 간단함과 추상화와 밀접한 관계가 있다고 한다.
'개인 공부 > 스터디' 카테고리의 다른 글
[이펙티브 자바] equals 재정의 (0) | 2023.06.13 |
---|---|
[이펙티브 자바] 상속보다는 컴포지션을 사용하라 (1) | 2023.06.13 |
[이펙티브 자바] Comparable (0) | 2023.05.30 |
[이펙티브 자바] 불필요한 객체 생성 (2) | 2023.05.16 |
[이펙티브 자바] Builder (0) | 2023.05.09 |