반응형

짧은 영어로 번역하는것이라 오역, 의역이 있을수 있습니다.

좀더 정확한 정보를 얻거나 실력을 향상시키실 분들은 해당 블로그에 직접 가셔서 여러번 읽어보시길 바랍니다.

 

 

출처 : https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013

 

10 Common Software Architectural Patterns in a nutshell

Ever wondered how large enterprise scale systems are designed? Before major software development starts, we have to choose a suitable…

towardsdatascience.com

출처 2 : https://mingrammer.com/translation-10-common-software-architectural-patterns-in-a-nutshell/

-> 다른분이 번역한 포스팅

 

큰 규모의 시스템을 어떻게 디자인 하는지에 대해서 궁금해 본적이 있는가?

주요 소프트웨어 개발을 시작하기 전에,

우리가 원하는 기능성과 품질 요소를 제공할 수 있는 구조를 선택해서 적용해야 한다.

그렇기 때문에, 우리는 그것들을 적용하기 전에 각기 다른 설계구조에 대해서 이해를 해야 한다.

 

설계 패턴(architectural Pattern)이란 무엇인가?

위키에 따르면 아래와 같다.

- 설계 패턴이란 일반적으로, 소프트웨어 구조 안의 주어진 문맥속에서 일반적으로 발생하는 문제들에서

다시 사용할 수 있는 패턴들을 뜻한다.

 => 유형화된 해결책들.

 

이 포스팅에서, 난 아래의 각각의 사용처와 장점을 지닌 10가지 설계구조를 설명할 수 있을것이라고 믿는다.

각 패턴들의 이름은 아래와 같다.

1. 계층화 패턴 [Layered pattern]

2. 클라이언트 - 서버 패턴 [Client-Server pattern]

3. 마스터 - 스렐이브 패턴 [Master-slave pattern]

4. 파이프 - 필터 패턴 [pipe-filter pattern]

5. 브로커 패턴 [Broker pattern]

6. 피어 투 피어 패턴 [Peer-to-peer pattern]

7. 이벤트 버스 패턴 [Event-bus pattern]

8. MVC 패턴 [Model-View-Controller pattern]

9. 블랙 보드 패턴 [Blackboard pattern]

10. 인터프리터 패턴 [Interpreter pattern]

 

 

1. 계층화 패턴

 

이 패턴은 프로그램들의 구조를 서브 Task,각각의 구분된 추상화 레벨들로부터 프로그램을 구분시켜주는 구조이다.

각 계층은 자신의 상위 계층에 서비스를 제공한다.

ex : IOS의 Layer Structure 이미지

 

ex : 블루투스의 Protocol Stack Layer

 

가장 일반적으로 찾을 수 있는 시스템에서 사용하는 4계층은 아래와 같다.

1. Presentation Layer (또는 UI Layer로 알려짐)

2. Application Layer (또는 Service Layer로 알려짐)

3. Buiseness Layer (또는 Domain Layer로 알려짐)

4. Data Access Layer (또는 Persistence Layer로 알려짐)

 

계층화 패턴은 일반적인 PC 프로그램 혹은 웹 프로그램에서 주로 사용된다.

 

 

2. Client - Server Pattern 

이 패턴은 주로 두개의 부분으로 구분 할 수 있는 한개의 서버와 다수의 클라이언트로 구성된다. 

서버는 다수의 클라이언트들에게 서비스를 제공한다.

클라이언트는 서버로부터 서비스를 요청하며, 서버는 관련된 서비스를 해당 크라이언트에게 제공한다.

나아가서 서버는 계속 클라이언트의 요청이 있는지 확인한다.

 

Server - Client 패턴은 Email, 웹 공유 문서 혹은 은행서비스 등의 프로그램에 쓰인다.

 

 

3.  Master - Slave pattern 

이 패턴은 두개의 부분으로 구성된다. 바로 마스터와 슬레이브이다.

마스터는 각각의 슬레이브들(100% 동일한)에게 작업을 분할한다.

그리고 슬레이브는 계산된 최종 결과를 마스터에게 반환한다.

 

Master-Slave 패턴은 DB 복제에서, 신뢰할 수 있는 마스터 DB, 그리고 그 마스터 DB와 동기화된 슬레이브 DB

에서 사용되며 컴퓨터 시스템에서 bus에 연결된 주변장치 등에서 사용된다.

-> master drive 와 slave drive

 

4. Pipe - Filter Pattern

이 패턴은 Data의 Stream을 처리하고 진행하는 구조에서 사용될 수 있다.

각각의 진행 단계는 내부에 Filter 구성을 감싸고 있다.

데이터는 Pipe를 지날 때 특정 처리단계를 거치게 되며,해당 pipe는 지연처리 혹은 동기화를 목적으로 사용 될 수 있다.

 

Pipe-Filter 패턴은 Compiler, 연속적으로 어휘 분석, 변경, 의미 분석 그리고 code 생성을 수행하는 필터에 사용된다.

 

 

5. Broker Pattern 

이 패턴은 분리된 분산시스템에 사용되는 구조이다. 이 구성들은 각각 다른 원격 서비스 호출에 상호작용을 할수 있다.

브로커는 동등한 구성요소들간의 통신을 조정하는 역할을한다.

 

서버들은 서버들의 능력(서비스와 특징)을 브로커에게 전파(publish)한다.

클라이언트들은 브로커에게 요청하고, 브로커는 해당 클라이언트에 적용할 수 있는 

레지스트리에 등록된 서비스로 redirect한다.

 

이 패턴은 Apache ActiveMQ, Apache Kafka, RabbitMQ, JBossMessaging 같은 메세지 브로커 프로그램에서 사용된다.

 

 

6. Peer-To-Peer Pattern 

이 패턴에서는 개개의 구성품들을 Peer라고 한다.

피어들은 기능적으로는 클라이언트이며 다른 피어들로부터 요청을 받는측면에서는 서버라고 할 수 있다.

피어는 서버 혹은 클라이언트처럼 행동할 수 있고 이것은 그때그때 역할이 바뀐다.

 

Peer-To-Peer 패턴은 네트워크 파일 공유 시스템(Gnutella or G2), 멀티미디어 프로토콜(P2PTV, PDTP)에 사용된다.

 

 

7. Event-bus-pattern 

이 패턴은 주로 이벤트를 다루며 4개의 주요 구성품을 갖는다.

4개의 주요 구성으로는 이벤트 소스, 이벤트 리스너, 채널, 그리고 이벤트 버스가 있다.

이벤트 소스는 메세지를 이벤트 버스에 속한 개개의 채널에 알리고 이벤트 리스너는 개개의 채널에 대해서 구독을 한다.

리스너는 이전에 구독한 채널을 통해서 전파되는 메세지를 알아차릴 수 있다.

 

Event-bus-pattern은 안드로이드 개발 및 Noti 서비스에 사용된다.

 

 

 

8. Model-View-Controller Pattern

MVC 패턴으로도 알려진 이 패턴은 프로그램의 상호작용을 3가지 부분으로 나눈 것이다.

Model : 핵심적인 기능, data를 포함한다.

View : 정보를 유저에게 보여준다.(여러개의 View가 존재할 수 있다.)

Controller : 유저로부터의 입력을 다룬다.

 

이것은 정보가 사용자에게 제공되는 방식과 사용자로부터 받아들여지는 방식에서  정보의 내부적인 표현을 분리하기 위해서 나뉘어진다. 이는 각 구성품들을 분리하며, 코드의 효율적인 재사용을 가능하게 한다.

 

주요 프로그래밍 언어에서 WWW어플리케이션 구조에 사용한다.

(Redis 그리고 Django등등)

 

 

