[알고리즘] 6. 자료구조

1. 자료구조 기본

1.1 컴퓨터 기본 커리큘럽

1.1.1 기본언어

1.1.2 자료구조

1.1.3 알고리즘

1.2 자료구조란?

데이터를 담는 구조

1.3 기본 자료 구조

1.3.1 변수

  • int x=4;

1.3.2 배열

  • int[] arr={0,1,2};
  • 장점: arr[i]번째 수를 바로 일 수 있음.
  • 딘잠: 데이터 넣고 빼기가 힘듬(배열 앞뒤로 다 이동시키고 삽입)

    1.3.3 링크드 리스트

  • 앞의 값이 다음 값을 알고있음
  • 장점: 데이터 넣고 빼기 용이
  • x[i]번째 값 알기 어려움(처음부터 탐색)

2. 기초 자료구조

자료구조가 설계된 목적을 이해해야함

  • 스택
  • 트리
  • 그래프

2.1 스택(Stack)

  • 선형 자료구조
in/out
  • LIFO(Last in first out)
  • push(), .pop(),
  • 스택 오버플로우란 push()할때 할당된 공간이 다 차서 넘치는것
  • 스택언더플로우란 공간에 데이터가 하나도 없을때 pop()하는것

2.1.1 스택 구현

  • push()
  • pop()
  • top()
  • size()

2.2 큐(Quque)

<-out <- in
  • FIFO(First in first out)
  • push(), .pop(),
  • 스택 오버플로우란 push()할때 할당된 공간이 다 차서 넘치는것
  • 스택언더플로우란 공간에 데이터가 하나도 없을때 pop()하는것

  • 큐의 문제점 : 공간활용이 안좋음 >> 해결 원형큐

2.2.1 원형큐

배열 공간을 원형으로 만들어서 함

2.2.2 큐 활용문제 예시

괄호가 올바른지 판단하기

2.3 트리(Three)

  • root
  • 노드(정점)
  • 간선
  • 트리의 재귀적성질

2.3.1 트리순회

  • 전위순회 : root-Left-Right
  • 중위순회 : Left-Root-Right
  • 후위순회 : Left-Right-Root

2.4 우선순의 큐

  • 큐에 넣고 우선순위가 높은것 순으로 뽑기
  • 배열을 이용한 우선순의 큐는 뽑고 다시채워야 해서 O(n^2)걸림->느림

2.4 힙(Heap)

부모값이 항상 자식보다 작은 이진트리

아래 트리에 4를 추가한다고 하면.

3
5 7
23 7 9 null

–4추가

3
5 7
23 7 9 4

4랑 7비교 4랑 7변경

3
5 4
23 7 9 7

4랑 3비교 유지 > 정렬끝!!

3
5 4
23 7 9 7

2.4.1 힙의 삽입의 시간복잡도

완전 이진트리의 높이

노드수 높이
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4

노드의 개수가 n개일때의 높이 = logn

2^n-1

  • 힙 값 삽입의 시간복잡도=> O(logn)
  • 힙 값 삭제의 시간복잡도 => O(logn)

[알고리즘] 5. 고급 정렬(합병정렬, 퀵정렬)

1. 로그 개념과 효율성

log2 16=4;
logx y = N;
x^n=y;
nlog n <- n이커질수록 o(n)과 속도 차이가 크다

2. 고급정렬 종류

2.1 합병정렬

정렬할 값을 반으로 나눠 각각 정렬 후 두 정렬을 크기순으로 합침

2.1.1 고급정렬 예제

1) 아래 배열 정렬

4 14 8 23 11

2) 반으로 나누기->각 값이 하나씩 있을때까지

4 14 8 3 23 11
4 14 8 3 23 11
4 14 8 3 23 11

3) 각각 크기순으로 배열 합치기

4 14 8 3 23 11
4 8 14 3 11 23
3 4 8 11 14 23

2.1.2 합병정렬 시간복잡도

1) 왼쪽 /오른쪽 합병정렬 T(n/2) +T(n/2) => n
2) 두 배열 합치기 o(n)
3) T(n)=2*T(n/2)+O(n)
이걸 풀면…
T(n)=O(nlogn)

2.1.3 합병정렬 재귀함수 디자인

1) 함수 정의
2) 기저조건 s>=e이면 retrun
3) mearge(arr, s, e)
mearge(arr, s, mid)
mearge(arr, mid+1, e)

2.1.4 합병정렬 구현

1
2


2.2 퀵정렬

임의의 값 하나를 기준으로 기준값보다 큰건 오른쪽 작은건 왼쪽으로 보내기

2.2.1 예시

1) 아래 배열 퀵정렬

3 1 5 4 2

2) 배열 제일 앞숫자3 기준 정렬

1 2 3 5 4

3-1) 3기준 앞 배열 제일 앞 숫자1로 정렬

1 2 3 5 4

3-2) 3기준 뒤 배열 중 가장 앞 숫자 5기준으로 정렬

1 2 3 5 4

