SlideShare a Scribd company logo
1 of 63
NCSOFT / A2 Seed
성낙호 / 조현철
자바스크립트로 쉽고 빠른 UE4 개발하기
Unreal.js
조현철
NCSOFT A2 Seed 프로그램팀
3년 차 개발자
React-UMG 개발, 발표
성낙호
NCSOFT A2 Seed AI Tech팀
18년 차 개발자
헥스플렉스 <더 보스:라 코사 노스트라>
레드덕 <AVA>, <Metro Conflict>
Unreal.js 개발, 발표
발표자 소개
발표에서 다룰 내용
1. Unreal.js
2. UI Development with Unreal.js
Unreal.js JavaScript powered Unreal Engine 4
언리얼 마켓플레이스에 무료 공개
언리얼 데브 그랜트 수상
https://github.com/ncsoft/unreal.js
Unreal.js – 오픈 소스 프로젝트
즐거운 개발
• 프로젝트 시작 초기의 가장 큰 고민거리
• 몇 번이나 갈아 엎게 될까?
• 어떤 일 때문에 좌절하고, 어떤 작업에 짜증날까?
고통스러운 (이제까지의) 현실
기획 = 생각 → 문서 작성 → 대기 → (튜닝 → 실행 → 대기)*
코딩 = 기획서 확인 → 코드 작성 → 디버그(빌드 → 대기 → 실행 → 대기 → 수정)*
아트 = 툴1 → 툴2 → 툴3 → 툴1 → 툴4 → ...
Silver bullet
기획자, 아티스트…
• 필요한 툴을 그때 그때 만들어 주는 개발자
• 잦은 변심에도 짜증 내지 않는 개발자
개발자…
• 빌드, 크래쉬 없이 개발할 수 있는 환경
• 생각하는 속도로 코딩할 수 있는 환경
현실
• 고통스러운 UE4 Tool Extension 만들기
• 고통스러운 C++ coding
• 고통스러운 Blueprinting
(커 보이는) 남의 떡
• JavaScript로 쉽게 만드는 Application
• Node.js
• VSCode (https://code.visualstudio.com/)
• Slack
• React-native (https://facebook.github.io/react-native/)
Imagine...
• 개발 과정의 수많은 "대기(wait)"를 없앨 수 있다면?
• 빌드, 크래쉬가 없어질 수 있다면?
• 코드를 고치면 바로 작동을 확인할 수 있다면?
• 필요로 하는 많은 툴을 webapp 만들 듯 만들어 낼 수 있다면?
• Web application 만드는 기분으로 UE4를 확장할 수 있다면?
• 내 게임에 맞춤형 데이터 에디터를 Native UE4처럼 만들 수 있다면?
• 게임 UI 제작, 보수가 기분 나쁘지 않은 일이 될 수 있다면?
• 최신 Web UI Framework을 사용하여 AAA 게임 UI를 만들 수 있다면?
Code like a ninja with JavaScript!
• 무정지 개발 – Zero build
• 코드 재활용 – DRY (Do not Repeat Yourself)
• 함수형 언어 – Closure (over lambda)
• 절차적 UI – Modern web development
REPL: Interactive Coding Window
왜 JavaScript?
Battle-proven
• Web era: First Class Language
High performance / Flexibility
• Node.js로 입증된 효용성
• Functional programming을 매우 손쉽게 구사 가능
Rich community
• npm: 무료로 사용 가능한 '엄청나게' 많은 재사용 가능한 코드
Rich IDE
• Visual Studio, Visual Studio Code, Chrome devtools
Debugging
Profiling
V8의 강력하고 쉬운 프로파일링 도구.
보다 쉬운 최적화가 가능한 환경을 제공.
Do not reinvent the wheel
• Host 기능을 그대로 활용 및 확장
• Logic: Actor/Component
• UI: Slate / UMG
• Open source를 최대한 leverage!
• 널리 사용되는 빠른 스크립트 엔진 도입
Technical details
Unreal.js는 세심하게 설계된 Script Bridge Layer
1. Bridge
1. UE4  JS : Auto reflection (UCLASS, UFUNCTION, USTRUCT, UPROPERTY, …)
2. JS  UE4 : Type Declaration(UCLASS, UFUNCTION, USTRUCT, UPROPERTY, …)
2. JavaScript as a First class language
3. Node.js 유사 JavaScript 개발 환경
1. Auto completion, live reload
2. npm
3. Chrome devtools
Wiki
https://github.com/ncsoft/Unreal.js/wiki
Example
https://github.com/ncsoft/Unreal.js
https://github.com/ncsoft/Unreal.js-demo
Editor Extension
Cyberpunk City Simulator by mflux
출처 : https://forums.unrealengine.com/showthread.php?97521-Cyberpunk-City-Simulator-(Procedural-UE4-JS)&p=455447#post455447
UI Development with Unreal.js
바뀌고.. 바뀌고.. 또 바뀌고….
한번에 끝나는 일이 거의 없음.
자잘한 수정사항이 많아서 빠른 개발
환경이 필수적임.
UI Development?
Slate UMG
Previous work: UI
Previous work: UI
• Scaleform, Coherent UI, EA webkit, Awesomium, BLUI, …
• 별도의 UI process
• Engine과 상관 없는 renderer.
• Web스럽거나, 다시 만든 바퀴
UI 개발 방향
UIFast Iteration
Performance Productivity
Flexibility
UMG.js
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(STextBlock).Text(FText::FromString("A text")
)
]
+ SVerticalBox::Slot()
[
SNew(SCheckBox)
.IsChecked(this, &SPBMainWidget::HandleCheckBoxIs
Checked, &SPBMainWidget::bCheckboxValue)
.OnCheckStateChanged(this, &SPBMainWidget::OnChec
kBoxChanged, &SPBMainWidget::bCheckboxValue)
[
SNew(STextBlock).Text(FText::FromString("A ch
eckbox"))
]
]
UMG.div({'slot.size.size-rule': 'Fill'},
UMG(Button,{OnClicked:_ => fire()},"RUN"),
UMG(MultiLineEditableTextBox, {
'slot.size.size-rule': 'Fill',
WidgetStyle: {
'font.font-object' : GEngine.SmallFont,
'font.size': 20
},
Text: source,
$link: _elem => {
elem = _elem
},
$unlink: _ => {
}
})
)
초기 개발 방식 - Angular.js (In House Code!) + Jade + UMG.js
function rootScope(scope) {
scope.text = 'Hello Scope!'
scope.count = 0
scope.inc = () => scope.count++
scope.items = []
scope.discard = (item) => {
scope.items = _.filter(scope.items,
(i) => i != item)
}
scope.add = () => {
scope.items.push({key:Math.random(),
value:Math.random()})
}
_.range(0,10).forEach(()=>scope.add())
}
div
span.full
Button.full
text {{text}}
div.full
Button.full(fn.on-clicked="inc()")
text {{count}}
Button.full(fn.on-clicked="add()")
text Click button above!
span
text.yellow >
EditableText(Binding.Text='text',
fn.on-text-
changed='text = ^arguments[0]')
span
list.full(repeat='item in items',on-
click="discard(item)")
HorizontalBox.small
text.full {{item.key}}
text.full {{item.value}}
초기 개발 방식 - Angular.js (In House Code!) + Jade + UMG.js
• 높은 유지보수 비용.
• 높은 러닝 커브.
• 웹에서는 어떻게 쓰는지는 대충 알겠는데, 게임에서는 어떻게 써야하나.
• 앞의 세가지 이유로 생산성이 너무 떨어졌음.
일단은 UMG.js만 쓰기로 결정.
Only UMG.js
UMG.div({'slot.size.size-rule': 'Fill'},
UMG(Button,{OnClicked:_ => fire()},"RUN"),
UMG(MultiLineEditableTextBox, {
'slot.size.size-rule': 'Fill',
WidgetStyle: {
'font.font-object' : GEngine.SmallFont,
'font.size': 20
},
Text: source,
$link: _elem => {elem = _elem},
$unlink: _ => {}
})
)
Pros.
• 빠른 개발
• 비교적 쉬움
Cons.
• 정리되지 않는 코드
• 디버깅 지옥
• UMG Instance와 JS간의 Coupling
장점에 비해 단점이 너무 치명적.
Web에서 많이 쓰이는 UI Framework를 찾아보자.
• react-umg
• Github에 공개된 오픈소스.
• UMG에서 React를 사용할 수 있게 하는
React renderer의 POC 구현체.
그러던 와중…
React에 대해 간단하게 알아봅시다
• Facebook에서 공개한 자바스크립트 UI 라이브러리
• Custom Component를 만들고 조합하여 View를 손쉽게 만들 수 있음.
• DOM Dependency가 없음.
• 재사용성이 높음.
• 웹 뿐만 아니라 많은 플랫폼에서 이미 검증된 라이브러리.
• 수많은 오픈소스와 예제들.
- A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
React - One way Data Flow
• Data flows down
• Props is immutable
• States is mutable
• Event flows up
• Render by setState
setState()
Parent
Child ChildChild
props props props
event
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {secondsElapsed: 0};
}
tick() {
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>Seconds Elapsed: {this.state.secondsElapsed}</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}
ReactDOM.render(<HelloMessage name="Jane" />, mountNode);
React.createElement('div',
null,
'Hello ',
this.props.name)
Transform!
React - Component Lifecycle
출처 : https://velopert.com/1130
React-UMG
React-UMG
• A React renderer for Unreal Motion Graphics With Unreal.js
• https://github.com/ncsoft/React-UMG
• npm i --save react-umg
• Pure React.js를 사용하며, Web에서의 React.js와 유사한 개발 환경을 제공.
• React.js가 React DOM에 render 한다면, UE4에서는 React-UMG에 render.
React-UMG
• React Component는 대문자로, UMG element Type은 소문자를 사용.
• etc. UButton => uButton
• Web에서의 DOM Element를 UMG Widget이 대체.
• 웹 개발에 친숙한 element Type Naming
• UVerticalBox => div
• UHorizontalBox => span
• UTextBlock => text
• UImage => img
• UEditableText => input
React-UMG
• React Native에서 사용되는 Interface를 그대로 사용.
• UWidget을 상속받은 Class를 React Element로 Wrapping하여 사용.
• 미리 등록된 Widget Type에 맞는 UMG 인스턴스를 생성.
• Component를 Render할 때 마운트된 Component 대로 부모와 자식을 연결.
Real
Dom
Virtual
Dom
React
Components
setStatePatch
Event
Render
Web React-UMG
Virtual
Dom
React
Components
setStatePatch
Event
RenderUMG Widget
UMG Widget
UMG Widget
UMG Widget
…
Render할 대상만 다를 뿐 구조적으로 크게 다르지 않음.
React-UMG
class MyComponent extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {text:"MyComponent"};
}
OnTextChanged(value) {
this.setState({text: value});
}
render() {
return (
<div>
<uEditableTextBox Text={this.state.text} OnTextChanged={value=> this.OnTextChanged(value)}/>
<text Text={this.state.text}/>
</div>
)
}
}
Create a Component
let widget = ReactUMG.wrap(<MyComponent/>);
widget.AddToViewport();
return () => {
widget.RemoveFromViewport();
}
Draw With React-UMG
React-UMG
Make a Custom Widget Class Render With Custom Widget Class
React-UMG
class RadarWidget extends JavascriptWidget {
properties() {
this.size/*int*/;
this.speed/*float*/;
this.padding/*int*/;
}
OnPaint(context) {
let {size,speed,padding} = this
let r = size/2
let t = $time
let dx = (r - padding) * Math.cos(t * speed)
let dy = (r - padding) * Math.sin(t * speed)
context.DrawLine({X:r,Y:r},{X:r+dx,Y:r+dy},{G:1,A:1},true)
}
}
let Radar_C = uclass(RadarWidget)
ReactUMG.Register('uRadar',Radar_C)
class Radar extends React.Component {
render() {
return (
<div>
<uRadar {...this.props} {...this.state}/>
</div>
)
}
}
Technical details
Dependency Injection
• React는 여러 플랫폼을 지원하기 위해 구현 클래스를 Injection할 수 있는
구조로 설계.
• DOM 환경에서 주입되는 Class와 React Native에서 주입되는 Class가 다름.
• React-UMG도 환경에 맞는 Component Class를 Injection.
Batching
• 컴포넌트가 여러 번 업데이트될 때, 마지막 한번만 렌더링하는 것이 효율적.
• React는 기본적으로 업데이트를 배치로 묶어서 처리.
• setState는 ReactUpdates.enqueueUpdate를 호출하여 Queue에 추가.
• 렌더링은 배치가 끝났을 때 ReactUpdates.batchedUpdates에 의해 한번에
처리.
Batching
ReactComponent.prototype.setState = function (partialState, callback) {
this.updater.enqueueSetState(this, partialState);
// ...
};
// updater
var ReactUpdateQueue = {
enqueueSetState: function (publicInstance, partialState) {
// ...
var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
queue.push(partialState);
enqueueUpdate(internalInstance);
}
}
function enqueueUpdate(component) {
// ...
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
dirtyComponents.push(component);
}
Pooling
• 자주 할당되는 객체를 사용이 끝난 후 해제하지 않고 다시 사용함.
• React에서는 PooledClass 모듈을 통해 객체 풀링을 지원.
• Pooling에 추가된 Class는 getPooled 함수로 풀에서 인스턴트를 얻음.
• Pool에서 가져온 인스턴스는 사용이 끝난 후 release 함수 호출로 반환.
var TRANSACTION_WRAPPERS = [ON_UMG_READY_QUEUEING];
function ReactUMGReconcileTransaction() {
this.reinitializeTransaction();
this.reactMountReady = CallbackQueue.getPooled(null);
}
var Mixin = {
getTransactionWrappers: function() {
return TRANSACTION_WRAPPERS;
},
getReactMountReady: function() {
return this.reactMountReady;
},
getUpdateQueue: function() {
return ReactUpdateQueue;
},
destructor: function() {
CallbackQueue.release(this.reactMountReady);
this.reactMountReady = null;
},
};
PooledClass.addPoolingTo(ReactUMGReconcileTransaction);
Pooling
Transaction
• React의 Transaction은 어떤 함수를 실행하기 전과 후에 특정 동작을 수행할 수
있도록 감싸줌.
• 함수를 감싸는 Transaction Wrapper는 함수 수행 중에 예외가 나도 항상
호출되도록 되어 있어서 외부 자원의 상태를 안전하게 관리.
ReactUpdates.batchedUpdates(() => {
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
transaction.perform(() => {
nextComponent.mountComponent(...);
});
ReactUpdates.ReactReconcileTransaction.release(transaction);
});
ReactUMGComponent
• UMG Widget의 Lifecycle 관리.
• mountComponent가 실행될 때 UMG Widget을 생성 후 부모 Widget에 Add
Child.
• UMG Widget이 Destroy 될 때 자동으로 React Component도 언마운트.
• UserWidget는 PanelWidget과 같은 위상에서 동작하도록 구현.
• PanelWidget의 AddChild와 UserWidget의 SetRootWidget이 같은 형태로
동작하도록 구현.
Demo
Tip
Garbage Collection
• JS에서 UE4 Instance를 가지고 있는 경우는 GC가 되지 않음.
• 주의해야 하는 점
• GC된 UE4 Instance에게 JS로 접근하는 경우
• UE4은 Destroy 됬는데 JS에서 Ref를 가지고 있는 경우
Container Component / Presentational Component
• Container Component
1. 데이터와 비즈니스 로직을 다룬다
2. Component Tree를 렌더링한다
• Presentational Component
1. 상태를 포함하지 않는다.
2. 컴포넌트 속성에 대한 Pure Function으로 구성한다
3. 표현만을 담당한다
출처: https://css-tricks.com/learning-react-redux/출처 : https://www.theodo.fr/blog/2016/03/getting-started-with-
react-redux-and-immutable-a-test-driven-tutorial-part-2
Redux
도입 후기
React-UMG 도입 후기
• 재사용성을 높이면서 반복되는 코드를 줄일 수 있었고 코드도 간결해짐.
• 뛰어난 생산성과 보다 쉬운 디버깅 환경.
• React의 Performance Cost Model이 단순해서 최적화하기가 쉬움.
• Container Component / Presentational Component
• View를 버리더라도 Logic은 재사용 가능해짐.
• Modding을 지원할 수 있는 기반을 마련할 수 있었음.
결론
결론
• Unreal.js 쓰세요.
• UE4에서의 빠른 개발과 풍부한 표현을 보장해줍니다.
• React-UMG 쓰세요.
• 웹에서는 이미 대세인 React를 UE4에서 웹과 크게 다르지 않은 환경에서
개발 할 수 있습니다.
We are hiring!
감사합니다.

