[선행 작업]

- 마스터 서버의 mysql 에서 복제 전용 계정을 새로 만들던가 기존 계정에 복제 관련 권한을 추가해 줘야한다.

mysql> GRANT REPLICATION SLAVE ON *.* TO 'id'@'ip' IDENTIFIED BY 'password';


- 마스터, 슬레이브에서 replication 할 db 의 데이터를 맞춰둔다. (덤프 이용)

* DB 데이터 백업

# mysqldump -u계정명 -p비밀번호 db > db.sql


* 함수, 프로시저, 트리거 를 함께 백업해야 할 경우

# mysqldump --routines --trigger -u계정명 -p비밀번호 db > db.sql


* 함수, 프로시저, 트리거 만 백업해야 할 경우 (테이블 제외)

# mysqldump --routines --no-create-info --no-data --no-create-db --skip-opt db > db_no_tables.sql


* 백업 데이터 복원

# mysql -u계정명 -p비밀번호 db < db.sql




[설정]

1) 마스터 설정파일 수정

/etc/my.cnf.d/server.cnf

----

[mysqld]

log-bin=mysql-bin

server-id=1

----

위 항목 추가


2) 마스터 mysql 실행 & 마스터 설정 확인

# service mysql start

mysql> show master status;

+------------------+----------+--------------+------------------+

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000001 |      906 |              |                  |

+------------------+----------+--------------+------------------+

* file, position 기록해놓기.


3) 슬레이브 설정파일 수정

/etc/my.cnf.d/server.cnf

----

[mysqld]

server-id=2

# replicate-do-db='repl' 

# 위 설정을 통해 하나의 db 만 replication 가능. 없으면 모든 db 를 replication 함.

# 몇몇개의 db 만 replication 할 경우 replicate-do-db 항목을 여러개 추가

----

위 항목 추가


4) 슬레이브 mysql 실행 & 슬레이브 마스터 연결 설정

# service mysql start

mysql> change master to

master_host='192.168.0.1',

master_user='id',

master_password='password',

master_log_file='mysql-bin.000001',   # 마스터 설정에서 확인한 file 이름

master_log_pos=906;                   # 마스터 설정에서 확인한 position 번호


5) 슬레이브 replication start

mysql> start slave;



[참고 링크]

http://we-minarida.tistory.com/entry/%EC%8B%A4%EC%82%AC%EC%9A%A9-db-%EC%97%90%EC%84%9C-mysql-replication

http://server-talk.tistory.com/241

https://blurblah.net/1490


[오류 발생]


The user specified as a definer ('user'@'ip') does not exist different ip address


- 해당 오류는 계정 정보의 불일치로 여러가지 경우에 발생하며 일반적인 경우에는 권한 추가 등과 같은

  널리 알려진 방법으로 해결 가능하다



[원인]


- 업무상의 이유로 서버가 변경되면서 IP 도 바뀌게 됨.

- 서버 변경 후 procedure 의 definer (정의자) 변경을 하지 않아서 발생함


(Heidisql 사용)


정의자를 알맞는 계정으로 수정하면 됨.


'Programming > DB' 카테고리의 다른 글

[Mysql & MariaDB] Master Slave Replication 설정  (0) 2019.01.03
[Mysql & MariaDB] 백업 & 복원  (0) 2018.10.04
[MariaDB] Clustering  (0) 2018.09.18
[MariaDB] Character Set 변경  (0) 2018.09.17

* Jupyter Lab : Jupyter Notebook 을 좀 더 개선한 버전

* 아래 설치, 실행, 원격접속 방법은 Jupyter Notebook, Jupyter Lab 둘 모두 동일합니다.

* 기본 환경

 - Anaconda3

 - Python3.5



[설치]

- Jupyter Lab

(anaconda)$ conda install jupyterlab


- Jupyter Notebook

(anaconda)$ conda install jupyter



[실행]

- Jupyter Lab

(anaconda)$ jupyter lab


- Jupyter Notebook

(anaconda)$ jupyter notebook



[원격 접속을 위한 설정]

- Jupyter Lab

(anaconda)$ jupyter lab --generate-config

(anaconda)$ jupyter lab password


- Jupyter Notebook

(anaconda)$ jupyter notebook --generate-config

(anaconda)$ jupyter notebook password



각각 $HOME/.jupyter/ 위치에 jupyter_notebook_config.json, jupyter_notebook_config.py 파일이 생성됩니다.

json 파일에는 암호화된 비밀번호가 입력되어있고 해당 암호를 복사하여

jupyter_notebook_config.py 파일의 c.NotebookApp.password 항목에 입력합니다.


* $HOME/.jupyter/jupyter_notebook_config.json

* $HOME/.jupyter/jupyter_notebook_config.py


[jupyter_notebook_config.py]

c.NotebookApp.password = 'sha1:*********'    # 외부 접속시 사용할 비밀번호

c.NotebookApp.ip = '*'                              # 어디서든 접속 가능

c.NotebookApp.port = 8888                       # 접속에 사용할 포트



[비밀번호 설정 다른 방법]

파이썬을 실행해서 코드를 통해 비밀번호를 얻을 수 있습니다.


(anaconda)$ python

>> from notebook.auth import passwd

>> passwd()

>> Enter password: 

>> Verify password: 

'sha1:********'


출력되는 sha1 암호문자열을 복사해서 사용하시면 됩니다.



* 참고 링크

https://unix.stackexchange.com/questions/423778/log-iptables-events-on-centos-7

http://flowvalue.tistory.com/2



[rsyslog 수정 (root)]

# vi /etc/rsyslog.conf


// add rule

...

#### RULES ####

...

kern.* /var/log/iptables.log 



[rsyslog 재시작 (root)]

# service rsyslog restart  

or  

