SlideShare une entreprise Scribd logo
1  sur  76
Télécharger pour lire hors ligne
React 애플리케이션 아키텍처
아무도 알려주지 않아서 혼자 삽질했다
손병대 ( miconblog@gmail.com )
왜 React 하나요?
왜 React 하나요?
저는 문제 해결에 집중할 수 있었습니다.
왜 React 하나요?
다른말로 표현하면 아키텍처에 집중할수있어서 좋았습니다.
1년동안 여행을 다녀왔어요.
왜죠?
코딩이 하고 싶었거든요.
그래서 여행하며 정보북을 만들었어요.
http://rlibro.com
첫 커밋은 2015년 12월 31일!
그때 그시절 그 코드가 지금은 참 가소롭다.
샘플은 곧 나의 아키텍처
하지만 현실의 문제는 늘 샘플을 벗어난다.
쉽게 무너지는 아키텍처
새로운 것들은 계속 나오는데 적용하지 않을수도 없고,…
스펙은 계속 바뀌고… OTL
문서를 꼼꼼히 읽자.
문서에 모든 답이 다 있다.
그런데,.. 문서가 또 너무 많아 -_-;
좋은 아키텍처는 

디자인 되야하고
플랜 되어져야 한다.
좋은 디자인을 위해 알아야할 것들
1년 6개월전에 알았더라면 좋았을 것들…
React는 빙산의 일각1
React는 빙산의 일각2
첫번재, 컴포넌트 역할 정의
뭣이 컴포넌트인가?
Lv1. 버튼
버튼을 컴포넌트로 만들어봅시다.
기본 HTML 버튼은 그냥 좀 구려요.
아이콘도 없구요
그래서 버튼의 색상도 바꾸고
아이콘도 넣고 싶어요
버튼을 컴포넌트로 만들면 props 에는 아이콘과 스타일을 넣어볼수 있습니다.
<Button	icon=‘power’	style={…}>Click	me!</Button>
Lv2. 검색창
이번엔 검색창이에요.
이녀석의 props에 뭐가 있으면 좋을
까요?
<SerachBar	onSearch={	keyword	=>	{	console.log(keyword)	}	}	/>	
일단 엔터를 치면 검색어와 함께 콜백을 받는다
고 합시다.
초기값도 필요하지 않을까요?
				<SerachBar		
			initialValue={‘슬로베니아’}	
							onSearch={	keyword	=>	{	console.log(keyword)	}	}		
				/>	
컴포넌트 설계는 역할을 어떻게 정의하느냐가 전부에요!
Lv3. 자동완성
좀더 나가 봅시다.
<SerachBar		
			initialValue={‘슬로베니아’}	
			dataSource={[..]}	
							onSearch={	keyword	=>	{	console.log(keyword)	}	}		
				/>	
props 에 무엇을 넣을까요?
그런데 키워드로 검색된 결과는 어떻게 가져오죠?
SearchBar의 역할을 화면 랜더링 전용으로 한정한다면
데이터를 불러올 녀석이 필요합니다.
Lv4. 컨테이너 컴포넌트
중요한 규칙하나, 컨테이너는 데이터를 다룬다
<SerachBarContainer>	
			<SerachBar		
						initialValue={'여행'}	
						dataSource={[]}	
						onSearch={	keyword	=>	{	console.log(keyword)	}	}		
			/>	
</SerachBarContainer>	
그림으로 그려보면 대략 이런 모습입니다.
import	SerachBar	from	'./SerachBar';	
class	SerachBarContainer	extends	React.PureComponent		{	
	 state	=	{	
					 loading:	false,	
								results:	[]	
			}	
	 	
			render	()	{	
					 return	(	
										<SerachBar	dataSource={this.state.results}	onSearch={this.handleSearch}/>	
				);	
			}	
					
			handleSearch	=	(query)	=>	{	
					
								this.setState({loading:true})	
								fetch('/search')	
								.then((결과)=>{	
										this.setState({results:결과,	loading:false})	
								})	
					 	
			}	
}	
코드로 바꾸면 대충 이런 모습이겠죠?
그림으로 그려보면 대충 이렇습니다.
데이터를 가져오는 역할을 누구에게 줄것인가? 