2.2.2 퀵정렬 시간복잡도

평균적으로는 O(nlogn) 가장 오래 걸리면 O(n^2)

2.2.3 퀵정렬 구현

1
2


2.3 힙정렬

트리구조를 이용한 정렬 나중에 나옴!

[알고리즘] 4. 재귀함수

1. 재귀함수

자기자신을 부르는 함수

1.2 재귀함수가 의미있는 예제

  • 펙토리얼 n! = n(n-1)(n-2)…*1
    1
    2
    3
    4
    int getFactorial(int n){
    if(n==1) return 1;
    else return n*getFactorial(n-1);
    }

함수 호출 흐름

  1. main에서 getFactorial(3) 호출된다고 가정.
  2. getFactorial(3)에서
    3*getFactorial(2)리턴
  3. getFactorial(2)에서
    2*getFactorial(1) 리턴
  4. getFactorial(1)에서 1리턴
  5. 123 도출

1.2 두가지 계산반벙

1.2.1 순차적 계산방법

A를 계산, A를 이용해서 B를 계산, B를 이용해서 C를 계산..
n!=n(n-1)…1

1.2.2 귀납적 계산방법

구하려고 하는 값은 f(x) f(x)를 구하기 위해 또 f(x)를 활용함
n!= 5f(4)
n!=5
4f(3)

n! = 5
432*f(1)

  • n의 m제곱을 귀납적으로 정의
    n^m = nn^(m-1)

    n^m = n
    nn..n^0

1.3 수납적 귀납법

명제 p(n)이 모든 n에 성립함을 증명.
p(k)가 성립한다고 가정후 p(k+1)이 성립함을 증명.

2 재귀함수 디자인

2.1 3가지 절차

1) 함수의 역할을 명확하게 정의

2) 기저조건에서 함수가 제대로 동작함을 보임

3) 함수가 제대로 동작한다고 가정하고 함수를 완성

2.2 재귀함수 구현

2.2.1 n의 m제곱

1) getPower(n,m)은 n의 m승을 반환하는 함수이다.

ex) getPower(2,4)=16

2) 기저조건 getPower(n,0)=1
3) getPower(n,m)=n * getPower(n, m-1)

2.2.2 이진수 출력하기

1) pringBin(x)는 X를 이진수로 바꿔출력하는 함수
2) 기저조건 printBin(1)=1, printBin(0)=0
3) printBin(x)={ print(x/2); print(x%2);}

2.2.3 펠린드롬인지 판별하기

  • 펠린드롬은 좌우 대칭인 값을 말함
    1) isPal(String, start, end)
    2) 기저조건: start==end isPal(String, start, end)=true;
    3) isPal(String, start, end)
    if(String.start==String.end) return isPal(String, start+1, end-1);
    else return false;

[알고리즘] 3. 정수(Integer)

1. 정수

1.1 약수

특정 수를 나누어 떨어지게 하는 수

1.1.1 약수 구하기 구현

1.2 소수

약수가 1과 자기자신인 수

1.2.1 소수 구하기 구현

1.2.2 에라토스테네스의 체(소수 구하기) 구현

1.3 소인수 분해

숫자N을 소수의 곱으로 나타냄

1.3.1 구현

1.4 공약수와 공배수

A,B 공약수, A와 B의 공통된 약수
AB 공배수 A와 B의 공통된 배수

1.4.1 최대공약수(GCD), 최소공배수(LCM)

1.4.2 유클리드 호제법

a, b, r(a/b)
b, r(a/b) , r(b, r(a/b))
… a, b, r==0일때, b 가 최대공약수

1.4 파스칼 삼각형

1
2
3
4
5
1
121
1331
3C0, 3C1, 3C2, 3C3
14641

콤비네이션 값 구할때 사용(20C11)

[알고리즘] 2. 시간복잡도

1. 시간복잡도

문제가 얼마나 빠르게 해결되는지 나타냄
대략적으로 몇개의 명령을 수행하는지?

1.1 for문

1
2
3
for(int i=0 ; i<n; i++){
int a=0;
}

int a=0;명령을 n번 수행 >> 시간복잡도 O(n)

1.2 n*n 이중for문

1
2
3
4
5
for(int i=0 ; i<n; i++){
for(int j=0 ; j<n; j++){
int a=0;
}
}

int a=0;명령을 n*n번 수행 >> 시간복잡도 O(n^2)

1.3 n(n-1)(n-2) …2*1 이중for문

1
2
3
4
5
for(int i=0 ; i<n; i++){
for(int j=0 ; j<i; j++){
int a=0;
}
}

int a=0;명령을 n(n-1)/2번 수행 >> 1/2nn >> 상수는 무시 >> 시간복잡도 O(n^2)

1.4 if절 있는 for문

1
2
3
4
5
for(int i=0 ; i<n; i++){
if(i==1){
int a=0;
}
}

최악의 경우 n번 수행(if절 결과에 따라) > O(N)
최고차항만 체크