# systemctl restart rsyslog



[iptables 수정 (root)]

# vi /etc/sysconfig/iptables


*filter

...

*nat

...

-A PREROUTING ~~~

-A INPUT ~~~

-A OUTPUT ~~~

...

-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " 

COMMIT



[iptables 재시작 (root)]

# systemctl restart iptables


log level - warn

iptables -A INPUT -j LOG --log-prefix "BAD_INPUT: " --log-level 4

iptables -A FORWARD -j LOG --log-prefix "BAD_FORWARD: " --log-level 4

iptables -A OUTPUT -j LOG --log-prefix "BAD_OUTPUT: " --log-level 4


log level - debug

iptables -A INPUT -j LOG --log-prefix "BAD_INPUT: " --log-level 7

iptables -A FORWARD -j LOG --log-prefix "BAD_FORWARD: " --log-level 7

iptables -A OUTPUT -j LOG --log-prefix "BAD_OUTPUT: " --log-level 7




출처: https://jhproject.tistory.com/109


다른사람들이 작성한 python 코드를 보다보면

*args, **kwargs 를 심심치 않게 본다.

그냥 막연하게 "어떤 파라미터를 몇개를 받을지 모르는 경우 사용한다" 라고 알고 있었지만

자세히 설명한 예 가 있어서 소개한다.



*args

- 파라미터를 몇개를 받을지 모르는 경우 사용한다. args 는 튜플 형태로 전달된다.

예)

def print_param(*args):
    print args
    for p in args:
        print p

print_param('a', 'b', 'c', 'd')
#('a', 'b', 'c', 'd')
#a
#b
#c
#d


**kwargs

- 파라미터 명을 같이 보낼 수 있다. kwargs는 딕셔너리 형태로 전달된다.

def print_param2(**kwargs):
    print kwargs
    print kwargs.keys()
    print kwargs.values()

    for name, value in kwargs.items():
        print "%s : %s" % (name, value)

print_param2(first = 'a', second = 'b', third = 'c', fourth = 'd')

#{'second': 'b', 'fourth': 'd', 'third': 'c', 'first': 'a'}
#['second', 'fourth', 'third', 'first']
#['b', 'd', 'c', 'a']
#second : b
#fourth : d
#third : c
#first : a



그러면 두개를 같이 쓰는 경우는??

def print_param3(*args, **kwargs):
    print args
    print kwargs

print_param3('a', 'b')
#('a', 'b')
#{}

print_param3(third = 'c', fourth = 'd')
#()
#{'fourth': 'd', 'third': 'c'}

print_param3('a', 'b', third = 'c', fourth = 'd')
#('a', 'b')
#{'fourth': 'd', 'third': 'c'}



응용 해 보자

def print_param4(a, b, c):
    print a, b, c

p = ['a', 'b', 'c']
print_param4(*p)
#a b c

p2 = {'c' : '1', 'a' : '2', 'b' : '3'}
print_param4(**p2)
#2 3 1



* 일반 EBS(ELASTIC BLOCK STORE)를 사용중일 경우 서버를 중지하지 않고도 볼륨을 확장할 수 있습니다.

* 서버를 중지하지 않고 확장 진행 가능 : t2, m3, m4, c3, c4, r3, r4등 현제 세대 인스턴스

* 서버를 중지해야만 확장 진행 가능 : m1, m2, c1, c2, t1 등 이전 세대 인스턴스


[진행 방법]]

* 스크린샷은 제가 이미 디스크 용량을 10 -> 20 기가로 확장 한 후 찍어서 조금 다르게 나옵니다.


1. AWS 콘솔에 접속 후 EC2 대시보드로 이동


2. EBS(ELASTIC BLOCK STORE) - 볼륨 메뉴로 이동 후 확장하려는 인스턴스의 볼륨 선택



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


3. 해당 볼륨을 오른쪽 클릭(또는 상단 작업버튼)을 통해 '볼륨 수정(Modify Volume)' 기능 성택


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


4. 확장하려는 만큼의 디스크 용량 입력 후 수정



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


5. 선택한 볼륨의 상태(state) 값이 'in-uses-optimizing' 으로 변하면 다음 작업 진행 (새로고침을 눌러 확인)



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


6. EC2 인스턴스 쉘(SSH) 접속

7. lsblk 명령어를 통해 현재 디스크 상태 확인

8. sudo growpart /dev/xvda 1   (/dev/xvda 과 1 사이의 띄어쓰기 주의)

9. sudo resize2fs /dev/xvda1

10. 확장된 디스크 용량 확인 및 대시보드의 상태값 확인 (in-use - completed)











'Programming > ETC' 카테고리의 다른 글

웹훅(Webhook)이란?  (1) 2019.02.11
[Yona] 설치형 이슈 트래커 Yona 설치  (0) 2019.01.03
[VirtualBox] CentOS 7 가상환경 생성 및 셋팅  (0) 2018.11.09
[VirtualBox] 네트워크 설정  (0) 2018.11.08
이슈 트래커 종류  (1) 2018.09.19



(1~4번 영상)
리액트 소개 및 특징



(5번 영상)
  • webpack
  1. 코드들을 의존하는 순서대로 하나 또는 여러개의 파일로 만들어줌
  2. gulp 와 비슷. 더 좋다
  1. 여러개의 자바스크립트 파일을 하나도 만들어 주거나 규칙에 따라 분리할 수도 있다.
  2. ES6 - 모던 자바스크립트 사용할 때 구형브라우저에서 지원이 안되서 바벨을 이용해 변환하여 여러종류의 브라우저에서 실행 하능
  3. 프로젝트를 만들 때 전체적으로 파일들을 관리해 주는 도구

  • babel
  1. 자바스크립트 변환 도구
  2. 노드나 자브스크립트 엔진에서 모든 문법을 지원해 주지는 않음
  3. 리액트는 JSX 문법을 사용해 컴포넌트를 작성하는데 이때 바벨을 사용함

