게임코디 게임코디 연구소 GCGC 프로카데미 교육센터   회원가입 회원등급 실무자 인증 공지사항 RSS
게임프로그래머 만담 커뮤니티 베타게시판 :   지금은 개발중  |             |   무리수 건의함  |  이미지 HDD  |
게임개발자 실시간 만담
   로그인이 안돼요 자동 로그인


새로운 댓글
  안녕 ~ 게임코디 ㅋㅋ
  막아야 하는데 귀찮아...
  답글은 달고 봅니다 ㅋ...
  ㅋㅋㅋㅋㅋㅋ 이러지 ...
  이러지 마십쇼 아직 작...
  아 포인트는 어제 19시...
  두구두구두구두구....
  오!
  누군가 전염병주식회사...
  앗 아앗...
  16200원
  삼성전자우KODEX200KO...
  오오 마토찡의 게임
  되는걸로 알고있습니다...
  코스피 1680찍고 말...
  2019버전이긴 한데, ...
  흠... 과연
  올해만 버티시고5기가/...
  호우 감사함돠
  답변들 감사합니다. dl...
  .....
  비쥬얼이 재미있어보이...
  글로벌 판데믹으로 변...
  해외 직구 배송비 포함...
  ㅎㅎ 그런가요? 감사합...
  아... 사놓을걸...미...
  저도 유투브 보다가 이...
  마감되었습니다. 감사합...
  외부로부터 의도하지 ...
  쩐이 없는거 같어요총...

# 여기는 읽기 전용의 구 '게임코디 1st' 입니다

# 우리는 이제 게임코디 2nd 로 갑니다. https://gamecodi.com

게임 프로그래머의 만담은 새로운 '게임코디 2nd' 에서 진행됩니다.

개발만담 - 개발,업무,우리의 밥벌이와 관련된 만담 게시판.

Loading...
UniRX, MVP 패턴을 적용하여 프로젝트를 진행하신분 있으신가요?
  Feeder 
작성 : 2016-04-21 22:29:45    |    조회 : 7,694
            
  

 MVC, MVP 패턴으로 개발을 해볼려고 알아보던중 UniRX라는걸 알게 되엇습니다.

구글링으로 정보를 좀 얻었으나..(슬라이드 Github 예제)

실제 MVP 패턴이 적용되어 UniRX를 이용한 프로젝트를 찾기가 어렵더군요..

UniRX에 관한 정보는 일본 사이트가 많아 더 쉽지 않구요..


혹시 참고할만한 프로젝트가 있거나

관련 노하우 있으면 도움 부탁드립니다.




  
ddayin


Unity 에서 MVC 패턴으로 개발하는 Tutorial 영상이 있네요~

그리고 이건 제 포트폴리오인데 좀 부끄럽지만 공유해 봅니다.. (MVC 패턴 적용 중인 상태입니다.)
2016-04-21
23:28:12

  
Feeder


오... 프로젝트 잘 봣습니다. 감사합니다ㅎㅎ 참고하겠습니다!

2016-04-22
10:06:03

  
comjin


http://blog.ejonghyuck.net/220414547578

↑블로그            
이미 보셨겠지만
정보가 많이요 
제블로그는 아닙니다.
여기서 많이 배워서 잘 사용하고 있습니다.
unirx 너무 좋더군요.

2016-04-22
10:45:13

 * 탈퇴       
정환나라

http://www.gamecodi.com/board/zboard-id-GAMECODI_Talkdev-no-3488-z-11.htm

여기 링크가..
2016-04-22
10:49:45

  
Feeder


답변감사합니다.

저 글들을 참고 햇는데.. 제가 아직 미숙해서 인지 제대로 활용이 안되더라구요..

단순이 사용은 되는데 패턴을 어떤식으로 잡고 가야하는건지 감이 안와서..

좀 더 시도를 해보아야 할듯 하네요

2016-04-22
11:00:27

  
Ruel


** 작성자(또는 관리자)에 의해 삭제된 댓글입니다 **
2016-04-24
23:43:53

  
Ruel


UniRx사용한지는 한 1년이 넘어가는 사용자입니다.

UniRx에서 권장하는 MVRP를 사용하는것 기준으로는

UI 표현을 위한 로직이 Presenter에,
기획 데이터의 초기화 결과물중, Subscribe할 데이터들을 ReactiveProperty<T>로 두고 사용합니다.
Dictionary → ReactiveDictionary<T>
List → ReactiveCollection<T>
를 사용합니다.

