MariaDB에서의 쿼리 계획(Query plan) 활용

게임 서비스 시 서버 측면에서 성능상 문제가 되는 부분은 DB와 관련된 부분일 것이다. 과거에는 거의 모든 게임 데이터 관리 및 최종 동기화 등을 RDBMS에 의존하였기 때문에 쿼리 최적화는 게임 서버 최적화에서 매우 중요한 부분이었다. 최근에는 성능상의 이유로 캐시나 NoSQL 을 이용하는 경우가 많지만, 결제 관련 내용이나 사용자 간 거래 등 atomic 한 처리가 필요한 데이터들을 관리하는 데는 여전히 RDBMS를 사용하는 경우도 많다. 또한 이러한 결제나 거래 관련 데이터들은 통계 처리 등의 이유로 복잡한 쿼리의 대상이 되는 경우가 많기에 아직도 RDBMS 쿼리 튜닝은 게임 서버 성능 최적화에서 적지 않은 비중을 차지한다.

쿼리 최적화시에는 실행 시간을 기반으로 한 프로파일링이 크게 의미가 없다. 쿼리의 실행 시간에 가장 큰 영향을 주는 요소들은 RDBMS가 설치된 머신의 스펙과 쿼리의 대상이 되는 레코드의 수, 그리고 인덱스 접근/ 사용 방식과 중첩 쿼리의 실행 순서 등 쿼리 자체의 실행 과정이다. 이 중 머신의 스펙과 대상 레코드의 수는 최적화의 대상으로 보기는 어렵다. 따라서 최적화의 대상은 쿼리 실행 과정인데, 이는 단순히 실행 시간만을 측정해서는 알 수 없기 때문이다.

따라서 여러 RDBMS(Mysql, Mariadb, Oracle, Postgresql 등)에서는 어떠한 쿼리가 주어지면 해당 쿼리를 어떤 순서로 어떤 데이터를 활용하여 처리하겠다는, 쿼리 계획(query plan) 을 보여주는 기능을 제공한다.

Mariadb 에서는 쿼리 계획을 확인하는 명령어를 두 개 제공한다. EXPLAIN과 ANALYZE가 그것이다. EXPLAIN는 예상되는 실행 계획을 보여주고, ANALYZE는 쿼리를 실제 실행한 후 실행한 쿼리 계획을 보여준다. 언뜻 보기엔 ANALYZE가 더 유용해 보이지만, 쿼리 실행 시 디비에 부하가 가해질 수 있고, 레코드가 늘어나거나 하면 실행 계획 또한 바뀔 수 있으므로 실 서비스에서 실행시와 동일한 정보를 알려주지는 않는다. 두 명령어가 제공하는 쿼리 계획에 대한 정보는 같다.

Mariadb는 (10.0.1 이후부터) SELECT, UPDATE, DELETE 쿼리의 실행 계획을 조회하는 기능을 제공한다. UPDATE와 DELETE의 경우 각각 수정/삭제할 대상 레코드를 어떻게 찾느냐에 대한 계획을 보여주기에 실행 계획은 SELECT의 그것과 큰 차이가 없다.

EXPLAIN을 이용하여 쿼리 계획을 보는 방법은 간단하다. 실행할 쿼리 앞에 EXPLAIN을 붙여 주면 된다.

이미지

EXPLAIN을 실행하면 위와 같은 결과가 출력된다. JOIN이나 서브 쿼리가 포함되어 여러 단계의 처리가 필요한 경우, 각 단계별로 실행 계획을 보여준다.

쿼리 계획에는 다음 항목들이 표시된다.

● id : 대상 쿼리문에 JOIN이 포함되어 있을 때, 어떠한 순서로 테이블이 JOIN되는지를 나타내는 값이다.

● select_type : 각 단계를 실행할 때 어떤 종류의 SELECT가 실행되었는지를 나타낸다. 최적화 시에는 크게 중요하지는 않으나, 값이 DEPENDENT SUBQUERY, 혹은 DEPENDENT UNION 인 경우 의존성 등의 문제로 쿼리가 특정 순서로만 실행되어야 함을 뜻하므로 비효율적인 쿼리일 가능성이 있다.

● table : 해당 단계에서 접근하는 테이블의 이름이다. 실제 테이블, 혹은 임시 테이블일 수 있다.

● type : 테이블 내에서 접근이 필요한 레코드를 어떻게 찾았는지에 대한 정보이다.
인덱스 접근 여부 및 방식 등에 대한 내용도 포함하므로 쿼리 최적화 시 반드시 확인해야 할 값이다. 몇 가지 중요한 값에 대해서만 부연 설명하겠다.
 ○ system : 테이블 내에 레코드가 1개 이하인 경우이다. 이 경우에는 레코드를 더 추가한 후 다시 쿼리 계획을 확인하는 것이 좋다.
 ○ const, eq_ref : 해당 단계가 PK 나 유니크 인덱스 검색을 이용해 레코드에 접근함을 뜻한다. 일반적으로 가장 빠른 검색 방법이다.
 ○ ref : 인덱스를 이용하여 동등 비교 연산을 통해 레코드에 접근함을 뜻한다. 위의 두 개만은 못하지만, 역시 매우 빠른 검색 방법이다.
 ○ fulltext : 전문 인덱스(Fulltext Index) 를 이용하여 레코드에 접근함을 뜻한다. 전문 인덱스는 일반적인 비교 연산으로 접근이 어려운 경우에 주로 사용되므로 최적화하기 어려운 경우가 많다.
 ○ range: 인덱스를 이용하여 값 비교 연산 ( , BETWEEN 등 )을 이용하여 레코드에 접근함을 뜻한다.
 ○ index : index 전체를 스캔해야만 필요한 레코드에 접근할 수 있음을 뜻한다. 풀 테이블 스캔보다는 빠르지만, 인덱스가 매우 큰 경우 등에는 비효율적이다.
 ○ ALL : 인덱스를 이용하여 필요한 레코드를 검색할 수 없어, 전체 테이블을 스캔해야만 함을 뜻한다. 당연히 테이블 내 레코드 수에 따라 실행 시간이 매우 길어지므로 적절한 인덱스 추가나 HINT 문 사용 등을 통해 최적화하는 것이 좋다.

● possible_keys : 레코드에 접근하기 위해 사용할 수 있는 키, 혹은 인덱스 목록을 보여준다. 실제로 사용된다는 의미가 아니므로 실제로 어떠한 키가 사용되었는지는 key 항목을 확인해야 한다.

● key, key_len : 레코드에 접근하기 위해 어떠한 index를 참조하는지, 인덱스 중 몇 바이트를 참조했는지에 대한 정보이다. key_len 은 둘 이상의 컬럼으로 구성된 인덱스를 참조했을 경우에만 의미가 있다.

● ref: 인덱스 검색 시 비교 연산 등에 사용되는 기준값을 보여준다. 최적화 시에는 큰 의미는 없다.

● rows : 필요한 레코드들을 추려내는 과정에서 몇 개의 레코드에 접근해야 하는지를 예측하여 보여준다.

● extra : 이상의 항목 외의 특이 사항들이 있다면 해당 내용을 표시해준다. 예를 들어, 접근해야 하는 컬럼이 모두 인덱스에 포함되어 있어 인덱스 검사만으로 필요한 값을 반환할 수 있다면 Using index 가 표시된다. 때에 따라 성능에 영향을 줄 수 있는 값들이 있으므로, 최적화 시에 이 컬럼이 비어 있지 않다면 확인할 것을 권한다.

MariaDB는 쿼리 계획을 만들 때 인덱스의 크기나 수, 레코드의 수 등을 같이 고려하므로 같은 쿼리라 하더라도 실행 계획 조회 시점에 따라 실행 계획이 달라질 수 있다. 그러므로 유효한 데이터를 얻기 위해서는 될 수 있는 대로 실 서비스에서, 혹은 실 서비스와 최대한 비슷한 환경에서 실행 계획을 조회하는 것이 좋다.

한 가지 유의할 점은, MariaDB는 쿼리 계획을 만들 때 인덱스의 크기나 수, 레코드의 수 등을 같이 고려하므로 같은 쿼리라 하더라도 실행 계획 조회 시점에 따라 실행 계획이 달라질 수 있다. 그러므로 유효한 데이터를 얻기 위해서는 될 수 있는 한 실 서비스에서, 혹은 실 서비스와 최대한 비슷한 환경에서 실행 계획을 조회하는 것이 좋다.

지금까지 RDBMS 의 쿼리를 최적화할 때 쿼리 계획 조회가 왜 필요한지, 그리고 MariaDB 에서 쿼리 계획 조회 시 어떠한 정보들을 알 수 있는지에 대해 알아보았다. 쿼리 계획은 최적화에 필요한 모든 정보를 제공하지는 않지만 기본이 되는 정보를 제공해 주기에, 쿼리 최적화 시 꼭 한번은 쿼리 계획을 확인할 것을 권하고 싶다.

아이펀팩토리 아이펀 디플로이 테크니컬 디렉터 민영기

개발 환경, 테스트 환경, 그리고 라이브