codesandbox 사용 (https://codesandbox.io/)
리액트 샘플) http://bit.ly/beginreact


[문법]
import : 모듈을 사용함
class : Component 를 만듬 (다른 방법 - 함수를 통해서 만들 수 잇음)
render : 반드시 JSX 형태의 코드를 return 해줘야 함




(6번 영상)
  • JSX : HTML 처럼 생긴 문법이 자바스크립트 코드로 변환됨
  1. 태그는 반드시 받혀야 한다
  2. 최상위 element는 꼭 하나여야 한다. (태그가 2개 이상일 경우 최상위에 하나의 태그로 감싸줘야함)
    이 경우 불필요한 최상위 element가 하나 생기게 되는데 React 16.2 이상에서 fragment 기능으로 방지할 수있다.
  3. JSX 안에서 자바스크립트 값을 사용할 때는 {변수명} 으로 사용한다
  4. var 변수는 scope 가 함수 단위이다.
function foo(){                scope 단위    ┐
    var a = 'hello'                          │
    if(true) {                               │
        var a = 'bye'                        │
        console.log(a) // bye                │
    }                                        │
    console.log(a) // bye                    ┘
  1. const, let 변수는 scope 가 블록 단위이다.
function foo(){                scope 단위         ┐
    let a = 'hello'                               ┘
    if(true) {                               ┐
        let a = 'bye'                        │
        console.log(a) // bye                ┘
    }                                             ┐
    console.log(a) // bye                         ┘
  1. ES6 에서 var 은 더이상 쓰지 않음
    고정 상수는 const, 일반 변수는 let 사용
  2. JSX 내부에서 조건식 사용하기
    1)  삼항 연산자 사용 ( 조건 ? true : false )
    2)  && 연산자 사용
    3)  function 함수 작성 ( => 화살표 함수로도 사용 가능. 화살표 함수는 this, argument super 가 없는 함수임)


+ self closing tag : <input />



(7번 영상)
@ JSX 에서 css 스타일과 class 사용방법

React 사용방법은 기존 css 사용법과 조금 다르다
  1. Style 을 객체 형태로 넣어줌
  2. 속성은 기존 단어가 아닌 특수문자를 제외하고 camel case 로 적는다.
  3. class 는 className 으로 입력해야 한다.
const style = {
    backgroudColor : 'red',   // 기존 : backgroud-color
    color : 'white',
    fontSize : '36px'         // 기존 : font-size
}

// 적용방법
<div style={style} className="app">
</div>

  1. JSX 내부에서 주석은 그냥 출력되어 버린다.
    일반 주석 및 멀티라인 주석 모두 출력됨.
    일반적으로 주석은 멀티라인으로 작성하고 {} 로 감싸준다
return {
    <div>
        // 주석
        /*
            주석
        */
        위 두 주석 모두 오류
        일반적으로 주석은 멀티라인
        {/* 주석 사용 */}
        태그 사이에는 그냥 주석 사요 가능
        <h1
            // 주석 가능
        >
        </h1>
    </div>
}





(8번 영상)
주제 : Props

  • Props : 부모에서 자식으로 일방적으로 전달. 자식에서 값을 변경할 수 없다.(읽기 전용)
  1. <Child value = "value">    : value 가 props 이다
  2. default props 값을 class 내부에 static 으로 지정해 놓을 수 있다
    class 외부에 설정할 수 있지만 static 으로 사용하는게 최신 자바스크립트 문법에 더 알맞다.
- 기본 static 사용법 (최신 사용법)
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {

static defaultProps = {
name : 'basic'
}
render() {
return (
<div className="App">
props test : {this.props.name}
</div>
);
}
}
export default App;

- 외부 설정
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {

render() {
return (
<div className="App">
props test : {this.props.name}
</div>
);
}
}

App.defaultProps = {
name : 'basic'
}

export default App;


  • 단순히 불러오기만 할 class 일 경우 함수형 component 로 만든다
- SampleFunctionalCoimponent.js
import React from 'react'

const SampleFunctionalComponent = ({ test }) => {
return (
<div>hi this is sample functional component : {test}</div>
);
};

SampleFunctionalComponent.defaultProps = {
test : 'test hi'
}

export default SampleFunctionalComponent;

- App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import SampleFunctionalComponent from './SampleFunctionalComponent'

class App extends Component {

static defaultProps = {
name : 'basic'
}
render() {
return (
<SampleFunctionalComponent />
);
}
}
export default App;

1) import 에 Componenet 선언이 필요없다
2) class 선언이 아니고 하나의 변수로 만든다
3) 함수형 컴포넌트의 파라미터 (=test) 는 비구조화 할당 문법이 사용됨.
4) 

* 비구조화 할당 문법
 : 여러 변수 또는 파라미터를 각각의 값에 맞게 할당할 때 하나씩 지정해 주지 않고 객체로 한번에 지정해 주는 방식

  • 함수형 컴포넌트와 클래스형 컴포넌트의 차이점 (함수형 컴포넌트 기준)
  1. state 기능이 없음
  2. life cycle 없음
    > 장점
  1. 초기 마운트 속도가 미세하게 빠르다
  2. 불필요한 기능이 없어서 메모리 자원을 덜 사용한다
- 어떤값을 가져와서 단순히 보여주기만 한다면 함수형 컴포넌트가 약간 더 효율적이다
- 컴포넌트가 매우매우 많다면 조금 더 효율적이겠지만 크게 차이나지는 않을 것이다.



Class Field 문법 : https://tc39.github.io/proposal-class-fields/

(9번 영상)
주제 : state