2. 입력크기에 따른 수행시간

  1. n의 입력 값에 따라 수행시간 다름
  2. 컴퓨터 사양에 따라 다름

2.1 O(N) 시간복잡도

  • n이 9000만개일때 보통 1초

2.2 O(N^2) 시간복잡도

  • n이 10000개일때 보통 1초 > 명령어 실행수 대략 1억에 1

3. 정렬의 시간복잡도

3.1 선택정렬

최소값 1번 찾는데 O(N)번 * N번 > O(n^2)

3.2 삽입정렬

원소 하나 삽입 시 O(N)걸림 * N번 > O(n^2)

3.3 버블 정렬

인접한 원소 비교해서 뒤로 보냄 O(n) 걸림 * n번 > O(n^2)

  • 선택, 삽입, 버블 정렬은 시간복잡도가 안 좋은편!!

[알고리즘] 1. 정렬 기초(선택정렬, 삽입정렬, 버블정렬)

1.정렬

오름차순, 내림차순

1.1 정렬의 종류

  1. 선택정렬
  2. 삽입정렬
  3. 버블정렬

1.1.1 선택정렬 예시

배열을 순서대로 탐색하면서 최소값을 앞으로 이동시킴

0) 주어진 배열
2 5 6 7 1 3
1) 첫번째 정렬(1과 2 자리변경)
1 5 6 7 2 3
2) 두번째 정렬(배열2부터 최소값찾기/2와 5자리 변경)
1 2 6 7 5 3
3) 세번째 정렬(배열3부터 최소값찾기/3와 6자리 변경)
1 2 3 7 5 6
4) 네번째 정렬(배열4부터 최소값찾기/5와 7자리 변경)
1 2 3 5 7 6
5) 다섯번째 정렬(배열5부터 최소값찾기/6와 7자리 변경)
1 2 3 5 6 7
6) 선택정렬끝!!

1.2.1 삽입정렬

기준 배열과 나머지 배열 비교하여 작은것 것을 앞으로 바꿈

ex)

0) 주어진 배열
2 5 9 1 6
1) 첫번째 정렬

(2와 5비교 유지)

2 5 9 1 6

(2와 9비교 유지)

2 5 9 1 6

(2와 1비교 1과 2위치 변경)

1 5 9 2 6

(1과 6비교 유지)

1 5 9 2 6
2) 두번째 정렬(배열2부터 최소값찾기/2와 5자리 변경)

(5와 9비교 유지)

1 5 9 2 6

(5와 2비교 자리변경)

1 2 9 5 6

(2와 6비교 유지)

1 2 9 5 6
3) 세번째 정렬(배열3부터 최소값찾기/3와 6자리 변경)

(5와9비교 유지)

1 2 5 9 6

(5와 6비교 유지)

1 2 5 9 6
4) 네번째 정렬(배열3부터 최소값찾기/3와 6자리 변경)

(9와9비교 변경)

1 2 5 6 9
5) 삽입정렬끝!!

1.3.1 버블정렬

인접한 두 원소 비교 해서 큰 수를 뒤로 보냄

ex)

0) 주어진 배열
3 2 5 1 4
1) 첫번째 정렬

(3과 2비교 자리 바꿈)

2 3 5 1 4

(3과 5비교 유지)

2 3 5 1 4

(5와 1비교 자리 변경)

2 3 1 5 4

(5와 4비교 변경 > 5자리 확정)

2 3 1 4 5
2) 두번째 정렬

(2와 3비교 유지)

2 3 1 4 5

(3와 1비교 자리변경)

2 1 3 4 5

(3와 4비교 유지 > 4자리 확정)

2 1 3 4 5
3) 세번째 정렬

(2와1비교 변경)

1 2 3 4 5

(2와 3비교 유지 > 3자리 확정)

1 2 3 4 5
4) 네번째 정렬

(1와2비교 유지 > 2자리 확정)

1 2 3 4 5
5) 버블정렬끝!!

[Hexo와 깃허브로 블로그 만들기] 블로그에 layout 만들어 빠른 포스팅 하기

1. /scaffolds 파일 아래 blog.md 파일을 만든다.

원하는 형식으로 Front-Matter부분을 수정한다.

1
2
3
4
5
6
7
8
9
10
11
12

---
title: {{ title }}

categories:
[tec, blog]
tags:
[blog, tec, hexo, github]

toc: true
date: {{ date }}
---

2. 커멘드 창에서 (프로젝트 위치아래에서) 아래와 같이 명령어를 입력한다.

1
$ hexo new blog -p tec/blog/blog13 "레이아웃 만들기"
  • blog: 아까 scaffolders에서 만든 레이아웃 파일명
  • -p: 경로명
  • “레이아웃만들기”: title안에 들어갈 내용
    명령어 옵션 참고

3. /source/_posts/tec/blog/blog13.md 파일이 생성된 것을 확인 할 수있다.

1
2
3
4
5
6
7
8
9
10

---
title: "레이아웃 만들기"
categories:
[tec, blog]
tags:
[blog, tec, hexo, github, google-analytics]
toc: true
date: 2019/10/18 13:09:23
---

