요구 사항 : "채널 서버와 게임 서버 모두에서 아이템을 사용 할 수 있게 해주세요"
개발자 관점에서 해석 -> 서로 다른 분산 컴포넌트에서 같은 기능들을 사용 할 수 있게 해주세요
용어 정의 : 컴포넌트. 분산 시스템 구성 요소.

문제 상황 : "채널 서버와 게임 서버는 서로 다른 컴포넌트다"
채널 서버와 게임 서버가 가지고 있는 데이터와 데이터를 유지하는 자료 구조가 다르기 때문에 추상적으로는 '아이템 사용'이라는 같은 기능이지만 구현 방법은 서로 다르다.

예를 들어 채널 서버는 데이터 A, B, C를 항상 유지하고 있고, 게임서버는 B 데이터만을 가지고 있다고 가정하자. 아이템 사용을 위해서는 A, B, C 데이터가 필요하다고 할 때, 채널 서버는 필요한 데이터들을 이미 가지고 있으므로 아이템 사용에 별다른 준비 과정이 필요 없지만 게임 서버는 A 만 가지고 있으므로 B, C를 얻어 오는 부분이 따로 구현 되어야 한다. 또한 채널 서버는 아이템 사용 결과만을 클라이언트에게 리턴하면 되지만 게임서버는 아이템 효과들을 캐릭터 정보에 반영 해야하는 이슈 처럼 아이템 사용 결과를 처리하는 방식도 두 컴포넌트간에 서로 다르다.

따라서 기능이 변경 되는 경우 그에 맞춰 항상 두 곳을 수정 해야 하는 이슈가 발생한다.

생각의 시작..기능 변경시 두 곳을 고치지 않고 공통 기능을 사용하는 방법이 없을까?

1. 코드 레벨에서의 공유
동일한 코드를 파일 링크 등을 통해 두 컴포넌트에서 공유

장점 :

- 동일한 코드를 재사용 할 수 있는 경우라면 직관적이며 구현이 간단 하다는 장점이 있다
- 위와 같이 동일 코드를 적용 할 수 없는 경우라면  코드 레벨에서 공유는 장점이 없다.
단점 :
- 결국 호출 부분 외에 다른 부분들은 서로 다른 code snippet을 가지게 되며 이는 파일 링크 등을 통한 코드 레벨에서 공유는 기능 변경 이슈 발생 시 항상 두 부분을 동시에 수정해야 하는 유지 보수 비용을 크게 감소 시키진 못한다.
- #ifdef 등 컴파일 플래그를 이용한 공유는 코드 분석 및 유지 보수 비용 증가
- 개발자는 항상 하나의 기능이 두 컴포넌트에 구현 되어 있음을 알아야 하는 유지 보수 비용 증가

2. 모듈(dll, lib or so) 레벨에서 공유
공통 기능을 모듈화 시키고 각 컴포넌트에서 모듈을 import 하는 방식으로 공유

장점 :

- 추상화(eg. "아이템을 사용한다. 하지만 난 자세한 사항은 모르겠다")가 잘 정의되었다는 가정하에 중복 코드 개발 비용을 줄일 수 있다.
단점 :
- 추상화를 위해 모듈내에서 사용하는 데이터가 이미 컴포넌트에 존재하고 있는 데이터와 중복이 발생하는 경우 저장 공간 낭비, 성능 낭비등의 문제와 동일 데이터에 대한 동기화 문제가 발생 할 수 있다.
- 성능이나 기존 컴포넌트 데이터들과의 호환성을 위해 각 컴포넌트마다 다른 추상화 모듈을 제공한다면 코드레벨 공유와 같은 단점을 가지게 된다.
- 컨넥션이 변경 될때마다 데이터 로딩과 같은 초기화 작업들을 다시 해줘야 한다. 컨넥션이 자주 바뀌고 기능의 사용이 빈번하다면 성능 이슈가 발생 할수 있다.
- 모듈에서의 장애가 서버 컴포넌트까지 확장 된다. 만일 장애 파급 효과를 제한하기 위해 중요한 기능들만 따로 모아 컴포넌트를 분리한 경우라면 분리의 의미가 없어진다

3. 컴포넌트 레벨에서 공유(back-end 방식)
공통 기능을 처리하는 back end 서버를 두고 front-end 서버들이 질의 하는 방식

장점 :
- '모듈 레벨에서 공유'의 장점에 추가하여 컨넥션이 변경 되더라도 기존 데이터들을 유지 할 수도 있다.
- 장애 파급 효과를 제한 할수 있으며 하나의 컴포넌트에서 장애가 나도 다른 컴포넌트에 질의 하는 형식으로 장애를 극복 할 수 있다.
단점 :
- 추가적인 메시지 트래픽 비용
- front-end <-> back-end 컴포넌트간 메시지를 릴레이 하는 기능 추가 구현 비용. 메시지 내용이 변경 되는 경우 릴레이 부분도 항상 같이 수정해 줘야 하므로 새로운 유지 보수 포인트가 발생 할 수 있다.
- 메시지 시퀀스가 길어짐으로써 시스템 복잡도 증가

4. 컴포넌트 레벨에서 공유(front-end 방식)
클라이언트와 직접 연결을 맺는 공통 기능 컴포넌트를 두고 클라이언트가 계속 연결을 유지하며 공통 기능이 필요할 때마다 질의하는 방식

장점 :
 - back-end 컴포넌트 레벨 공유 방식의 장점에 추가 하여 컨넥션이 변경 될 이슈가 없으므로 클라이언트 접속 동안 데이터를 계속 유지 할 수 있다.
단점 :
- 컨넥션 위치 관리 비용, 데이터 동기화 비용이 추가 된다.
예를 들어 게임 서버에 위치한 사용자가 아이템을 사용하게되면 게임 서버에 접속한 사용자의 데이터를 업데이트 해야 하기 때문에 공통기는 컴포넌트는 또다른 컨넥션이 어느 컴포넌트에 접속 중인지를 항상 파악하고 있어야 한다.
Posted by kukuta

댓글을 달아 주세요