* state : 컴포넌트 스스로가 가지고 있는 객체. 따라서 컴포넌트 스스로가 값을 변경 할 수 있다. (setState 사용)


- 카운터 하는 소스 작성... ( 카운터에 나오는 숫자는 유동적. 숫자가 바뀔때 마다 rerender 해줘야 한다. )

* 아래는 전부 class 안에 정의한다.

1) state 정의 : 객체여야 한다. 문자열, 숫자 안됨.

2) 객체 안에 요소를 정의 한다.

3) 카운터 값을 변경하기 위해 custom method 를 만든다.

4) 카운터 기능을 위해 증가 감소 함수를 만드는데, 함수 안에서 state 값을 직접 조절하면 안된다.

    컴포넌트에서 state 값이 update 된지 모른다.

5) state 값이 변경되는걸 component 가 알기 위해서는 항상 setState 함수를 통해 변경해줘야 한다.


- 잘못된 state 사용방법

handleIncrease = () => {
this.state.counter = this.state.counter + 1;
}


- 올바른 사용방법

import React, { Component } from 'react';

class Counters extends Component {
state = {
counter : 0
}
handleIncrease = () => {
this.setState({
counter : this.state.counter + 1
})
}
handleDecrease = () => {
this.setState({
counter : this.state.counter - 1
})
}
render(){
return(
<div>
<h1>counter</h1>
<div>value : {this.state.counter}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}

export default Counters;


* render 함수는 그냥 함수로 작성했는데 increase, decrease 함수는 왜 화살표 함수( => )로 작성했을까?

  : 증감 함수를 화살표가 아닌 기본 함수로 작성하게 되면 함수 안에서 this 가 어느것을 가리키는지 모르게 된다.

  : 해당 문제를 해결해주기 위해서는 constructor 를 이용해야 한다.

    1) counter component 가 생성될 때 항상 constructor 가 제일 먼저 실행되고,

    2) constructor 에서는 상속받은 Component 의 기본 생성함수를 먼저 호출해주도록 한다. ( super 사용 )

    3) 그 다음 counter component 에서 사용되는 increase, decrease 함수의 this 가 constructor 의 this 라는걸 명시해 준다. ( binding 해줌 )


- 예시

import React, { Component } from 'react';

class Counters extends Component {
state = {
counter : 0
}

constructor(props){
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}

handleIncrease() {
this.setState({
counter : this.state.counter + 1
})
}
handleDecrease = () => {
this.setState({
counter : this.state.counter - 1
})
}
render(){
return(
<div>
<h1>counter</h1>
<div>value : {this.state.counter}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}

export default Counters;



* props 는 부모자 자식에게 넘겨주는 변경 불가능한 값

* state 는 자기 자신이 가지고 있는 변경 가능한 값




lifecycle api : https://react-anyone.vlpt.us/05.html




(10번 영상)
주제 : life cycle api

* life cycle api 사용 시기

 1) component 가 브라우저에 나타날 때

 2) component 가 브라우저에서 업데이트 될 때

 3) component 가 브라우저에서 사라질 때



* 종류 (매우 많다)


1. Mount - Component 가 브러우저에 나타남

  1) constructor : Component 가 만들어질 때 가장 먼저 실행되는 함수

  2) getDerivedStateFromProps : props 로 받은 값을 그대로 state 에 동기화 시키고 싶을 때 사용 (mount, update 두 부분에서 사용)

  3) render : DOM, 태그 등등 정의

 * 이후 브라우저에 표시되고 난 다음

  4) componentDidMount : 외부 라이브러리, 차트 라이브러리 등등 사용할 때, ajax, api 요청을 할 때 이곳에서 실행

                                    뷰가 다 그려지고 스크롤을 이동, 이벤트 listening


2. Update - Component 에서 props, state 값이 변경됨

  1) getDerivedStateFromProps : props 로 받은 값을 그대로 state 에 동기화 시키고 싶을 때 사용 (mount, update 두 부분에서 사용)

  2) shouldComponentUpdate : (중요) component 가 update 되는 성능을 최적화 시킬 때 사용

   - 부모 component 가 rerender 되면 자동적으로 자식 component 도 rerender 된다. 하지만 불필요할 때가 있다.

   - react 는 virtual DOM 을 사용하지만 기본적으로는 rerender가 발생하면 기본 DOM 과 virtual DOM 둘 다 다시 그린 후 변경점을 비교하게 된다

   - 이 기능을 사용하게 되면 virtual DOM 에 그리는 것조차 막아서 뷰의 변경을 방지 할 수 있다. (성능 최적화 관점)

   - 해당 함수는 true, false 값을 반환하며, true 는 render 실행, false 는 실행 안함

 * render 가 실행되고 브라우저에 반영되기 바로 직전

  3) getSnapshotBeforeUpdate : render 되고 브라우저에 표시되기 전에 이 함수에서 특정 로직을 수행한다.

   - 스크롤 위치, DOM 크기 가져오기 등등

 * 위 작업들을 모두 마치고 component 가 모두 update 되고난 후

  4) componentDidUpdate : state 가 변경되었을 때 이전 상태와 현재 상태를 비교해서 특정 작업을 해야할 때


3. Unmount - Component 가 브러우저에서 사라짐

  1) componentWillUnmount : 마운트 때 listen 시킨 이벤트들을 해제할 때 사용됨





lifecycle api : https://react-anyone.vlpt.us/05.html

(11번 영상)
주제 : life cycle api

* 코드 샘플

1. constructor
 - 컴포넌트가 제일 먼저 만들어질 때 호출됨.
 - super 사용 용도 : 상속받은 Component 의 원래 가지고 있던 생성자를 먼저 호출해 주고 작업을 하도록 하기 위함