ReactiveCollection은 List와는 조금 틀려서 일부 기능이 없을 수 있는데, 이는 LINQ로 보완해서 사용합니다.
최근 IL2CPP로 오면서 이 부분에 있어서는 많은 문제가 해결은 되었지만(더불어 다른 문제가 생기고 있는점은... 음;),
Linq사용이 불안하시면, UniLinq라는 라이브러리를 검색해봐주시면 도움이 되실것 같습니다.
위 UniLinq는 NUnit을 통한 기기에서의 Unittest가 가능하게끔 테스트된 코드가 300 case넘게 설정이 되어있습니다.
현재까지는 Linq로 인하여 중국쪽 단말들이나, iOS에서의 운용에서도 문제된 부분이 없습니다.

우선... 가령 gold값을 운용한다고 하면,
ReactiveProperty<int> UserData.Instance.Gold; 를 두고,

Presenter에 UnityEngine.UI.Text goldView;를 둔다고 한다면,
Gold.Subscribe(gold=>goldView.text=gold); 혹은 Gold.SubscribeToText(goldView); 를 초기화하는 메소드에 두어서
Network 통신 관련 handler등에서 UserData.Instance.Gold.Value = ?; 갱신을 수행하였을때 View에 반영되는 형태로 두게합니다.

실 프로젝트에서는 이보다는 복잡한 내용들이 있긴하지만... 간단하게 사례를 올린다면 위 정도 패턴일것 같습니다.

MVRP패턴을 따르게 되면 구현 전반적으로 원패턴의 구현이 안정적으로 이루어질 수 있게됩니다.
다른 작업자의 작업물에 있어서도 해당 프레임워크에서의 제약사항을 고수하게 두면,
개인간에 다소 스타일차가 벌어지는 부분이 있더라도 작업물 이관시에 큰 무리 없이 넘겨받을 수 있게됩니다.

uFrame이라는 UniRx를 사용하는 MVVM프레임워크가 있는데, 처음 여기서 Rx를 접했다가 현재는 사용하지 않고 있습니다.
(UniRx페이지에서 나온대로 아무래도 너무 복잡해지는 감이 있었습니다)
최근에 에디터를 포함해 완전히 소스 공개가 되었다고 (이전에는 일부가 dll) 합니다.

1년정도 써보고 느끼는건 아무래도 내부가 event driven이다보니, promise pattern을 통한 구현이라,
callback hell을 회피하면서도 코드로직으로 인한 퍼포먼스 저하는 상당부분 덜어내고 있다는 생각을 하고 있습니다.

함수형 프로그래밍이 가능해지긴 하는데, 이 부분은 어디까지나 stream운용에 국한해서 사용하고 있고,
Coroutine이 적합한 상황에서는 Coroutine을 사용합니다.

IEnumerator F(); 에 대해 F().ToObservable().Subscribe()하는 형태로 coroutine내부에서 throw를 하더라도 subscribe의 2인수로 exception을 받아 처리할 수 있습니다. 혹은 Observable.FromCoroutine<T>((ob,canceller)=>...); 로도 Coroutine을 오갈 수 있으나, 이 경우 Coroutine내에서 Observer에 대하여 OnNext, OnError, OnComplete의 주기를 신경써주셔야합니다.

UniRx는 5버전대에 들어가면서 iOS의 AOT support(Mono2x지원)을 종료했습니다.
(다만 5버전대로 들어가면 rx의 어마어마한 callstack이 상당부분 경감됩니다.)
이 부분 참고하시는게 좋을듯하고,
경험상 UniRx의 Rx도 그렇지만, 다른 진영의 Rx (가령 RxSwift, RxJs, RxJava)의 코드를 참고하시는게 도움이 많이 되시지 않나 싶습니다.

구체적인 적용 사례에 대해서 고민하고 계시다면, 해당 내용을 알려주시면 같이 고민해드리겠습니다.
2016-04-24
23:44:42

  
Feeder


구체적인 답변 감사합니다. 정말 많은 도움이 되네요.

현재 프로젝트 초기 단계에서 구조를 고민하면서 틀을 짜꼬 있는 중이였습니다.

지금 익힌 내용으로 차근차근 시도해 보겠습니다.

감사합니다.

2016-04-25
01:04:08

  
Feeder


음... 몇가지 생각하면서 확신이 안드는 부분들이 있는데요..

-MVP패턴 기준으로 Presenter는 로직을 담당하고 View 와 Model을 연결 시켜주기 위해서라면 View(UILabel, Animation 등)를 참조하며 Update 나 Corutine 사용하기 위해 Monobehaviour를 상속받고 Gameobject에 컴포넌트로 박혀 사용이 되나요?