4. 해당 파일에 원하는 글을 써서 배포한다.

[React 교과서] 6장 React 에서 이벤트 다루기

리엑트 교과서를 정리한 내용입니다.

6.1 React에서 DOM이벤트 다루기

아래 예제 코드는 이벤트 리스너에서 this를 콘솔에 표시하도록 한 코드. 여기서 event 객체는 내장 DOM이벤트를 객체를 개선한 것으로 합성 이벤트라고 부름

1
2
3
4
5
<button onclick={(function(event){
console.log(this.event)
}).bind(this)}>
Save
</button>

아래 경우에 bind(tnis)로 바인딩하지 않는다.

  • this를 이용해서 해당 클래스를 참조 할 필요가 없을때
  • ES6+ 클래스 대신 예쩐방식인 React.createClass()를 사용할때. 이때는 createClass()가 자동으로 바인딩함.
  • 화살표 함수(() => {})를 사용할 때

Reaact버전 15에서 지원하는 DOM 이벤트

이벤트 분류 React가 지원하는 이벤트
마우스 이벤트 onClick, onContentMenu,
onDoubleClick, onDrag,
onDragEnd, onDragEnter,
onDragExit, onDragLeave,
onDragOver, onDragStart,
onDrop, onMouseDown,
onMouseEnter, onMouseLeave,
onMouseMove, onMouseOut,
onMouseOver, onMouseUp
키보드 이벤트 onKeyDown, onKeyPress, onKeyup
클립보드 이벤트 onCopy, onCut, onPaste
폼 이벤트 onChange, onInpute,
onSubmit, onTnvalid
포커스 이벤트 onFocus, onBlur
터치 이벤트 onTouchCancel, onTouchEnd,
onTouchMove, onTouchStart
UI이벤트 onScroll
휠 이벤트 onWheel
영역선택 이벤트 onSelect
이미지 이벤트 onLoad, onError
애니메이션 이벤트 onAnimationStart, onAnimationEnd,
onAnimationIteration
트랜지션 이벤트 onTransitionEnd

6.1.1 캡쳐 및 버블링 단계

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Mouse extends React.Component {
render() {
return <div>
<div
style={{border: '1px solid red'}}
onMouseOverCapture={((event)=>{
console.log('mouse over on capture event')
console.dir(event, this)}).bind(this)}
onMouseOver={((event)=>{
console.log('mouse over on bubbling event')
console.dir(event, this)}).bind(this)} >
Open DevTools and move your mouse cursor over here
</div>
</div>
}
}

6.1.2 React이벤트 살펴보기

6.1.3 React 합성 이벤트 객체 다루기

1
2
3
4
5
6
7
8
9
10
11
12
13
class Mouse extends React.Component {
render() {
return <div>
<div
style={{border: '1px solid red'}}
onMouseOver={((event)=>{
console.log('mouse is over with event')
console.dir(event)}).bind(this)} >
Open DevTools and move your mouse cursor over here
</div>
</div>
}
}

6.1.4 이벤트와 상태 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Content extends React.Component {
constructor(props) {
super(props)
this.state = {counter: 0}
}
handleClick(event) {
this.setState({counter: ++this.state.counter})
}
render() {
return (
<div>
<button
onClick={this.handleClick.bind(this)}
className="btn btn-primary">
Don't click me {this.state.counter} times!
</button>
</div>
)
}
}

6.1.5 이벤트 핸들러를 속성으로 전달하기

1
2
3
4
5
6
7
8
9
class ClickCounterButton extends React.Component {
render() {
return <button
onClick={this.props.handler}
className="btn btn-danger">
Increase Volume (Current volume is {this.props.counter})
</button>
}
}

6.1.6 컴포넌트 간의 데이터 교환

1
2
3
4
5
6
7
8
9
class ClickCounterButton extends React.Component {
render() {
return <button
onClick={this.props.handler}
className="btn btn-info">
Don't touch me with your dirty hands!
</button>
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Content extends React.Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
this.state = {counter: 0}
}
handleClick(event) {
this.setState({counter: ++this.state.counter})
}
render() {
return (
<div>
<ClickCounterButton handler={this.handleClick}/>
<br/>
<Counter value={this.state.counter}/>
</div>
)
}
}

6.2 React가 지원하지 않는 DOM이벤트 처리하기

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Radio extends React.Component {
constructor(props) {
super(props)
this.handleResize = this.handleResize.bind(this)
let order = props.order
let i = 1
this.state = {
outerStyle: this.getStyle(4, i),
innerStyle: this.getStyle(1, i),
selectedStyle: this.getStyle(2, i),
taggerStyle: {top: order*20, width: 25, height: 25}
}
}
getStyle(i, m) {
let value = i*m
return {
top: value,
bottom: value,
left: value,
right: value,
}
}
componentDidMount() {
window.addEventListener('resize', this.handleResize)
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
}
handleResize(event) {
let w = 1+ Math.round(window.innerWidth / 300)
this.setState({
taggerStyle: {top: this.props.order*w*10, width: w*10, height: w*10},
textStyle: {left: w*13, fontSize: 7*w}
})
}
render() {
return <div>
<div className="radio-tagger" style={this.state.taggerStyle}>
<input type="radio" name={this.props.name} id={this.props.id}>
</input>
<label htmlFor={this.props.id}>
<div className="radio-text" style={this.state.textStyle}>{this.props.label}</div>
<div className="radio-outer" style={this.state.outerStyle}>
<div className="radio-inner" style={this.state.innerStyle}>
<div className="radio-selected" style={this.state.selectedStyle}>
</div>
</div>
</div>
</label>
</div>
</div>
}
}