9. Blackboard Pattern 

이 패턴은 해결책이 알려지지 않은 문제를 해결하는데 유용합니다.

Blackboard Pattern은 3가지로 구성되어 있습니다.

 

Blackboard : 솔루션 공간안의 오브젝트들을 포함하는 구조화된 전역 메모리

Knoledge source : 자체 표현에 특화된 모듈

control component : 선택, 구성과 실행 모듈

 

모든 구성들은 Balckboard에 접근해야 한다.

구성들은 Blackboard에 추가될 새로운 Data객체들을 생성할지도 모른다.

구성들은 Blackboard상의 특별한 종류의 Data를 찾고,

Knoledge source에 존재하는 패턴과 매치되는 해당 Data를 찾을 수 있다.

 

 Blackboard pattern은 주로 음성인식, 차량 식별과 추적, 단백질 구조 식별, 수중음파 해석등에 사용된다.

 

 

10. interpret pattern 

이 패턴은 특정한 언어에 대한 통역 프로그램의 구성품을 디자인할 때 사용된다.

이것은 주로 어떻게 프로그램의 줄들, 특정한 언어로 쓰여진 문장 혹은 표현식을 어떻게 평가할지 지정한다

기본적인 개념은 언어의 각 표식에 따라 계층을 만드는 것이다.

 

 

PS : Component를 구성 혹은 구성품이라고 번역해봤는데 뭔가 적절한 번역을 못찾겠음

반응형
Posted by Sweetmeats_boy

2019. 7. 31. 12:57 기타 상식

FirebaseMessage 란?

반응형

참고 출처 :  https://firebase.google.com/docs/android/setup

 

Android 프로젝트에 Firebase 추가  |  Firebase

시작하기 전에 Android 스튜디오를 설치하거나 최신 버전으로 업데이트합니다. Android 앱이 다음을 충족하는지 확인합니다. API 수준 16(Jelly Bean) 이상 타겟팅 Gradle 4.1 이상 사용 앱을 실행할 기기 또는 에뮬레이터를 설정합니다. Google Play가 포함된 에뮬레이터 이미지를 에뮬레이터에서 사용해야 합니다. Google 계정을 사용하여 Firebase에 로그인합니다. Android 앱 프로젝트가 준비되지 않았다면 빠른 시

firebase.google.com

Firebase Message 란?

GCM[Google Cloud Message ] 지원이 사실상 종료됨에 따라 필수적으로 Migration해야 하는 서비스이다.

위 출처에서는 기본적으로 FCM을 Android에서 사용하려면 어떻게 해야하는지 잘 설명하고 있다.

 

 위 FCM 문서 내용중 중요한것은 아래와 같다.

1. Target SDK 버전은 16이상.

2. Gradle은 4.1 이상

 

만약 GCM에서 FCM으로 Migration해야한다면 아래의 링크, 영상을 확인하면 된다.

 - https://developers.google.com/cloud-messaging/android/android-migrate-fcm

 

Migrate a GCM Client App for Android to Firebase Cloud Messaging  |  Cloud Messaging  |  Google Developers

You can migrate an existing GCM client app on Android to Firebase Cloud Messaging (FCM) using the instructions in this guide. Before getting started, keep in mind: GCM and FCM SDKs cannot co-exist within an application. GCM tokens retrieved via GoogleCloud

developers.google.com

Migration 과정은 간단하게는 GCM관련 permission, service등을 제거 한 후 

FCM관련 service를 사용하게 하면 된다.

 

 

FCM의 적용, Migration의 방법에 대해서는 매우 간단하며 만약 기존의 GCM을 사용하고 있었다면

아마 Token을 얻어오는 과정만 수정한다면 그외에는 건드릴게 있나 싶다.

 

 

다만 개인적으로 해당 작업을 하면서 시간을 엄청 날렸던 점들에 대해서 적어보려고 한다.

우선 내가 Unity Client에 대해서 급작스럽게 fcm을 적용해야 하는 처지가 되서 진짜 맨땅에 헤딩을 엄청 했다.

기본적인 Gradle Build부터 현재 게임에 붙어있는 SDK들이 무엇인지 파악도 안된 상태에, 또 SDK들이 어떻게 엮여있는지 등등 하나하나 확인하며 작업하고 빌드하고 확인하는 과정을 주구장창했었는데 사실 엄청 간단했다.

 

우선 위의 출처에 나와있는 Firebase Message service문서를 순서대로 따라하면

Build.gradle에 implementation 'com.google.firebase:firebase-messaging:18.0.0' 이런식으로 나와있을 것이다.

 

이 문서에서 나오는 버전의 경우 반드시 최신버전은 아니기 때문에 만약 최신버전으로 적용하려고 한다면

maven을 확인하면 된다.

 

반면 나의 경우 게임에 엮여있는 SDK들 중 이미 FCM을 lib수준에서 implement하고 있던 SDK[KaKao......ㅅㅂ]가 있었고 

이부분을 모른채 공식 문서만 따라서 진행하던 나는 뭐가 문제인지 모르고 시간낭비만 했었다.

 

내가 implement로 추가한 FCM 버전과 SDK에서 이미 적용한 버전이 달랐던 부분이 문제였는데

SDK에서는 15.0.2를 참조했고 위 문서에서는 18.0.0을 참조하게 했으니 1차 문제였다.

2차적인 문제는 15.0.2에서는 FirebaseinstanceIDService를 사용하는 반면

18.0.0에서는 deprecated되어 않도록 문서가 작성되어 있다는 것이다.

[더 짜증나는건 FCM 이놈들이 딱히 버전 충돌같은 것을 언급도 안했다는 것]

 

아무튼 사용하려는 Firebase 버전에 따라서 Token을 얻어오는 과정이 다르니 반드시 확인하도록 하자.

반응형

'기타 상식' 카테고리의 다른 글

함수 호출 정보에 관하여  (0) 2019.09.05
게임에서의 랜덤값에 대해서  (0) 2019.09.02
멀티 스레드에 관해서  (0) 2019.07.14
ORM이란?  (0) 2019.06.23
LockFree란?  (0) 2017.03.03
Posted by Sweetmeats_boy
반응형

참고 출처 : https://docs.unity3d.com/kr/2018.2/Manual/android-gradle-overview.html

 

Android용 Gradle(Gradle for Android) - Unity 매뉴얼

Gradle은 빌드 프로세스 수를 자동화하는 Android 빌드 시스템입니다. 이 자동화로 인해 가장 일반적인 빌드 오류가 발생할 확률이 줄어듭니다. 특히 Unity 에디터에서 Gradle을 사용하면 DEX(Dalvik Executable 포맷) 파일의 메서드 레퍼런스 수가 감소하므로 DEX 제한과 관련된 문제가 발생할 가능성이 더 적습니다. 하지만 Gradle과 디폴트 Unity Android 빌드 시스템의 차이점으로 인해 일부 기존 프로젝트를 Grad

docs.unity3d.com

Unity에서 Android 용 Gradle 빌드 설정하는 방법은 위의 출처를 참조하면 된다.

 

참고출처2 : http://blog.naver.com/PostView.nhn?blogId=sdragoon&logNo=221378742876&parentCategoryNo=&categoryNo=29&viewDate=&isShowPopularPosts=true&from=search

 

Unity Gradle Build란 무엇이며 어떤 상황에 사용하는가?

 

우선 unity로 앱, 게임을 개발할 시 안드로이드 Native 기능들을 사용하고자 할 경우 

주로 PlugIn 형태로 만든 후 프로젝트에 Import하여 빌드해서 사용한다.

이러한 PlugIn들은 Gardle을 통해서 Unity가 빌드 시 필요한 Native모듈에서 lib를 다운받는데