-그렇다면 Model 은 Monobehaviour 를 상속받지 않고 C# 기본 클래스로 생성해서 데이터만 정의하게 되나요?(로직 구현이 없을테니...최대한 경량화..?) 

-Presenter가 View와 Model을 둘다 멤버나 참조로 가지고 있는 모습은 패턴에 어긋나나요? (Presenter 의 멤버이다 보니 한번에 관리가 되어 편해 보이나.. Gameobject에 컴포넌트 놓고 구성 변수들만 클래스화(Model) 되어잇지 다른 차이점이 없는것 같아 맞는 방법인지 의문이네요.)

-Model(데이터 클래스)은 싱글턴이나 특정 위치에(게임매니저 등) 위치하여 외부 입력이나 작용으로 의해 데이터가 변하게 된다면 변경된 Model이 해당 Presenter로 변경이 되엇다 알려주는 것이 아닌, 변경된 데이터를 Presenter는 구독(UniRX일 경우, 아니라면 Delegate..?)을 하여 변경된 정보에 따른 내용 반영을 View에다가 해주는것인가요?

-Presenter와 Model을 상호간 참조하며 작용한다던가.. 뭐 이런 방법이 옳지 않다면 기능이 추가될때마다 Delegate를 사용해야 하는 건가요..?(아직 시도해보기 전이라 왠지 비효율적이라는 생각이 언뜻 드네요..)


뭔가 비슷한 질문들이 많은데.. 머릿속이 아리송 한것이.. 찜찜한것이..

머릿속에 걸려 넘어가질 않는군요..

2016-04-25
01:34:52

  
Ruel


1. View는 MonoBehaviour로 구현하고 있습니다. Presenter는 MonoBehaviour가 아닌 형태로 구현할 수도 있겠지만, MonoBehaviour로 구현합니다. View는 SerializableField에 참조하는 형태로 구현합니다. 단 독자적인 Metaprogramming기법을 통해 Component reference상단에 코드로 각 객체의 경로를 모두 코드상에 서술하고있으나, Build전에 MonoBehaviour의 SerializableField을 통해 Serialize되는 형태로 구현합니다. (이편이 Deserialization중 가장 빠릅니다)

2. Model은 MonoBehaviour로 구현하면 안됩니다. 10만개의 MonoBehaviour를 생성하면 유니티는 약 100MB의 메모리를 사용합니다. 유니티가 버티질 못합니다.

3. Presenter는 1에서 서술했듯, "참조" 형태로 View를 연결하고 있으며, 통상 Model은 초기화 코드에서 코드로 참조합니다. 물론 구현형태에 따라 Model을 "참조" 할수도 있겠으나, 저는 그렇게 구현하진 않습니다.

4. Model은 정확하게는 데이터 클래스를 말하는게 아니라 각 데이터 그 자체를 말합니다(int gold;수준의) 배치는 프로젝트의 스타일과 여타 상황에 따라 달라질 수 있겠지만, 통상은 그렇습니다. 보통 데이터의 변경을 알려주고.. 라는 부분은 Rx가 없는 상황 하에서라면, event를 구현하여 변수마다.. 만드는 것이 맞겠습니다. 다만 Rx를 사용하면 이런 복잡한 절차가 ReactiveProperty로 끝납니다 (간편해지는 장점이 있습니다). 다만 Presenter에서 이를 Subscribe하고 있는데, 이 ReactiveProperty가 통채로 바뀌게되면 당연히 구독이 안되게되니 이런데서 주의가 필요합니다.

말씀하시는대로 Presenter에서 가령 ModelManager같은 클래스가 있다고 하면, ModelManager에서는 event(delegate)를 제공하고, 데이터 그 자체를 들고있으면서 Presenter는 이에 대해 이벤트 구독을 수행하여, 데이터의 변경을 감지하면 View에 feedback하는 형태로 구현합니다. (패턴이론상 이렇긴 하지만... 정말 이걸 하실거라면 ReactiveProperty를 사용한후 이를 subscribe하는 형태를 추천드립니다. 데이터가 아닌 어떤 함수화 형태라면 IObservable<T>을 반환하는 메소드형태도 있습니다.)

만약 model manager에서 view로 직접 참조하는 구조를 가지게되면 model manager는 해당 view에 대해 종속적이게 되고 더이상 MVP라 부를 수 없는 구조가 됩니다. 간단하게 말하면 View가 프로젝트에서 삭제되더라도 ModelManager는 아무렇지도 않게 컴파일 되어야 패턴이 준수된것입니다. 더불어 View와 Model의 작업 책임자는 다른경우가 많은데, 인터페이스 없이 직접 발송해주는 형태를 가진 경우, View의 책임자는 Model의 책임자에게 대하여 약간의 구현을 위해 작업을 의뢰할 수 밖에 없는 형태가 됩니다 (이 시점에서 이미 좋은 구현패턴이 아닙니다)