6.3 React를 다른 라이브러리와 통합하기: jQurey UI이벤트

6.3.1. 버튼 통합하기

방법1 jQuery슬라이더를 위한 이벤트를 React컴포넌트에서 등록하는 방법

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
31
32
33
34
35
36
37
class SliderButtons extends React.Component {
constructor(props) {
super(props)
this.state = {sliderValue: 0}
this.handleSlide = this.handleSlide.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSlide(event, ui) {
this.setState({sliderValue: ui.value})
}
handleChange(value) {
return ()=> {
$('#slider').slider('value', this.state.sliderValue + value)
this.setState({sliderValue: this.state.sliderValue + value})
}
}
componentDidMount() {
$('#slider').on('slide', this.handleSlide)
}
componentWillUnmount() {
$('#slider').off('slide', this.handleSlide)
}
render() {
return <div>
<button disabled={(this.state.sliderValue<1) ? true : false}
className="btn default-btn"
onClick={this.handleChange(-1)}>
1 Less ({this.state.sliderValue - 1})
</button>
<button disabled={(this.state.sliderValue>99) ? true : false}
className="btn default-btn"
onClick={this.handleChange(1)}>
1 More ({this.state.sliderValue + 1})
</button>
</div>
}
}

6.3.2 라벨 통합하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class SliderValue extends React.Component {
constructor(props) {
super(props)
this.handleSlide = this.handleSlide.bind(this)
this.state = {sliderValue: 0}
}
handleSlide(event) {
this.setState({sliderValue: event.detail.ui.value})
}
componentDidMount() {
window.addEventListener('slide', this.handleSlide)
}
componentWillUnmount() {
window.removeEventListener('slide', this.handleSlide)
}
render() {
return <div className="" >
Value: {this.state.sliderValue}
</div>
}
}

[React 교과서] 5장 React 컴포넌트 라이프사이클 이벤트

리엑트 교과서를 정리한 내용입니다.

5.1 React컴포넌트 라이프사이클 이벤트 한눈에 살펴보기

라이프사이클 이벤트를 기반으로 컴포넌트의 동작을 제어하고 사용자 정의를 할 수 있다.

  • 마운팅 이벤트 : React엘리먼트를 DOM 노드에 추가할때 발생
  • 갱신 이벤트 : 속성이나 상태가 변경되어 React엘리먼트를 갱신할 때 발생
  • 언마운팅이벤트 : React엘리먼트를 DOM에서 제거할때 발생

5.2 이벤트 분류

  • 마운팅 : React가 이벤트를 한번만 실행
  • 갱신: React가 이벤트를 여러번 실행
  • 언마운팅: React가 이벤트를 한번만 실행

아래 순서로 라이플 사이클이 실행된다

  1. constructor() : 엘리먼트를 생성하여 기본속성과 상태를 설정할때 실행
  2. 마운팅
    • componentWillMount(): DOM에 삽입전에 실행
    • componentDidMount(): DOM에 삽입 후에 실행
  3. 갱신
    • componentWillRecetiveProps(nextProps) : 컴포넌트가 속성을 받기 직전에 실행
    • shouldComponentUpdate(nextProps, nextState) : 컴포넌트가 갱신되는 조건을 정의해서 재렌더링을 초적화함. boolean값을 반환
    • componentWillUpdate(nextProps, nextState) : 컴포넌트가 갱신되기 직전에 실행
    • componentDidUpdate(prevProps, prevState) : 컴포넌트가 갱신된 후에 실행
  4. 언마운팅
    • componentWillUnmount() : 컴포넌트를 DOM에서 제거하기 전에 실행, 구독한 이벤트를 제거하거나 다른 정리 작업 수행 가능
  • 라이플사이클 이벤트와 속성 및 상태의 상관관계
마운팅 컴포넌트 속성 갱신 컴포넌트 상태 갱신
constructor()
componentWillMount() componentWillRecetiveProps()
shouldComponentUpdate() shouldComponentUpdate()
componentWillUpdate() componentWillUpdate()
render() render() render()
componentDidUpdate() componentDidUpdate()
componentDidMount()
forceUpdate()를 이용한 갱신 언마운팅
componentWillUpdate()
render()
componentDidUpdate()
componentWillUnmount()

5.3 이벤트 구현

라이프사이클 이벤트를 구현하려면 클래스에 메서드를 정의해야함.
ex) componentDidMouht()를 정의하면 컴포넌트 클래스의 엘리먼트가 DOM에 추가되었을때 이 메서드 호출하고 마운팅으로 분류 되어있으므로 컴포넌트 클래스의 인스턴스마다 한번만 호출됨.