More Related Content

What's hot

GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자TonyCms
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기YEONG-CHEON YOU
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀승명 양
 
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다Lee Dustin
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018devCAT Studio, NEXON
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPSeungmo Koo
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018devCAT Studio, NEXON
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략YEONG-CHEON YOU
 
언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링TonyCms
 
UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1Hong-Gi Joe
 
Windows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonWindows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonSeungmo Koo
 
Ndc12 이창희 render_pipeline
Ndc12 이창희 render_pipelineNdc12 이창희 render_pipeline
Ndc12 이창희 render_pipelinechangehee lee
 
멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)Bongseok Cho
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012Esun Kim
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012devCAT Studio, NEXON
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019devCAT Studio, NEXON
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기Sang Heon Lee
 
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화Jaeseung Ha
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010devCAT Studio, NEXON
 

What's hot (20)

GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀NDC 11 자이언트 서버의 비밀
NDC 11 자이언트 서버의 비밀
 
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다레퍼런스만 알면 언리얼 엔진이 제대로 보인다
레퍼런스만 알면 언리얼 엔진이 제대로 보인다
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
심예람, <프로젝트DH> AI 내비게이션 시스템, NDC2018
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략
 
언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링
 
UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1
 
Windows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonWindows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance Comparison
 
Ndc12 이창희 render_pipeline
Ndc12 이창희 render_pipelineNdc12 이창희 render_pipeline
Ndc12 이창희 render_pipeline
 
멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)멀티스레드 렌더링 (Multithreaded rendering)
멀티스레드 렌더링 (Multithreaded rendering)
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
[NDC 2014] 던전앤파이터 클라이언트 로딩 최적화
 
송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010송창규, unity build로 빌드타임 반토막내기, NDC2010
송창규, unity build로 빌드타임 반토막내기, NDC2010
 

Similar to [NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기

[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...
[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...
[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...JinKwon Lee
 
Front end dev 2016 & beyond
Front end dev 2016 & beyondFront end dev 2016 & beyond
Front end dev 2016 & beyondJae Sung Park
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발지수 윤
 
Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기hanbeom Park
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱NAVER D2
 
20131217 html5
20131217 html520131217 html5
20131217 html5DK Lee
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolhyunae lee
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolhyunae lee
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기John Kim
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02정출 김
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안Jeongsang Baek
 
자바스크립트 디버깅
자바스크립트 디버깅자바스크립트 디버깅
자바스크립트 디버깅용성 양
 
React native 개발 및 javascript 기본
React native 개발 및 javascript 기본React native 개발 및 javascript 기본
React native 개발 및 javascript 기본Tj .
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기Huey Park
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Testbeom kyun choi
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)LanarkSeung
 
Node.js의 도입과 활용
Node.js의 도입과 활용Node.js의 도입과 활용
Node.js의 도입과 활용Jin wook
 

Similar to [NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기 (20)

[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...
[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...
[Korea Linux Forum] Implementing web based online multiplayer tetris with Ope...
 
Front end dev 2016 & beyond
Front end dev 2016 & beyondFront end dev 2016 & beyond
Front end dev 2016 & beyond
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발
 
Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기Android Native Module 안정적으로 개발하기
Android Native Module 안정적으로 개발하기
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱
 
20131217 html5
20131217 html520131217 html5
20131217 html5
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
 
ARTIK 710 IoT class 02
ARTIK 710 IoT class 02ARTIK 710 IoT class 02
ARTIK 710 IoT class 02
 
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
소셜게임 서버 개발 관점에서 본 Node.js의 장단점과 대안
 
자바스크립트 디버깅
자바스크립트 디버깅자바스크립트 디버깅
자바스크립트 디버깅
 
React native 개발 및 javascript 기본
React native 개발 및 javascript 기본React native 개발 및 javascript 기본
React native 개발 및 javascript 기본
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기
 
Nexacro
NexacroNexacro
Nexacro
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
 
Node.js의 도입과 활용
Node.js의 도입과 활용Node.js의 도입과 활용
Node.js의 도입과 활용
 

[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기

  • 1. NCSOFT / A2 Seed 성낙호 / 조현철 자바스크립트로 쉽고 빠른 UE4 개발하기 Unreal.js
  • 2. 조현철 NCSOFT A2 Seed 프로그램팀 3년 차 개발자 React-UMG 개발, 발표 성낙호 NCSOFT A2 Seed AI Tech팀 18년 차 개발자 헥스플렉스 <더 보스:라 코사 노스트라> 레드덕 <AVA>, <Metro Conflict> Unreal.js 개발, 발표 발표자 소개
  • 3. 발표에서 다룰 내용 1. Unreal.js 2. UI Development with Unreal.js
  • 5. 언리얼 마켓플레이스에 무료 공개 언리얼 데브 그랜트 수상 https://github.com/ncsoft/unreal.js Unreal.js – 오픈 소스 프로젝트
  • 6. 즐거운 개발 • 프로젝트 시작 초기의 가장 큰 고민거리 • 몇 번이나 갈아 엎게 될까? • 어떤 일 때문에 좌절하고, 어떤 작업에 짜증날까?
  • 7. 고통스러운 (이제까지의) 현실 기획 = 생각 → 문서 작성 → 대기 → (튜닝 → 실행 → 대기)* 코딩 = 기획서 확인 → 코드 작성 → 디버그(빌드 → 대기 → 실행 → 대기 → 수정)* 아트 = 툴1 → 툴2 → 툴3 → 툴1 → 툴4 → ...
  • 8. Silver bullet 기획자, 아티스트… • 필요한 툴을 그때 그때 만들어 주는 개발자 • 잦은 변심에도 짜증 내지 않는 개발자 개발자… • 빌드, 크래쉬 없이 개발할 수 있는 환경 • 생각하는 속도로 코딩할 수 있는 환경
  • 9. 현실 • 고통스러운 UE4 Tool Extension 만들기 • 고통스러운 C++ coding • 고통스러운 Blueprinting
  • 10. (커 보이는) 남의 떡 • JavaScript로 쉽게 만드는 Application • Node.js • VSCode (https://code.visualstudio.com/) • Slack • React-native (https://facebook.github.io/react-native/)
  • 11. Imagine... • 개발 과정의 수많은 "대기(wait)"를 없앨 수 있다면? • 빌드, 크래쉬가 없어질 수 있다면? • 코드를 고치면 바로 작동을 확인할 수 있다면? • 필요로 하는 많은 툴을 webapp 만들 듯 만들어 낼 수 있다면? • Web application 만드는 기분으로 UE4를 확장할 수 있다면? • 내 게임에 맞춤형 데이터 에디터를 Native UE4처럼 만들 수 있다면? • 게임 UI 제작, 보수가 기분 나쁘지 않은 일이 될 수 있다면? • 최신 Web UI Framework을 사용하여 AAA 게임 UI를 만들 수 있다면?
  • 12. Code like a ninja with JavaScript! • 무정지 개발 – Zero build • 코드 재활용 – DRY (Do not Repeat Yourself) • 함수형 언어 – Closure (over lambda) • 절차적 UI – Modern web development
  • 14. 왜 JavaScript? Battle-proven • Web era: First Class Language High performance / Flexibility • Node.js로 입증된 효용성 • Functional programming을 매우 손쉽게 구사 가능 Rich community • npm: 무료로 사용 가능한 '엄청나게' 많은 재사용 가능한 코드 Rich IDE • Visual Studio, Visual Studio Code, Chrome devtools
  • 16. Profiling V8의 강력하고 쉬운 프로파일링 도구. 보다 쉬운 최적화가 가능한 환경을 제공.
  • 17. Do not reinvent the wheel • Host 기능을 그대로 활용 및 확장 • Logic: Actor/Component • UI: Slate / UMG • Open source를 최대한 leverage! • 널리 사용되는 빠른 스크립트 엔진 도입
  • 18. Technical details Unreal.js는 세심하게 설계된 Script Bridge Layer 1. Bridge 1. UE4  JS : Auto reflection (UCLASS, UFUNCTION, USTRUCT, UPROPERTY, …) 2. JS  UE4 : Type Declaration(UCLASS, UFUNCTION, USTRUCT, UPROPERTY, …) 2. JavaScript as a First class language 3. Node.js 유사 JavaScript 개발 환경 1. Auto completion, live reload 2. npm 3. Chrome devtools
  • 22. Cyberpunk City Simulator by mflux 출처 : https://forums.unrealengine.com/showthread.php?97521-Cyberpunk-City-Simulator-(Procedural-UE4-JS)&p=455447#post455447
  • 23. UI Development with Unreal.js
  • 24. 바뀌고.. 바뀌고.. 또 바뀌고…. 한번에 끝나는 일이 거의 없음. 자잘한 수정사항이 많아서 빠른 개발 환경이 필수적임. UI Development?
  • 26. Previous work: UI • Scaleform, Coherent UI, EA webkit, Awesomium, BLUI, … • 별도의 UI process • Engine과 상관 없는 renderer. • Web스럽거나, 다시 만든 바퀴
  • 27. UI 개발 방향 UIFast Iteration Performance Productivity Flexibility
  • 28. UMG.js SNew(SVerticalBox) + SVerticalBox::Slot() [ SNew(STextBlock).Text(FText::FromString("A text") ) ] + SVerticalBox::Slot() [ SNew(SCheckBox) .IsChecked(this, &SPBMainWidget::HandleCheckBoxIs Checked, &SPBMainWidget::bCheckboxValue) .OnCheckStateChanged(this, &SPBMainWidget::OnChec kBoxChanged, &SPBMainWidget::bCheckboxValue) [ SNew(STextBlock).Text(FText::FromString("A ch eckbox")) ] ] UMG.div({'slot.size.size-rule': 'Fill'}, UMG(Button,{OnClicked:_ => fire()},"RUN"), UMG(MultiLineEditableTextBox, { 'slot.size.size-rule': 'Fill', WidgetStyle: { 'font.font-object' : GEngine.SmallFont, 'font.size': 20 }, Text: source, $link: _elem => { elem = _elem }, $unlink: _ => { } }) )
  • 29. 초기 개발 방식 - Angular.js (In House Code!) + Jade + UMG.js function rootScope(scope) { scope.text = 'Hello Scope!' scope.count = 0 scope.inc = () => scope.count++ scope.items = [] scope.discard = (item) => { scope.items = _.filter(scope.items, (i) => i != item) } scope.add = () => { scope.items.push({key:Math.random(), value:Math.random()}) } _.range(0,10).forEach(()=>scope.add()) } div span.full Button.full text {{text}} div.full Button.full(fn.on-clicked="inc()") text {{count}} Button.full(fn.on-clicked="add()") text Click button above! span text.yellow > EditableText(Binding.Text='text', fn.on-text- changed='text = ^arguments[0]') span list.full(repeat='item in items',on- click="discard(item)") HorizontalBox.small text.full {{item.key}} text.full {{item.value}}
  • 30. 초기 개발 방식 - Angular.js (In House Code!) + Jade + UMG.js • 높은 유지보수 비용. • 높은 러닝 커브. • 웹에서는 어떻게 쓰는지는 대충 알겠는데, 게임에서는 어떻게 써야하나. • 앞의 세가지 이유로 생산성이 너무 떨어졌음. 일단은 UMG.js만 쓰기로 결정.
  • 31. Only UMG.js UMG.div({'slot.size.size-rule': 'Fill'}, UMG(Button,{OnClicked:_ => fire()},"RUN"), UMG(MultiLineEditableTextBox, { 'slot.size.size-rule': 'Fill', WidgetStyle: { 'font.font-object' : GEngine.SmallFont, 'font.size': 20 }, Text: source, $link: _elem => {elem = _elem}, $unlink: _ => {} }) ) Pros. • 빠른 개발 • 비교적 쉬움 Cons. • 정리되지 않는 코드 • 디버깅 지옥 • UMG Instance와 JS간의 Coupling 장점에 비해 단점이 너무 치명적. Web에서 많이 쓰이는 UI Framework를 찾아보자.
  • 32. • react-umg • Github에 공개된 오픈소스. • UMG에서 React를 사용할 수 있게 하는 React renderer의 POC 구현체. 그러던 와중…
  • 33. React에 대해 간단하게 알아봅시다
  • 34. • Facebook에서 공개한 자바스크립트 UI 라이브러리 • Custom Component를 만들고 조합하여 View를 손쉽게 만들 수 있음. • DOM Dependency가 없음. • 재사용성이 높음. • 웹 뿐만 아니라 많은 플랫폼에서 이미 검증된 라이브러리. • 수많은 오픈소스와 예제들. - A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
  • 35. React - One way Data Flow • Data flows down • Props is immutable • States is mutable • Event flows up • Render by setState setState() Parent Child ChildChild props props props event
  • 36. class Timer extends React.Component { constructor(props) { super(props); this.state = {secondsElapsed: 0}; } tick() { this.setState((prevState) => ({ secondsElapsed: prevState.secondsElapsed + 1 })); } componentDidMount() { this.interval = setInterval(() => this.tick(), 1000); } componentWillUnmount() { clearInterval(this.interval); } render() { return ( <div>Seconds Elapsed: {this.state.secondsElapsed}</div> ); } } ReactDOM.render(<Timer />, mountNode); class HelloMessage extends React.Component { render() { return <div>Hello {this.props.name}</div>; } } ReactDOM.render(<HelloMessage name="Jane" />, mountNode); React.createElement('div', null, 'Hello ', this.props.name) Transform!
  • 37. React - Component Lifecycle 출처 : https://velopert.com/1130
  • 39. React-UMG • A React renderer for Unreal Motion Graphics With Unreal.js • https://github.com/ncsoft/React-UMG • npm i --save react-umg • Pure React.js를 사용하며, Web에서의 React.js와 유사한 개발 환경을 제공. • React.js가 React DOM에 render 한다면, UE4에서는 React-UMG에 render.
  • 40. React-UMG • React Component는 대문자로, UMG element Type은 소문자를 사용. • etc. UButton => uButton • Web에서의 DOM Element를 UMG Widget이 대체. • 웹 개발에 친숙한 element Type Naming • UVerticalBox => div • UHorizontalBox => span • UTextBlock => text • UImage => img • UEditableText => input
  • 41. React-UMG • React Native에서 사용되는 Interface를 그대로 사용. • UWidget을 상속받은 Class를 React Element로 Wrapping하여 사용. • 미리 등록된 Widget Type에 맞는 UMG 인스턴스를 생성. • Component를 Render할 때 마운트된 Component 대로 부모와 자식을 연결.
  • 42. Real Dom Virtual Dom React Components setStatePatch Event Render Web React-UMG Virtual Dom React Components setStatePatch Event RenderUMG Widget UMG Widget UMG Widget UMG Widget … Render할 대상만 다를 뿐 구조적으로 크게 다르지 않음. React-UMG
  • 43. class MyComponent extends React.Component { constructor(props, context) { super(props, context); this.state = {text:"MyComponent"}; } OnTextChanged(value) { this.setState({text: value}); } render() { return ( <div> <uEditableTextBox Text={this.state.text} OnTextChanged={value=> this.OnTextChanged(value)}/> <text Text={this.state.text}/> </div> ) } } Create a Component let widget = ReactUMG.wrap(<MyComponent/>); widget.AddToViewport(); return () => { widget.RemoveFromViewport(); } Draw With React-UMG React-UMG
  • 44. Make a Custom Widget Class Render With Custom Widget Class React-UMG class RadarWidget extends JavascriptWidget { properties() { this.size/*int*/; this.speed/*float*/; this.padding/*int*/; } OnPaint(context) { let {size,speed,padding} = this let r = size/2 let t = $time let dx = (r - padding) * Math.cos(t * speed) let dy = (r - padding) * Math.sin(t * speed) context.DrawLine({X:r,Y:r},{X:r+dx,Y:r+dy},{G:1,A:1},true) } } let Radar_C = uclass(RadarWidget) ReactUMG.Register('uRadar',Radar_C) class Radar extends React.Component { render() { return ( <div> <uRadar {...this.props} {...this.state}/> </div> ) } }
  • 46. Dependency Injection • React는 여러 플랫폼을 지원하기 위해 구현 클래스를 Injection할 수 있는 구조로 설계. • DOM 환경에서 주입되는 Class와 React Native에서 주입되는 Class가 다름. • React-UMG도 환경에 맞는 Component Class를 Injection.
  • 47. Batching • 컴포넌트가 여러 번 업데이트될 때, 마지막 한번만 렌더링하는 것이 효율적. • React는 기본적으로 업데이트를 배치로 묶어서 처리. • setState는 ReactUpdates.enqueueUpdate를 호출하여 Queue에 추가. • 렌더링은 배치가 끝났을 때 ReactUpdates.batchedUpdates에 의해 한번에 처리.
  • 48. Batching ReactComponent.prototype.setState = function (partialState, callback) { this.updater.enqueueSetState(this, partialState); // ... }; // updater var ReactUpdateQueue = { enqueueSetState: function (publicInstance, partialState) { // ... var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []); queue.push(partialState); enqueueUpdate(internalInstance); } } function enqueueUpdate(component) { // ... if (!batchingStrategy.isBatchingUpdates) { batchingStrategy.batchedUpdates(enqueueUpdate, component); return; } dirtyComponents.push(component); }
  • 49. Pooling • 자주 할당되는 객체를 사용이 끝난 후 해제하지 않고 다시 사용함. • React에서는 PooledClass 모듈을 통해 객체 풀링을 지원. • Pooling에 추가된 Class는 getPooled 함수로 풀에서 인스턴트를 얻음. • Pool에서 가져온 인스턴스는 사용이 끝난 후 release 함수 호출로 반환.
  • 50. var TRANSACTION_WRAPPERS = [ON_UMG_READY_QUEUEING]; function ReactUMGReconcileTransaction() { this.reinitializeTransaction(); this.reactMountReady = CallbackQueue.getPooled(null); } var Mixin = { getTransactionWrappers: function() { return TRANSACTION_WRAPPERS; }, getReactMountReady: function() { return this.reactMountReady; }, getUpdateQueue: function() { return ReactUpdateQueue; }, destructor: function() { CallbackQueue.release(this.reactMountReady); this.reactMountReady = null; }, }; PooledClass.addPoolingTo(ReactUMGReconcileTransaction); Pooling
  • 51. Transaction • React의 Transaction은 어떤 함수를 실행하기 전과 후에 특정 동작을 수행할 수 있도록 감싸줌. • 함수를 감싸는 Transaction Wrapper는 함수 수행 중에 예외가 나도 항상 호출되도록 되어 있어서 외부 자원의 상태를 안전하게 관리. ReactUpdates.batchedUpdates(() => { var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(); transaction.perform(() => { nextComponent.mountComponent(...); }); ReactUpdates.ReactReconcileTransaction.release(transaction); });
  • 52. ReactUMGComponent • UMG Widget의 Lifecycle 관리. • mountComponent가 실행될 때 UMG Widget을 생성 후 부모 Widget에 Add Child. • UMG Widget이 Destroy 될 때 자동으로 React Component도 언마운트. • UserWidget는 PanelWidget과 같은 위상에서 동작하도록 구현. • PanelWidget의 AddChild와 UserWidget의 SetRootWidget이 같은 형태로 동작하도록 구현.
  • 53. Demo
  • 54. Tip
  • 55. Garbage Collection • JS에서 UE4 Instance를 가지고 있는 경우는 GC가 되지 않음. • 주의해야 하는 점 • GC된 UE4 Instance에게 JS로 접근하는 경우 • UE4은 Destroy 됬는데 JS에서 Ref를 가지고 있는 경우
  • 56. Container Component / Presentational Component • Container Component 1. 데이터와 비즈니스 로직을 다룬다 2. Component Tree를 렌더링한다 • Presentational Component 1. 상태를 포함하지 않는다. 2. 컴포넌트 속성에 대한 Pure Function으로 구성한다 3. 표현만을 담당한다
  • 57. 출처: https://css-tricks.com/learning-react-redux/출처 : https://www.theodo.fr/blog/2016/03/getting-started-with- react-redux-and-immutable-a-test-driven-tutorial-part-2 Redux
  • 59. React-UMG 도입 후기 • 재사용성을 높이면서 반복되는 코드를 줄일 수 있었고 코드도 간결해짐. • 뛰어난 생산성과 보다 쉬운 디버깅 환경. • React의 Performance Cost Model이 단순해서 최적화하기가 쉬움. • Container Component / Presentational Component • View를 버리더라도 Logic은 재사용 가능해짐. • Modding을 지원할 수 있는 기반을 마련할 수 있었음.
  • 61. 결론 • Unreal.js 쓰세요. • UE4에서의 빠른 개발과 풍부한 표현을 보장해줍니다. • React-UMG 쓰세요. • 웹에서는 이미 대세인 React를 UE4에서 웹과 크게 다르지 않은 환경에서 개발 할 수 있습니다.

Editor's Notes

  1. 이 세션에서는 자바스크립트로 쉽고 빠르게 unreal engine 개발을 하는 방법에 대하여 소개 드릴 예정입니다.
  2. 오늘 발표는 저와 제 동료 조현철님이 공동으로 진행할 예정입니다. 저희 둘은 NCSoft A2 Seed에 소속되어 있습니다.
  3. 두 가지 주제로 발표를 구성하였습니다.  먼저, 제가 unreal.js를 만들게 된 배경과 간략한 소개를 드리고,  조현철님이 unreal.js를 react와 결합하여 게임 UI 및 툴을 어떻게 쉽고 빠르게 만들 수 있는 지에 대해 말씀 드릴 예정입니다.
  4. 첫번째 주제, unreal.js에 대하여 말씀드리겠습니다.
  5. Unreal.js는 ncsoft에서 발표한 오픈 소스 프로젝트입니다. 현재 unreal marketplace에 무료로 공개되어 있으며, 작년에 unreal devgrant를 수상하기도 하였습니다. 오늘 발표 내용을 직접 체험해 보고 싶으시다면, 마켓플레이스에 들어가셔서 unreal.js를 설치하시고 데모 프로젝트를 다운로드 받아 실행하실 수 있습니다.
  6. 2년 전, 대규모 MMORPG 프로젝트를 시작하려니 고민이 생겼습니다. 과연 프로젝트가 완성될 때까지 몇 번이나 갈아 엎게 될 것인지, 또 어떠한 일 때문에 좌절하고, 어떠한 일 때문에 짜증이 날 것인지… 야근이나 크런치를 하게 된다면, 미연에 방지할 수는 없을 지… 예견된 고행은 피할 수 있다면 피해야 한다고 생각하였습니다.
  7. 개발자들의 일상을 살펴보면, ‘반복’의 천국이라는 것을 쉽게 알 수 있는데, 반복은 대부분, “대기”하는 시간을 포함합니다. 대기하는 과정에서 개발자들은 집중도를 쉽게 잃습니다. 프로그래머의 경우 , 코드를 작성하고, 빌드하여 실행하고 확인하는 과정을 문제가 해결될 때까지 반복하는데, 수십 초에서 수 분에 이르는 빌드와 실행 대기 시간이 늘어날 수록 프로그래머의 주의는 분산되고, 결과물의 수준은 점점 낮아집니다. 이는 결국, 다시 작업해야 하는 상황을 만들게 되어, 개발 기간을 연장시킵니다. 
  8. 만약, 문제를 해결할 수 있는 툴을 쉽게 만들어 사용할 수 있고, 새로운 기획을 쉽게 구현해 바로 테스트해 볼 수 있다면 어떨까요?  만약 빌드나 크래쉬 없이 개발할 수 있다면 어떨까요? 만약 생각하는 속도로 코딩할 수 있다면 어떨까요? 그렇게 된다면, 게임 개발이 조금 더 재미 있어질 수 있지 않을까 생각했습니다. 
  9. 언리얼 엔진에 내가 필요한 툴을 그때 그때 만들어 추가한다는 것은, 그다지 '마음 편히 계획'할 수 있는 일은 아닙니다. 최신 프로그램 언어에 비하여 C++로 프로그래밍하는 것은 상대적으로 고통스럽습니다. Blueprint는 전문 프로그래머에게 생산성 측면에서 적합하지 않습니다.
  10. 남의 떡이 더 커 보이기 때문일 지도 모르지만… 게임 이외의 다른 분야에서는 이미 성공한 쉽고 빠른 개발 방법의 사례가 많습니다. 재미 삼아 서버 프로그래밍을 할 수 있도록 만들어 준 node.js, 데스크탑 어플리케이션 개발을 웹 개발처럼 만들어 버린 electron, 모바일 어플리케이션 개발을 웹 개발처럼 만든 react-native 등을 보면, 웬지 Unrealengine개발도 그렇게 할 수 있을 것 같고, 그렇게 해야 할 것 같아 보였습니다.
  11. 상상해 보세요. 대기, 빌드, 크래쉬가 없고, 변경한 코드의 효과를 즉시 확인할 수 있으며, 툴을 Web app 만들 듯 추가하고, AAA class UI를 홈페이지 만들 듯 쉽게 만들고, 수정할 수 있다면 어떨까요?
  12. 만약 JavaScript로 그렇게 할 수 있다면, 생각하는 대로, 정지 없이, 함수형 언어의 혜택을 최대한 누리며, 최신 웹 기술을 그대로 적용할 수 있을 것입니다.
  13. Script를 engine에 적용하면, 인터랙티브한 개발 환경을 만들기 쉽습니다. 이 화면은 Javascript Console 창에서 실행 중에 코드를 입력하는 모습으로, auto completion이 작동하고 있는 것을 확인할 수 있습니다.
  14. 잘 아시다시피, JavaScript는 (과거 flash, Java applet, ActiveX, SilverLight 등을 몰아 낸 …) web 시대의 표준 언어입니다. 여러 웹 브라우저들은 지난 십수년간 서로 치열하게 경쟁해 왔습니다. 이 과정에서 내장된 Javascript engine들의 성능은 지속적으로 향상되었고, 그 결과 JavaScript는 웹 언어에서 범용 언어로 진화하였습니다. Node.js가 그 사례입니다. Node.js의 npm에서는 재사용 가능한 많은 수의 모듈을 인용할 수 있습니다. 새로운 기능을 만들어야 할 때, 직접 구현하지 않고 이미 만들어져 있는 기능을 활용할 수 있다는 것은, 새로운 개발 경험을 제공합니다. 또한, 가장 널리 사용되는 언어이기에, 이미 구축되어 있는 다양한 통합 개발 환경에서 디버깅, 프로파일링 등의 고급 기능을 사용할 수도 있습니다.
  15. 보시는 화면은 Chrome devtool을 이용해 unreal.js를 debugging하는 모습입니다. Unreal.js는 chrome devtool 이외에 VSCode, Visual Studio 등의 IDE에서 debugging을 지원합니다.
  16. Chrome devtool을 이용하면 매우 정밀한 수준의 javascript profiling도 가능합니다. 이 모습은 unreal.js로 만든 코드를 chrome devtool로 profiling하는 모습입니다.
  17. 엔지니어링의 기본 원칙을 지키는 것은 매우 중요합니다. 예를 들어 script로 UI를 만들어 표현하기 위해서, Slate나 UMG가 아닌 별도의 UI renderer를 사용하는 것은 '바퀴를 새로 만드는 일'에 해당하는 것입니다.  따라서, 새로운 도구는 언리얼 엔진에서 제공하는 기능을 확장하는 형태여야 합니다. 앞서 설명한 대로 Javascript는 npm이라는 막강한 오픈 소스 커뮤니티를 갖고 있습니다. 따라서, 새로운 기능을 개발할 때 npm에 원하는 기능이 있는지 살펴 보는 것만으로도, 생산성은 매우 높아집니다. 또한, Unreal Engine 만을 위한 Javascript engine을 새로 만드는 것은 절대 가능한 선택지가 될 수 없습니다.
  18. Unreal.js는 JavaScript와 UnrealEngine을 잇는 브릿지 레이어입니다. 브릿지는 UnrealEngine Core에서 제공하는 reflection 기능을 이용하여 Javascript로 UE4의 대부분의 기능을 노출합니다. 또한, 반대로 Javascript에서 UFUNCTION, UCLASS, UPROPERTY등을 새로 정의하는 것도 가능합니다. Unreal.js는 JavaScript를 C++과 거의 동일한 위상으로 사용할 수 있도록 합니다. 또한, unreal.js coding 환경이 기존의 node.js나 web 개발 환경과 유사하도록 설계하여, 크롬을 이용한 프로파일링이나, IDE에서의 auto completion 뿐만 아니라, 게임 재가동 없이 코드를 변경하자마자 반영되는 live reload도 가능합니다.
  19. Unreal.js가 오픈소스로 공개되고 수 많은 문서들이 Unreal.js 의 github wiki에 존재합니다. 저희 개발팀이 필요한 기능을 구현할 떄마다 wiki에 문서를 작성하고 있으니 이 부분을 잘 읽어보시면 많은 도움이 되지 않을까 합니다.
  20. JavaScript로 작성된 코드를 unreal engine에 port하는 것도 매우 간단합니다. 왼편의 화면은 유명한 2048 게임의 input, presentation 부분만 unreal engine 기능으로 변경한 게임 화면입니다. 오른쪽은 springy라는 graph visualization library를 unreal engine의 canvas drawing 기능에 연결한 것입니다.
  21. Editor 확장을, 엔진을 빌드, 리부트하지 않고, web app 만들 듯이 만들 수 있습니다. 무엇보다 엔진에 이미 존재하는 많은 에디터 기능들을 javascript로 embed하여 사용할 수 있기 때문에, webapp을 만드는 것보다 오히려 더 손쉽게, 멋있고 사용성이 좋은 에디터를 빨리 만들 수 있습니다. 왼편의 에디터 화면은 JSON으로 정의한 schema에 의해 / 자동으로 생성된 , 프로퍼티 편집기가 포함된 예제 에디터 화면입니다. 오른 쪽의 화면은 Blueprint, Anim Blueprint, Material editor 등의 back bone인 graph editor를 javascript로 확장한 모습입니다.
  22. Michanel Chang, mflux님은 unreal.js를 이용하여 도시 시뮬레이션 게임을 제작 중입니다. 화면 상의 모든 메쉬는 unreal.js로 procedural 하게 만들어 낸 것이며, 모든 로직은 javascript로 작성되었습니다. 제 발표는 여기까지입니다. 이어서 조현철님이 발표해 주시겠습니다.
  23. 이어서 발표할 내용은 소개해드린 Unreal.js를 이용하여, Game UI와 툴을 빠르고 쉽게 개발할 수 있는 방법에 대해 소개해드리겠습니다.
  24. Game UI나 Tool을 제작하는 것은 게임 개발에 많은 부분을 차지합니다. 이것은 한번에 끝나지 않고 수 많은 수정사항과 시행착오를 거치게 되는데요. 빠른 개발 환경이 제공되지 않는다면 이것은 굉장히 고통스러운 작업이 될 수 있습니다. (20s)
  25. 언리얼엔진에서 제공되는 UI 제작 방법은 C++ 기반의 Slate로 구성하는 방법과 Slate를 Blueprint에서 사용하기 위해 노출된 UMG를 사용하는 방법이 있습니다. 왼쪽 화면에 보이는 것과 같이 언리얼 에디터의 모든 UI는 Slate로 구성되며, 이것은 C++을 통해 작성할 수 있습니다. 또 UMG는 Blueprint와 위즈윅한 에디터 편집 기능, Widget Animation 편집 기능 등을 통해 UI를 제작할 수 있는 환경을 제공해 줍니다. (30s)
  26. 이외에도 Autodesk의 Scaleform, Coherent Labs의 Coherent UI, EA Webkit 등과 같은 UI 미들웨어를 통해 UI를 구성할 수도 있습니다. 하지만 이것은 별도의 UI 프로세스로 Engine과 상관 없는 renderer를 사용하게 되는데요. 그것보다는 Slate/UMG 와 같은 언리얼 엔진에서 구현된 기능을 사용하는 것이 보다 화려한 UI와 나은 성능을 가져다 줄 수 있을 것이라고 생각했습니다. (30s)
  27. 저희가 이전보다 나은 방향의 UI 개발 프로세스를 구상하며 잡은 기조는 크게 다음과 같습니다. 1. Slate / UMG를 Javascript로 제어함으로써 뛰어난 ‘성능’을 보장합니다. 2. 적은 타이핑으로 풍부한 표현이 가능하게 하여 보다 나은 생산성을 보장하도록 합니다. 3. 코드를 저장하면 변경된 사항을 바로 확인할 수 있게 하여 보다 빠른 개발이 가능하도록 합니다. 4. 기능별로 모듈화 하여 보다 확장성 있도록 UI를 구성합니다. (30s)
  28. 왼쪽의 코드는 Slate 코드이고, 오른쪽의 코드는 Unreal.js 에서 Javascript로 UMG를 제어하는 UMG.js의 코드입니다. UMG.js는 Slate/UMG와 같은 계층구조를 가지고 있지만, Javascript의 뛰어난 표현력과 Live Reload 기능을 통해 빠른 개발을 보장해줍니다. (20s)
  29. 저희 개발팀의 초기 개발 방식으로 Angluar.js 라는 프레임워크를 모방하여 만든 프레임워크에 Jade라는 Template Engine을 붙여서 사용하는 방식을 채택하였습니다. 이것은 Controller의 scope 안에 들어있는 요소들을 Jade에 미리 선언된 View에 그리는 방식으로 전통적인 MVC 모델에 기반하여 코드를 작성할 수 있으며 양방향 바인딩을 지원하고 있습니다 . (30s)
  30. 하지만 이런 개발방식은 오래가지 못했는데요. Angluar.js를 모방하여 만든 구현체다보니 Angluar.js에서 사용되는 기능들을 하나하나씩 옮기며 코드를 수정하기에는 유지보수 비용이 너무 컸습니다. 그리고 러닝 커브가 높아서 코드를 쓰기가 어려웠고, 게임 UI를 구성할 때에는 어떻게 사용하는지에 대한 이해가 어려웠습니다. 특히 퍼포먼스 이슈와 같은 문제가 생겼을 때 이것을 개선하기 위해 어떻게 써야하는지에 대해서 잘 몰랐습니다. 일단 앞의 세가지의 이유로 코드 생산성이 너무 떨어졌기 때문에, UMG.js 만으로 UI 개발을 진행해보기로 결정했습니다. (40s)
  31. 하지만 UMG.js 만으로 UI를 제작하는 것도 어려움이 많았습니다. 초기에는 이전 개발방식보다 빠르고 쉽다는 점이 매력적이었지만 남이 쓴 코드를 고치거나 디버깅을 하기가 너무 어려웠습니다. 리팩토링을 하더라도 코드를 쓴 사람마다 스타일이 너무 달랐고 Framework없이 순수한 Javascript만 사용하다 보니 코드를 망가뜨리기가 너무 쉬웠습니다. 또 UMG instance와 javascript 간의 coupling이 심해 이슈가 발생했을 때 대응하는 것이 어려웠습니다. 장점에 비해 단점이 치명적이었기 때문에 저희는 새로운 방향에 대해서 찾아야 했습니다. (30s)
  32. 그러던 와중 drywolf라는 개발자가 github에 올린 react-umg라는 오픈소스 구현체를 발견했습니다. 이것은 UMG에서 React를 사용할 수 있게 하는 React renderer의 POC 구현체였는데요. 이것이 POC로 구현된 코드다 보니 미비한 부분이 많았지만 제가 평소에 React에 대해서 관심이 많았고, React의 장점에 대해서 익히 들었던 터라 이것을 도입하는 것이 많은 부분에서 이점을 가져다 줄거라고 판단했습니다. 그래서 react-umg의 코드를 수정하여 적용해보기 시작했습니다. (30s)
  33. 우선 React-UMG에 대해서 설명드리기 전에 이것의 기반이 되는 React에 대해서 간단하게 설명드리겠습니다. (10s)
  34. React는 Facebook에서 공개한 자바스크립트 UI 라이브러리입니다. 이것은 Custom Component를 만들고 조합하여 View를 손쉽게 만들 수 있으며 재사용성이 높다는 장점을 가지고 있습니다. 뿐만 아니라 React Native 와 같은 라이브러리를 통해 Android, iOS, 데스크탑 등 다양한 환경에서 이미 검증된 라이브러리입니다. 또 DOM Dependency가 없어 Unreal.js에서 사용하기 적합할 것으로 기대했습니다. (30s)
  35. React의 데이터 흐름은 단방향이고 상위 Component에서 하위 Component로 흐릅니다. 오른쪽 그림에 보시는 것과 같이 Props은 Child가 Parent로부터 받은 변경 불가능한 데이터인데요. 이것에 의해 Parent가 변경된 사항을 Child에 반영하게 됩니다. State는 컴포넌트 안에서 변경 가능한 데이터로, State의 변경을 통해 Component는 자식 Component를 포함하여 다시 Render 하게 됩니다. 또 상위 Component는 하위 Component에 이벤트를 추가해 변경사항을 감지하게 하여 State를 변경할 수 있습니다. (30s)
  36. React.js의 예제 코드를 보시면 더 쉽게 이해하실 수 있을 것 같습니다. 보시는 것과 같이 웹에서 쓰이던 코드들과 유사하고 꽤 단순한 편인데요. 이것은 Babel이라는 Javascript Compiler를 통해 XML의 문법을 사용할 수 있도록 하여 보다 나은 코드 생산성을 제공해줍니다. 왼쪽 코드에 보시는 것과 같이 XML 형식의 코드가 아래와 같이 변형되어 적용된 것을 확인할 수 있습니다. 오른쪽 코드는 1초마다 UI가 업데이트 되는 간단한 Component 인데요. 1초마다 setState를 호출하여 1초마다 해당 Component를 새로 그리게 되는 단순한 처리를 하고 있습니다. 이처럼 동적으로 변경되는 사항을 state를 변경하여 새로 그림으로써 쉽게 표현할 수 있습니다.
  37. React에서 제공하는 Component Lifecycle API 를 통해 다양한 구현이 가능합니다. 이것은 각 Component에 필요한 요소를 주입하는 것 뿐만 아니라, Logic과 View를 분리하는데 있어 꽤 편리하게 사용됩니다. 또 업데이트 처리를 필요한 경우에만 함으로써 코드를 최적화 할 수 있습니다. 좀 더 자세히 설명 드리면 React는 State가 변경되면 Sub-tree를 다시 Render 합니다. 그래서 계층 구조가 깊어지거나 Component가 비대한 경우 성능이 좋지 못할 수 있습니다. Lifecycle API 중 슬라이드 상에 동그라미로 표시된 ShoudComponentUpdate 함수를 통해 해당 Component가 변했는지 확인하여 render 여부를 결정할 수 있습니다. 이러한 최적화 테크닉은 React-UMG도 동일하게 적용되어 있는 부분이어서 Web 환경의 React.js 와 동일한 테크닉이어서 웹에서의 많은 사례를 참고하실 수 있습니다.
  38. 다음은 React-UMG에 대해 소개해드리겠습니다.
  39. React-UMG는 Unreal.js 에서 사용할 수 있는 UMG를 위한 React renderer 입니다. Github과 npm을 통해 공개되어 있으니 Script 경로에 설치하시면 사용이 가능합니다. 이것은 순수한 React.js를 사용하고 있으며, 웹에서 사용하는 것과 유사한 개발 환경을 제공되도록 개발하고 있습니다. React.js가 React DOM에 rende한다면, UE4에서는 React-UMG에 rende한다는 부분만 다른 부분입니다.
  40. React-UMG는 Web에서의 Coding Style을 유사하게 가져가기 위한 컨벤션을 사용합니다. Web에서 React Component를 대문자로, DOM Element를 소문자로 사용하듯이 UMG element Type을 소문자로 시작하도록 하고 있으며, Web에서 많이 쓰이는 Type naming을 그대로 쓸 수 있도록 하였습니다.
  41. React-UMG를 개발을 하는데 있어서 가장 크게 도움이 됬던 부분은 React Native의 구현체가 공개되어 있었다는 점입니다. 모바일 환경에서 사용하게 하기 위해 쓰였던 여러가지 테크닉들과 인터페이스를 React-UMG에서도 많은 부분에 활용하고 있습니다. 이것에 대해서는 뒤에 구체적으로 설명해드리도록 하겠습니다. React-UMG에서는 UWidget을 상속받은 모든 Class를 React Element로 사용 할 수 있으며, 이것은 C++ / Blueprint 뿐만 아니라 Javascript에서 구현된 Custom Widget Class도 사용 가능합니다. 여기서 하나의 React Element는 UMG 인스턴스를 래핑하고 있는 객체로 보시면 될 것 같은데요. React Element를 생성하면 미리 등록된 Widget Type에 맞는 UMG 인스턴스를 생성함으로써 Widget이 화면에 표시되게 됩니다. 이러한 React Element로 구성된 Component를 Render하게 되면 / 마운트된 Component Tree 구조대로 부모 컴포넌트와 자식 컴포넌트를 연결함으로써 / React Render Tree를 UMG Render Tree로 사용할 수 있게 됩니다 (60s)
  42. 다음 그림은 Web에서의 React.js와 React-UMG의 Render 절차를 도식화하여 비교한 것 입니다. 보시는 것과 같이 React.js의 Virtual Dom을 동일하게 사용하고 있으며 Dom에 그리느냐, UMG Widget에 그리느냐만 다르지 구조적으로 크게 다르지 않습니다. (20s)
  43. 다음은 React-UMG를 이용해 구현해 본 간단한 예제입니다. 아까 설명드린 것 처럼 웹 환경에서 React.js로 구현한 코드와 크게 다르지 않습니다. 또 UMG.js로 구현한다면 다소 지저분해질 수 있는 부분도 보다 쉽게 구현할 수 있다는 것을 확인하실 수 있습니다. 왼쪽의 Create Component의 코드는 간단하게 EditableTextBox에 의해 state가 변경되고 그것이 TextBlock에 적용되게 한 예제입니다. 이렇게 구성된 Component를 오른쪽 코드와 같이 React-UMG에 그려서 화면에 표시합니다. (40s)
  44. React-UMG에서는 Javascript 에서 기존 Widget Class를 상속받아 구현된 Class를 기존 Widget들과 동일하게 사용할 수 있습니다. 이것을 통해 C++과 Blueprint에서 할 수 있던 부분들을 Javascript에서도 구현할 수 있습니다. 다음 코드는 JavascriptWidget을 상속받아 React-UMG에서 사용하는 코드 입니다. (24s)
  45. 다음은 React-UMG의 기술적 세부사항에 대해서 설명드리겠습니다. 이 내용은 기술적 기반에 대한 디테일한 설명이기 때문에 모르고 지나가셔도 괜찮습니다.
  46. React.js는 여러 플랫폼을 지원하기 위해 구현 클래스를 Injection할 수 있는 구조로 설계되어 있습니다. React Native에서 사용하는 Class와 DOM 환경에서 사용되는 Class를 별도로 구현하고, 사용할 플랫폼에 맞는 Class만 Injection하여 사용하면 되는 구조로 되어있는 것입니다. React-UMG도 ReactUMGComponent라는 Component Class를 구현하여 UMG 환경에 맞춰서 사용하고 있습니다. 또 배치, 트랜잭션 등을 제외한 React가 동작하는데 필요한 나머지 정책들은 React 기본 정책을 사용하고 있습니다. (35s)
  47. 다음은 Batching에 대한 설명해드리겠습니다. 만약 같은 컴포넌트가 여러 번 업데이트 될 때 여러 번 렌더링하는 것 보다 마지막에 한번만 렌더링하는 것이 효율적입니다. React는 기본적으로 업데이트를 배치로 묶어 처리하고 있으며, setState 함수로 변경할 state를 Queue에 추가하게 되면 실제 렌더링은 배치가 끝났을때 batchedUpdates 함수가 호출될 때 한번에 처리하게 됩니다. (30s)
  48. 다음은 Batching에 대한 간단한 구현입니다. 보시는 것과 같이 enqueueSetState 함수에서 변경할 state를 Queue에 추가하고, Batch 업데이트가 끝났을때 렌더링 처리하는 것을 확인할 수 있습니다.
  49. 다음은 Pooling에 대해 설명드리겠습니다. 자주 할당되는 객체를 사용이 끝난 후 해제하지 않고 다시 사용함으로써 메모리 사용량을 줄이고 GC가 자주 발생하지 않도록 하고 있습니다. React는 PooledClass 모듈을 통해 객체 풀링을 지원하고 있는데요. Pooling에 추가된 Class는 getPooled 함수를 통해 간단하게 풀에서 인스턴트를 가져올 수 있습니다. Pool에서 가져온 인스턴스는 사용이 끝난 후 release 함수를 통해 반환합니다. (35s)
  50. 이것은 React-UMG의 구현의 일부로, Pooling에 필요한 구성요소가 어떤 것들인지 한눈에 보실 수 있습니다. (10s)
  51. 다음은 Transaction에 대해 설명드리겠습니다. React는 Transaction 처리를 통해 어떤 함수를 실행하기 전과 후에 특정 동작이 수행될 수 있도록 보장해줍니다. 함수를 감싸는 Transaction Wrapper는 함수 수행중에 예외가 나더라도 항상 호출되도록 되어있어 외부 자원의 상태를 안전하게 관리합니다. 아래 코드를 통해 batchedUpdates에서 Transaction 처리가 어떻게 되고 있는지 확인하실 수 있습니다. (30s)
  52. 다음은 ReactUMGComponent 에 대한 설명입니다. 이것은 앞서 설명드린 의존성 주입에 필요한 ReactComponent이며 DOM이 아닌 UMG widget에 render할 수 있도록 구현된 Component입니다. 이 Component를 통해 부모 Widget과 자식 Widget을 연결시킬 수 있으며, Widget들의 Lifecycle 관리도 이것을 통해 처리하도록 되어 있습니다. 다소 조금 특이한 부분은 툴팁과 같은 Delegate에 Widget을 Binding 해야 하는 경우 React Component를 Destroy 하지 않았는데 Widget이 Destroy되는 경우가 발생 할 수 있습니다 이것을 막기위해, UMG Widget이 Destroy될 때 자동으로 React Component도 언마운트되도록 처리하여 메모리 누수를 막고 있습니다. 또 UserWidget을 상속받은 JavascriptWidget이 PanelWidget을 상속받은 Widget들처럼 동작할 수 있도록 확장하여 Custom Widget Class의 구현도 지원할 수 있었습니다. (60s)
  53. Demo를 보여드리겠습니다. (300s)
  54. 다음은 React-UMG를 활용하는데 도움될 만한 팁에 대해서 소개해드리겠습니다.
  55. 이 부분은 React-UMG의 이슈라기보다는 Unreal.js를 사용하게 되면 생기는 이슈인데요. Unreal.js 뿐만 아니라 다른 Script Plugin을 도입하더라도 생기는 이슈일 것 같습니다. Javascript에서 UObject 를 생성하여 사용하던 도중 GC가 되어 사라지는 경우가 생기면 매우 곤란할텐데요. 이런 부분을 막기 위해 Javascipt에서 ref를 가지고 있는 경우 GC가 되지 않도록 막고 있습니다. 하지만 주의해야 할 부분이 있는데요. GC된 언리얼 Instance에 대해 Javascript에서 접근하는 경우입니다. 이 경우 instance에 대한 접근이 원활하지 않아 에러가 발생할 수 있습니다. 뿐만 아니라 Javascript에서 Destroy 된 언리얼 인스턴스를 가지고 있는 경우 UnrealGC에서 GC처리가 제대로 되지 않아 문제가 생길 수 있습니다. 그래서 Destroy될 때 Javascript상에 가지고 있는 ref를 비워줘야 문제가 생기지 않는데요. 그러지 않은 경우 Crash가 발생할 수 있습니다.
  56. React로 UI를 잘 만들기 위해서는 Container Component와 Presentational Component의 개념에 대해서 알아두면 도움이 될것 같습니다. Container Component는 비즈니스 로직, 액션 처리를 담당하고 있으며 Container Component는 Props을 통해 Presentational Component에 함수를 보냅니다. 또 Presentational Component는 받은 함수를 콜백으로써 단순한 호출을 하거나 Props을 반영합니다. 또 화면의 Layout을 구성하는 역할을 하며 Style을 포함하고 있습니다. 이러한 두 가지 타입의 Component의 조합을 통해 같은 View 이지만, 안에서 동작하는 로직이나 데이터가 다르게 하는 것도 가능하겠지요. (30s)
  57. 다음은 Redux에 관한 내용인데요. React로만 코드를 작성하게 되면 부모와 자식간의, 혹은 자식들끼리의 Communication을 하는 것이 굉장히 귀찮거나 복잡하게 되서 난감한 경우가 있을텐데요. 이런 부분에 대해서는 Redux 라는 Global State를 통해 Communication 하는 것도 방법이 될 수 있습니다. 이처럼 UI 특성에 따라 Redux , RxJS와 같은 라이브러리를 추가로 도입해보는 것도 좋은 방법이 되리라 생각합니다. (30s)
  58. 도입 후기입니다.
  59. 저희는 React-UMG를 도입하고 많은 부분을 개선할 수 있었습니다. React의 장점을 그대로 가져갈 수 있었을 뿐만 아니라, 엔진에서 제공하는 UMG의 기능을 React의 Component로써 활용할 수 있어서 기반 Component를 만들지 않더라도 필요한 기능을 구현할 수 있었습니다. 뿐만 아니라 저희는 내부적으로 Modding이 가능했으면 좋겠다라는 요구사항이 있었는데요. Component의 조합을 통해 Modding을 지원할 수 있는 기반을 마련할 수 있었습니다. (30s)