독서

[데이터 중심 애플리케이션 설계] 4장

오렌지색 귤 2023. 11. 15. 02:19
반응형

핵심 내용

 

1. 순회식 업그레이드는 정지 시간 없이 새로운 버전의 서비스를 출시 가능하게 하고 배포를 덜 위험하게 만든다.

 

2. 순회식 업그레이드 중이거나 여러 가지 다른 이유로 다양한 노드에서 다른 버전의 여러 애플리케이션 코드가 수행된다. 따라서 시스템을 흐르는 모든 데이터는 하위 호환성상위 호환성을 제공하는 방식으로 부호화해야 한다.

 

3. 다양한 데이터 부호화 형식으로는 JSON, XML, CSV 같은 텍스트 형식과 스리프트, 프로토콜 버퍼, 아브로 같은 이진 스키마 기반 형식이 존재한다.

 

 

 

배운 내용

 

1. 프로토콜 버퍼와 같은 구조화된 데이터 직렬화 방식에서 필드에 새로운 태그 번호를 부여하는 방식으로 스키마에 새로운 필드를 추가할 수 있다. 새로 추가되는 필드는 상위 호환성을 유지하려면 optional로 하거나 기본값을 가져야 한다. 또한, 각 필드에 고유한 태그 번호가 있는 동안에는 태그 번호가 계속 같은 의미를 가지므로 하위 호환성도 유지할 수 있다.


2. 아브로 스키마에는 태그 번호가 없고, 바이트열을 살펴보면 필드나 데이터타입을 식별하기 위한 정보가 없다. 따라서 아브로를 이용해 이진 데이터를 파싱하려면 정확히 같은 스키마를 사용하는 경우에만 이진 데이터를 올바르게 복호화할 수 있다.

 

3. REST는 프로토콜이 아니라 HTTP의 원칙을 토대로 한 설계 철학이다. REST는 간단한 데이터 타입을 강조하며 URL을 사용해 리소스를 식별하고 캐시 제어, 인증, 콘텐츠 유형 협상에 HTTP 기능을 사용한다.

 

4. 원격 프로시저 호출(RPC) 모델은 원격 네트워크 서비스 요청을 같은 프로세스 안에서 특정 프로그래밍 언어의 함수나 메서드를 호출하는 것과 동일하게 사용 가능하게 해준다. (이런 추상화를 위치 투명성이라 한다)

 

5. 액터 모델은 kafka, rabbitmq와 같은 메시징 브로커나 리액터, RxJava와 같은 리액티브 프로그래밍과는 다르다. 액터 모델은 동시성 관리와 상태 관리에 더 초점을 맞추며, Erlang, Akka와 같은 구현체가 존재한다.

 

 

 

찾아본 내용

 

1. 순회식 업그레이드에서 레코드 스키마의 수정으로 인한 데이터 유실을 방지하고 상위 및 하위 호환성을 유지하는 방법에는 여러 전략이 있습니다:



버전 관리: 레코드에 버전 필드를 추가하여 스키마 변경을 추적합니다. 이렇게 하면 서로 다른 버전의 스키마를 사용하는 레코드를 동시에 처리할 수 있습니다.

 

점진적 마이그레이션: 새로운 스키마로의 전환을 한 번에 수행하는 대신 점진적으로 수행합니다. 새 스키마를 도입할 때 기존 데이터를 새 형식으로 마이그레이션하고, 이 과정에서 데이터 유실을 최소화합니다.

 

호환 가능한 변경: 스키마 변경 시 하위 호환성을 유지하기 위해 추가만 하고 기존 필드를 제거하거나 변경하지 않는 방법입니다. 예를 들어, 새로운 필드를 추가할 때는 기본값을 설정하거나 선택적으로 만듭니다.

 

중앙 집중식 스키마 관리: 스키마 변경을 중앙에서 관리하여 모든 데이터 소스 및 소비자가 동일한 스키마 버전을 사용하도록 합니다.

 

데이터 검증 및 백업: 업그레이드 전에 데이터를 검증하고 백업하여 변경 중에 발생할 수 있는 데이터 손실을 방지합니다.

 