class App extends Component {
constructor(props){
super(props);
console.log('constructor')
}
........
}

2. componentWillMount
 - 사라짐

3. componentDidMount

class App extends Component {

constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
}

.................

}


* 특정 DOM 에 어떤 작업을 하고 싶을 때 ref 사용. ( 태그에 아이디를 붙이는 것과 비슷함. ref 로 직접 가져올 수 있다. )
class App extends Component {
constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
console.log(this.myDiv.getBoundingClientRect())
}
render() {
return (
<div ref={ref => this.myDiv = ref}>
hi
</div>
);
}
}



4. componentWillReceiveProps

 - 16.3 부터 사라짐


5. getDerivedStateFromProps

 - 16.3 부터 사용 가능

 - setstate 사용 불가.

 - 변경 할 state 값을 바로 return 해주면 setState 사용하지 않고도 state 에 값이 적용된다.

 - state 와 props 값의 동기화


[StateComponent.js]

import React, { Component } from 'react';
class StateComponent extends Component {
state = {
value : 0
}
static getDerivedStateFromProps(nextProps, prevState){
if(prevState.value != nextProps.value){
return {
value : nextProps.value
}
}
return null;
}
render(){
return(
<div>
<p>props : {this.props.value}</p>
<p>value : {this.state.value}</p>
</div>
);
}
}

export default StateComponent;


[App.js]

import React, { Component } from 'react';
import StateComponent from './StateComponent'
class App extends Component {
state = {
count : 1
}
constructor(props){
super(props);
console.log('constructor')
}
componentDidMount(){
console.log('componentDidMount')
// console.log(this.myDiv.getBoundingClientRect())
}

handleClick = () => {
this.setState({
count : this.state.count + 1
})
}

render() {
return (
<div>
<h1>hi</h1>
<StateComponent value={this.state.count} />
<button onClick={this.handleClick}> click </button>
</div>
);
}
}
export default App;



6. shouldComponentUpdate

 - 다음 받아올 props, state 값을 가져옴

 - return 값에 따라 값의 업데이트 여부가 결정됨 ( true : 업데이트 , false : 안함 )

 - 특정 조건에서 update 를 막아줄 수 있는 함수


7. componentWillUpdate

 - 사용하지 않음



8. getSnapshotBeforeUpdate

 - update 되기 바로 직전 DOM 상태를 return

 - 직전 상태 (스크롤 위치 등) 를 componentDidUpdate 를 통해서 유지 시킬 수 있다.



9. componentDidUpdate

 - getSnapshotBeforeUpdate 에서 획득한 이전 상태를 3번째 파라미터로 받아 작업 진행



10. componentWillUnmount

 - component 가 사라질 때 호출됨


* sample : count 가 10이 넘어가면 StateComponent 를 더이상 표시하지 않게되고

              StateComponent 가 사라지면 StateComponent 클래스에 구현된 componentWillUnmount 에 의해 특정 로직이 수행됨


[App.js]

render() {
return (
<div>
<h1>hi</h1>
{ this.state.count < 10 && <StateComponent value={this.state.count} /> }
<button onClick={this.handleClick}> click </button>
</div>
);
}



11. componentDidCatch

 - component 에서 에러가 발생했을 때 확인할 수 있음

 - render 함수 안에서 에러가 나면 app 자체가 crash 발생함

 - 에러를 캐치하기 위해서는 자식 component 에서는 불가능하고 부모 component 에서만 가능하다





(12번 영상)
주제 : 필요 도구 설치

* 개발환경 설정

1. Node.js 설치 (webpack, babel 을 사용하기 위해 필요)
 - NVM (Node Version Manager) 사용하면 편하다 (추천)  : https://github.com/creationix/nvm


2. yarn 사용 : https://yarnpkg.com/en/docs/install#windows-stable
 - Node.js 를 설치하면 기본적으로 NPM 이 설치되지만, 대신 yarn 을 사용하는걸 추천.
 - NPM 보다 좀더 개선된 버전이라고 보면 됨.


3. IDE
 - 익숙한것 사용하기
 - vscode : https://code.visualstudio.com/


4. git : https://gitforwindows.org/
 - 형상관리


자세한 설치방법은 추후 업데이트



(13번 영상)
주제 : create react app 사용

1. 설치 확인

 - Node.js 버전 확인 :  $ node -v

 - yarn 버전 확인 :  $ yarn -v


2. create-react-app 설치 : https://github.com/facebook/create-react-app

 - 페이스북에서 만든 react 프로젝트를 통합 설치해주는 툴

 - webpack, babel 설치 및 설정을 간소화 시켜줌


설치

$ npm install -g create-react-app

$ create-react-app hello-react

or

$ npx create-react-app my-app



* 프로젝트가 생성되면 개발을 시작해보자!




14번






15번

[배열에 데이터 삽입하기]

(참고)


* 자식 컴포넌트에서 부모 컴포넌트로 값 전달하기


1. 부모 컴포넌트에서 handleCreate 라는 메소드를 만들고 자식 컴포넌트로 props 로 전달한다.
2. 자식 컴포넌트에서 props 로 전달받은 handleCreate 메소드를 호출해서 데이터가 부모 컴포넌트로 전달되도록 한다.

* 기본 form 속성으로 버튼 type 이 submit 일 경우 클릭하면 페이지가 새로고침 된다.
  해당 새로고침을 방지하기 위해 handleSubmit 함수를 작성해준다.

* 리액트에서는 불변성을 꼭 유지해 줘야한다.
* 어떤 값을 수정할때는 꼭 setState 를 사용해야하며, 그 내부의 배열이나 객체를 수정해야 할 때는
   기존 배열, 객체를 수정하지 않고 원본을 기준으로 새로운 배열, 객체를 만들어서 값을 주입해 주어야 함.