서버 개발자에게 컴퓨팅 자원은 곧 비용이다. 대충 한 열 명의 동접마다 한대씩 서버를 할당한다면 누구나 더 편하게 서버를 개발할 수 있을지도 모르겠지만, 현대의 기술은 아직 우리에게 이런 여유(혹은 낭비)를 허용하지 않고 있다. 게다가 열 명당 하나씩 서버를 둘 수 있다손 치더라도, 이로 인해 엄청나게 늘어나는 서버의 수를 관리하는 서버에 몰리는 부하를 처리해야하는 골치아픈 문제는 결국 그대로 남아있게 된다. 그러므로 결국 서버를 최대한 최적화하고 적당한 하드웨어를 찾아서 배포하는 방법론은 당분간 어쩔 수 없는 서버 개발자의 숙명이다.

클라이언트 개발자가 여러 대의 단말에서 테스트 한다면, 서버 개발자는 다양한 환경에서 서버 환경을 구축하고 테스트하게 된다. 끝없이 수정한 코드를 다시 실행해볼 개발 서버, 개발팀, 기획팀, 사내, QA팀을 위한 테스트 서버, FGT나 CBT등을 위한 일정 규모의 라이브에 준하는 서버, 그리고 실제로 서비스하는 라이브 서버, 마지막으로 게임이 성공해서 새로운 서버를 열어야하는 경우까지.. 안드로이드와 iOS라는 꽤나 다른 OS에서 동일한 어플리케이션을 동시에 준비하는 클라이언트 개발자들의 노력도 대단하지만, 상황에 따라 소규모부터 대규모까지 동시에 서버 환경을 만들어내야하는 서버 개발자의 고생도 더하면 더하지 덜하진 않다.

그렇다면 각각의 상황에 맞춰 필요한 하드웨어의 미덕과 준비 방법은 어떻게 될까. 이번 칼럼에서는 이를 이야기해보려고 한다.

1. 개발 환경

의외로 많은 개발자들이 개발 환경 하드웨어의 중요성을 무시하곤한다. 개발 환경의 서버는 최적화되기 전의 코드를 수행한다. 또한 끝없이 코드를 컴파일해야 한다. 그러므로 개발 생산성과 테스트 용이성을 위하여, 개발 환경의 하드웨어는 그 어떤 환경보다도 빠르고 많은 CPU 코어, 이래도 될까 싶을 정도로 많은 메모리와 디스크 용량, 가능한 예산 내에서 무조건 최대한 빠른 형태의 IO를 지원하는 디스크를 확보해야한다.
강력한 하드웨어는 개발과 동시에 빠른 피드백이 이루어지는 팀 테스트와 수정을 동시에 진행하는 경우에도 도움이 된다. 예를들어 스크럼 같은 개발 방법론을 활용하여 빠르게 개발해보고 포스트모템을 진행하는 경우, 강력한 개발 환경에서 단시간 안에 코드를 바꾸고 컴파일해서 테스트 해볼 수 있을 때 가장 효율이 좋다.

2. 테스트 환경

테스트 환경은 다양한 파트의 요청사항에 따라 끝도 없이 늘어날 수 있다는 것이 특징이다. 동일한 환경을 쉽고 간편하게, 그리고 필요에 따라 적절한 수준의 하드웨어에 배포할 수 있도록 배려하는 것이 중요하다. 스트레스 테스트를 위해서는 가능한 분리된 인스턴스에서 각각의 로그와 프로파일링 정보를 얻어내는게 중요하다면, 펀테스트를 위해서는 소수의 인원이 즐겁게 즐길 수 있도록 유도하는 환경이 되어야 한다.

보통 테스트 환경에서 코드를 컴파일할 일은 거의 없다. 즉, 새로 만든 패키지를 빠르게 배포하는 것이 중요하고, 사용자의 수나 컨텐츠의 양에 따른 하드웨어 능력의 분배가 중요하다. 또한 쉽게 배포하는 만큼이나 만들어진 서버 환경을 쉽게 회수할 수 있는 것 역시 중요하다.
그러므로 내부에서 사용할 때에는 vm으로 여러 개의 인스턴스를 관리할 수 있도록 하거나, 클라우드 등에서 저렴한 하드웨어를 필요할 때마다 만들어서 사용하는 것이 좋다.

3. 라이브 환경

라이브 환경을 결정하는 것은 보통 서버 개발자가 아니라 퍼블리셔인 경우가 많다. 물론 그렇긴해도 일반적으로 대형 퍼블리셔가 관리하는 IDC거나, 클라우드로 서버를 배포하는 경우가 가장 흔하다.
이 경우 서버 개발자가 준비해야하는 것은 동접자에 따른 전체적인 서버의 수와 구성 방식이다. 그리고 이를 위해서는 잘 구성된 스트레스 테스트 환경과 성능 프로파일링 방법이 필요하다. 그러므로 라이브 환경 설정은 테스트 환경의 연장선에 있다고 할 수 있다. 라이브 서버에 새로운 서버를 추가하는 경우에도 이는 마찬가지이다. 이 때 사용자의 분산과 추가 작업의 양을 결정하는 것은 비슷한 환경에서 얼마나 테스트를 해보았느냐에 달려있다.
또한 라이브 환경 서버 설정은 비용과 밀접한 관련을 가지게 되므로, 예상 동접은 소화할 수 있되, 노는 서버가 없도록 조율할 필요가 있다. 동시에 넉넉한 서버를 확보하기위하여 서버 개발자는 프로젝트의 책임자에게 잘 설명하여 퍼블리셔를 설득할 수 있는 이론적 기반을 마련해줄 수 있다면 금상첨화일 것이다.

지금까지 서버의 환경에 따른 구성과 이를 위해 중요한 부분은 무엇인지, 어떻게 준비해야하는지를 간단히 살펴보았다. 실제로 어떤 서버를 얼마나 준비해야하는지는 서비스 별로 가이드를 하기에 녹록치 않은 것이 사실이다. 게임마다 로직이 다르고, 장르마다 필요한 서비스가 다르다. 또한 어떤 기능을 어떻게 최적화했느냐에 따라 필요한 하드웨어의 사양은 천차만별이다. 그렇다보니 물고기를 주기보다는 물고기를 잡는 방법을 알려주라는 탈무드의 말과 같이, 주로 원론적인 내용 위주로 정리하게 되었다. 이번에도 미약하나마 서버 개발자들의 고민을 조금이라도 해결해주기를 바라며 이 칼럼을 마친다.

아이펀팩토리 박근환 TD

SQL 의 CAP 이론과 NoSQL 의 BASE

CAP 이론

분산 시스템 설계에 많이 인용되는 CAP 이론은 UC Berkeley 의 Eric Brewer 교수님이 제안한 개념이다. 분산 시스템 설계니 당연히 한 대의 서버로 이루어진 시스템이 아니라 여러 서버로 이루어진 시스템을 가정하는데, Consistency, Availability, Partition Tolerance 라는 세 가지 속성의 약자를 따서 CAP 라고 이름이지어진 이 개념은 Partition tolerance 한 시스템을 구현하기 위해서는 Consistency 나 Availability 둘 다를 얻을 수 없음을 의미한다. 좀 더 쉽게 말하면 C, A, P 이 세 속성 중에 기껏해야 두 개 밖에 취할 수 없다는 뜻이다.

여기서 Consistency 는 다른 서버에서도 가장 최근에 쓰여진 데이터가 읽혀야 됨을 의미한다. 예를 들어 A 와 B 라는 서버가 분산 시스템을 구성하고 있다면, A 라는 서버에 데이터를 쓰면 그 바로 뒤에 B 서버에서 누군가 그 데이터를 읽어들일 때 가장 최근의 데이터를 읽을 수 있어야 됨을 뜻한다.

Availability 는 보낸 요청에 대해서는 응답을 줄 수 있어야 됨을 의미한다. 그 응답이 가장 최근의 응답이 되었든, 아니면 살짝 이전의 데이터가 되었든말이다. 이 자체로는 너무 쉽고 당연한 것 같지만, 시스템이 “가장 최근의 데이터만을 줘야된다” 라는 제약이 붙게 되면, 가장 최근인지 아닌지 판단을 할 수 없는 경우 응답을 보내지 못할 수도 있게 된다는 점을 기억하자.

Partition tolerance 는 서버간의 통신에서 설령 네트워크가 끊긴 수준의 오류가 있더라도 시스템이 동작해야됨을 의미한다.

.

RDBMS 와 ACID 속성

RDBMS 는 Relational Database Management System 의 약자이다. 우리가 보통 DB 라고 말하는 것은 원칙적으로 DBMS 를 의미한다. 그러니 RDBMS 도 보통 RDB 라는 이름으로 부르기도 한다. R에 해당하는 Relation(al) 은 “데이터를 테이블 형태” 로 관리함을 의미한다. SQL 서버들이 테이블을 만들고 그 안에 데이터를 저장하는 것을 기억하는가? SQL 쿼리 문도 “CREATE TABLE …” 로 시작한다. 바로 SQL 이 RDB 이기 때문이다. 우리가 일반적으로 사용하는 DB 들은 이 RDB 형태들이다.

전통적인 RDB 에서는 Network Partition 을 크게 고려하지 않았다. DB 는 같은 데이터센터 안에, 심지어 같은 랙에 존재하고 있고 그 때문에 서버간 통신은 굉장히 잘 관리가 되는 안정적인 상황이었기 때문이다.

대신 RDB 에서는 ACID 라는 속성을 중요하게 생각해왔다. Atomicity, Consistency, Isolation, Durability 의 약자를 모아서 단어를 만든 것이다.