이 때 피룡한 class를 찾지 못하거나 기타 문제를 발생 시킬 수 있다.

 

Unity gradle 빌드는 이러한 문제를 사전에 방지할 수 있다.

 

빌드설정에서 우선 Gradle Build로 Export를 진행하는 것인데 Export 시 AndroidStudio(이하 AS) 용 프로젝트가 생긴다.

 

이렇게 추출한 프로젝트를 AS에서 빌드를 해봄으로써 Gradle에 대해서 우선적으로 확인을 해보는 것이다.

 

이러한 과정을 거치면 우선 Unity Build중 Gradle에 의해서 빌드가 실패할 때 발생하는 시간 소모를 줄일 수 있다.

 

Unity에서 Gradle 빌드 시 Export된 프로젝트에서 생성되는 Build.Gradle은 Unity에서 빌드 시 활용하게 되는데

해당 파일을 Unity Asset/PlugIns/Android 폴더에 복사 후 mainTemplate로 이름을 변경한다. 

 

그 후에 Unity 빌드 세팅에서 export를 해제한 후 빌드를 수행한다면 빌드 시 해당 mainTemplate 파일을 참고하여

 

빌드가 진행 된다.

 

----------------------

참고 출처 2에서도 나와있지만 개인적으로 고생했던 사항이라서 다시 적어둔다.

 

현재 서버에서 얼떨결에 클라이언트까지 맡게되서 처음 해본 Gradle 빌드 시도중 고생했던 경험을 적어본다.

 

멋모르고 Gradle 빌드 후 Export된 프로젝트의 Build.gradle(추후 mainTemplate로 바꿀)의 BuildScript항목에서

 

dependencies 항목에 classPath로 build:gradle:x.x.x가 있고 하이라이팅 되면서 최신버전으로 바꿀 수 있도록

 

정보를 AS에서 제공ㅇ하고 있었고 최신버전이 좋은것 같길래 해당 버전을 임의로 수정했었다.

 

그후 해당 파일을 sync 후 mainTemplate로 적용 후 빌드를 진행했는데 당연히 빌드 중 에러가 발생하였다.

 

우선 우리가 Export할 때 Unity에서 사용중인 gradle 버전이 위에서 수정한 항목으로 추출되는 것이다.

 

따라서 해당 gradle 버전을 변경하고 싶다면 우선 Unity가 사용하는 Gradle을 변경해준 후 다시 Export해야 한다.

 

Unity 설치 경로/Editor/Data/PlaybackEndgines/AndroidPlayer/Tools/gradle/lib 폴더를

 

Unity를 끈 후 다른 gardle버전의 lib로 덮어씌워주면 된다.

(ex : 특정 gradle 버전 다운 후 해당 폴더안의 lib 폴더)

 

반응형
Posted by Sweetmeats_boy

2019. 7. 21. 16:45 Network

RabbitMQ에 대해서

반응형

참고 출처 : https://skibis.tistory.com/310

 

RabbitMQ란 AMQP을 기반으로 만들어진 프로그램이다.

 

RabbitMQ와 관련된 주요 용어는 아래와 같다.

 

producer : 메세지를 보내는 App

publish : Producer가 메세지를 보내는 것

Queue : 메세지를 저장하는 버퍼, Queue는 Exchange에 Binding 된다.

Consumer : 메세지를 수신하는 App

 - 동일 업무를 처리하는 Consumer는 보통 한개의 Queue를 본다.

 - 여러 Consumer가 같은 Queue를 볼 때 자동으로 메세지가 분배되서 전달된다.

Subscribe : Consumer가 메세지를 수신하기 위해 Queue를 실시간 리스닝 하도록 한다.

Exchange : Producer가 전달한 메세지를 Queue에 전달하는 역할을 한다.

 - 메세지가 Queue에 직접 전달되지 않고 exchange type에 정의한 대로 동작한다. 

ExchangeType : type에는 fanout, direct, topic, header 4가지가 존재한다.

Binding : Exchange와 Queue를 연결해주는 작업

Routing : Exchange와 Queue에 메세지를 전달하는 과정을 의미한다.

RoutingKey : Exchange와 Queue가 binding 될 때 Exchange가 Queue에 메세지를 전달할지 여부를 결정한다.

 

 

Exchange를 별도로 명시하지 않은 경우, RabbitMQ의 기본적인 흐름은 아래와 같다.

1. Producer가 메세지를 생성하여 전송.

2. Queue가 이 메세지들을 순차적으로 쌓는다.

3. Consumer가 Queue에 대한 Biunding을 가지고 있다가 메세지를 Queue에서 수신한다.

 

 

메세지의 분배 [ Round - robin Dispatching ]

RabbitMq는 Consumer가 병렬처리를 쉽게 할 수 있도록  같은 Queue를 바라보고 있는 Consumer에게 균등 분배한다.

즉, 첫 메세지는 Consumer1, 두번째 메세지는 Consumer2에게 주는 식으로 중복처리되지 않게 자동 분배를 해준다.

 - 이 특징을 통해서 RabbitMQ는 수평적 확장이 용이하다.

 

공평한 분배 [ Fair dispatch ]

여러 consumer에게 round robin을 통해 메세지를 균등하게 전달하지만 완전한 균등은 아니다.

이 때 Busy한 서버에게 메세지가 계속 전달되지 않도록 prefetchCountㄹ하는 개념을 사용한다.

prefetchCount가 1일 때는 아직 sck를 받지목한 메세지가 1개라도 존재 시,

해당 Consumer에게 메세지를 할당하지 않는다.

[prefetchCount는 해당 Consumer의 동시 처리가능한 메세지 갯수를 의미하는 듯]

 

메세지 수신 통보 [ Acknowledgement ]

많은 프로토콜이 메세지 전달 보장을 위해서 Acnowledgement( ACK ) 라는 개념을 사용해서

메세지에 대한 응답을 보내주도록 되어 있다.

ACK의 중요성은 메세지가 확실히 처리되었는지를 확인할 수 있게 해주며 ACK가 온 메세지에 한해서만

Queue에서 삭제를 진행하기 때문이다.

 

 

Consumer 중 일부가 죽었을 시 대응방법

ACK가 오지 않는 Consumer가 존재 시(Disconnect등의 경우) 해당 메세지를 다음 Consumer에게 할당한다.

 

 

RabbitMQ가 죽었을 경우 대응 방법

RabbitMQ는 Queue에 메세지를 보관하고 ACK를 받은 경우에만 메세지를 Queue에서 삭제한다.

Consumer가 죽었을 시 메세지를 보존할 수 있지만 RabbitMQ가 죽은 경우는 어떻게 해야할까

RabbitMQ가 죽는다면 Queue에 있는 메세지들 역시 날아가 버릴 것이다.

이 경우에 대한 대비책은 메세지들을 Queue에 저장 시 File에도 기록하는 것이다.

 

반응형

'Network' 카테고리의 다른 글