물론 이런 패턴들을 준수하며 작성한다는것은 조금씩의 손이 더 가게 되어있습니다. Singleton하나를 작성하더라도 (shared)Instance를 작성하기 위한 약간의 번거로움이 존재하듯이요. 다만 이런 구현형태에는 나름대로의 위와같은 이유가 있다는점을 이해하신다면 와닿는 부분이 있지 않을까 생각합니다.
2016-04-25
03:26:13

  
Feeder


답변 감사합니다.

어떤식으로 구현해야 할지 이제 알듯 합니다.

확실히 Rx를 사용하는게 번거로움을 줄일수 있겟네요.

이제야 머릿속에 그림이 그려집니다.. 많이 배웠습니다.

정말 감사합니다.

2016-04-25
11:35:11

  
Feeder


음.. 코루틴을 사용할려고 보니..

Model에다가 시간에 따른 변화를 모두 이벤트로 구현 한다음.. Presenter에서 코루틴을 구현하여 코루틴 내부에 Model에 지정해준 이벤트 들을 각각 호출하는 식으로 구현이 되나요..?

이해 했다고 생각햇는데 해보니 막상 뭔가 이상해서ㅠㅠ 이래서 Rx를 쓰는건지..싶네요..

2016-04-25
19:05:21

  
Ruel


** 작성자(또는 관리자)에 의해 삭제된 댓글입니다 **
2016-04-25
20:05:43

  
Ruel


음.. 단순히 데이터의 변화를 통보받는데 있어서는 코루틴은 적합하지 않는거같습니다;

Rx의 IObservable이 data의 변화에 대한 감시자(Observer)의 감시 대상물(Observable)이라 한다면,
Coroutine은 비동기의 순차처리에 적합한 기능입니다. (가령 A를 한다음 B를 하여, C를 순차적으로 처리해야할때)
따라서 Coroutine으로 데이터의 감시를 한다 하는 부분은 Update로 구현하는것과 큰 차이가 없습니다.

가령 Rx를 안쓰는 형태로 구현을 한다면

-----

// Model (Non-Rx)

public class LoginAPI : SomeAPIBases
{
public void Fetch()
{
...
(int gold) =>
{ // some callbacks
UserData.Instance.Gold = gold;
};
}
}


public class ShopPurchaseAPI : SomeAPIBases
{
public void Fetch()
{
...
(int gold) =>
{ // some callbacks
UserData.Instance.gold = gold;
};
}
}


public class UserData : Singleton<UserData>
{
private int _gold;
public event Action<int> onGoldChanged;

int Gold
{
set
{
this._gold = value;
onGoldChanged.Invoke(value);
}
get
{
return this._gold;
}
}
}
...

// HeaderPresenter
...
public UnityEngine.UI.Text goldLabel;

public void OnEnable()
{
UserData.Instance.onGoldChanged += UpdateGold;
}

public void OnDisable()
{
UserData.Instance.onGoldChanged -= UpdateGold;
}

public void UpdateGold(int updatedGold)
{
this.goldLabel.text = string.Format("{N:0}",updatedGold);
}

-----

이걸 Rx를 쓴다면


public class LoginAPI : SomeAPIBases
{
public void Fetch()
{
...
(int gold) =>
{ // some callbacks
UserData.Instance.gold.Value = gold;
};
}
}


public class ShopPurchaseAPI : SomeAPIBases
{
public void Fetch()
{
...
(int gold) =>
{ // some callbacks
UserData.Instance.gold.Value = gold;
};
}
}


public class UserData : Singleton<UserData>
{
public ReactiveProperty<int> gold = new ReactiveProperty<int>();
}

// HeaderPresenter
...
public UnityEngine.UI.Text goldLabel;
public IDisposable subscription = null;

public void Start()
{
UserData.Instance.gold.Subscribe((int updatedGold) =>
{
this.goldLabel.text = string.Format("{N:0}",updatedGold);
}).AddTo(this); // AddTo는 IDisposable을 MonoBehaviour가 Destroy될때 같이 Dispose(); 호출 하게끔 해주는 static extension입니다.
}
2016-04-25
20:09:47

  
Ruel


public IDisposable subscription = null; // 이 행은 불필요하군요.
2016-04-25
20:11:35

  
Feeder


음... 그렇네요..