* 배열에 추가하는 방식은 concat 사용 (C 언어에서 문자열 이어붙이기와 같은 명령어)

* 배열에 고유한 id 값이 증가하면서 추가되도록 할 때는
  1. '... spread 전개 연산자'를 사용
  2. 기존 속성 값을 그대로 입력
  3. object.assign 객체 사용

* state 에 변수를 선언하는 이유는, render 함수에서 사용하면서 변수가 수정되었을 때 꼭 rerender 되게끔 만들게 하기 위함

[App.js - 새로고침 방지]

handleSubmit = (e) => {
e.preventDefault();
this.props.onCreate(this.state);
this.setState({
name: '',
phone: '',
})
}


[자식 컴포넌트]
- 부모 컴포넌트로 props 전달


[App.js - 배열에 고유 id 값 증가 방법]
1)
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({
...data,
id: this.id++,
})
});
}

2) 
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat({
name: data.name,
phone: data.phone,
id: this.id++,
})
});
}

3) 
handleCreate = (data) => {
const { information } = this.state;
this.setState({
information: information.concat( Object.assign({}, data, {
id: this.id++
}))
});
}




16번


[자바스크립트 배열 내장 함수 - map]

(참고)

* 기본 배열 선언 : numbers = [1,2,3];
* map 사용 : squared = numbers.map(n => n * n);
* 사용 -> squared : [1, 4, 9]  -> 기존 numbers 배열을 제곱으로 만들어줌

- defaultProps 지정해 줄때는 항상 static 으로 선언해야 한다.


* 배열에서 키가 없다면 리스트 항목을 추가 제거할 때 매우 비효율적으로 동작한다.

[PhoneInfoList.js]
render() {
const { data } = this.props;

const list = data.map(
info => (<PhoneInfo info={info} key={info.id} />)
);
return (
<div>
{list}
</div>
);
}




17번

[배열 조작]


(참고)

* 배열은 항상 불변성을 유지해야 한다.
* slice 와 concat 을 혼합해서 배열의 중간 값만 제거할 수 있다.
* 제거 방법
 1) slice : 파라미터 (a,b) - a번째에서 시작해서 b번째 까지만 가져온다
 2) filter : 조건으로 값을 가져올 수 있다. - 기존 배열을 변경하지 않는다.

ex) slice


ex) filter

[App.js]
handleRemove = (id) => {
const { information } = this.state;
this.setState({
information: information.filter(info => info.id !== id)
});
}



1





(18번 영상)
[배열 안의 데이터 수정하기]

*  일반적인 데이터 수정 방법 2가지
[
...numbers.slice(0,2),
9,
...numbers.slice(3,5)
]

numbers.map(n => {
if (n == 3) {
return 9;
}
})







(19번 영상)
[shouldComponentUpdate 를 통한 최적화. 불변성을 왜 유지하는가?]

(참고)
Immutable.js : https://facebook.github.io/immutable-js/
Immer.js : https://github.com/mweststrate/immer

* 중첩된 render 가 호출되면 변하지 않는 항목이 다시 render 되는 불필요한 상황이 발생한다
* shouldComponentUpdate 를 통해 방지 할 수 있다.

* 배열, 객체는 call by reference 이므로 하나의 변수를 다른 변수에 동일하게 지정하도록 하면 하나를 변경하면 둘 모두 변경된다.
ex) a = [0,1,2]
     b = a
     b.push(3)
     b = [0,1,2,3]
     a = [0,1,2,3]

* 이럴때는 지정이 아닌 새로운 변수로 만들어지도록 해야한다.
ex) a = [0,1,2]
     b = [...a, 3]

이러한 객체나 배열이 길어지거나 깊어지면 복잡해지는데, 이럴 때 사용하기 좋은 라이브러리가 있다. (참고 확인)




(20번 영상)

[이름으로 전화번호 찾기]

* keyword state 를 추가하고 render 안에서 PhoneInfoList 컴포넌트의 data 속성에 바로 filter 기능을 넣어 검색 가능하도록 만든다





(21번 영상)

[Ref 를 통하여 DOM 에 직접 접근하기


* Ref 사용법 2가지

 1) 함수 사용 : 태그 속성에 ref 함수를 작성. id 를 지정해주는 것과 비슷한듯


 2) (react 16.3 버전 이상에서만 가능)

     상단에 id 설정해 줄때 React.createRef() 를 사용한다

     focus 를 호출할 때는 1번과 다르게 이름 뒤에 current 를 꼭 붙여줘야한다.


input1 = null
input2 = React.createRef();

handleSubmit = (e) => {
e.preventDefault();
this.props.onCreate(this.state);
this.setState({
name: '',
phone: '',
});
// this.input1.focus()
this.input2.current.focus();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<input
name="name"
placeholder="이름"
onChange={this.handleChange}
value={this.state.name}
ref={this.input2}
// ref={ref => this.input1 = ref}
/>
<input
name="phone"
placeholder="전화번호"
onChange={this.handleChange}
value={this.state.phone}
/>
<button type="submit">등록</button>
</form>
);
}






(22번 영상)

[마치면서]


추천)


1. prettier : 코드 정리

2. 리액트 컴포넌트 스타일링 : css, sass 스타일 컴포넌트를 쉽게 사용할수 잇음

3. immutable.js : 불변성 변수 사용

4. immer.js : 3번과 비슷한데 엄청 비슷

5. 리덕스 : 데이터 관리 시 update 로직을 다른 파일로 분리, 컴포넌트 등 프로젝트 구조를 체계적으로 만들 수 있음

              상태 관리 라이브러리

6. 몹X 라이브러리 : 리덕스랑 비슷? 찾아봐야함

7. 리액트 라우터 v4 : 여러 페이지로 프로젝트를 구성해야 할 때