1
2
3
4
5
6
7
8
9
10
11
12

class Content extends React.Component {
componentWillMount(){
console.log(ReactDOM.findDOMNode(this)) // DOM 노드가 null
}
componentDidMount(){
console.dir(ReactDOM.findDOMNode(this)) // DOM 노드가 <div>
}
render(){
return()
}
}
  • DOM은 늘 대문자로 쓴다.

5.4 모든 이벤트 실행하기

  • Logger컴포넌트의 렌더링과 세번의 갱신 실행 코드
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class Content extends React.Component {
    constructor(props) {
    super(props)
    this.launchClock()
    this.state = {
    counter: 0,
    currentTime: (new Date()).toLocaleString()
    }
    }
    launchClock() {
    setInterval(()=>{
    this.setState({
    counter: ++this.state.counter,
    currentTime: (new Date()).toLocaleString()
    })
    }, 1000)
    }
    render() {
    if (this.state.counter > 2) return <div/>
    return <Logger time={this.state.currentTime}></Logger>
    }
    }
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
31
32
33
34
35
36
37
38
39
40
41
42
class Logger extends React.Component {
constructor(props) {
super(props)
console.log('constructor')
}
componentWillMount() {
console.log('componentWillMount is triggered')
}
componentDidMount(e) {
console.log('componentDidMount is triggered')
console.log('DOM node: ', ReactDOM.findDOMNode(this))
}
componentWillReceiveProps(newProps) {
console.log('componentWillReceiveProps is triggered')
console.log('new props: ', newProps)
}
shouldComponentUpdate(newProps, newState) {
console.log('shouldComponentUpdate is triggered')
console.log('new props: ', newProps)
console.log('new state: ', newState)
return true
}
componentWillUpdate(newProps, newState) {
console.log('componentWillUpdate is triggered')
console.log('new props: ', newProps)
console.log('new state: ', newState)
}
componentDidUpdate(oldProps, oldState) {
console.log('componentDidUpdate is triggered')
console.log('old props: ', oldProps)
console.log('old state: ', oldState)
}
componentWillUnmount() {
console.log('componentWillUnmount')
}
render() {
console.log('rendering... Display')
return (
<div>{this.props.time}</div>
)
}
}

5.5 마운팅 이벤트

마운팅 이벤트 유형은 실제 DOM에 컴포넌트를 추가하는 것에 대한 이벤트다.

  • componentWillMount(): React엘리먼트가 실제 DOM에 곧 추가 될 것을 알림
  • componentDidMount(): React엘리먼트를 실제 DOM에 추가한 시전으로, 이 시점의 React엘리먼트는 DOM노드임.
    *constructor()는 componentWillMount()보다 먼저 실행됨.

5.5.1 componentWillMount()

초기 렌더링 직전에 실행됨. 브라우저와 프론트엔드에서 이루어짐.
서버 렌더링 과정에서도 componentWillMount()는 실행됨.

5.5.2 componentDidMount()

초기렌더링 마친 후 실행됨. 브라우저에서 한번 실행되고 서버렌더링에서는 실행 안 됨.
자식엘리먼트를 참조로 접근할 수 있음. 자식 컴포넌트의 componentDidMount()는 부모 컴포넌트의 componentDidMount()보다 먼저 호출됨

componentDidMount() 이벤트는 다른 라이브러리를 통합하기 가장 적절한 위치임.

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
class Users extends React.Component {
constructor(props) {
super(props)
this.state = {
users: [] // 이렇게 초기화 해놔야 render()에서 해당 상태가 존재하는지 안 하는지 신경 안쓸 수 있음
}
}
componentDidMount() {
fetch(this.props['data-url'])
.then((response)=>response.json())
.then((users)=>this.setState({users: users}))
}
render() {
return <div className="container">
<h1>List of Users</h1>
<table className="table-striped table-condensed table table-bordered table-hover">
<tbody>{this.state.users.map((user)=>
<tr key={user.id}>
<td>{user.first_name} {user.last_name}</td>
<td> {user.email}</td>
<td> {user.ip_address}</td>
</tr>)}
</tbody>
</table>
</div>
}
}

XHR 요청을 위한 코드를 componentDidMount()에 사용하는 것이 좋음

5.6 갱신 이벤트

마운팅 이벤트는 React를 다른 프레임워크나 라이브러리 데이터 저장소와 연결하는데 사용하곤 함.
갱신 이벤트는 컴포넌트를 갱신하는것과 관련됨.

  1. componentWillRecivierProps(newProps)
  2. shouldComponentUpdate()
  3. componentWillIpdate()
  4. componentDidUpdate()

5.7 언마운팅 이벤트