Atomicity 는 관련된 작업들은 전부 반영되거나 아니면 하나도 반영이 안되거나 해야된다는 것을 의미한다. “All or nothing” 인데, 쉽게 생각해서 우리가 SQL 에 transaction 을 만들면 그 안의 작업들이 모두 다같이 반영되어야 되는 것을 생각해보면 이해가 쉬울 것이다.

Consistency 는 CAP 의 consistency 와는 약간 다르다. CAP 에서는 서로 다른 서버라 하더라도 가장 최근 데이터를 반환함을 의미하지만, 여기서 consistency 는 DB 의 상태가 늘 일관된 상태를 유지해야됨을 의미한다. 예를 들어 DB 데이터의 속성이나 테이블 내 제약 등이 지정되어있는 경우 이를 준수하는 상황이 계속 일관되게 이어져야 된다는 것이다.

Isolation 은 여러 작업이 실행되더라도 그것이 순차적으로 실행된 것과 같은 결과를 내야됨을 의미한다. 만일 두 작업이 겹치는 것이 아예 없다면 이는 전혀 상관없이 동시에 실행될 수 있어야 되고, 만일 겹치는 부분이 있으면 순서대로 처리가 되어야지 겹쳐서 처리되어 데이터가 이상한 상태가 되어서는 안된다는 것을 뜻한다.

Durability 는 일단 작업이 완료 되었다고 리포팅이 되었다면 그게 DB 에 영구적으로 반영이 되어야 함을 의미한다. 설령 DB 가 크래쉬 하더라도 말이다.

.

NoSQL 등장의 배경

앞서 언급한 것처럼 DB 에서는 Partition 의 상황보다는 ACID 를 훨씬 중요한 가치로 생각을 하고 그쪽으로 많은 연구들이 이루어졌다. 그러나 구글이나 아마존, 페이스북 등 인터넷 회사들의 경우 데이터 센터가 여러곳에 분산되는 것이 일반적이다. 그런데 DB 는 한 곳에서만 가져다가 써야된다고 하면 이는 성능상의 큰 병목이 될 것이다. 그때문에 DB 역시 여러곳에 분산을 해야되는 상황이 되었고, 이 때문에 partition tolerance 를 중요한 가치로 인식하게 되었다.

앞에서 Partition tolerance 를 취하면 consistency 나 availability 둘 중 하나 밖에 취할 수 없다고 말을 했다. 그런데 실제 상황에서 consistency 가 그렇게까지 강하게 요구되지 않는 경우들이 많다는 것을 알게 됐다. 구글 검색을 했는데, 방금 crawler 가 긁어온 최신의 데이터를 꼭 보여줘야될 필요는 없지 않은가. 친구가 facebook 에 글을 쓰고 1-2초 지나서 내 화면에 뜬다고 문제가 될 건 없는 경우 등도 마찬가지다.

그래서 consistency 를 좀 약하게 보장하고 대신 시스템의  availability 를 좀 더 보장하는 방법들이 소개 되기 시작했다. 이 때 나온 개념이 eventual consistency 이다. 어느 한쪽이 데이터를 쓰더라도 다른쪽이 가장 최근의 데이터가 아니라 그 전의 데이터를 볼 수 있음을 의미한다. 이렇게 되면 “요청에 응답을 보내야 한다” 라는 availability 기준이 “이전 데이터라도” 보낼 수 있게 되니 크게 향상될 수 있다.

기존에 데이터를 쓰면 다음에 데이터를 읽는 쪽에서는 가장 최근의 데이터를 받아야 된다는 것은 이와 대비해서 strong consistency 라는 표현을 쓴다.  그리고 이런 속성의 DB 는 strong consistency 의 RDB 와는 사뭇 다르다. 그래서 기존의 SQL 과 다른 DB 로 NoSQL 이라는 이름을 얻게 되었다.

이런 속성으로 SQL 의 ACID 에 대응하는 NoSQL 의 주요 속성으로 BASE 를 이야기 한다. Basically Available, Soft-state, Eventual consistency 의 약자를 딴 것이다.

.

게임에서의 SQL 과 NoSQL 의 적용

NoSQL 이 처음 소개되었을 때에는 그것이 새로운 개념이다보니 기존 SQL 을 대체하는 우월한 개념처럼 잘못 인식되곤 했다. 하지만 SQL 과 NoSQL 은 가정하는 상황이 완전히 다른 별개의 솔루션들이다. 풀어야 되는 문제가 다르면 다른 솔루션을 적용해야되는 것처럼, SQL 과 NoSQL 역시 필요에 따라 다르게 사용하는 것이 바람직하다.

앞서 설명한 것처럼 SQL 은 strong consistency 를 보장한다. 그 때문에 consistency 가 중요한 상황에서는 SQL 이 더 적합하다. 그 때문에 많은 경우에 유저 데이터를 SQL 에 저장하는 것이다.

NoSQL 은 partition tolerance 와 availability 가 중요한 상황에서 유용하다. 디비가 먼 지역에 분산되어있고, 반드시 최신 데이터를 보여주지 않아도 되는 경우에 유용할 수 있다. 아니면 적어도 몇초 나 몇분 단위로 싱크만 맞아도 되는 경우라면 적합하다. 이런 이유로 많은 경우에 로그데이터를 NoSQL 에 저장하기도 한다.

이번 컬럼에서는 SQL 과 NoSQL 이 어떤 이유로 나오게 되었고 각각 어떤 것을 중요하게 생각하는지를 설명했다. 어떤 경우도 만능의 솔루션은 없다. 한 선택에 의한 트레이드 오프는 필연적이라고 할 수 있다. 각 솔루션의 배경에 맞게 적절하게 사용하는 것이 무엇보다 중요하다.

아이펀팩토리 문대경 대표

모바일 환경에서도 온라인 게임을 즐길 수 있는 이유

■ 상황 요약
게임을 플레이할 때 거의 무선 통신을 이용해서 게임을 한다. 스마트폰으로 WiFi 나 LTE 혹은 간혹 3G 통신을 쓰기도 하고, PC나 랩탑으로 게임을 할 때도 굳이 유선 랜을 쓰는게 선 없이 아니라 WiFi를 쓰기도 한다.

무선 통신으로 보내는 메시지는 얼마나 잘 깨질까?

1
▲ 출처 : https://xkcd.com/654/

  1. 여보세요. 메건 찾아? 걔 게임 중이야 / 알아. 근데 나초가 참 맛있는데.
  2. 나초 칩 위에 모두 치즈를 얹고, 쑤어 크림이랑 살사에 빠뜨리면…
  3. 으음 그거 맛있지. 재료도 다 있네. / 만들어 봐! / 그럴께 / 어서!
  4. (전자렌지 돌아가는 소리)
  5. 내 WiFi!
  6. (쾅) 헤드샷.

조금 과장되긴 했지만, 전자렌지를 쓰면 흔히 2.4 GHz 대역을 쓰는 WiFi 신호에 악영향을 준다. (사실 이건 WiFi가 쓰는 ISM 대역은 전자렌지가 방출하는 신호 때문에 간섭이 커서, 다른 용도로 할당하기 어려워서 특정 기준만 만족하면 아무나 쓸 수 있는 대역이라 그런 것이다.)


■ 문제
무선 환경 자체가 어떤 문제를 주는가? 물리적인 문제와 게임에서 흔히 쓰는 TCP 프로토콜 자체의 문제를 확인해보겠다.


무선 환경에 영향을 주는 것들
WiFi 처럼 주파수 대역을 다른 통신 방식 (Bluetooth, …) 이나 전자렌지 같은 전자 제품과 공유하지 않는 경우에도, 무선 통신은 여러 가지 문제를 겪는다.

우선 무선 신호를 쏘면 이 신호는 감쇄 (attenuation 혹은 path-loss) 된다. 물리법칙에 의해 먼거리를 갈수록 신호 세기가 줄어든다. 그래서 스마트폰 게임을 할 때 기지국 (base station) 과의 거리가 멀면 통신 상태가 고르지 않은 경우가 있다.

또한 무선 신호는 중간의 장애물 등으로 인해 음영지역 (shadowing) 이 생길 수 있다. 특히 WiFi 나 3G, 혹은 LTE 에서 사용하는 주파수는 30 Mhz 보다 큰 상대적으로 고주파 대역이다.(수백에서 수 기가 Hz 정도의 영역) 이 경우 사실상 무선 신호는 직진하는 것에 가깝다. 그래서 장애물이 있다면 신호 전송이 쉽지 않다. 다만 상대적으로 큰 물체 — 예를 들어 큰 빌딩 — 에는 신호가 “반사” 해서 신호가 가기는 한다. 반사되면서 세기가 좀 줄어들기는 해도 말이다.

마지막으로, 직진해서 온 신호, (여러 경로로 )반사된 신호가 모두 스마트폰 등에 도착한다. 그러면 진행해 온 경로에 따라서 도착하는 시간에 미묘한 차이가 생기고, 이에따라 상쇄/보강 간섭도 일어난다. 그리고 좀 더 미세한 수준에서 보면, (시간 상으로) 이전에 보낸 신호가 늦게 도착해서, (시간 상으로) 현재에 해당하는 신호와 서로 간섭을 일으켜서 문제를 일으키기도 한다.

덤으로, 모바일 게임의 경우 한 자리에서만 플레이하는 것도 아니다. 걸어다니면서 (포켓몬 고?), 혹은 자동차나 지하철, 기차 등을 타고 이동하면서 플레이하는 것도 흔하다. 이 경우 기지국과의 이동 방향/속도에 따라서 도플러 효과가 발생하고, 인접한 주파수 대역을 쓰는 다른 통신, 혹은 자신의 통신의 다른 부분에 (악)영향을 준다.