8. 타입스크립트 : 컴포넌트를 더 확실하게 사용하고 싶을때

9. Jest, Enzyme : 테스트 코드 개발 시 사용


























'공부 > 프로그래밍' 카테고리의 다른 글

[VScode] c++ 개발환경 설정  (0) 2020.01.25

두 숫자 더하기 문제

내용

  • 주어진 정수배열 안에서 두 숫자를 더해 target 이 되는 숫자의 index 로 이루어진 배열을 반환하라

조건 및 제약사항

  • 주어진 배열에는 정확히 하나의 해답만 존재한다.
  • 각 숫자는 한번만 사용 가능하다.

예제

  • nums = [2, 7, 11, 15], target = 9
    • result = [0, 1]

코드

import java.util.HashMap;
import java.util.OptionalInt;
import java.util.stream.IntStream;

public class LeetCode1 {
    /**
     * 1. Two Sum
     * https://leetcode.com/problems/two-sum/
     *
     * Example:
     * Given nums = [2, 7, 11, 15], target = 9,
     * Because nums[0] + nums[1] = 2 + 7 = 9,
     * return [0, 1].
     * */

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] result = solution.twoSum2(new int[]{2, 7, 11, 15}, 9);
        System.out.println(result[0] + " / " + result[1]);
    }

    static class Solution {
        // 스트림 사용. 그러나 2중 반복문으로 시간복잡도 조금 더 높음
        public int[] twoSum(int[] nums, int target) {
            for (int i = 0; i < nums.length; i++) {
                int temp = i;
                OptionalInt a = IntStream.range(i+1, nums.length)
                        .filter(j -> nums[temp] + nums[j] == target)
                        .findFirst();

                if (a.isPresent()) {
                    return new int[]{i, a.getAsInt()};
                }
            }

            return nums;
        }

        // Hashmap 사용. 정석 방법.
        public int[] twoSum2(int[] nums, int target) {
            HashMap<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                map.put(target - nums[i], i);
            }
            for (int i = 0; i < nums.length; i++) {
                if (map.containsKey(nums[i])) {
                    return new int[]{i, map.get(nums[i])};
                }
            }
            return nums;
        }
    }
}

* mongo-c-driver 1.6.3 버전 사용

* $ : 일반 사용자 계정 , # : 루트 계정


[mongo-c-driver Github]

https://github.com/mongodb/mongo-c-driver



[설치]

(원하시는 위치에서 진행해 주세요.)

$ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.6.3/mongo-c-driver-1.6.3.tar.gz

$ tar xzf mongo-c-driver-1.6.3.tar.gz

$ cd mongo-c-driver-1.6.3

$ ./configure --disable-automatic-init-and-cleanup

$ make

$ sudo make install



[확인]


1) /usr/local/include/libmongoc-1.0


2) /usr/local/include/libbson-1.0




[참조방법 예시]


1) gcc -o mongo-c-test mongo-c-test.c -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0 -L/usr/local/lib/ -L/usr/lib64 -lmongoc-1.0 -lbson-1.0


2) makefile

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

INCMONGO = -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/libbson-1.0

LIBMONGO = -L/usr/local/lib/ -L/usr/lib64

LIBS    = -lmongoc-1.0 -lbson-1.0

CFLAGS  = $(INCMONGO) $(LIBMONGO) $(LIBS)

TARGET  = mongo-c-test


all: $(TARGET)


$(TARGET):

        $(CC) -o $@ $@.c $(CFLAGS) 


clean:

        rm -f $(TARGET)

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

(예시일뿐 필요한 내용으로 수정하셔야 합니다.)



[예제 소스]

* DB 풀 사용법이 포함된 소스입니다.



#include <bcon.h>
#include <mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define SERVER "mongodb://url"
#define DATABASE "MONGO_TEST"

int main(int argc, char *argv[])
{
mongoc_client_t *client;
mongoc_collection_t *collection;
//mongoc_index_opt_t opt;
bson_t *doc;
bson_error_t error;

mongoc_client_pool_t *pool;
mongoc_uri_t *uri; // 몽고DB 서버주소

mongoc_init();

uri = mongoc_uri_new(SERVER);
pool = mongoc_client_pool_new(uri);

mongoc_client_pool_set_error_api(pool, 2);
mongoc_client_pool_max_size(pool, 2); // DB풀에 DB클라이언트 2개

client = mongoc_client_pool_pop(pool);
collection = mongoc_client_get_collection(client, DATABASE, "TEST");

int temp = 0;
while (true)
{

if (temp < 100)
{
temp++;
printf("%d\n", temp);

doc = bson_new();
BSON_APPEND_UTF8 (doc, "user", "user2");
BSON_APPEND_INT32(doc, "temp_idx", temp);
if (!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error))
{
fprintf(stderr, "%s\n", error.message);
}
char *str;
str = bson_as_json(doc, NULL);
printf("doc : %s\n", str);
bson_free(str);
bson_destroy(doc);

}
else
{
break;
}
usleep(100);
}
mongoc_client_pool_push(pool, client);
mongoc_client_pool_destroy(pool);
mongoc_uri_destroy(uri);
mongoc_cleanup();

return 0;
}


- 결과

1) 콘솔


2) robomongo




---


<CentOS 7 가상환경 생성 및 셋팅>


1. 새 가상환경 만들기


1.1) 새로 만들기 클릭



1.2) 메모리 설정




1.3) 디스크 용량 설정



1.4) 가상 이미지 생성 완료



2. 가상환경 네트워크 준비하기


2.1) VirtualBox 전체 환경설정

* 각 가상환경 설정 버튼과 혼동하지 말자



2.2) 네트워크 탭에서 NAT 네트워크에 사용할 새로운 세팅 생성