폴리글랏 퍼시스턴스: 다양한 데이터 저장 기술을 사용하여 하나의 저장소에서 지원하지 않는 기능을 다른 저장소에서 지원하게 함으로써 호환성 문제를 해결합니다.

 

피처 토글: 새로운 스키마와 관련된 기능을 활성화하거나 비활성화할 수 있는 기능 토글을 사용하여, 전체 시스템에 영향을 주지 않고도 새 스키마를 점진적으로 도입할 수 있습니다.

 


2. MySQL에서는 왜 대부분의 관계형 데이터베이스와는 달 기존 데이터를 다시 기록하지 않고 널을 기본값으로 갖는 새로운 칼럼을 추가하는 간단한 스키마 변경을 허용하지 않는가?

 

스토리지 엔진의 특성: MySQL에서는 여러 스토리지 엔진이 사용됩니다. InnoDB 같은 일부 엔진은 데이터와 인덱스를 클러스터형식으로 저장합니다. 이러한 구조에서는 새로운 칼럼을 추가할 때 기존의 모든 레코드를 재배치하거나 다시 쓰는 작업이 필요할 수 있습니다.


데이터 무결성 유지: MySQL은 데이터 무결성을 매우 중요하게 여깁니다. 스키마 변경 시 기존 데이터의 무결성을 유지하는 것이 중요한데, 이를 위해서는 데이터를 다시 쓰는 작업이 필요할 수 있습니다.


트랜잭션 안정성: InnoDB와 같은 스토리지 엔진은 트랜잭션 안정성을 제공합니다. 이는 스키마 변경 중에도 데이터 일관성과 무결성을 유지해야 함을 의미합니다. 때문에, 이런 변경이 발생할 때 전체 데이터를 검토하고 필요에 따라 재작성하는 과정이 필요할 수 있습니다.

 


3. gRPC는 외부 서비스에서 다른 서비스의 메서드를 직접 호출하고, 내부 함수에 접근을 맘대로 하는거야? 그럼 캡슐화나 보안이 안되는거 아냐?

 

gRPC (Google Remote Procedure Call)는 분산 시스템에서 서비스 간 통신을 위해 사용되는 프레임워크입니다. gRPC를 사용하면 한 서비스에서 다른 서비스의 메서드를 직접 호출할 수 있으며, 이는 마치 로컬 함수를 호출하는 것처럼 느껴질 수 있습니다. 그러나 이 과정에서 캡슐화와 보안이 손상되지는 않습니다.

 

캡슐화: gRPC는 메서드를 원격으로 호출하지만, 이는 서비스가 외부에 노출하도록 명시적으로 정의된 인터페이스를 통해서만 가능합니다. 개발자는 어떤 메서드가 외부에서 접근 가능할지 결정할 수 있으며, 내부 로직은 숨겨질 수 있습니다. 이는 객체 지향 프로그래밍의 캡슐화 원칙과 유사합니다.


보안: gRPC 자체가 보안 문제를 일으키지는 않습니다. 오히려 gRPC는 TLS/SSL을 통한 보안 통신을 지원하며, 인증 및 권한 부여 메커니즘을 통해 보안을 강화할 수 있습니다. 이는 서비스 간 통신이 안전하게 이루어지도록 보장합니다.


접근 제어: gRPC 서비스를 설계할 때, 개발자는 특정 메서드에 대한 접근 권한을 제어할 수 있습니다. 예를 들어, 특정 역할이나 사용자만이 특정 메서드를 호출할 수 있도록 설정할 수 있습니다.


인터페이스 정의: gRPC에서는 Protocol Buffers (protobuf)를 사용하여 서비스 인터페이스를 정의합니다. 이는 어떤 메서드가 외부에 노출될지, 그리고 이러한 메서드들이 어떤 매개변수와 반환 타입을 갖는지 명확하게 지정합니다.

 

 

4. 스레드를 직접 처리하는 대신 로직이 액터에 캡슐화된다 의 의미는 애플리케이션의 동시성과 병렬 처리 관리가 액터라는 개념을 통해 이루어진다는 것을 의미한다.

 