유선 통신인 10G Ethernet 의 경우, 상대적으로 나중에 나온 표준이고 데이터센터 환경에 가까운 곳에서 쓰기 때문에 비트 오류율 (BER) 목표치가 대략 1/10^12 다. 즉, 1 Tbit 정도 보내면 오류가 하나 이하인 확률을 의미한다. 대략 이런 환경에서 하나의 일반 이더넷 (ethernet) 프레임 하나 (1500 bytes 정도)가 잘못 전송될 확률은 약 0.00000015 % 정도다. 거의 오류 날 확률이 없는 셈.

반대로 LTE 환경에서 최대 전송속도일 때 쓰는 64-QAM 의 경우 BER은 1/10^3 수준까지 올라갈 수도 있다. 아주 나이브하게 계산하면 이더넷 프레임 하나를 보냈을 때 오류 없이 전송할 확률이 22% 쯤 된다.


TCP 특성
TCP는 현재의 인터넷을 움직이는 가장 중요한 전송 프로토콜입니다. 아마 네트워크 간 연결 (즉 인터넷 그 자체) 을 담당하는 IP 만큼이나 중요한 프로토콜로 그 역사가 길기도 합니다. TCP 설계 철학과 구현에서 모바일에 영향을 받는 부분은 아래와 같다.

  • 종단간 원칙 (end-to-end principle): 통신하는 양쪽 끝의 주체 — 게임이라면 게임 서버와 클라이언트 — 에서 필요로하는 정보만 프로토콜에 담으며, 이를 이용해서 잘 할 수 있는 것만 처리. 예를 들어 TCP는 종단간 RTT 를 측정하고, 이를 이용해서 그 사이에 들어갈 수 있는 (전송 중인) 메시지 양을 추정하고, 이 값을 이용해서 혼잡 제어를 수행한다.
  • 약한 체크섬: 현대적인 관점에서 볼 때, 단순히 전체 메시지의 바이트 합으로만 이뤄진 16bit 체크섬은 오류를 복구할 수 없으며, 검출할 수 있는 오류 수에도 한계가 있습니다.
  • (상대적으로) 오류 없는 하위 계층에 대한 가정: TCP 메시지가 중간에 손실되거나 중복 전송되면 메시지가 없어진 이유가 적대적인 무선 환경 (혹은 데이터링크/물리 계층) 때문이 아니라, 메시지가 너무 많아서 생긴 혼잡 제어로 인해 없어진것이라고 가정하는 것.

 
■ 해결책
앞서 말한 내용만 놓고보면, 현대의 무선 통신은 오류도 엄청 날 것 같고, 그 오류 위에서 TCP를 쓰는건 말도 안되는 일 같다. 하지만 지금 모바일 게임을 플레이하면 전혀 그런 문제를 겪는 것 같지 않다. 왜 그런지 살펴봅시다.


채널 코딩
무선으로 신호를 보내는 (논리적이고도 물리적인) 주파수 대역을 “채널” 이라고 부릅니다. 이 채널에 신호를 보낼 때 0을 0, 1을 1로 보내는게 아니라,

  • 오류가 있다면 이걸 감지하고
  • 감지된 오류가 있다면 수정할 수 있는 여러 bit의 심볼로 변환하는

방식으로 바꿔서 보냅니다. 이런 방식을 오류를 인지하면 재전송하는 방식 (Backward Error Correction) 에 빗대어 FEC (Forward Error Correction) 이라고 부른다. 이런 변환은 “채널 코딩” 이라고 부릅니다. 가장 흔히 쓰이고, 다른 더 복잡한 채널 코딩 방식의 기반이 되는 컨볼루션 코드 (convolutional code) 는 다음과 같이 만든다.

2

  • 입력이 들어올 때마다 하나씩 오른쪽 레지스터로 시프트
  • 레지스터에 들어있는 값과 입력값이 각각 + 로 표시한 xor 게이트를 거쳐서 출력으로.
  • 입력에 대한 처리가 끝나면, 레지스터 값들이 0이 될 때까지 0을 추가로 넣는다. (그 동안 값도 출력으로 사용)

예제로 든 컨볼루션 코드는 1/3 rate 코드라고 부르는데, 입력 값 대비 출력 값이 세 배라서. 인코딩한 결과는 받는 쪽에서 SW를 사용하는 경우 Viterbi 알고리즘을 써서 다이너믹 프로그래밍으로 디코딩하거나, 이에 대응하는 Trellis diagram 을 하드웨어로 만든 구현을 써서 디코딩한다.

3

위 인코더에서 m_1 은 상태에 포함되지 않는 입력 값이라서, 상태 값은 2 bit으로 표현되고, 시작과 끝은 00 이고 이걸 이용해서 오류를 수정한다. 여기서 0이 들어왔을 때의 상태 전이를 실선, 1이 들어왔을 때의 상태 전이를 점선으로 표현하고, 한 bit 들어올 때마다 오른 쪽으로 한 칸씩 움직이는 걸 의미한다. 시작과 끝이 00 이고, 일부 bit이 오류일 수 있을 때, 이 중 가장 높은 확률인 경로를 찾는 다이너믹 프로그래밍 알고리즘이 Viterbi 알고리즘이다. 위 다이어그램에서 해당 알고리즘으로 붉은 선으로 표시된 것이 해당 경로다. (0, 1, 0, 1 이 전송된 것으로 판정)

추가로 이런 컨볼루션 코드 출력 결과를 양 끝단에서 서로 동의한 형태로 일부 bit을 제거해서 — puncturing 이라고 부른다 — 통신 환경이 양호할 때 오류율을 거의 증가시키지 않으면서 전송량을 늘릴 수도 있다.

터보 코딩과 LDPC
이 컨볼루션 코드는 802.11 WLAN — 흔히 말하는 WiFi — 나 GSM 을 사용하는 3G 통신 등에 광범위하게 사용한다. 이런 컨볼루션 코드를 기반으로 해서 더 좋은 성능 — 더 좋은 채널 코딩 후의 BER — 을 갖는 채널 코딩도 존재한다. 802.11ac 에서는 LDPC 를 써서 추가적인 성능을 끌어내고, LTE나 심우주 임무 (deep-space mission) 에서는 터보코드를 이용한다.

터보코드는 두 개의 컨볼루션 코드를 써서, 데이터, 데이터에 대한 패리티, 데이터의 순서를 (미리 정의한 방법을 써서) 섞은 것(인터리브)에 대한 패리티를 보낸다. (두 패리티를 각각 컨볼루션 코드 인코더를 이용해서 생성합니다) 디코딩하는 단계가 “터보”에 해당하는 단계입니다. 이 부분은,

  • 데이터에 대한 디코딩 — 단 0, 1을 고르는게 아니라 0, 1일 확률을 구하는 — 을 수행
  • 인터리브한 데이터에 대한 디코딩 (역시 확률을 구함)
  • 다시 이 데이터를 가지고 데이터 디코딩 (첫 단계의 반복)
  • 인터리브에 대한 디코딩을 수행

이렇게 데이터 디코딩을 반복해서 BER을 향상시키는 방식으로 동작한다. 그리고 반복마다 BER이 내려간다. (즉 더 잘 디코딩한다)

예를 들어 LTE 시스템에서 얘기하는 1/10^3 정도의 오류율을 갖는 채널이 있을 때, 이 위에 터보 코드를 끼얹으면 약 1/10^6 이하의 (유효한) BER로 감소한다. 즉, 이더넷 프레임을 하나 보낸다면 오류가 발생할 확률이 78% 에서 1% 이하수준으로 떨어진다. 또한 이 BER에서 전송이 실패했을 때는, ARQ가 자동으로 실패한 메시지를 재전송한다. (TCP와는 달리 MAC 수준에서는 수학적으로 훨씬 나은 CRC나 패리티를 이용하기 때문에, 에러가 감지되지 않고 TCP까지 올라갈 확률은 천문학적으로 낮다.)

TCP 강화
TCP는 그 긴 역사에 걸맞게 처음 프로토콜을 작성할 때완 다른 현재의 환경에 적합한 변경 사항들을 추가하고 있다. 앞에서 언급한 TCP의 문제는 다음과 같은 방책을 가지고 있다.

– 종단간 원칙 (end-to-end principle)
TCP 성능을 위해서는 종단간 왕복 시간 (RTT)에 대한 추정이 어느 정도 정확해야 한다. TCP 에 대한 RFC-7323 에선 TCP 헤더에 타임스탬프를 추가해서 RTT를 더 정확하게 측정할 방법을 제공한다. 이를 이용해서 네트워크 지연 시간의 변동으로 RTT를 제대로 측정하지 못해서 재전송이나 타임아웃이 일어나는 문제를 줄일 수 있다.

또한 대부분의 TCP 알고리즘 향상분은 OS 업데이트로 반영될 수 있어서 개발자가 크게 신경쓰지 않아도 된다. 예를 들어, TCP timestamp 가 추가된 linux kernel 버전으로 올리면 해당 효과를 바로 받을 수 있다. (현재 이미 광범위하게 사용되는 확장 기능) 비슷하게, Android 커널 버전이 올라가거나, iOS 버전업에도 비슷한 효과가 따라올 수 있다.