DOM에서 요소를 분리하거나 제거하는것

5.7.1 componentWillUnmount()

DOM에서 컴포넌트가 제거되기 직전 호출.
ex)타이머 제거하거나 DOM요소 정리하거나, componentDidMount()에서 연결한 이벤트 제거 등.

[React 교과서] 4장 React 컴포넌트의 객체 상태

리엑트 교과서를 정리한 내용입니다.

리엑트에서 가장 중요한 부분이다.

4.1 React컴포넌트의 상태란?

React의 상태는 컴포넌트의 변경 가능한 데이터 저장소이다.
컴포넌트를 속성과 상태가 있는 함수라고 생각하면 함수의 결과가 UI표현(뷰)이다.
속성과 상태는 모두 뷰를 갱신하기 위해 사용하지만 목적이 다름.

  • 상태:
    상태는 이름을 활용하여 접근함. this.state 객체속성 ex) this.state.inputFileValue
    뷰의 랜더링이 갱신될 때 동적 정보를 출력하기 위해 사용됨.
    관련된 부분만 갱신됨.

아래 안티 패턴 예시
상태 외의 다른 값을 변경해도 뷰를 갱신할 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let inputValue ='Texas'
class Autocomplete extends React.Component {
updateValues(){ //--사용자 입력에 의해 실행됨
this.props.inputValue = 'California'
inputValue ='California'
this.inputValue='California'

}
render(){
return(
<div>
{this.props.inputValue}
{inputValue}
{this.inputValue}
</div>
)
}
}

속성은 부모 컴포넌트에서 새로운 값을 전달하면 뷰를 갱신하여 현재 다루는 자식 컴포넌트의 새로운 인스턴스를 생성함.
해당 자식 컴포넌트의 컨텍스트내에서 this.props.inputValue=’California’로 변경해도 소용이 없음!

4.2 상태 객체 다루기

4.2.1 상태 객체에 접근하기

맴버변수로 this 를 통해 접근 가능. this.state.name와 같은 방식으로 접근.
render()에서 this.state를 랜더링 할 수 있음. ex) {this.state.inputFieldValue}

  • 현재 시간 출력하는 시계 구현하기
    • 폴더 구조
      /clock
      index  
      
      /jsx
      script.jsx  
      clock.jsx  
      
      /js
      script.js  
      clock.js  
      react.js  
      react-dom.js  
      
1
2
3
4
5
6
7
8
9
10
11

class Clock extends React.Component{
render(){
return <div>{this.state.currentTime}</div>
}
}

ReactDOM.render(
<Clock/>
document.getElementById('content')
)

위와 같이 하면 ‘currentTime’ 값이 null이라는 오류가 발생한다.
속성과 달리 상태는 부모 객체에서 설정하는것이 아니고 render()안에서 setState를 실행 할 수도 없다.

4.2.2 초기 상태 설정하기

초기 상태를 설정하려면 React.Component를 사용하는 ES6클래스의 생성자에서 this.state를 선언함. 반드시 super()에 속성을 전달하여 실행한다.

1
2
3
4
5
6
7
8
9
class MyFancyComponent extends React.Component{
constructor(props){
super(props)
this.state = {...}
}
render(){
...
}
}

초기 상태를 설정하면서 다른 로직도 추가 가능.
ex) new Date()를 사용하여 currentTime 값을 설정함. toLocaleString()을 사용하면 상용자 위치에 맞는 적절한 날짜시간 형식을 보여줄 수 있음.

1
2
3
4
5
6
7
class Clock extends React.Component{
constructor(props){
super(props)
this.state={currentTime: (new DAte()).toLocaleString('en')}
}
...
}

초기 상태 주의사항

  • this.state는 반드시 객체여야함.
  • 생성자 메서드의 이름은 반드시 constructor로 함.
  • 부며 클래스가 있는 클래스에서 construtcor()매서드를 생성하면 항상 super()를 호출함.
  • 상속으로 클래스를 구현하면 constructor()매서드를 따로 작성하지 않으면 super()를 호출한것으로 가정함.
  • constructor()메서드 내에서 한번만 this.state로 직접 상태를 선언하고 그 외 부분에서는 this.stat=…로 직접 상태 선언하지 않는다.

4.2.3 상태 갱신하기

클래스 매서드인 this.setState(data, callback)를 사용하면 상태 변경 가능.
data를 현재 상태에 병합하고 render()을 호출, 이후 callback함수 실행됨.
setState()가 비동기로 작동함.

시계를 시작하려면 setInterval()을 한번 호출해야함.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Clock extends React.Component{
counstructor(props){
super(props)
this.lauchClock()
this.state ={
currentTime: (new DAte()).toLocaleString('en')
}
}
launchClock(){
setInterval(()=> {
console.log('Updating time...')
this.setState({
currentTime: (new Date()).toLocaleString('en')
})
}, 1000)
}
render() {
console.log('Rendering Clock...')
return <div>{this.state.currentTime}</div>
}
}