액터 모델: 액터 모델은 동시성을 처리하는 프로그래밍 패러다임입니다. 이 모델에서, 액터는 독립적인 연산 단위로서, 메시지를 받고, 처리하고, 결과를 다시 메시지로 보낼 수 있습니다.


캡슐화의 중요성: 각 액터는 자신만의 상태를 가지고, 다른 액터와 메시지를 통해서만 상호작용합니다. 이는 액터가 자신의 상태를 스스로 관리하며, 다른 액터나 스레드에 의해 직접적으로 변경되지 않는다는 것을 의미합니다. 즉, 액터 내부의 로직과 상태는 외부로부터 캡슐화되어 보호됩니다.


스레드 관리의 단순화: 전통적인 동시성 프로그래밍에서 개발자는 스레드를 직접 생성하고 관리해야 하며, 데드락, 레이스 컨디션과 같은 복잡한 문제를 해결해야 합니다. 하지만 액터 모델에서는 이러한 복잡성을 액터 시스템이 대신 처리합니다. 개발자는 액터 간의 메시지 전송에만 집중하면 되며, 액터 시스템이 스레드 할당, 메시지 큐 관리 등을 자동으로 처리합니다.


동시성과 병렬처리의 안전성: 액터 모델은 메시지 기반 통신을 사용하기 때문에, 여러 액터가 동시에 활동하더라도 서로의 상태를 직접적으로 변경하지 않습니다. 이는 데이터 경쟁(race condition)과 같은 동시성 문제를 크게 줄여줍니다.

 

 

 

궁금한 내용

 

1. 순회식 업그레이드(단계적 롤아웃) 방식은 k8s 환경에서 주로 하는 배포 방식인가요?

 

순회식 업그레이드(단계적 롤아웃) 방식은 Kubernetes(K8s) 환경에서 매우 일반적으로 사용되는 배포 방식 중 하나입니다. 이 방식은 새 버전의 애플리케이션을 점진적으로 배포하면서 기존 버전의 인스턴스를 하나씩 대체하는 방식으로 작동합니다.


점진적 업데이트: 순회식 업그레이드를 통해 새 버전의 애플리케이션을 서서히 배포함으로써, 모든 인스턴스를 한 번에 업그레이드하는 리스크를 피할 수 있습니다. 이는 동시에 발생할 수 있는 다운타임과 문제점을 최소화합니다.


트래픽 관리와 부하 분산: 순회식 업그레이드 중에는 새로운 버전과 이전 버전의 인스턴스가 동시에 실행됩니다. 이를 통해 트래픽을 새롭고 오래된 버전 사이에 분산시키고, 부하가 한쪽에 집중되는 것을 방지할 수 있습니다.


롤백 용이성: 업그레이드 중 문제가 발생하는 경우, Kubernetes는 자동으로 이전 버전으로 롤백할 수 있는 기능을 제공합니다. 이는 업그레이드 프로세스의 안전성을 보장합니다.


확장성과 유연성: Kubernetes의 순회식 업그레이드는 확장성이 높고, 다양한 배포 요구사항에 맞춰 조정할 수 있습니다. 예를 들어, 업그레이드 속도, 업데이트 대상 인스턴스의 수, 헬스 체크 방법 등을 사용자가 정의할 수 있습니다.


순회식 업그레이드는 Kubernetes의 Deployment 리소스를 통해 구현되며, 이것은 Kubernetes의 핵심 기능 중 하나로 광범위하게 사용됩니다. 이 방식은 안정성과 유지보수성을 중시하는 현대적인 클라우드 네이티브 애플리케이션 배포에 적합합니다.

 


2. 데이터베이스에 값을 저장하고 미래에 찾아보는 경우 하위 호환성은 분명히 필요하다. 마찬가지로 순회식 업그레이드로 배포를 하게 되어 갱신된 인스턴스와 갱신되지 않은 인스턴스가 동시에 존재하게 된다면, 새로운 버전으로 저장하고 예전 버전으로 값을 읽을 가능성이 있기에 상위 호환성도 필요하게 된다. 실제로 순회식 업그레이드를 적용해봤거나 해야한다면 어느 정도 수준의 상위 및 하위 호환성을 유지해야할까요?

반응형