그리고 그런 녀석을 뭐라고 부를(정의) 것인가?
두번째, 컴포넌트 분리하기
역할을 어떤 기준으로 나누고 분배할 것인가?
사용자 이벤트 처리는 누가 하지?
화면을 기준으로 컴포넌트를 나눌때 나타나는 현상
click!
컨테이너가 이벤트를 담당할경우 해당 컨테이너까지 

이벤트를 끌어올려야한다. … 귀찮아!
) (
) (
.(.
.(.
. .(
.(.
적당히 나누는데도 한계가 있다!
) (
) (
.(.
.(.
. .(
.(.
) (
.(.
.(.
) (
라우터를 이용한 컴포넌트 분리
중첩 라우터를 이용해
집중할 관심사를 완전히 분리한다.
:
( )(
./ ( )(
./
(/
( )(
./ ( )(
( )(
./ ( )(
/
/ (
라우터를 이용한 컴포넌트 분리
라우터가 로드할 페이지를 결정할때 중첩
된 부모 페이지가 있으면 같이 로드된다.
C
( )(
./ ( )(
./
(/
( )(
./ ( )(
( )(
./ ( )(
:
/ (
부모는 자식이 필요로 하는
값이 없으면 아예 랜더링을 하지 않는다.
즉, 선택적으로 Props를 주입할수있다.
라우터를 이용한 컴포넌트 분리
1. 중첩된 부모 라우터에서 필요한 값을 한번만 로드한다.
2. 자식 라우터에는
로드된 값을 선별해서
값이 있을때만 주입하고 랜더링한다.
3. 이렇게 하면 자식 라우터는 필요한 값을 항상
주입 받은 상태로 넘어오기 때문에 기다릴 필요
가 없게된다.
C
( )(
./ ( )(
./
(/
( )(
./ ( )(
( )(
./ ( )(
:
/ (
사용자 이벤트 처리는 누가 하지?
Redux를 이용한 컴포넌트 분리
click! 컨테이너까지 이벤트를 올려주세요!
스토어를 연결한 컨테이너를 중간중간 만든다.
이벤트 처리는 여기서 하기로 하자!
) ( ).
) ( ).
) ( ).
) ( ).
) ( ).
) ( ).
사용자 클릭 이벤트
Redux를 이용한 컴포넌트 분리
click!
이벤트 처리는 역시 dispatch 액션!!
. .
. .
. .
. .
. .
. .
)
. (
그럼에도 불구하고 콜백을 올리는건
여전히 귀찮다…
Redux를 이용한 컴포넌트 분리
콜백이 귀찮을땐 dispatch를 내려준다.
. .
. .
.
.
)
. (
Redux를 이용한 컴포넌트 분리
너무 깊어 dispatch도 내려주기 귀찮을땐
context 매직을 사용한다.
export	default	class	BookNoteList	extends	React.PureComponent	{	
		static	contextTypes	=	{	
				store:	React.PropTypes.object	
		};	
			
		render()	{	
		return(	
		<div>	
		<Button		
					onClick={	
						()=>	this.context.store.dispatch(액션)		
					}	
		>	컨텍스트 쓰지말래도 난 쓸꺼야! </Button>	
		</div>	
		)	
		}	
}	
Provider를 이용해 주입한 store 컨텍스트를 사용할수있다.
. .
. .
)
. (
Redux와 컴포넌트를 연결하는 방법
connect(mapStateToProps,	mapDispatchToProps)(ContainerComponent)	
connect(mapStateToProps)(ContainerComponent)	
dispatch 내리면 코드가 간결해진다.
단점, redux에 의존성이 생긴다.
어짜피 재사용하기 힘들다면 GoGo!
(
(
)
)
dispatch와 callback을 혼용하는 경우
Redux 아키텍처 상에서 Ajax 호출을 관리하지 않는 경우
지오코딩은 구글맵 SDK를 이용해 호출한다.
A
A
)(
React는 빙산의 일각 리마인드
브라우저(글로벌) 영역
애플리케이션 영역
리덕스 영역
Middleware Control Flow
. E A A E A I - E /
l pSh
/
E E
EC
. )/ )/
pSh MS
( A A
( C A
EC AA
E
E E
/) .
iMS
E
sRf T rk
Pao f
E
Lj
. E A
( A A
C CE
gc
E C CE
/
e
사용자
A
(
Pao
/
e / OP V
EC A
A A
,
Lj
pSh
E EE A
mn
d
bU
A
Lj
EC A
이제 겨우 요거 했다!
재사용 가능한 컴포넌트란?
2. 프로젝트 내에서 컨테이너도 재사용하고 싶다면.
1. 프로젝트 내에서 뷰를 재사용하고 싶다면
3. 다른 프로젝트에서도 쓸수있게 만든다.
컴포넌트에서 데이터 로드에 대한 역할을 제거해라!
기능을 효율적으로 묶고, 아키텍처를 최대한 활용해라!
데이터 로드 및 아키텍처에 대한 의존도를 낮추고
필요하다면 props로 주입 받아라
세번째, Redux 아키텍처
아키텍처를 이해하면 개발도 쉬워진다.
Lv1. 리듀서
리듀서 항상 사이드 이펙트가 없는 순수 함수로 작성 되야 한다.
순수함수란? (Pure Function)
인풋이 같으면 항상 같은 값을 반환한다.
그러니까 주어진 값으로 계산만 해라!
쉬운말로 딴짓 하지마!
그래서 리듀서의 역할은 매우 단순하다
,
O NT
R : !
I A C
단순하지만 굉장히 어려운 이뮤터빌리티!
리듀서의 상태 변경 로직은
단순한 삼중등호를 이용한다.
즉, 상태 반환시
항상 새로운 상태 레퍼랜스를 반환해야한다.
기존 상태에 값만 변경하는 행위는
객체의 참조를 변경시키지 않는다
const	initialState	=	{	x:1,	y:	2	};	
function	reducer(state=initialState,	action)	{	
state.x	=	3;	
state.y	=	action.payload;	
return	state;	
}	
:& A
3 : : &
,
단순하기 때문에 개발자의 책임도 많아진다.
변경을 알리는 로직은 어떤 값이 변경 됐는지
구분하지 않고 단순히 상태가 변경 됐을 때
모두 구독자에게 알려준다.
Note that selectorFactory is responsible for all caching/memoization of
inbound and outbound props. Do not use connectAdvanced directly
without memoizing results between calls to your selector, otherwise the
Connect component will re-render on every state or props change.
function	mapStateToProps(	state:	Object	)	{	
	 // 이곳에서 캐싱/메모이제이션을 처리해서 넘겨야한다.	
		const	testState	=	state.get(‘test');		
		const	testValue	=	reselectValue(testState);	
		// 결국 이곳에서 반환되는 값들은 React의 shouldComponentUpdate 사이클을 타게 된다.	
		return	{	
				test:	testValue,		
		};	
}	
export	default	connect(mapStateToProps)(ReactComponent);	
&
Redux 코드를 까보면 나오는 주석!
아! -__-;;;; 얘들은 이런 중요한 얘기를 문서가
아닌 코드에 심어 놓는구나…
브라우저(글로벌) 영역
애플리케이션 영역
리덕스 영역
Middleware Control Flow
. E A A E A I - E /
l pSh
/
E E
EC
. )/ )/
pSh MS
( A A
( C A
EC AA
E
E E
/) .
iMS
E
sRf T rk
Pao f
E
Lj
. E A
( A A
C CE
gc
E C CE
/
e
사용자
A
(
Pao
/
e / OP V
EC A
A A
,
Lj
pSh
E EE A
mn
d
bU
A
Lj
EC A
Redux 아키텍처의 이해, Reducer 요기!
Lv2. 액션 생성자
액션 생성자는 항상 순수한 액션을 반환해야한다.
redux-thunk 가 불러오는 오해
thunk 액션은 순수 오프젝트가 아니라 함수다!
액션 생성자는 본래 plain object 를 반환하는 녀석이다.
'
: 1
: ) ( ( : 1
function	createThunkMiddleware(extraArgument)	{	
		return	({	dispatch,	getState	})	=>	next	=>	action	=>	{	
				if	(typeof	action	===	'function')	{	
						return	action(dispatch,	getState,	extraArgument);	
				}	
				return	next(action);	
		};	
}	
const	thunk	=	createThunkMiddleware();	
thunk.withExtraArgument	=	createThunkMiddleware;	
export	default	thunk;	
thunk 미들웨어는 몇줄 안돼…

진짜 단순하다.
그러나 thunk 액션 생성자는 액션도 반환할수있다.
즉, 누구나 알고 있는 기본 아키텍처의 변경을 가져온다.
'
: 1
: ) ( ( : 1
액션 생성자를 오해하게 만드는 예제
export	function	requestUserLocation(){	
		return	(dispatch,	getState)	=>	{	
				return	dispatch({	
						type:	'USER_LOCATION_REQUEST'	
				});	
		}	
}	
redux-thunk 를 이용한 샘플을 따라하면서 잘못 사용하고 있다.
테스트하기 어렵다.
dispatch를 직접 실행하면서 본래 목적과 혼용되기 쉽다.
코드만 보면 dispatch가 갑자기 어디선가 주입된다.
왜!
안좋아?
액션 생성자를 잘못 쓴 예제
export	function	addComment	(noteId,	noteAuthorId,	content)	{	
		const	currentUser	=	Parse.User.current();	
		return	(dispatch,	getState)	=>	{	
				dispatch({	type:	types.ADD_COMMENT_REQUEST	});	
				Parse.Cloud	
						.run('addComment',	{	
								noteId:	noteId,	
								fromUserId:	currentUser.id,	
								toUserId:	noteAuthorId,	
								content:	content	
						})	
						.then(	note	=>	{	
								dispatch({	
										type:	types.ADD_COMMENT_SUCCESS,	
										response:	Object.assign({},	normalize(note.toJSON(),	noteSchema)	),	
										meta:	{	
												request:	{	
														objectName:'DiaryNote'	
												}	
										}	
								})	
						});	
		}	
}	
dispatch 실행한다.
비동기 호출을 하고 있다.
역시나 테스트하기 어렵다
왜!
안좋아?
액션 생성자를 사용하는 올바른 예!
export	function	addComment(	noteId,	values	)	{	
		if(	!values	)	{	return	{	type:	types.NO_VALUE	}	}	
		values.author	=	Parse.User.current();	
		values.referrerId	=	noteId;	
		return	{	
				type			:	types.PARSE_SERVER,	
				payload:	{	
						objectName:	'Comment',	
						method				:	'POST',	
						params				:	values,	
				},	
				meta			:	{	
						prefix:	'COMMENT_ADD',	
						noteId,	
						schema:	Schemas.COMMENT,	
				},	
		};	
}	
왜!
좋아?
테스트하기 쉽다.
단순하다.
브라우저(글로벌) 영역
애플리케이션 영역
리덕스 영역
Middleware Control Flow
. E A A E A I - E /
l pSh
/
E E
EC
. )/ )/
pSh MS
( A A
( C A
EC AA
E
E E
/) .
iMS
E
sRf T rk
Pao f
E
Lj
. E A
( A A
C CE
gc
E C CE
/
e
사용자
A
(
Pao
/
e / OP V
EC A
A A
,
Lj
pSh
E EE A
mn
d
bU
A
Lj
EC A
Redux 아키텍처의 이해, 액션 생성자
요기!
Lv3. Redux 미들웨어
Redux 아키텍처에서 비동기는 미들웨어가 처리한다.
미들웨어는 순차적으로 실행이 되므로 상황에 따라서 마지막 미들웨어는 실행되지 않을수도 있다.
		compose(	
				//applyMiddleware(require('redux-immutable-state-invariant')()),	
				applyMiddleware(thunk,	parse),	
				applyMiddleware(sagaMiddleware),	
				//applyMiddleware(createLogger()),	
				applyMiddleware(redirectMiddleware),	
				window.devToolsExtension	?	window.devToolsExtension()	:	f	=>	f,	
		),	
여기서 정의된 순서로 실행된다.
Middleware
A / ) / / / / (A
/
/ /
/
(/ A ) /
미들웨어
Thunk
미들웨어
Saga
미들웨어
Logger
미들웨어
Custom..
액션을 처음으로 다시 되돌릴수도 있다.
액션은 중간에 사라지기도 한다.
미들웨어를 통과한 마지막 액션은
항상 순수한 액션 객체여야 한다.
다음 미들웨어에 액션을 넘기면서 진행된다.
새로운 액션을 만들수도 있다.
미들웨어 안에서 변형되는 다양한 액션들
import	{	browserHistory	}	from	'react-router';	
export	default	store	=>	next	=>	action	=>	{	
		if	(	action.redirect	)	{	
				setTimeout(()	=>	{	
						browserHistory.replace(action.redirect.pathname);	
				},	0);	
		}	
		next(action);	
}	
action.redirect 값이 있으면 

URL을 변경하는 간단한 미들웨어
미들웨어
Thunk
미들웨어
Saga
미들웨어
Custom) . ) .
. ) (
미들웨어 안에서 다양하게 응용되는 상황들
N P I
.
미들웨어
Thunk
미들웨어
Saga
미들웨어
Custom. .
. (
)
A ) R
P I
.
A P I R a R
P RS
RTOC
브라우저(글로벌) 영역
애플리케이션 영역
리덕스 영역
Middleware Control Flow
. E A A E A I - E /
l pSh
/
E E
EC
. )/ )/
pSh MS
( A A
( C A
EC AA
E
E E
/) .
iMS
E
sRf T rk
Pao f
E
Lj
. E A
( A A
C CE
gc
E C CE
/
e
사용자
A
(
Pao
/
e / OP V
EC A
A A
,
Lj
pSh
E EE A
mn
d
bU
A
Lj
EC A
Redux 아키텍처의 이해, 미들웨어
요~오기!
네번째, 비동기 제어
비동기를 제어하는 자가 프로그램을 지배한다.
redux-saga 를 알아보자!
saga는 테스크 단위로 관리한다.
비동기 상황을 제너레이터의 코루틴를 이용해 동기식 작업으로 전환시켜준다.
이건 앞에서 설명했던 그림입니다.
N P I
.
미들웨어
Thunk
미들웨어
Saga
미들웨어
Custom. .
. (
)
A ) R
P I
.
A P I R a R
P RS
RTOC
Saga는 앞에서 설명했던 그림과 유사한 일을 합니다.
N P I
.
Saga
Task
Saga
Task
Saga
Task. .
. (
)
A ) R
P I
.
A P I R a R
P RS
RTOC
Saga 미들웨어 하나로 모든 상황을 제어할수있다.
단, 이 모든 관리는 Generator 코루틴에 대한 이해를 필요로 한다.
정보북을 생성하는 Task를 봅시다.
import	{	put,	call,	select,	take,	fork	}	from	'redux-saga/effects';	
			import	*	as	types	from	‘../actionType/redBookType';	
			... 중략 ...			
function*	postRedBook(	uname,	cityName,	countryName,	coverImage,	geoPoint,	authorId	)	{}	
function*	createRedBookTask()	{	
		while	(	true	)	{	
				const	action	=	yield	take(types.CREATE_REDBOOK);	
				const	{	uname,	cityName,	countryName,	coverImage,	geoPoint,	authorId	}	=	action.payload;	
				const	response	=	yield	postRedBook(uname,	cityName,	countryName,	coverImage,	geoPoint,	authorId);	
				if	(	response.success	)	{	
						yield	put({	type:	types.CREATE_REDBOOK_SUCCESS,	payload:	{	uname,	book:	response.success	}	});	
						yield	put({	type:	types.CLOSE_BOOK	});	
						yield	put({	type:	'SYS_CREATE_DIARYNOTE_BY_REDBOOK',	payload:	{	book:	response.success,	authorId	}	});	
				}	
		}	
}	
export	default	function*()	{	
		return	[	
				yield	fork(loadRedBooksTask),		
				... 중략 ...			
				yield	fork(createRedBookTask),	
		];	
}	
코드를 읽어보세요.
생각해 봅시다.
Redux와 Router 연동 전략
글쓰기 페이지에서 글을 다 쓰면 목록 페이지로 되돌리고 싶다.
글이 제대로 저장되면 이전 화면으로 돌아가고 싶다.
/guide/Flores,Guatemala/notes/create/guide/Flores,Guatemala
컴포넌트 중심의 사고라면 콜백이 참 쉽다.
render()	{	
		.. 코드 중략 ..	
return	(	
<div>	
			.. 코드 중략 ..	
			<Button	onClick={this.handleSubmit}>작성</Button>	
</div>	
)	
}	
handleSubmit	=	(	)	=>	{	
			this.setState(	{loading:	true}	);	
			savePost(	this.state.content,	{		
					success:	()	=>	{	
browserHistory.goBack();	
					},	
					error:	()	=>	{	
this.setState(	{	loading:	false	}	);	
					}	
			});		
}	
하지만 리덕스 아키텍처에서는 비동기 호출은 미들웨어에게 맞긴다.
리덕스 아키텍처에서는 액션을 호출한다.
render()	{	
		.. 앞에서와 동일 코드라 생략 ..	
}	
handleSubmit	=	(	)	=>	{	
			const	{	content	}	=	this.state;	
			this.props.dispatch(	{	type:	‘SAVE_NOTE’	,	payload:	{	content	}	}	);		
}	
그럼 성공했을때 URL은 어디서 바꾸지?
(
)
생각해볼수 있는 전략 4가지
1. 라우터와 리덕스를 동기화 시킨다.
- SAVE_NOTE_SUCCESS 액션을 라우팅 리듀서가 받아서 상태를 바꾸면 알아서 라우더가 변경된다
- 라우팅 리듀서에 매번 액션을 정의 하기가 좀 거시기해…
2. 라우팅 리듀서가 모든 메시지를 모니터하고 있다가 

액션에 redirect payload가 있다면 URL을 변경한다.
- 하지만 미들웨어가 모든 메시지를 모니터하는게 좀 걸려..
3. 특정 비동기 액션이 끝나면 명시적으로 라우팅 액션을 실행한다.
- Saga 라면 이 부분을 좀더 쉽게 할수있겠지
- 미들웨어에서 비동기를 처리하더라도 콜백을 받을수 있기 때문에 쉽게 라우팅 액션 처리가 가능하다.
4. 2번과 3번을 적절히 조합.
- 공통 액션 처리에 대한 공통 라우팅 전략으로 적합하다.
- { type: ‘SAVE_NOTE’, payload: { content }, redirect: { pathname: ‘/guide’ } }
그밖에, 아키텍처에 영향을 주는 결정
스펙 변경
모듈 업데이트 ( webpack, react-router v3 to v4 )
배포 환경의 변화
immutablejs 도입
Flow type checker / typescript 도입
ServerSide Rendering
클라우드 API / GraphQL 도입
Rx / MobiX 등 근간을 이루는 아키텍처 패러다임의 변화
이상 끝!
질문은 메일로… 오프에선 맥주로…
여행기는 페북으로… 여행정보는 알리브로에…
miconblog@gmail.com		
facebook.com/wearemooving	
rlibro.com

Contenu connexe

Tendances

MySQLからPostgreSQLへのマイグレーションのハマリ所
MySQLからPostgreSQLへのマイグレーションのハマリ所MySQLからPostgreSQLへのマイグレーションのハマリ所
MySQLからPostgreSQLへのマイグレーションのハマリ所Makoto Kaga
 
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019confluent
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoTakayuki Shimizukawa
 
CloudWatch(+sns+sqs)で障害対応を自動化してみた
CloudWatch(+sns+sqs)で障害対応を自動化してみたCloudWatch(+sns+sqs)で障害対応を自動化してみた
CloudWatch(+sns+sqs)で障害対応を自動化してみたTerui Masashi
 
超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座Samir Hammoudi
 
Amazon EKS によるスマホゲームのバックエンド運用事例
Amazon EKS によるスマホゲームのバックエンド運用事例Amazon EKS によるスマホゲームのバックエンド運用事例
Amazon EKS によるスマホゲームのバックエンド運用事例gree_tech
 
NY Meetup: Scaling MariaDB with Maxscale
NY Meetup: Scaling MariaDB with MaxscaleNY Meetup: Scaling MariaDB with Maxscale
NY Meetup: Scaling MariaDB with MaxscaleWagner Bianchi
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화sung ki choi
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기SeungYong Oh
 
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 Vienna
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 ViennaAutovacuum, explained for engineers, new improved version PGConf.eu 2015 Vienna
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 ViennaPostgreSQL-Consulting
 
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについて
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについてCentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについて
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについてNobuyuki Sasaki
 
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...NTT DATA Technology & Innovation
 
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...NTT DATA Technology & Innovation
 
基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をしますyoku0825
 
Dockerライフサイクルの基礎 地雷を踏み抜けろ!
Dockerライフサイクルの基礎 地雷を踏み抜けろ!Dockerライフサイクルの基礎 地雷を踏み抜けろ!
Dockerライフサイクルの基礎 地雷を踏み抜けろ!Masahito Zembutsu
 
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판BJ Jang
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...Amazon Web Services Korea
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Nobuhiro Iwamatsu
 

Tendances (20)

MySQLからPostgreSQLへのマイグレーションのハマリ所
MySQLからPostgreSQLへのマイグレーションのハマリ所MySQLからPostgreSQLへのマイグレーションのハマリ所
MySQLからPostgreSQLへのマイグレーションのハマリ所
 
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019
Please Upgrade Apache Kafka. Now. (Gwen Shapira, Confluent) Kafka Summit SF 2019
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for Django
 
CloudWatch(+sns+sqs)で障害対応を自動化してみた
CloudWatch(+sns+sqs)で障害対応を自動化してみたCloudWatch(+sns+sqs)で障害対応を自動化してみた
CloudWatch(+sns+sqs)で障害対応を自動化してみた
 
超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座超実践 Cloud Spanner 設計講座
超実践 Cloud Spanner 設計講座
 
Amazon EKS によるスマホゲームのバックエンド運用事例
Amazon EKS によるスマホゲームのバックエンド運用事例Amazon EKS によるスマホゲームのバックエンド運用事例
Amazon EKS によるスマホゲームのバックエンド運用事例
 
NY Meetup: Scaling MariaDB with Maxscale
NY Meetup: Scaling MariaDB with MaxscaleNY Meetup: Scaling MariaDB with Maxscale
NY Meetup: Scaling MariaDB with Maxscale
 
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
제프리 리처의 Windows via C/C++ : 8장 유저 모드에서의 스레드 동기화
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
 
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 Vienna
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 ViennaAutovacuum, explained for engineers, new improved version PGConf.eu 2015 Vienna
Autovacuum, explained for engineers, new improved version PGConf.eu 2015 Vienna
 
E.G.G.卒業生コメント
E.G.G.卒業生コメントE.G.G.卒業生コメント
E.G.G.卒業生コメント
 
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについて
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについてCentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについて
CentOS 8で標準搭載! 「389-ds」で構築する 認証サーバーについて
 
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
トランザクション処理可能な分散DB 「YugabyteDB」入門(Open Source Conference 2022 Online/Fukuoka 発...
 
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...
Apache Hadoopに見るJavaミドルウェアのcompatibility(Open Developers Conference 2020 Onli...
 
基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします
 
Dockerライフサイクルの基礎 地雷を踏み抜けろ!
Dockerライフサイクルの基礎 地雷を踏み抜けろ!Dockerライフサイクルの基礎 地雷を踏み抜けろ!
Dockerライフサイクルの基礎 地雷を踏み抜けろ!
 
ヤフー社内でやってるMySQLチューニングセミナー大公開
ヤフー社内でやってるMySQLチューニングセミナー大公開ヤフー社内でやってるMySQLチューニングセミナー大公開
ヤフー社内でやってるMySQLチューニングセミナー大公開
 
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판
Open Source GIS 기초교육 4일차 - GeoServer 기초 2014년 7월판
 
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
 
Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料Yocto Project ハンズオン プレゼン用資料
Yocto Project ハンズオン プレゼン用資料
 

En vedette

행복한 원격근무의 조건
행복한 원격근무의 조건행복한 원격근무의 조건
행복한 원격근무의 조건병대 손
 
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기Kim Hunmin
 
오픈소스따라하기
오픈소스따라하기오픈소스따라하기
오픈소스따라하기병대 손
 
프론트엔드 코딩 컨벤션 자동화 도구
프론트엔드 코딩 컨벤션 자동화 도구프론트엔드 코딩 컨벤션 자동화 도구
프론트엔드 코딩 컨벤션 자동화 도구Taegon Kim
 
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기Jae Sung Park
 
암호화 이것만 알면 된다.
암호화 이것만 알면 된다.암호화 이것만 알면 된다.
암호화 이것만 알면 된다.KwangSeob Jeong
 
자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법Minsuk Lee
 
인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템NAVER D2
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기JeongHun Byeon
 

En vedette (9)

행복한 원격근무의 조건
행복한 원격근무의 조건행복한 원격근무의 조건
행복한 원격근무의 조건
 
React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기React로 TDD 쵸큼 맛보기
React로 TDD 쵸큼 맛보기
 
오픈소스따라하기
오픈소스따라하기오픈소스따라하기
오픈소스따라하기
 
프론트엔드 코딩 컨벤션 자동화 도구
프론트엔드 코딩 컨벤션 자동화 도구프론트엔드 코딩 컨벤션 자동화 도구
프론트엔드 코딩 컨벤션 자동화 도구
 
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기
[DEVIEW 2017] 14일만에 GitHub 스타 1K 받은 차트 오픈소스 개발기
 
암호화 이것만 알면 된다.
암호화 이것만 알면 된다.암호화 이것만 알면 된다.
암호화 이것만 알면 된다.
 
자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법자기소개서, 이력서 쓰는 법
자기소개서, 이력서 쓰는 법
 
인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템인공지능추천시스템 airs개발기_모델링과시스템
인공지능추천시스템 airs개발기_모델링과시스템
 
Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기Node.js API 서버 성능 개선기
Node.js API 서버 성능 개선기
 

Similaire à React 애플리케이션 아키텍처 - 아무도 알려주지 않아서 혼자서 삽질했다.

More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinDong Chan Shin
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Ryan Park
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기철민 배
 
안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트병한 유
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스Sungik Kim
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작Taegon Kim
 
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰Eunhyang Kim
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱NAVER D2
 
CRUD Pattern in Ajax
CRUD Pattern in AjaxCRUD Pattern in Ajax
CRUD Pattern in AjaxRhio Kim
 
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁창규 김
 
[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어NAVER D2
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Nam Hyeonuk
 
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내Tae-Seong Park
 
센차 터치2 시작하기 | Devon 2012
센차 터치2 시작하기 | Devon 2012센차 터치2 시작하기 | Devon 2012
센차 터치2 시작하기 | Devon 2012Daum DNA
 
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)YoungSu Son
 

Similaire à React 애플리케이션 아키텍처 - 아무도 알려주지 않아서 혼자서 삽질했다. (20)

More effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshinMore effective c++ chapter1 2_dcshin
More effective c++ chapter1 2_dcshin
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
React 실무활용 이야기
React 실무활용 이야기React 실무활용 이야기
React 실무활용 이야기
 
안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스NDC11_김성익_슈퍼클래스
NDC11_김성익_슈퍼클래스
 
Modern android
Modern androidModern android
Modern android
 
React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작React Native를 사용한
 초간단 커뮤니티 앱 제작
React Native를 사용한
 초간단 커뮤니티 앱 제작
 
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰
WTM 2018 2개월차 신입 백엔드 개발자의 따끈따끈 개발 썰
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱
 
CRUD Pattern in Ajax
CRUD Pattern in AjaxCRUD Pattern in Ajax
CRUD Pattern in Ajax
 
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁
R.java가 사라졌어요 어떻하죠?:Aquery라이브러리와 안드로이드 개발팁
 
RxJava in Looky
RxJava in LookyRxJava in Looky
RxJava in Looky
 
[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약
 
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 
센차 터치2 시작하기 | Devon 2012
센차 터치2 시작하기 | Devon 2012센차 터치2 시작하기 | Devon 2012
센차 터치2 시작하기 | Devon 2012
 
Light Tutorial Django
Light Tutorial DjangoLight Tutorial Django
Light Tutorial Django
 
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)
[NEXT] Android 개발 경험 프로젝트 4일차 (Networking)
 

React 애플리케이션 아키텍처 - 아무도 알려주지 않아서 혼자서 삽질했다.