setState()로 상태를 교체할때 상태 항목이 여러개 있으면 명시해준것만 바뀌고 나머진 값이 그대로임.
setState()가 render()를 실행시킴.

4.3 상태 객체와 속성

상태 객체와 속성은 모두 클래스의 맴버이며 각각 this.state와 this.props를 말함.

  • 상태 객체 vs 속성 객체
    • 상태 객체는 변경가능, 속성 객체는 변경 불가능.
    • 상태는 해당 컴포넌트 자체에서 정의, 속성은 부모 컴포넌트에서 전달(부모컴포넌트에서만 값을 변경 가능함).
    • 상태는 컴포넌트에서 설정되고 갱신, 속성은 뷰 생성시에 정해지고 변경안됨.

4.4 상태비저장 컴포넌트

  • 상태비저장 컴포넌트는 상태 객체가 없고 이벤트 또는 메서드를 갖지 않음.
  • 상태비저장 컴포넌트의 목적은 뷰를 랜더링 하는것 뿐임.
  • 속성을 전달받아 처리.
  • 예측하기 편해서 이해, 유지보수, 디버깅이 편함.
    => 상태비저장컴포넌트 많이 사용하고 상태저장컴포넌트는 적게 사용하는게 바람직함.

아래는 상태비저장 컴포넌트 예제

1
2
3
4
5
class HelloWorld extends React.Component{
render(){
return <h1{...this.props}> Hello{ this.props.frameworkName} world!!!</h1>
}
}

상태가 필요하지 않으면 함수로 선언하면됨.

1
2
3
4
5
6
7
8
9
10
functipn Link(props){
return <a href ={props.href} target="_blank" className="btn btn-primary">
{props.text}</a>
}

ReactDOM.render(
<Link text ='Buy React Quickly'
href ='https://www.manning.com/books/react-quickly' />,
document.getElementById('content')
)

1
2
3
4
5
6
7
8
9
const Link = (props)=>{
return (
<href={props.href}
target ="_blank"
className="btn btn-primary" >
{props.text}
</a>
)
}

상태비저장 컴포넌트는 상태를 가질 수 없지만 propTypes와 defaultProps를 프로퍼티로 가질 수 있다.

1
2
3
4
5
6
7
8
9
10
function Link (props){
return <a href = {props.href}
target="_blank"
className="btn btn-primary">
{props.text}
</a>
}

Link.propTypes={...}
Link.defaultProps={...}

4.5 상태비저장 컴포넌트와 상태저장 컴포넌트의 비교

HTML 렌더링을 처리하는것으로 충분한 경우 상태비저장 컴포포넌트가 더 선언적이고 작동이 잘됨.

  • 상태를 사용해야 하는 경우

    • UI 상태, 상호작용, 서버에서 데이터 불러오는것 등 을 관리하려면 상태저장 컴포넌트를 활용한다.
  • 아날로그와 디지털 방식으로 노출하는 시계

    • 프로젝트 구조
      /clock-analog-digital
      /jsx
      analog-display.jsx  
      clock.jsx  
      digital-display.jsx  
      script.jsx  
      
      /js
      analog-display.js  
      clock.js  
      digital-display.js  
      script.js  
      react.js  
      react-dom.js  
      
      /
      index.html
1
2
3
4
5
6
7
8
...
render() {
console.log('Rendering...')
return <div>
<AnalogDisplay time={this.state.currentTime}/>
<DigitalDisplay time={this.state.currentTime}/>
</div>
}
1
2
3
const DigitalDisplay = function(props){
return <div>{props.time}</div>
}
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
const AnalogDisplay = function (props) {
let date = new Date(props.time);
let dialStyle = {
position: 'relative',
top: 0,
left: 0,
width: 200,
height: 200,
borderRadius: 20000,
borderStyle: 'solid',
borderColor: 'black'
};
let secondHandStyle = {
position: 'relative',
top: 100,
left: 100,
border: '1px solid red',
width: '40%',
height: 1,
transform: 'rotate(' + (date.getSeconds() / 60 * 360 - 90).toString() + 'deg)',
transformOrigin: '0% 0%',
backgroundColor: 'red'
};
let minuteHandStyle = {
position: 'relative',
top: 100,
left: 100,
border: '1px solid grey',
width: '40%',
height: 3,
transform: 'rotate(' + (date.getMinutes() / 60 * 360 - 90).toString() + 'deg)',
transformOrigin: '0% 0%',
backgroundColor: 'grey'
};
let hourHandStyle = {
position: 'relative',
top: 92,
left: 106,
border: '1px solid grey',
width: '20%',
height: 7,
transform: 'rotate(' + (date.getHours() / 12 * 360 - 90).toString() + 'deg)',
transformOrigin: '0% 0%',
backgroundColor: 'grey'
};
return React.createElement(
'div',
null,
React.createElement(
'div',
{ style: dialStyle },
React.createElement('div', { style: secondHandStyle }),
React.createElement('div', { style: minuteHandStyle }),
React.createElement('div', { style: hourHandStyle })
)
);
};
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×