– 약한 체크섬
TCP 수준의 체크섬 오류가 일어나려면,

  • ECC 를 사용한 채널 코딩에서 에러 복구가 실패
  • 링크 계층의 체크섬 검사에서 확인 실패하고 통과 (CRC32)
  • IP 체크섬 검사 통과 (다만 IP의 체크섬은 TCP 수준으로 약함)

해야 가능하다. 그리고 처음 두 단계에서 대부분 걸러지기 때문에 실제로 문제를 일으킬 가능성은 매우 낮다.

– 오류 없는 하위 계층
WiFi 나 3G UMTS, 그 이후의 LTE 환경 등에서는 전송 오류 등이 발생하지 않도록 채널 코딩을 수행한다. 또한 전송 오류가 발생했을 때에도, 자동 재전송 메커니즘이 내장되어있기 때문에, 단순히 전송을 포기하는 것이 아니라 자동으로 해당 프레임을 재전송해서 TCP 계층에서 혼잡이 발생했다고 잘못판단할 가능성을 낮춘다.

TCP에서 재전송을 위한 타임아웃이 굉장히 긴데 (같은 ACK이 3번 온게 아닌 이상 2 RTT), 링크 계층의 재전송 시간은 LTE 의 경우 약 8ms 등으로 굉장히 짧아서 링크 수준의 전송 실패로 TCP 재전송이 일어날 가능성은 낮다.

■ 결론
모바일 / 무선 환경에서도 별 무리 없이 게임을 즐길 수 있는 것은 TCP 수준, 그리고 무선 통신 수준에서 광범위한 최적화가 이루어져서다. 무선 통신 수준에서는 물리적인 무선 통신 용량에 거의 근접한 채널 코딩 알고리즘이 적용되고 있으며, 새 무선 표준이 나올 때마다 — 그리고 해당 무선 표준이 통신사 망에 넓게 적용될 때 마다 — 더 나은 통신 방식으로 발전한다. 비슷하게 OS 수준의 TCP 기능 강화도 지속적으로 이뤄지고 있다. 앞으로도 이런 변화가 계속 될거라 기대하며 글을 마칩니다.

아이펀팩토리 김진욱 CTO

2015년 12월 버전 APNs 변경 사항 정리

Apple과 google 에서 제공하는 푸시 서비스는 모바일 게임 운영 중 공지 및 광고, 이벤트 홍보 등 다양한 용도로 활용되는 기능이다. 푸시는 가장 널리 퍼진 모바일 디바이스 플랫폼인 ios/android 모두에서 사용할 수 있으며, 게임이 실행중이지 않더라도 메시지를 전송할 수 있다. 또한 전화번호 등의 개인정보를 수집,관리하지 않고도 게임 유저들에게 필요한 정보를 알릴 수 있다. 반면, 메시지 전송을 위해서는 전적으로 Google/Apple 에서 제공하는 플랫폼을 사용할 수 밖에 없어 이를 위한 구현 및 관리, 업데이트가 필요하다는 단점도 있다.