많은 도움이 되네요..

 계속된 많은 질문에도 답변해주셔서 감사합니다.

2016-04-26
10:05:11



목록보기  |  
SORT :: |  번호순  |  최근댓글  | HIT
notice
■■ 개발만담 게시판 안내 ■■  [7]
   게임코디 11/07/04 4355
4943
게임 주제의 KBS 다큐 두 편  [1]   
  술취한아저씨
20/03/15 1250
4942
visual studio 2017 이거 옵션 뭘 바꿔야 할까요?  [7]   
  아쥬
20/03/08 1328
4941
리포지드... 보고 있나? 이것이 [ 리메이크 ] 다!  [2]   
  노코드
20/03/08 1766
4940
VSCode C# Update 주의  [3]   
  시니컬춥스
20/03/06 1591
4939
NDC 20 행사 잠정연기 ㅜㅜ  [2]   
  게임코디
20/03/05 1139
4938
블소 프론티어  [7]   
  뎐삼
20/03/05 1079
4937
std말고 간단한(?) 컨테이너들 모은 라이브러리 (오픈소스) 혹시 없을까요...  [9]   
  아쥬
20/03/02 1507
4936
게임 개발자 학습 로드맵 (GitHub 펌)  [1]   
  장찌루
20/02/28 1808
4935
두 유 노우 재택근무 프로그래머 ?  [5]   
  노코드
20/02/25 1822
4934
재택근무 시행 게임사  [16]   
  뎐삼
20/02/25 2074
4933
프로그래머 실무 면접에 관한 동영상 링크 투척해요~~  [6]   
  ProgC
20/02/25 1354
4932
중견회사들은 신작게임 안 만드나요?  [8]   
  imays
20/02/24 1788
4931
근본없는 블렌더 -5편- retopo     
  뎐삼
20/02/24 457
4930
근본없는 블렌더 -4편- 채색     
  뎐삼
20/02/24 826
4929
근본없는 블렌더 -3편- 버텍스 직접 편집  [1]   
  뎐삼
20/02/22 612
4928
근본없는 블렌더 -2편- 스컬프팅     
  뎐삼
20/02/22 598
4927
근본없는 블렌더 -1편- 설치 및 기본조작  [2]   
  뎐삼
20/02/21 1097
4926
비쥬얼스튜디오에 build clean 할 때...     
  아쥬
20/02/21 298
4925
안드로이드에서 네이티브 코드로 IPC사용시 대량의 데이터 처리  [6]   
  아쥬
20/02/20 666
4924
2020 NDC 발표자를 모집합니다  [4]   
  게임코디
20/02/18 1278
4923
언리얼 빌드후, 안드로이드에서 크래시 확인하는 좋은 방법이 있을까요?  [4]   
  아쥬
20/02/13 910
4922
쌩초보주의)) 유니티 모바일과 컴퓨터 개발이 차이가 있나요?  [2]   
  김김김민
20/02/13 1134
4921
개발 소스의 해킹보안에 대해 질문드립니다.  [10]   
  군림주먹
20/02/12 1460
4920
APK 앱서명의 보안성에 대해 궁금합니다.  [1]   
  kachuuu
20/02/11 473
4919
게임서버프로그래밍 교과서에 첨부된 코드에 대한 주의사항  [4]   
  imays
20/02/11 1138
4918
C++표준을 따르면서 buffer에 쓰고 읽는법. 제대로 알고 계신가요?  [7]   
  retro
20/02/10 1726
4917
Creator's star  [3]   
  데미데루스
20/02/09 617
4916
리눅스 epoll 에서 epolloneshot, epollexclusive 플래그...  [10]   
  retro
20/02/09 1032
4915
언리얼에서 안드로이드 빌드할 때, 플러그인 낑가 넣으면...  [1]   
  아쥬
20/02/09 462
4914
프라우드넷  [8]   
  발코더6
20/02/07 1285
4913
이세계 카페에서 바리스타가 되는 게임! Coffee Talk     
  술취한아저씨
20/02/02 940
4912
개발자 번아웃 대처방법의 모든 것  [4]   
  노코드
20/01/29 2152
4911
앱스토어 검색어에 검색이 안됩니다.  [1]   
  닥터이블
20/01/26 490
4910
Vulkan과 메탈  [4]   
  그래픽스어린이
20/01/23 2012


목록보기  |   다음페이지  |   1 [2][3][4][5][6][7][8][9][10]..[142] [다음 10개]



게임코디 GAMECODI , 게임 프로그래머 만담 커뮤니티

게임코디 소개     |      크라우드펀딩 후원자     |      관리실 연락처     |