HTTP Protocol  (0) 2021.06.20
OSI 7계층과 TCP/IP 4 계층  (0) 2021.06.20
load balancing  (0) 2020.08.27
OSI 7계층와 TCP/IP 4 계층  (0) 2020.08.27
Thrift에 대해서 [C# 한정]  (0) 2020.01.10
Posted by Sweetmeats_boy
반응형

출처 : https://12bme.tistory.com/176?category=734721

 

[오픈소스] 메시지큐(Message Queue) 알아보기

메시지 큐 개념을 다시 잡아보고자 학습용도로 작성한 포스팅입니다. 출처는 http://zzong.net/post/3 입니다. 메시지 지향 미들웨어(Meesage Oriented Middleware: MOM)은 비동기 메시지를 사용하는 다른 응용 프..

12bme.tistory.com

메세지 지향 미들 웨어[Message Oriented Middleware : MOM]이란?

-  비동기 메세지를 사용하는 다른 응용프로그램 사이의 데이터 송수신을 의미.

 

이러한 MOM을 구현한 시스템을 Message Queue, 즉 MQ라고 칭한다.

 

MQ는 프로그램간, 프로세스간 데이터를 서로 교환할 때 사용하는 방법이다.

데이터를 교환할 때 시스템이 관리하는 메세지큐를 하용하는데 이때 사용하는 프로토콜을 

AMQP[Advanced Message Queing Protocol]이라고 한다.

 

 

메세지 큐의 장점은 크게 6가지가 있다.

1. 비동기 : Queue에 넣기 때문에 나중에 처리 할 수 있다.

2. 비동조 : Application과 분리 할 수 있다.

3. 탄력성 : 일부가 실패하더라도 Apllication 전체에 영향이 가지 않는다.

4. 과잉 : 실패할 경우 재실행이 가능하다.

5. 보증 : 작업의 처리상황을 알 수 있다.

6. 확장성 : 다수의 프로세스들이 큐에 메세지를 보낼 수 있다.

 

MQ는 주로 대용량 데이터를 처리하거나 채팅 혹은 비동기 데이터를 처리할 때 사용한다.

프로세스 단위로 처리하는 우베 요청이나 일반 프로그램 사용 시 사용자 혹은 데이터의 급증 시 

응답 대기 시간이 지연되어 서비스의 장애르 초래할 수 있기 때문에 우선 MQ 로 메세지, 데이터를 집중한 후 

필요한 프로그램에 작업을 분산시키는 것이 주 목적이다.

 

 

MQ 프로그램들은 다음 포스팅에서...

반응형

'Server' 카테고리의 다른 글

서버 Socket 설정하는 방법들  (0) 2019.09.06
게임 서버에서의 Log 구성  (0) 2019.09.04
게임 서버에서의 Log의 분류  (0) 2019.09.04
IOCP 동작원리에 대하여[작성중]  (0) 2019.08.26
IOCP에 대하여  (0) 2019.08.26
Posted by Sweetmeats_boy
반응형

우선 스레드란 프로세스 내부에서 공통 자원을 토대로 실행되는 가장 작은 작업단위라는 것을 모두 알 것이다.

 

멀티스레드란 한개의 프로세스 내에서 여러 스레드가 동시 다발적으로 작업을 수행하는 것을 의미한다.

 

그렇다면 멀티스레드의 장단점은 무엇일까?

 

우선 장점으로는 크게 응답성, 자원공유, 경제성, 멀티프로세서 활용 이렇게 4가지가 존재한다.

 

대화형 프로그램을 멀티스레드화 하면, 프로그램의 일부 스레드가 지연되더라도 다른 스레드가 여전히 수행된다.

 

예를 들면 웹페이지에서 이미지 로딩중에 다른 작업이 진행되는 경우 등이 응답성 측면에서의 장점에 속한다.

 

자원 공유와 경제성의 경우 같은 프로세스에 속한 스레드는 자원을 공유하기 때문에 context switching 등에서 좀더 비용이 적다는 이점이다.

 

마지막으로 멀티프로세서 활용의 경우 각각의 스레드를 다른 프로세서에서 병렬로 수행이 가능하다는 것이다.

 

단점의 경우는 크게 4가지로 볼수 있다.

첫번째로는 자원공유로 인해 발생하는 단점으로 각각의 스레드가 공유자원에 대해서 서로 간섭하는 경우가 생긴다는 것이다.

 

두번째로는 한개의 스레드만 실행 중인 경우 싱글 스레드와 차이가 없고 오히려 더 지연되는 경우가 생길 수 있다는 것이다.

 

세번째로는 멀티 스레드 적용 시 운영체제를 우선 고려해야 하고 응용프로그램의 경우 멀티 스레드를 고려한 구조로 설계되어야 한다는 것이다.

 

마지막으로는 각 스레드 별 스케줄링에 주의해야 한다는 것이다.

 

 

멀티 스레드 모델

 

멀티 스레드는 크게 3가지 모델로 구분할 수 있다.

1. 다 대 일[Many To one]

Many To one의 경우 여러 유저 스레드들이 한개의 프로세서로 매핑되는 방식이다.

스레드의 관리는 유저 레벨에서 이루어 지며 주로 커널 스레드를 지원하지 않는 시스템에서 사용한다.

다만, 이 경우 한개의 스레드만 커널에 접근 할 수 있다는 단점이 존재한다.

이 단점 때문에 진정한 의미의 동시성이 지원되지 않는다.

 

 

2. 일 대 일[One to One]

One to One의 경우 한개의 스레드를 한개의 프로세서에 한개의 스레드를 매핑 시키는 방법이다.

이 경우 위의 Many To One 모데에서 발생하던 단점인 특정 스레드가 커널 사용시 다른 스레드가 중단되는 단점이 사라진다. 

그러나 커널 스레드도 한정된 자원을 사용하기 때문에 무한정 생성할 수는 없으며 항상 스레드 생성 갯수를 염두해 두어야 한다.

 

 

3. 다 대 다

Many To Many 의 경우 여러개의 유저 스레드를 여러 개의 커널 스레드로 매핑시키는 방법이다.

Many to One, One to One의 단점을 해결하기 위해 고안된 방법이다.

커널 스레드는 생성된 사용자 스레드와 같은 수 또는 그 이하로 생성되어 스케쥴링 한다.

Many to One 방식에서 스레드가 시스템 호출 시 중단 되는 현상, One to One의 스레드 생성 갯수제한에 대해서 고민하지 않아도 된다. 커널에서 유저 스레드와 커널 스레드의 매핑을 조절하기 때문이다.

[출처 : 위키 https://ko.wikipedia.org/wiki/%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9 ]

 

 

 

 

반응형

'기타 상식' 카테고리의 다른 글

게임에서의 랜덤값에 대해서  (0) 2019.09.02
FirebaseMessage 란?  (0) 2019.07.31
ORM이란?  (0) 2019.06.23
LockFree란?  (0) 2017.03.03
메모리 거짓 공유란?  (0) 2017.01.13
Posted by Sweetmeats_boy

2019. 6. 23. 19:27 기타 상식

ORM이란?

반응형

O.R.M(Object Relational Mapping) 이란 무엇인가

 

 

간단히는 C#의 property / Java의 getter,setter를 이용하여

 

객체지향프로그래밍(O.O.P)의 객체와 관계형 데이터베이스 간의 Mapping을 지원해주는

 

Framework 혹은 Tool들을 의미한다.

 

 

그렇다면 ORM에는 어떤 것들이 있을까?

 

대표적으로 아래의 ORM들이 가장 대중적이다.

  • MyBatis.
  • iBatis.
  • JPA.
  • Hibernate

이 중 MyBatis, ibatis가 많이 쓰인다고 한다.

 

그렇다면 ORM들의 장단점은 어떨까

 

우선 장점에 대해서 알아보자.

1. 개발자로 하여금 좀 더 직관적이고 로직에 집중할 수 있게 도와준다.

 - SQL이 아닌 객체에 접근해서 Data를 조작하기 때문에 좀더 직관적이다.

 - SQL사용시 필요한 부수적인 코드들을 줄일 수 있다.

 - 객체에 관해 코드를 작성하므로 가독성이 높아진다.

 

2. 코드 재사용성 증 및 유지보수의 편리성이 증가한다.

 - Mapping 정보를 명확히 하기 때문에 ERD를 일일히 확인하지 않아도 된다.

 - MVC패턴에 활용하기 쉽다.

3. DBMS에 대한 종속성을 줄일 수 있다.

 - 개발자는 객체 정의에 집중함으로써 DBMS를 교체하는 등의 작업에서 작업 시간, 리스크를 줄일 수 있다.

4. SQL을 몰라도 독립적으로 개발이 가능하다.

 

반대로 단점들은 무엇이 있을까

1. 오롯이 ORM만 사용해서 모든 서비스를 구현할 수 없기 때문에 DBMS로 부터 완벽히 독립할 수 없다.

 - 필요한 경우 DBMS를 사용해야 하는 상황이 발생한다.

2. ORM으로 인해 프로젝트의 복잡성, 난이도가 증가할 수 있다.

3. 잘못된 사용으로 인해 속도가 느려지거나 기타 문제가 발생할 수 있다.

4. DBMS의 고유 기능을 사용 못하는 경우가 발생한다.

5. 프로시저 사용이 많은 환경에서는 ORM 적용으로 얻는 장점을 활용하기 힘들다.

 - 기존의 프로시저를 많이 사용하던 경우, 일일히 객체와 Mapping 시켜줘야 하며,

   이 과정에서 비용(리스크, 시간소모 등)이 발생한다.

 - 예 : User라는 table에 대해서 Person, Address 라는 객체를 구분해서 생성하는 경우

6. The Object-Relational Impedance Mismatch( 객체와 DBMS의 불일치성 ?)

 - Granualrity ( 세분성 )

    . 경우에 따라서 DB의 Table 명세보다 객체를 과도하게 만들 수 있다.

      -> User라는 Table이 Person, Address라는 클래스로 구분해서 생성하는 경우 등등

 - Inheritance ( 상속 )

    . ORM에서는 상속 개념을 사용할 수 없다.

 - Identity ( 일치 )

    . RDBMS에서는 Pk값등으로 일치여부를 판별하지만 자바는 객체주소 비교, 객첵밧 비교를 모두 지원한다.

 - Associations ( 연관성 )

    . 객체 지향 언어는 Referance를 통해 객체를 참조하지만 RDBMS는 외래키로 객체를 참조한다.

     -> 이 경우 쌍방향 참조를 할 때 java는 각 객체가 서로를 참조할 변수를 지녀야 하지만

         RDBMS는 외래키만 참조하면 된다.

      -> 즉, Java의 경우 방향정을 지니며 RDBMS는 방향성을 지니지 않는다.

 - Navigation ( 탐색 / 순회 )

    . Java의 경우 객체간의 연결을 통해서 이동하며 탐색/순회 한다

    . RDBMS에서는 일반적으로 쿼리를 최적화하여 엔티티를 탐색 및 선택한다.

반응형

'기타 상식' 카테고리의 다른 글

FirebaseMessage 란?  (0) 2019.07.31
멀티 스레드에 관해서  (0) 2019.07.14
LockFree란?  (0) 2017.03.03
메모리 거짓 공유란?  (0) 2017.01.13
Concurrency와 Parallelism의 차이에 대하여  (0) 2017.01.12
Posted by Sweetmeats_boy
반응형

eeRedis란 무엇인가에 대해서 간단하게 알아보자




Redis의 기능은 캐쉬서버라고 볼 수 있다.


우선 캐쉬서버란 무엇인가?


우리가 게임을 플레이하고 있다고 생각을 해보자.


클라이언트와 서버는 유저의 행동에 따라서 무수히 많은 통신을 하고 


게임 로직에 의거하여 플레이어의 정보를 수정, 갱신을 하게 된다.


만약 우리가 이러한 작업을 할 때 단순히 MYSQL등의 DB만을 사용한다면 어떻게 될까?


무수히 많은 SELECT 요청과 UPDATE 혹은 DELETE요청이 상대적으로 느린 DB에 쌓여서 


유저의 정보를 처리하는데에 많은 시간이 소요될것이고 


이에 따라서 서버에는 많은 과부하가걸릴 것이다.



이러한 문제를 해결하기 위해서 선택한 것이 메모리에서 해당 정보를 지닌채로


조회등의 요청이 올 시 메모리를 참조하게하고 데이터 갱신 등의 작업 시


우선 메모리를 갱신 한 후 DB에 적용하는 방법이다.



이러한 방식을 사용하는것이 Redis, Memecached 등등의 캐시 시스템인 것이다.


Memcached와 redis의 차이점은 추후 다른 글에서 자세히 알아보고 


우선은 Redis의 특징에 대하여 알아보자.


1. Redis는 영속성을 지원하는 인 메모리 데이터 저장소이다.

2. read 측면에서 성능을 향상시키기 위한 서버측 복제를 지원한다.[master, slave 서버]

3. write측면에서 성능을 향상시키기 위한 클라이언트 측의 샤딩을 지원한다.

4. ANSI C으로 작성되어 ANSI C컴파일러가 동작하는 곳이면 어디든 설치,실행이 가능하다.

5. Redis client는 다양한 언어로 포팅되어 있다.

6. 다양한 서비스에 활용되고 있으며 이를 통해 성능적으로 검증되었다.

7. 다양한 Data 형을 지원한다.

8. 메 모리 외의 영구 저장소를 지원하므로 instance 재시작에 대한 CacheWarmUp을 고려하지 않아도 된다.



출처 : http://blog.naver.com/PostView.nhn?blogId=newamsterdam99&logNo=220588699370&parentCategoryNo=6&categoryNo=&viewDate=&isShowPopularPosts=true&from=search



- ANSI C 란?

ansi c란 American Mational Standards Institute 의 약자로 미국에서 공인된 표준이지만 현재는 국제적으로 공인된 C의 표준이다.

이 표준의 목적은 C기반 Program들의 형식과 이를 해석하는 방식을 명시함으로써,

C언어 기반 Program의 이식성, 신뢰성, 유지보수성, 효율적인 실행을 증진시키는 것이다.

-> 현재 대부분의 C컴파일러는 해당 표준을 준수한다.


- Redis가 지원하는 Data형의 종류

String : 문자열 및 숫자, 바이너리 이미지등을 저장가능.[최대 512MB]

Set : 하나의 키값에 대한 여러 값을 저장, Set간의 연산으로 교집합, 합집합을 계산할 수 있다.

Sorted Set : 내부의 값들을 오름차순으로 저장한다.

Hashes : 해싱된 키값과 이에 대한 String을 저장

List : String들의 집합으로 LinkedList와 흡사, push와 pop으로 데이터 추가,제거가 가능하다.


- CacheWarmUp이란?: 

자세한 내용은 외국 블로그 번역 게시판 참고


- Sharding이란?

수평분할과 샤딩이라는 것이 있는데 우선 수평분할(horizontal pratialing)의 경우 동일한 스키마를 지닌 다른 테이블에 데이터를 저장하는 것을 의미한다.

이러한 방법은 인덱스의 크기를 줄이고 작업 동시성을 늘리기 위한 것이다.

이와 달리 샤딩은 동일한 스키마를 지닌 물리적으로 다른 DB에 데이터를 저장하는 것을 의미한다. 샤딩의 경우 다른 DB에 데이터가 존재하는 것이기 때문에 몆몆 기능적인 부분에서 제약이 존재한다.(예 : join의 경우, 일관성 유지, 데이터의 복제 등등)


간단히 말하자면 하나의 DB에 담기 방대한 자료를 동일 사양, 동일 내용의 다른 DB에 저장하는 것을 Sharding이라고 한다.



반응형
Posted by Sweetmeats_boy

2017. 3. 3. 18:29 기타 상식

LockFree란?

반응형

예제 및 내용 출처 : http://www.gamedevforever.com/83





비교적 최근에 알게된 개념인데 LockFree라는게 있다.



맨처음에 LockFree라는 이름만 듣고는 Lock을 안쓰는 알고리즘같은건줄 알았다.

근데 좀 딴얘기라서 당황


LockFree가 하는일은 무엇일까?

우선적으로 알아둬야 할 개념으로서 Atomic 연산이 있다.

"Atomic연산은 일련의 모든 연산이 끝나기 전에는 다른 프로세스가 해당 연산에 대해서 

어떠한 변화도 줄수 없어야 한다. 또한 전체 연산 중 어느 하나라도 실패할 경우 

모든 연산은 실패하며 시스템은 연산이 시작하기 전으로 복구되어야 한다."


사실 아직도 위글만 보면 감이 좀 안잡히는데 중요한건 아래 내용이다.

특정 값이 예상한 값과 같다면 다음단계로 넘어가고, 

만약 변경되었을 경우 해당 연산을 다시 시작하도록 한다.


윈도우에서는 CAS(Compare And Swap)을 Interlocked함수를 활용하여 구현한다


LockFree를 사용하는 이유는 어떤 블로그에서 읽었는지 기억은 안나지만 아래의 이유였다.

" LockFree는 lock을 사용않아도 되도록 하는것이 아니라 여러 스레드에서 lock을 요청할 때 

발생할 수 있는 데드락을 막고 최소한 하나의 스레드가 작업을 수행할 수 있도록 해주기 때문이다. "


사실 이 LockFree알고리즘에 대해서 ABA문제라던가 아니면 들인 노력에 비해서 미비한 효과라던가 하는 포스팅도 볼 수 있는데 이부분은 좀더 알아본 후 추가 포스팅으로 작성할 것이다.



마무리로 간단한 예제를 적어본다.

  1. void Push(Node* pNewNode)  
  2. {  
  3.  do {  
  4.    Node* t = pTopNode;  
  5.    pNewNode->pNext = t;  
  6.  } while( !CAS(&pTopNode, t, pNewNode) );  
  7. }  




반응형

'기타 상식' 카테고리의 다른 글

FirebaseMessage 란?  (0) 2019.07.31
멀티 스레드에 관해서  (0) 2019.07.14
ORM이란?  (0) 2019.06.23
메모리 거짓 공유란?  (0) 2017.01.13
Concurrency와 Parallelism의 차이에 대하여  (0) 2017.01.12
Posted by Sweetmeats_boy
반응형
짧은 영어로 번역하는것이라 오역, 의역이 있을수 있습니다.

좀더 정확한 정보를 얻거나 실력을 향상시키실 분들은 해당 블로그에 직접 가셔서 여러번 읽어보시길 바랍니다.



출처 : GAFFER ON GAMES

 - http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/




TCP / IP

TCP는 'Transmission Control Protocol'이며 IP는 'Internet Protocol'입니다,

위의 두개는 당신이 온라인에서하는 모든 것, 웹 브라우저에서 email을 사용하기 위한 IRC의 기반이 되며 이 모든 것들은 TCP/IP 위에 지어졌습니다.


만약 당신이 TCP 소켓을 사용한 적이 있다면 당신은 이것이 신뢰할 수 있는 연결 기반의 Protocol 이라는 것을 알수 있다. 이것은 단순히 두 장치 사이에 연결을 만들고 두 컴퓨터 간의 데이터를 전송하는 것이 한쪽에서는 파일을 쓰고 다른 한쪽에서는 파일을 읽는 것과 매우 흡사하다는 것을 의미합니다.


이 접속은 신뢰할수 있고 정렬되어 있습니다. 

당신이 보낸 모든 데이터는 다른쪽에 도착할 때 당신이 작성한 순서대로 도착하는 것을 보장할 수 있습니다.

이것은 또한 data의 Stream이며 TCP가 주의해서 당신의 데이터를 패킷으로 분할하고 네트워크를 통해 당신에게 보낼수 있도록 합니다.


다시 말하지만 이것은 파일 입출력과 비슷하다는 것을 잊지마세요. 간단합니다!



IP


단순성은 TCP 밑의 저수준의 IP 프로토콜에서 일어나는 일과는 뚜렷한 차이가 있습니다.


여기에는 연결에 대한 개념은 없습니다, 대신 다음 목적지를 향해 한 컴퓨터를 지나가는 패킷이 있습니다.

이것은 사람이 많은 방에서 쪽지를 다른 한사람에게 전달해주는 것으로 볼 수 있습니다.


이것은 해당 사람에게 전달된다는 것을 보장하지 않습니다.

보낸사람은 그저 그 쪽지가 전달되는것을 희망하는것이 최선입니다.

[보낸사람은 그저 쪽지가 전달되기를 바랄 뿐입니다.]

해당 쪽지를 받았는지 아닌지는 절대 알수 없습니다, 다른사람이 답장을 쓰지 않는한 말이죠



물론 현실에서는 위에서 말한것보단 좀더 복잡하게 이루어집니다.

물론 어떠한 컴퓨터도 컴퓨터들을 지나 패킷들이 목적지까지 가장 빠르게 도달하는 정확한 전송과정을 알고있지 못하기 때문입니다.


때때로 'IP는 여러개의 복사된 패킷들에 따라서, 그 패킷들은 목적지까지 다다르는 여러 경로

를 만들어 냅니다., 그래서 제각각 도착시간이 다를수 있습니다.



이것은 인터넷이 스스로 형성되고 스스로 복구되도록 디자인되었기 때문이며 

접속문제가 생겨도 주변을 통해 접근할 수 있도록 하기 위해서입니다.

[위 문장 거의 의역]


당신이 실제로 어떻게 도달해야하는지에 대한 낮은 레벨에 대해서 어떻게 진행되는지 생각해보는것도 확실히 멋진 일이다. 당신은 이 내용을 TCP/IP illustrated 책에서 읽을 수 있다.



UDP


두 컴퓨터 사이의 소통을 마치 파일을 쓰는 것처럼 다루는 대신에,우리가 패킷들을 직접 보내고 받는건 어떨까?


우리는 이것을 UDP를 사용함으로써 할 수 있다.

UDP는 유저 데이터그램 프로토콜에 기반하고 이것은 TCP처럼 IP위에서 구현되는 또다른 프로토콜이다. 그러나 이번에는 복잡성과 여러 특징들을 대신 그저 IP위에 매우 얇은 계층을 더할 뿐입니다.


UDP를 통해서 우리는 패킷을 목표IP주소와 port로 보낼수 있습니다.

그리고 이것은 목적지를 향해서 컴퓨터에서 컴퓨터를 통해 도달하거나 혹은 이 과정중에 유실될 수 있습니다.


수신자 측에서, 우리는 단지 특정 포트를 통해 기다릴수 있으며[listen] 

익명의 컴퓨터로부터 패킷이 도착했을 때, 우리는 그제서야 패킷을 보낸측의 주소와 port를 알 수 있다.

[위 내용은 UDP는 실제 컴퓨터간의 연결을 통한 전송이아니라 목적지만 정하고 전달하는 특징 때문]


UDP는 순서를 유지해주지 않는 프로토콜이다. 

실제로 대부분의 전송된 패킷은 실제 전송한 것에 비해서 1~5%센트가 유실된다.

그리고 경우에 따라서 모든 패킷을 못받는 시기가 올 수 도 있다.

[당신과 당신이 원하는 목적지 사이에 수많은 컴퓨터들이 있기때문에 잘못 전달될 수 있다는 것을 명심해라]



그리고 UDP는 패킷의 순서를 보장해주지 않는다.

만약 5개의 패킷을 보냈다면 이것들은 3,1,2,4,5 순서로 도착할 수도 있다.

실제로 패킷들은 대부분의 경우에는 순서대로 도착한다.

다만 보장할 수 없다는 것이다.

[왠만하면 순서대로 오지만 결국 확인을 해야된다는 말]



마지막으로, 대부분의 UDP는 IP프로토콜의 위에 많은것을 추가하지 않았지만,

이것은 단 한가지를 당신에게 보장한다.

만약 당신이 패킷을 보냈다면, 이것은 보낸패킷들이 전부다 도착하거나 전부다 도착하지 않는다는 것이다.

따라서 만약 당신이 256바이트의 패킷을 다른 컴퓨터로 보냈다면, 그 컴퓨터는 100바이트만 수신하지 않고 256바이트의 모든 데이터를 받는다.


이것이 UDP가 당신에게 보장하는 단 한가지이다.



TCP와 UDP


우리는 TCP와 UDP 사이에서 어떤 것을 사용할 지 결정을 해야한다.

각각의 특징을 알아보자.


TCP

 - 접속기반 프로토콜

 - 순서와 신뢰성을 보장한다.

-> 여기서의 신뢰성은 보낸 메세지가 유실되지 않는다는 것.

 - 당신을 위해서 패킷에 저장된 data를 끊어준다.

 - 이것은 내부연결을 핸들링하여 보내려는 데이터가 너무 빨리 전송되지 않도록 합니다.

 - 사용하기에 쉽습니다, 당신은 그저 파일을 읅거나 쓰는것과 같은 작업을 하면 됩니다.



UDP

 - 연결[혹은 접속]이라는 개념이 없으며, 당신 스스로 이것에 대한 처리를 코드를 작성합으로써 처리해야 합니다.

 - 패킷의 순서 혹은 신뢰성을 보장하지 않습니다. 패킷들은 무작위 순서로 도착하거나, 중복되거나, 혹은 모든 패킷들이 다 도착하지 않을 수 있습니다.

 - 당신은 당신의 데이터를 잘라 패킷에 넣고 그것들을 보내야합니다.

 - 당신은 데이터가 인터넷연결보다 빠르게 전송되지 않도록 다뤄야 할 필요가 있습니다..

 - 만약 패킷이 유실되었다면, 당신은 이것을 알아 채고 필요하다면 데이터를 다시 전송할 방법이 필요합니다.


결정은 꽤 간단해보입니다, UDP는 우리가 모든 코드를 작성해서 고통을 받는 동안 TCP는 우리가 사용하기 쉽습니다.

그렇다면 우리는 바로 TCP를 선택해야 할까요?


틀렸습니다.


TCP를 사용하는 것은 최악의 경우 FPS같은 게임을 개발할 때 실수를 일으킬 수 있습니다.

왜 그런지 생각해봅시다. 당신은 TCP가 실제로 IP위에서 모든것을 간단하게 작업하는지에 대해서 살펴봐야 할 필요가 있습니다.



그렇다면 TCP는 실제 어떻게 작동하는가?

TCP와 UDP는 모두 IP를 기반으로 만들어 졌습니다.

그러나 둘은 근복적으로 차이점이 있습니다. UDP는 밑에있는 IP와 매우 흡사하게 행동합니다.

TCP는 파일 입출력처럼 느끼도록 모든것을 추상화하여 당신에게 패킷의 복잡성과 비신뢰성을 모두 숨김니다.


그렇다면 이것은 어떻게 이루어 지는가?


우선, TCP는 스트림기반의 프로토콜입니다.

따라서 당신은 그저 바이트 스트림을 작성하면 되며, TCP는 해당 스트림이 반대편까지 가로질러 가는것을 보장합니다.

IP는 패킷기반이며, TCP는 이 IP 위세 구축되었고, 그러므로 TCP는 반드시 당신의 데이터스트림을 패킷안에 잘라 넣어야 합니다.

이제 당신이 보내려는 데이터를 TCP는 코드 내부의 대기열에 넣습니다, 그러면 대기열에 데이터가 충분히 모였을 때 TCP는 패킷을 다른 장치에 전송합니다.


이것은 멀티플레이 게임에서 문제를 일으킬 수 있습니다.

만약 당신이 매우 작은 패킷을 보냈다면, TCP는 충분한 양의 데이터가 모이지 않았다고 판단하는 일이 발생할 수 있습니다.

이게 왜 문제냐면, 당신은 클라이언트에게서 입력정보를 가능하면 빨리 얻고 싶을것이기 때문입니다.

만약 TCP가 작을 패킷을 처리하는 것때문에 딜레이되거나 "엉망이 된다면", 클라이언트 유저는 게임이 거지같다고 느낄것입니다.

게임 네트워크는 주기적인 대신 우리가 원하는것처럼 빈번하게 수신되어야 합니다


TCP는 TCP_NODELAY라는 옵션을 지정할 수 있습니다.

이 옵션은 TCP가 충분한 데이터가 모이지 않더라도 당신이 데이터를 작성한 그 즉시, 

더 기다리지 않고 전송하도록 합니다.

이것은 경우에 따라서 Nagle 알고리즘을 사용하지 않는 방법으로 제공됩니다.


불행히도, 만약 당신이 이 옵션을 사용한다고 해도, TCP는 멀티플레이어 네트워크 게임에 사용하기에는 매우 중대한 문제점을 지니고 있습니다.


이 모든것은 TCP가 신뢰성과 순차성같은 환상을 당신에게 보여주기 위해서 어떠한 방법으로 손상되거나 순서가 없는 패킷들을 다루는지에서 시작됩니다.



실제로 TCP는 어떻게 구현되어 있을까?


기본적으로 TCP는 패킷안에 데이터를 자르고, 이 패킷을 IP를 통해 신뢰성 없이 전송한다.

그러면 반대편에서 이 패킷을 수신 후 스트림으로 재구성한다.


그렇다면 패킷이 유실되었을때는 어떤일이 일어나는가?

패킷이 순서 없이 도착하거나 망가지면 어떠한 일이 일어나는가??


어떻게 TCP가 작동하는지에 대해 깊게 들어가지 않아도 

TCP가 ACK를 수신하지 못해서 패킷이 유실되었다는 것을 알아차릴 때까지의 TCP의 전송방식은 기본적으로 매우 복잡하다.

중복된 패킷은 수신자 측에서 폐기되며 순서가 없는 패킷은 재정렬되기 때문에 모든것이 신뢰할수 있고 정렬된다.


문제는 만약 패킷이 누락될 때마다 우리가 TCP를 통한 동기화를 하려고 할 때, 

패킷을 다시 보내기 위해서 동기화를 멈추거나 지연시킨다는 것이다.

그렇다, 심지어 최신 데이터를 받았을 때도 최신 데이터를 큐에 넣고,

그리고 당신은 누락된 패킷이 재전송될때까지 이것에 접근할 수 없다.

패킷을 다시 보내려면 얼마나 걸릴까?

이것은 TCP로 데이터를 다시 보내 해결하기 위해서 최소 왕복하는 대기시간이 필요하다.

그러나 평균적으로 이것은 두배의 왕복시간[RTT (Round Trip Time )], 

그리고 발신자가 수신자에게 재전송할 패킷이 도달하는데 걸리는 시간이 필요하다.

따라서 만약 당신이 125ms의 ping을 갖고 있다면, 당신은 최선의 경우에도 패킷을 재전송하기위해서 1/5초를 기다려야 하며, 최악의 경우에는 상황에 따라서 당신은 1/2초 또는 더 오랜 시간을 기다려야 한다.

(재전송하는것이 또 실패할 수 있다는 것을 생각해보아라)


만약 TCP가 네트워크 손실을 나타내는 패킷을  잃어버리고 이것이 작동한다면 무슨일이 벌어질까? 매우 재밌어 질것이다.



왜 당신은 TCP를 네트워크 시간에 민감한데이터에 사용하면 안될까?


실시간 FPS게임에 TCP를 사용하는 문제는 Web브라우저 또는 e메일, 대부분의 App과는 비슷하지 않다는 것이다. 멀티플레이어 게임은 실시간으로 패킷의 전달을 요청한다.

당신의 게임 중 많은 부분, 플레이어 입력과 케릭터의 위치를 예로 들 수 있다.

이것은 실제로 몆초전에 어떤일이 일어났는지 신경쓰지 않으며, 당신은 오직 최신 데이터만 신경쓰면 된다. TCP는 이점을 염두해두고 설계되지 않았다.


멀티플레이어 게임의 매우 단순한 예를 고려해보면, 일종의 '슈터'같은 액션게임이 있다.

당신은 아주 간단한 방법의 네트워크를 원한다.

당신이 매 프레임마다 크라이언트에서 서버로 보낸 입력, 그리고 서버에서 매 프레임마다 처리하는 각각의 플레이어로부터의 입력, 시뮬레이션 처리, 게다가 랜더링을 위해서 클라이언트에게 게임 오브젝트의 현재 위치를 보낸다.


그래서 우리의 단순한 멀티플레이 게임에서는, 패킷을 잃을 때마다,

패킷을 다시 보내는 동안 모두 멈추고 기다려야한다.

클라이언트 게임 오브젝트에서 업데이트 받는것을 멈추면 그것들은 여전히 서있는것처럼 보일 것이다. 그리고 서버에서 클라이언트로부터 얻는 입력이 멈춘다.

그러면 유저는 움직이거나 솔 수 없다.

다시 보낸 패킷이 마침내 도착했을 때, 당신은 낡은것을 받고, 

이미 당신이 신경쓰지 않는 지나간 정보를 받는다.

덧붙여서 같은 시간에 도착한 패킷들은 다시 보내는 동안 큐에 저장된 채로 기다리고,

당신은 같은 프레임 내에서 모든 패킷에 대한 처리를 해야 한다.

모두다 엉망이다!


불행히도, 이 것을 고치기 위해서 TCP를 사용해서 당신이 할수 있는 것은 없고, 당신이 원하지 않더라도 이것은 TCP의 기본적인 성질이다.

이것은 그저 신뢰할 수 없는, 패킷 기반의 인터넷을 신뢰성있고 정렬된 스트림으로 보이게 할 뿐입니다.



신뢰성있고 정렬된 스트림은 우리가 원하지 않는 것입니다.

우리는 데이터 손실때문에 재발신을 기다리는 일 없이 클라이언트에서 서버로 가능한 빠르게 받은 데이터를 원합니다.


이것이 우리가 왜 실시간 데이터 네트워킹을 위해서 TCP를 절대 사용하면 안되는지에 대한 이유입니다.


잠깐, TCP와 UDP를 동시에 사용하면 안되는 이유는?


플레이어 입력, 상태와 같은 실시간 게임 데이터를 통해서, 오직 가장 최근의 데이터와 관련되어 있다. 그러나 다른 유형의 데이터는, 하나의 장비에서 다른 장비로 보낸 일련의 명령어라고 말하면, 신뢰성과 순서가 매우 중요할 수 있습니다.


UDP를 플레이어 입력과 상태에, TCP는 신뢰할 수 있고 정렬된 데이터에 사용하는것이 매력적입니다.

만약 당신이 예리하다면 아마도 신뢰할수 있고 정렬된 명령의 "Stream", 아마도 레벨로딩에 대한 것, 그리고 AI에 대한 다른것, 이 여러개가 있다는 점을 스스로 추측할 지도 모릅니다.

"글쎄, 난 난 AI 커맨드가 레벨로딩 커맨드를 보관한 패킷이 손실된다고 해도 사라지지 않기를 원해, 이건 상관없거든"

당신이 맞다, 그러니 커맨드의 흐름을 TCP소켓를 통해 구현하려고 시도할지도 모른다.


표면적으로는, 이것은 매우 좋은 생각같다. 문제는 이것이 TCP와 UDP는 모두 IP의 위에 만들어졌기 때문에, 각각의 프로토콜에 의해 보내진 내부패킷은 서로에게 영향을 줄수 있다는 것이다.

정확히 그것들이 어떻게 서로 영향을 미치는지는 꽤 복잡하고 어떻게 TCP가 신뢰성과 흐름을 제어하는지와 관련되어 있다, 그러나 근본적으로는 당신은 TCP가 UDP패킷들에서 패킷손실을 유발하는 경향이 있다는 것을 기억해야한다.

좀더 자세한정보는 "링크"에 있다.


또한, UDP와 TCP를 섞는것은 꽤 복잡하다.

만약 당신이 UDP와 TCP를 섞는다면 당신은 일정한 양의 제어권을 잃는다

[구현에서 컨트롤할수 있는 부분이 적어진다는 의미인듯.]

아마 당신은 TCP를 사용하는 것보다 더 효과적인 방법을 구현할 수 있을 것이다.

근데 그게 당신이 필요하는것 보다 더 적합한가??

만약 당신이 신뢰성과 정렬된 데이터를 원한다면. 이것은 가능하다, 

제공된 데이터가 사용가능한 대역폭에 비해 상대적으로 작으면 TCP를 통해 빠르고 더 안정적으로 보낼 수 있습니다.

거기에, 만약 당신이 집 인터넷으로 다른 누군가에게 말을 하기 위해서 연결을 가능하게 하기 위해서 NAT을 할 필요가 있다면, 이 NAT은 일종의 고통스러운 한번의 UDP 그리고 한번의 TCP(이게 가능할지는 모르겠지만)를 해야만 한다.



결론 


내가 추천하는 것은 당신이 UDP만 사용하라는 것도 아니고, 

그러나 당신이 오직 UDP를 게임 프로토콜로 사용하라는 것도 아니다.

TCP와 UDP를 섞지 말라는 것이다. 

대신 당신이 직접만든 UDP 프로토콜 안에 당신이 사용하길 원하는 TCP의 특별한 조각을 구현하는 방법을 배워라.

[UDP기반으로 신뢰성이 필요하다면 신뢰성 구현하는 걸 배우라는 의미인듯]


물론 이것은 HTTP에서 RESTfull 서비스를 사용해 게임을 하는 동안 다른사람과 말을 하는것은 문제가 안된다.

그것은 내가 말하려했던 것이 아니다.

당신의 게임이 돌아가는 동안의 TCP연결은 모든것을 가져오지는 않는다.

요점은, 당신의 게임 프로토콜을 UDP와 TCP로 구분하지 말라는 것이다.

게임이 돌아가는 동안 UDP를 통해 당신의 게임 프로토콜을 유지한다면 당신은

당신이 보냈고 받은 데이터와 신뢰성, 정렬 및 혼잡함을 방지하는 것을 완벽하게 구현할 수 있습니다.


이 시리즈의 나머지 기사는 당신이 어떻게 이를 구현하고, 가상 연결을 기반으로 UDP위에 프로토콜을 만듬으로부터, 신뢰성을 구축하고, 흐름을 통제와 혼잡성 방지를 보여줍니다.


다음 기사 : 패킷 전송과 수신






반응형
Posted by Sweetmeats_boy

블로그 이미지
Sweetmeats_boy

태그목록

Yesterday
Today
Total

달력

 « |  » 2024.11
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함