2.3) 네트워크 CIDR 은 가상OS에 분배될 내부 네트워크 IP 주소대역임

ex) 평소 사용하는 공유기들이 192.168.0.xxx IP 를 분배해 주는것과 같음

* 위에 써있는 10.0.2.0/24 를 192.168.0.0/24 로 변경해도 됨



2.4) 현재 사용중인 호스트 컴퓨터와 가상OS 를 포트포워딩 설정할 수 있음

아직 가상OS 설치를 하지 않았으므로 비운상태로 넘어가고 가상OS 설치를 끝낸 후 다시 설정함



3. 가상 OS 설치


3.1) 가상환경을 클릭하고 위 설정 버튼을 눌러 설정화면으로 이동

또는 가상환경을 오른쪽 클릭해서 나오는 메뉴에서 설정을 클릭해도 됨

* VirtualBox 전체 설정과 혼동하지 말 것.



3.2) 저장소 메뉴에서 '컨트롤러 : IDE' 항목의 광학 드라이브 항목



3.3) 받아놓은 CentOS 7 이미지 파일을 선택



3.4) '컨트롤러 : IDE' 항목 아래에 이미지가 추가된거 확인 후 '네트워크' 메뉴로 이동




3.5) 네트워크 어댑터를 'NAT 네트워크' 그리고 이름 항목을 2.3 에서 새로 만든 NAT네트워크 이름으로 지정



3.6) 기본적인 셋팅 완료. 가상 OS 설치 전 스냅샷 찍기

***** 스냅샷을 잘 만들어 두면 문제가 생겼을 경우 쉽게 복구할 수 있다. *****



3.7) 스냅샷 생성



3.8) 가상OS 설치 준비 완료


4. 가상 OS 설치


4.1) CentOS 7 설치 시작




4.2) 설치중 표시할 언어 - 한국어로 해도 상관없음



4.3) 기본적으로 네트워크가 꺼져있음. 클릭해서 설정을 변경하도록 하자.



4.4) 네트워크를 켜준다. 기본 설정이 자동으로 셋팅된다.

* 여기 나오는 IP 주소가 2.3, 2.4 에서 만든 NAT 네트워크 셋팅의 CIDR 네트워크 대역중 하나로 설정된다.

* 추후 이 IP로 포트포워딩을 설정한다.




4.5) 디스크 메뉴를 확인해야 한다.



4.6) 디스크 메뉴 안에서는 따로 건드릴건 없고 확인만 되면 완료 버튼을 눌러 되돌아가면 된다.



4.7) 두 항목 설정이 끝나면 설치시작 버튼이 활성화 되므로 설치시작 버튼을 눌러 다음 화면으로 넘어간다.



4.8) root 계정과 사용자 계정 둘다 설정해준다.



4.9) root 계정 비밀번호 설정



4.10) 사용자계정 설정

* 이 사용자를 관리자로 합니다. 체크하기



4.11) 설치가 끝날 때 까지 기다린다.



4.12) 설치가 끝나면 재부팅


*** 설치 끝나고 나서 스냅샷을 하나 더 찍어놓는 것도 좋다. ***

* 그러면 가상OS 를 사용하다가 문제가 발생했을 경우 지금 만든 스냅샷으로 복원하면

OS 를 새로 설치 하지 않고도 처음 OS 설치를 끝낸 순간으로 쉽게 돌아올 수 있다.


* 스냅샷 상태


5. CentOS 7 실행 및 네트워크 설정



5.1) 설치한 CentOS 7 을 실행한다.



5.2) 설치할 때 생성한 사용자 계정으로 로그인 후 ip addr 명령어를 통해 IP 를 확인한다.

OS 설치할 때 확인한 네트워크 IP 와 동일하게 표시될 것이고 이제 다시 2.3, 2.4 항목으로 돌아가 포트포워딩 설정을 해준다.



5.3) 가상OS CLI 화면에서 작업하기는 불편하므로 (해상도 변경의 까다로움, 클립보드 공유 설정 까다로움)

위처럼 SSH 포트를 포트포워딩 해주고 putty 또는 secureCRT 등등의 터미널 프로그램으로 작업할 수 있게 한다.



5.4) 터미널 프로그램으로 접속한다.

Host IP 는 현재 사용중인 컴퓨터 이므로 127.0.0.1 로 설정한다.

포트는 5.3 화면과 같이 가상OS 의 22번 포트와 매핑시킨 포트번호를 입력한다 (이 포스트에서는 10122)

접속 계정도 입력한다.



5.5) 접속해본다.



5.6) 위처럼 VirtualBox 화면을 사용하지 않고 터미널 프로그램으로 잘 연결되었다. 쉽게 작업하도록 하자.


*** 만약 웹서버를 올린다던가 DB 를 설치해서 테스트해보려 한다면

5.3 화면에서 가상OS 로 접근하려는 포트를 모두 추가해줘야 한다.

1) 웹서버라면 80 포트

2) DB 라면 각 DB에 맞는 포트 (ex : mysql - 3306)

그 외 필요한 포트를 모두 추가해 준다.

그 후에 웹서버나 DB를 실행하고 접근할 때는 Host 컴퓨터에서 127.0.0.1:10180 등과 같이 접속하면 된다.



***** 스냅샷은 자주 만들도록 하자. 매우 편하다. *****



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


'Programming > ETC' 카테고리의 다른 글

웹훅(Webhook)이란?  (1) 2019.02.11
[Yona] 설치형 이슈 트래커 Yona 설치  (0) 2019.01.03
[AWS] EC2 인스턴스 디스크 볼륨 확장  (0) 2018.12.07
[VirtualBox] 네트워크 설정  (0) 2018.11.08
이슈 트래커 종류  (1) 2018.09.19

+ Recent posts