2016년,(정확히는 2015년 연말경부터) Google 과 Apple 모두 새로운 푸시 서비스를 공개하였다. Google은 기존의 gcm 대신 firebase 와 통합된 푸시 서비스인 FCM을, Apple 은 새로운 프로토콜, 새로운 인증 방식을 적용한 푸시 서비스를 선보였다. 양쪽 모두 새로운 기능들을 많이 선보였지만, 테스트용 대시보드나 퍼널 분석 등 사용성 위주의 변경사항이 대부분인 FCM과는 달리 APNs는 연결 인증 방식 및 전송 프로토콜 등 기능 외 적인 부분에서도 많은 부분에서 변화가 있었다. 그 결과 기존 방식으로 APNs 에 메시지 전송 요청을 전송하는 어플리케이션 서버를 마이그레이션하기 위해서는 요청 전송 부분을 새로 만들어야만 한다.( 반면 Google은 https://developers.google.com/cloud-messaging/faq 에서 확인 가능한 것처럼 기존 프로토콜을 그대로 사용 가능하기에, 신규 기능을 사용하지 않는다면 url 교체 작업 정도면 충분하다. )

새로운 APNs의 변경점 중, 어플리케이션 서버 개발 및 운영과 관련하여 눈에 띄는 것들은 다음과 같다.

전송 가능한 메세지 최대 크기 증가

최대 전송 가능 메세지 크기가 2KB 에서 4KB 로 변경되었다. I18N 지원이나 추가 데이터 전송 등의 이유로 메세지 크기가 점점 커지는 경향이 있었는데 이러한 부분을 고려한 변경점으로 보인다.

토큰 기반 인증 지원

기존에는 APNs에 푸시 요청을 전송하려면 반드시 TLS 인증서 기반의 인증이 필요했다. 이러한 방식을 사용하기 위해서는 항상 인증서 갱신 주기를 신경 써야 하며, 개발(sandbox, development)환경/ 제품(production)환경에 사용되는 인증서를 구분해야 하는 등 신경 써야 할 것들이 많았다.

새로운 APNs에서는 인증서 기반의 인증을 사용하지 않고도 푸시를 전송할 수 있는 방법을 제공한다. 전송 요청 시마다 토큰을 같이 전달하는 방식이며, JWT( https://jwt.io/ ) 방식의 토큰을 사용한다. 토큰 생성에 필요한 key 는 애플 개발자 계정 페이지에서 얻을 수 있다.

기존의 인증서를 이용한 인증 역시 지원하므로 둘 중 하나를 선택해서 사용하면 된다.

이 인증 방식을 사용하면, 개발환경/제품환경에 관계 없이 푸시 전송을 요청할 수 있다. 또한 토큰 자체는 유효기간이 있지만, 토큰 생성에 사용되는 key는 유효기간이 없기 때문에 토큰 생성 기능을 한 번 구현해두면 갱신 등을 걱정할 필요 없이 계속 사용할 수 있다는 장점이 있다.

1
▲토큰 생성에 사용되는 key는 만료 기한이 없다.

제품(production) 인증서로 개발환경(sandbox, development) 대상 푸시 전송 가능

위에서도 언급했지만, 기존에는 제품 환경을 대상으로 푸시를 전송하는 경우와 개발 환경을 대상으로 전송하는 경우에는 별도의 인증서를 사용해야만 했다. 새로운 APNs에서는 제품 환경의 인증서를 이용하여 제품 환경과 개발 환경 모두에 푸시 전송 요청을 보낼 수 있다.

2
▲제품(production) 인증서로 개발 환경과 제품 환경 모두에 푸시를 보낼 수 있다.

전송 요청 프로토콜 변경

기존에 APNs에 전송 요청을 보낼 때는 tcp 로 전용 프로토콜을 통해 요청해야만 했다. 새로운 APNs는 HTTP/2 기반의 프로토콜을 사용한다.

HTTP/2 에 익숙하지 않으신 분들을 위해 간략히 설명하자면, HTTP/2 는 HTTP 1.1 과 비슷한 기능성을 지원하면서도 서버측에서의 응답 시간을 줄이는 것을 주된 목적으로 설계된 프로토콜이다. HTTP method 등 HTTP의 기본 기능은 최대한 바꾸지 않으면서 요청 생성/처리와 관련된 부분을 변경하였다. 예를 들면, 헤더에 인덱싱 개념을 도입하여 요청 자체의 크기를 줄이고 멀티플렉싱을 개념을 도입, 기존 HTTP 1.1 의 반응 속도를 떨어뜨리는 요인 중 하나였던 head-of-line-blocking 문제를 해결했다. head-of-line-blocking 문제란, 작업 시간이 오래 걸리는 작업이 진행 중이면 이미 처리가 끝났거나, 더 빨리 끝낼 수 있는 다른 작업들을 처리할 수 없는 상황을 말한다.

3

위의 그림에서, A의 요청에 대한 응답인 A’ 의 크기가 크거나 처리가 오래 걸리는 경우를 생각해 보자. 반대로 B’의 크기가 매우 작거나 빨리 처리할 수 있다면, 서버는 B’ 를 먼저 전송하고 클라이언트는 그에 대한 처리를 먼저 시작하는 편이 최적화에 도움이 된다. 하지만 HTTP 1.1 은 서버 측에서 요청을 받은 순서에 따라 응답을 보내야 한다고 규정하고 있으므로, 서버는 B’를 A’보다 나중에 보내야만 없다. 즉 B’ 는 A’에 의해 blocking 된 것이다.

반면 HTTP/2 에서는 여러 개의 요청을 별개의 스트림으로 나눠서 전송할 수 있다. 다른 스트림상의 요청은 위에서 언급한 전송 순서에 영향을 주지 않으므로 요청 A,B를 서로 다른 스트림을 이용해서 요청하면 서버에서는 먼저 처리가 끝난 B’를 먼저 전송할 수 있기에 B’는 A’에 의해 blocking 되지 않는다.

새로운 APNs에서는 이 멀티플렉싱 기능을 이용, 하나의 연결에서 다수의 요청을 동시에 전송할 수 있도록 지원하고 있다. 즉 여러 개의 디바이스를 대상으로 푸시 전송 요청을 날리려면 디바이스의 개수만큼 HTTP /2 요청을 보내야 한다. 위에서 설명한 토큰 인증을 사용할 경우, 요청 시마다 생성된 토큰을 포함하여 전송하여야 한다.

기존 방식과 비교했을 때 장점은, 우선 오류 발생 시 오류가 발생한 요청만 실패한다는 점이다. 기존 APNs의 경우, 다수의 전송 요청을 보낼 때 오류가 발생하면 해당 요청에 대한 오류 정보를 전송 후 바로 APNs측에서 연결을 종료했으며, 오류가 발생한 요청 이후의 모든 요청은 무시되었다. 따라서 오류 처리 시, 전송 요청이 어디까지 받아들여졌는지를 확인, 나머지 요청을 모두 재 전송하는 로직을 반드시 구현해야 했다. 반면 새로운 APNs에서는 문제가 있는 요청만 실패하며, 나머지는 모두 정상적으로 처리된다. 따라서 오류가 발생한 메세지에 대한 재전송만 신경 쓰면 된다.

두 번째 장점은 오류에 대한 좀 더 상세한 정보를 얻을 수 있다는 점이다. 기존 APNs에서는 요청 메세지 내의 형식 문제 등으로 오류가 발생한 경우 오류 코드 하나만을 반환하였는데, 오류 코드의 총 수가 10개 남짓으로 지나치게 단순하여 오류 원인을 파악하기 어려웠다. 새로운 APNs는 HTTP error code 및 error string을 동시에 제공, 오류 원인을 알아내기 쉬워졌다.

이 글을 작성하는 시점에, 새로운 APNs는 서비스 된 지 1년 이상이 지났다. 또한 Apple이 레거시 지원을 중요하게 여기는 회사는 아니기에, 신규 프로젝트 개발 시에는 물론이고 기존 방식의 APNs를 사용하여 서비스를 제공하고 있는 경우에도 새로운 APNs 사용을 고려할 필요가 있다. 변경점 중에는 프로토콜 외에 기능적인 변경도 있으며 푸시 서비스 운영에 영향을 줄 수 있는 변경들도 있기에 기존에 운영중인 프로젝트에 사용되는 푸시 기능도 마이그레이션하는 것을 권하고 싶다 .

아이펀팩토리 아이펀 디플로이 테크니컬 디렉터 민영기

Windows에서 Linux 머신을 구성하는 방법들


게임을 개발하다 보면 여러 가지 서버 환경을 준비해야 한다. 개발자가 사용할 개인용 개발 서버부터 팀원들이나 클라이언트 개발자가 꾸준히 접근할 팀 개발 서버, QA를 위한 테스트 서버, 상용화 환경을 준비하기 위한 것까지 최소한 서너가지의 서버 환경은 필수적이다. 또한 의외로 꼭 있으면 좋은 것이 기획자들의 데이터 테스트를 위한 기획자별 테스트 서버인데, 이 경우 전문 개발자가 아닌 사람들을 위한 배포용 서버 환경을 어떻게 구축 할지가 매우 중요해진다.


업무 환경에서 가장 많이 사용하는 운영체제는 대부분의 경우 Windows이다. 하지만 게임은 물론 다수의 프로젝트에서 사용하는 서버는 리눅스에서 동작하는 경우도 많다. 이 경우 전문 개발자가 아닌, 혹은 리눅스 서버 사용 경험이 거의 없는 사람과의 협업이 필요할 때 어떻게 이들을 위해 환경을 설정하고 공유하며 배포를 준비할 수 있을까. 이번에는 이에 대해서 이야기를 해보려고 한다.

 1. Hyper-V

1
(출처: https://www.microsoft.com/)


Hyper-V는 Windows에서 기본으로 지원하는 가상 컴퓨터 관리 기능이다. 다른 운영체제를 사용하기 위하여 추가로 프로그램을 설치하거나 할 필요가 없다는 것이 장점이다.


이후에 설명할 다른 가상 환경도 마찬가지 이지만, Hyper-V 역시 지정된 가상 컴퓨터 이미지를 공유할 수 있다. 이를 통하여 다른 사람들에게 쉽게 서버를 배포할 수 있다.


Hyper-V는 이와 같이 사용이 간단하고 배포가 손쉽지만, 아쉬운 부분이 있다. 대표적으로 NAT설정이 번거롭다.[1] 기본 기능을 통하여 바로 만들 수 있는 외부 스위치를 활용하는 경우, 새로운 하드웨어 주소가 가상 컴퓨터에 설정된다. 그러므로 하드웨어 주소를 통해 접근을 제한하는 네트워크 정책을 사용하는 회사의 경우, 배포가 쉽다는 장점과는 반대로 네트워크 시스템 담당자를 매우 귀찮게 만들게 된다. 즉, 전문 개발자가 아닌 사람과 협업하기 위한 서버 환경 설정 용으로 Hyper-V는 매우 편리하지만, 해당 가상 서버 환경에서 외부 네트워크 접속을 허용하기 위해서는 추가 작업이 필요하다.


하지만 서버가 외부 접속을 지원할 필요가 없다면, Hyper-V로 만든 가상 컴퓨터는 매우 쉽게 공유할 수 있는 리눅스 머신이다. 특히 기획자 개별 데이터 테스트용 서버 머신이라면, 가장 편리한 방법이 아닐까 생각한다.

 
2. Docker

2
(출처: https://www.docker.com/)


Docker는 리눅스 위에 얇은 추상화 레이어를 더해서 프로그램을 구동시킬 수 있는 컨테이너를 만들고, 그 위에서 리눅스 프로그램을 구동시킬 수 있도록 해주는 소프트웨어이다. 다시 설명하자면, Docker는 사용자가 직접 가상 운영체제를 설치하거나 유지보수하지 않더라도, 원하는 머신에 Docker만 깔면 동일한 환경에서 실행할 수 있도록 배포, 관리가 가능하게 만들어준다. 그리고 이 기능은 VM을 이용하는 것이 아니라, 각각의 운영체제에 직접 연동되어 동작한다. 현재 Docker가 지원하는 운영체제는 Mac, Windows, Linux이다.


이 글의 첫 부분에서 이야기한 다양한 서버 환경을 준비하는데 있어서, Docker는 Hyper-V보다 좀 더 나은 관리 방식을 제공한다. 실제로 Docker는 가상 컴퓨터의 관리보다는 소프트웨어 배포용 소프트웨어이기 때문이다. 출시를 위한 환경은 보통 단일한 서버보다는 여러 가지 종류의 서버가 상호 작용하는 형태를 취하게 되는데, Docker를 이용하면 각각의 기능에 따른 가상 환경을 운영체제부터 프로그램까지 전체를 관리하지 않아도 되기 때문에 상대적으로 편하게 유지보수가 가능해진다. 엔터프라이즈 환경에서 검증되었다는 것 역시 훌륭한 점이다.


물론 Docker도 진입장벽이라는 단점이 존재한다. 개발자들에게는 의아한 이야기일 수도 있지만 개발자가 아닌 사람들도 사용하기에는 GUI가 빈약하며 교육을 위한 시간과 비용이 필요하다.

 

 3. 그 외 가상화 소프트웨어

Hyper-V가 나오기 전부터 이미 여러 회사에서 VirtualBox나 VMWare 같은 가상화 관련 소프트웨어를 만들어왔다. 이들은 역사가 깊은 만큼 다양한 인프라스트럭처 관련 툴을 지원하기도 하고, 사용자의 규모에 따라 분리된 프로그램을 제공하기도 한다. 또한 Hyper-V의 약점이었던 NAT지원 등도 손쉽게 설정할 수 있다. 배포 역시 마찬가지로 이미지를 활용하면 어렵지 않다.


하지만 먼저 설치해야 할 프로그램이 존재한다는 것은 개발자가 아닌 사람들이 사용하기에 단점이며, 개발자들이 사용하는 상황에서도 특별한 경우가 아니라면 이러한 가상화를 사용하는 경우는 많지 않다.


편의성이 좀 더 뛰어난 경우가 많아 관련 기능을 사용해야 하는 경우라면 고려해 볼만 하다.

 

 4. 정리하며

서버 개발은 물론이요, 하다 보니 어느새 시스템 엔지니어링까지 해야 하는 수 많은 개발자 분들을 위해 빈약하나마 가상화 프로그램을 소개하는 내용을 정리해 보았다. 다양한 환경을 준비하고 공유하는 방법에 대한 의의도 있겠지만, 개발된 코드와 컨텐츠를 보관하는 것 만큼 이나 개발 환경과 구동 환경을 백업해두는 것도 중요한 만큼, 앞으로 오래오래 개발할 수 있는데 조금이나마 도움이 되었으면 하는 마음에 미약한 글을 여기서 정리한다.

아이펀팩토리   박근환 아이펀 엔진 테크니컬 디렉터


[1]: Hyper-V NAT 네트워크 설정, https://msdn.microsoft.com/ko-kr/virtualization/hyperv_on_windows/user_guide/setup_nat_network

네트워크 관련 용어들의 개념적 정리

영어권이 아닌 우리 한국 사람들은 영어로 표현된 단어의 미묘한 느낌을 캐치하기 보다는 그걸 전공 용어로 취급해서 그대로 외워버리는 경우가 많다. 하지만, 단어의 개념을 명확히 이해하면 그 개념이 다른 상황에서 사용되더라도 쉽게 이해할 수 있다는 장점이 있다. 아래 내용은 다들 알고 있는 단어들을 조금 다른 각도에서 설명을 시작하여 최근 많이 회자되는 Software Defined Networking (SDN) 과 관련된 기본 용어들까지에 대한 내용이다.

네트워크 : 일반화된 개념으로 네트워크는 점 들의 연결 관계를 선으로 표시한 것을 의미한다. 여기서 점과 선이 무엇을 의미하는지는 네트워크가 표현하려는 것에 따라 달라지는데, 점을 개인으로, 선을 개인간 관계로 생각하면 소셜 네트워크가 되는 것이고, 점을 옥천 허브 같은 물류 기지, 선을 도로라고 생각하면 물류 네트워크가 된다. 그리고 점을 컴퓨터로, 선을 회선으로 생각한다면 우리가 익숙한 컴퓨터 네트워크가 되는 식이다. 네트워크는 굳이 복잡한 모습일 필요는 없다. 단지 점 두 개가 이어진 것도 네트워크고 복잡하게 얽히고 설킨 것도 네트워크다.
8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%801

그림1 : 점들의 연결 관계가 네트워크이다. 그리고 단 2개의 점을 연결하더라도 마찬가지다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

스위치: 네트워크 상에서 한 점이 다른 둘 이상의 점에 연결되는 일은 흔하게 발생한다. 이 때 그 점은 들어온 입력을 여러 방향 (즉, ‘선’)으로 보낼 수 있고, 이처럼 경로를 결정한다는 의미에서 스위치라고 이야기한다. 마치 교차로에서 길을 선택하는 것과 같다고 생각하면 된다. 우리가 컴퓨터 네트워크에서 일반적으로 말하는 스위치는 OSI 모델상 제2계층인 “데이터링크 계층”에 해당하는 Ethernet 상의 데이터들의 경로를 결정한다고 해서 Layer 2 (또는 L2) 스위치라고 부른다. “스위치와 허브의 차이는..” 하는 식의 지식을 외우고 있는 사람들도 많을 것이다. 그것도 나쁘지 않지만, 경로의 결정을 하는 것이 스위치라고 이해하면 “ATM 스위치”, “패킷 스위칭” 이런 표현들이 무엇을 뜻하는 것인지 보다 쉽게 감이 올 것이다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%802
그림2 : 어떤 점들은 여러 점들과 연결될 수도 있다. 그렇게 되면 그 점은 여러 경로를 선택할 수 있게 된다. 이런 점을 스위치라고 한다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

브릿지 : 브릿지는 ‘다리’라고 번역된다. 하지만, 브릿지를 ‘다리’가 아닌 ‘이어주는 것’ 이라고 생각하는 것이 더 편리하다. 그렇게 이해하면 치과의 ‘치아 브릿지’ 라는 시술이 더 이상 암호 같은 의미가 아니라, 치아가 중간에 빠져서 떨어져 있던 두 치아사이에 보철물을 끼워넣는 것으로 이해될 수 있기 때문이다. 그리고 이렇게 이해하면, 앞서 설명한대로 여러 점을 ‘이어주는’ 스위치는 브릿지라고 쉽게 이해할 수 있다. 위의 그림에서 보면 왼쪽의 (서브)네트워크와 오른쪽의 (서브)네트워크 를 가운데 스위치가 이어주고 있다는 것을 알 수 있다. 그리고 “IP 네트워크를 브릿징한다” 라는 의미도 쉽게 이해될 것이다. 그렇다. 두 개의 IP 네트워크를 어떤 장비로 이어주는 것이다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%803
그림3: 위의 스위치는 양쪽의 네트워크를 이어주는 역할을 한다. 이어주는 역할을 하는 것을 브릿지라고 한다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

그럼 XenServer 와 같은 가상 서버에서 사용하는 네트워크 브릿지라는 표현은 어떤 의미일까? 이는 가상 서버안의 네트워크 카드와 물리 서버의 네트워크 카드를 이어주는 역할을 하는 매개체로 생각할 수 있다. VMware 의 경우 “가상 스위치” 라는 이름으로 같은 개념이 존재한다. 이와 관련해서는 아래에서 다시 설명하겠다.
8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%804

그림4 : 가상 솔루션들은 가상서버의 네트워크 카드와 물리 서버의 네트워크 카드를 연결하기 위해서 브릿지를 사용한다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

라우팅과 포워딩: 우리는 크게 신경을 쓰고 있지 않지만, router 나 switch 라고 말하는 장비들은 엄밀히 말해 크게 두 가지 일을 한다. 특정 목적지로 가기 위해서는 어떤 경로들이 있는지에 대한 정보들을 수집하는 것과, 그 정보들 중에 실제로 선택된 경로를 기반해서 패킷을 전달하는 일. 전자를 경로(route) 를 알아내는 일이라고 해서 라우팅(routing) 이라고 하고 후자를 실제로 패킷을 전달(forward) 하는 일이라고 해서 포워딩(forwarding) 이라고 한다. 우리가 보통 패킷을 전달하는 것을 라우팅이라고 부르는 경우가 많은데 이는 틀린 표현이다. 라우팅은 IP 패킷을 전달하는 것이라고 이해하고 있다면 이 역시 잘못된 것이다. 물론 많은 경우에 라우팅이 IP 패킷 전달을 의미하는 것으로 쓰이지만, 라우팅과 포워딩이라는 단어는 IP 와 같은 Layer 3 에 국한되는 것이 아닌 일반적인 개념으로 이해하는 것이 더 바람직하다.

Control plane과 data plane : Control plane 에 해당하는 라우팅은 경로 정보를 수집하는 것이라고 했다. 그리고 이들이 경로를 수집하는 방식은 자신이 알고 있는 정보를 이웃과 교환하는 것이다. 교환하는 정보가 선에 대한 정보 (Link state) 일 수도 있고, 자신이 알고 있는 경로 (Distance Vector) 에 대한 것일 수도 있다. 전자의 예로는 OSPF 같은 것이 있고 후자의 예로는 RIP 같은 것을 들 수 있다.

어쨌거나 자신이 알고 있는 정보는 그렇게 자주 바뀌지 않는다. 그때문에 정보의 교환 역시 빈번하게 발생하지 않는다. 이때문에 경로를 알아내는 라우팅 자체는 고성능일 필요는 없다. 그래서 대부분의 경우 control-plane 인 라우팅은 소프트웨어로 구현한다. 대신 라우팅에서는 각 지점들이 주고 받은 정보를 통해서 각 지점들이 최종적으로 똑같은 정보에 도달하는 것이 매우 중요하다. 그렇지 않으면 중간에 어떤 지점에서는 잘못된 경로를 알게 되기 때문이다. 즉, 라우팅은 각 지점들이 서로 주고 받은 경로 정보를 이용해서 독립적으로 연산을 수행해서 전체 경로들에 대해서 동일한 정보를 가지게 되어야 하는 것이다. 동일한 정보를 가지게 되는 것을 수렴한다고 말한다. 그리고 독립적인 연산을 하기 때문에 라우팅 알고리즘들은 분산 알고리즘이다. 라우팅 알고리즘들은 어떻게 하면 더 빨리 수렴할 수 있을까 하는 고민을 한다.

그러나 data plane 인 패킷 포워딩의 경우는 이야기가 달라진다. 얼마나 빨리 패킷을 전달할 수 있는지가 관건이다. 이를 소프트웨어로 구현을 하면, 매 패킷에 대해서 처리를 해줘야 되기 때문에 CPU 가 병목이 되게 된다. 그래서 이를 ASIC 형태의 하드웨어로 만들어버리게 되었다. 특히나 스위칭 패브릭이라고 하는 핵심 부분이 더욱 그렇다. 그리고 그 분야에서 가장 두각을 보인 것이 시스코다. (시스코는 샌프란시스코 도시 이름에서 시스코라는 이름을 따왔고, 회사 로고 역시 샌프란시스코의 금문교를 모델로 하고 있다.)

그러나 이런 하드웨어 접근 방식은 주어진 네트워크 환경에서 효율적인 성능을 낸다는 장점은 있었지만, 동시에 새로운 것들을 시도해볼 수 없다는 심각한 문제가 발생했다. 일례로, IPv4 에서 IPv6 로 넘어가기 위해서는 장비가 IPv4 스위칭 뿐만 아니라 IPv6 스위칭까지도 지원해야 되는데 하드웨어로 이미 박혀있는 것을 바꿀 수 있는 방법이 없는 것이다. 그리고 비록 control-plane 인 라우팅 부분을 하드웨어로 구현을 할 필요가 없지만 그 소프트웨어가 같은 장비 안에 있는 flash 메모리 등에 박혀있는 한 그걸 마음대로 바꾸기도 어려웠다. 이 때문에 네트워크는 기존 프로토콜들 관련해서는 10Mbps, 100Mbps, 1Gbps, 10Gbps 등 높은 고도화를 이루었지만, 새로운 프로토콜 관련해서는 상당 기간 정체를 앓게 된다.

2000년대 중후반에는 Internet Architecture 연구가 한창 붐을 이루었다. “우리가 새로 인터넷을 설계한다면 어떤 내용들이 포함되어야 할까?” 라는 주제의 연구들이었는데, 이는 기존의 인터넷이 설계될 때와 오늘날 가장 중요하게 생각하는 요소들이 많이 바뀌었기 때문에 생긴 자연스러운 움직임이었다. 하지만 대부분의 노력은 탁상 공론으로 끝나고 말았다. 바로 현재의 하드웨어 중심의 네트워크 구성 때문이었다.

이런 하드웨어 중심의 네트워크는 새로운 것을 시도하지 않는 한 크게 문제가 되지 않았다. 그렇지만 예전에 만들어진 인터넷이라는 옷은 지금에는 맞지 않은 것들이 많아서 새로운 기능들이 종종 필요해졌다. 예를 들어 데이터 센터 안에는 많은 수의 스위치가 들어가는데, 네트워크 구성을 기존의 단순 tree 형태로 하게 되면 최상위 스위치가 병목이 되어 링크가 아무리 빨라도 그만큼을 못 쓰게 된다.

그리고 데이터 센터 안에는 수 많은 스위치가 들어가는데 그 중 하나가 죽으면 다른 스위치들이 경로 정보를 주고 받고 수렴할 때까지 기다려야 된다. 그리고 라우팅 정보가 수렴하지 않으면 포워딩 역시 제대로 이루어질 수 없게 된다. 데이터센터 안의 네트워크 구성은 너무나 뻔해서 굳이 분산 알고리즘을 돌릴 필요가 없는데도 말이다.

이런 여러 이유 때문에 하드웨어 중심의 네트워크를 벗어나기 위한 노력이 시도되었다. 이름하여 Software Defined Networking 이다.

Software Defined Networking (SDN) : SDN 의 기본 아이디어는 “패킷 포워딩에 특화된 프로그래밍 가능한 더미 하드웨어” + “라우팅과 더미 하드웨어의 포워딩 테이블을 제어하는 현명한 외부 소프트웨어 (컨트롤러)” 로 정리할 수 있다. 이는 기존의 완전 소프트웨어 기반 솔루션과 완전 하드웨어 기반 솔루션의 하이브리드 형태로 이해할 수 있다. 소프트웨어 기반 솔루션은 포워딩 성능이 나오기 힘들었다. 하드웨어 기반 솔루션은 프로그래밍이 안됐다. 그래서 그 둘을 섞어서 포워딩 규칙을 프로그래밍할 수 있는 포워딩에 특화된 하드웨어와 이 포워딩 규칙을 제어하는 소프트웨어라는 방식을 채택한 것이다.

그리고 SDN 는 기존에 장비들이 분산 알고리즘을 돌리던 것에서 벗어나 외부 소프트웨어가 모든 하드웨어를 중앙 집중식으로 관리하게 된다. 그 때문에 오랜 시간이 걸릴 수 있는 분산 알고리즘의 수렴 과정을 피할 수 있게 되었다. 외부 소프트웨어 (콘트롤러) 가 바로 어떻게 하면 되는지 알려주면 되기 때문이다. 그리고 외부 소프트웨어가 네트워크를 정의한다(제어한다) 는 뜻에서 Software-Defined 라는 이름을 쓰게 된 것이다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%805

그림5: SDN 는 포워딩에 특화된 하드웨어들을 외부의 소프트웨어 중앙 집중방식으로 통제하는 형태이다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

잠깐. 그런데 포워딩에 특화된 하드웨어이면서 프로그래밍 가능하다고 했는데 어떻게 이런 게 가능할까? 앞서 하드웨어로 포워딩을 구현하면 바꾸는 것이 안된다고 했는데 말이다. 사실 여기서 말하는 하드웨어는 기존 ASIC 기반의 하드웨어와는 다르다. SDN 에서의 하드웨어는 입력으로 들어오는 패킷의 패턴 매칭 하드웨어라고 이해하는 것이 더 좋을 것이다. “이 패턴의 패킷은 여기로, 저 패턴의 패킷은 저기로” 이런 방식이다. 그 때문에 하드웨어는 특정 프로토콜에 종속되지도 않고, 외부의 소프트웨어는 패킷 패턴에 따른 경로만 프로그래밍하면 되는 것이다. 신박하지 않은가?

OpenFlow : 이처럼 SDN 에서 가정하는 하드웨어는 기존의 ASIC 기반 하드웨어와는 확연하게 달랐고, 이렇게 패턴 매칭 형태로 프로그래밍 가능한 스위치에 대한 Spec 이 OpenFlow 라는 이름으로 이루어졌다. 그리고 HP, DELL, IBM 등 메이저 스위치 제조업체들이 이 규격에 따라 OpenFlow 스위치들을 만들기 시작했다. 보다 자세한 내용은 여기를 참고하기 바란다. http://www.openflow.org/

가상화 (Virtualization) : 나는 virtualization 을 가상화로 번역하는 것이 상당히 많은 오해를 불러 일으키고 있다고 생각한다. 가상화는 왠지 가짜의 느낌을 주기 때문이다. 실은 Virtualization 이 가짜라기 보다 “나만이 쓰는 것처럼” 라는 의미에 가까운데 말이다. Server virtualization 은 나만이 쓰는 것 같은 서버, Storage virtualization 은 나만이 쓰는 것 같은 스토리지 이런 식이다. 그러니 Network virtualization 은 나만이 쓰는 것 같은 네트워크라는 뜻이 된다.

가상화 기술이 “나만이 쓰는 것처럼” 하는 기술이기 때문에, 필연적으로 자원의 공정한 분배와 분리를 지원해줘야 된다. 예를 들어 서버 가상화 기술은 각 가상 서버들이 공정하게 자원을 분배 받고, 다른 가상 서버가 자원을 쓰는 것 때문에 또 다른 가상 서버가 영향 받지 않게끔 하는 것이 핵심이다. 그리고 스토리지 가상화는 각 가상 스토리지가 공정하게 디스크 IO 를 분배 받을 수 있게끔 하고 다른 가상 스토리지 때문에 내 가상 스토리지의 IO 성능이 영향 받지 않게 해줘야 된다. 네트워크 가상화도 마찬가지다. 내 가상 네트워크가 일정 수준의 밴드위스를 보장 받아야 되고 이는 다른 가상 네트워크때문에 영향을 받아서는 안 된다.

이런 가상화 기술은 물리 자원 위에 소프트웨어적으로 만들어 주는 것이다 보니, 자원의 할당량을 변경하거나 다른 곳으로 이동 시키는 것이 자유롭다는 장점이 있다. 예를 들어 가상 서버에 CPU 를 추가한다거나 다른 물리 기계로 이동하는 것이 가능한 것처럼 말이다. 그리고 가상 네트워크에 밴드위스를 추가한다거나 다른 물리 네트워크로까지 가상 네트워크를 확장하는 것 등이 가능한 것처럼 말이다.

가상 스위치 : 이처럼 네트워크 자원의 배정과 분리, 그리고 제어가 가능하게 하려면 네트워크 가상화를 위해서 뭔가가 더 필요한 것은 당연하다. 바로 가상 스위치라는 개념이다. 가상 스위치는 보통 가상화 프로그램 안에 내장된다.

가상 스위치가 없는 경우 어떤 일이 벌어질까? 아래 그림을 보기 바란다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%806

그림6: 만일 가상 스위치가 존재하지 않는다면 같은 물리 머신안 가상 머신들이라도 통신을 위해서는 외부 스위치까지 갔다가 돌아와야 된다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)


가상 서버는 물리 서버와 마찬가지로 각각의 IP 를 받을 것이다. 그런데 같은 기계 안에 있더라도 가상 서버들끼리 통신을 하기 위해서는 물리 기계를 벗어나 외부 스위치 까지 가야되는 일이 발생한다. 이는 엄청나게 비효율적이다. 그럼 가상 스위치가 있는 경우는 어떨까? 아래를 보면 알겠지만 훨씬 더 효율성이 높아진다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%807그림 7 : 가상 스위치가 존재하는 경우 같은 물리 장비 안의 가상 서버들간의 통신이 훨씬 효율적으로 된다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

그 외에도 같은 물리 머신의 네트워크 카드로 통신하더라도, 가상 스위치를 분리함으로써 가상 서버들이 다른 네트워크에 존재하게 하는 것도 가능하고, 다른 기계에서 도는 가상 서버들이 같은 네트워크에 있도록 하는 것도 가능하다.

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%808

그림 8 : 가상 스위치를 분리해서 가상 서버들이 다른 네트워크에 존재하게 만들 수 있다. 맨 왼쪽의 가상 서버는 다른 두 가상 서버와 다른 네트워크에 포함된다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

8%ed%9a%8c%ec%bb%ac%eb%9f%bc-%ec%9d%b4%eb%af%b8%ec%a7%809
그림 9 : 가상 스위치는 서로 다른 물리 서버에 있는 가상 서버들간에 같은 네트워크 안에 있게 만드는 것도 가능하다. 이때 물리서버간 통신은 가상 스위치간 터널링으로 이루어진다. (아이콘 출처: WPZOOM, iconfinder.com, Creative Commons License)

이처럼 가상 스위치는 네트워크 가상화를 구현하기 위한 필수적인 기술이라고 할 수 있다. 그 때문에 최근 가상화 솔루션들은 모두 가상 스위치 기능들을 포함하고 있다. 그 중에서 Open vSwitch 는 오픈 소스 기반의 가상 스위치 구현이며, XenServer 의 가상 브릿지 구현은 Open vSwitch 을 활용하고 있다. (OpenFlow 와 Open vSwitch 는 이름도 유사하지만, 실제로도 같은 사람들이 만들었다)

이번 컬럼에서는 네트워크 관련 용어들을 정리해보았다. 서두에 이야기한 것처럼 비영어권인 우리는 많은 용어를 그냥 전공 용어겠거니 하며 외우는 경우가 많은데, 용어의 의미를 좀 더 명확히 이해하면 해당 용어의 확장이나 응용 역시 쉽게 이해할 수 있는 경우가 많으니 다소 이단적인 이번 컬럼에서의 용어 설명이 도움이 됐길 바란다.

아이펀팩토리 문대경 대표