Component

컴포넌트란?

- 리액트로 만들어진 앱을 이루는 최소한의 단위

- 기존의 웹 프레임워크는 MVC방식으로 분리하여 관리하여 각 요소의 의존성이 높아 재활용이 어렵다는 단점이 있었다. 반면 컴포넌트는 MVC뷰를 독립적으로 구성하여 재사용을 할 수 있고 이를 통해 새로운 컴포넌트를 쉽게 만들 수 있다.
- 컴포넌트는 데이터(props)를 입력받아 View(state) 상태에 따라 DOM Node를 출력하는 함수.
- 컴포넌트 이름은 항상 대문자로 시작하도록 한다. 
   (리액트는 소문자로 시작하는 컴포넌트를 DOM 태그로 취급하기 때문이다.

- UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 개별적으로 나누어 코딩한다.

- “props”라고 하는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지를 기술하는 React 엘리먼트를 반환한다.

 

컴포넌트의 종류

함수형 컴포넌트 (Stateless Functional Component)
- 가장 간단하게 컴포넌트를 정의하는 방법은 자바스크립트 함수를 작성하는 것이다.

import React from 'react';

function MyComponent(props) {
	return <div>Hello, {props.name}</div>;
}

export default MyComponent;

위의 예시처럼 export 구문을 통해 가져와 사용할 수 있고, import할때 확장자를 생략할 수 있는데 이 이유는 "웹팩 코드 검색 확장자(webpack module resolution)" 기능 덕분이다. 확장자가 파일 이름에 없는 경우 웹팩의 확장자 옵션(extentions)에 정의된 확장자 목록을 통해 확장자 이름을 포함한 파일이 있는지 확인하여 자동으로 임포트 한다.

 

2) 클래스형 컴포넌트 ( Class Component )

- 컴포넌트 구성 요소, 리액트 생명주기를 모두 포함하고 있다. (리액트 생명주기는 따로 조금더 자세히 알아보도록 한다.)

- 프로퍼티, state, 생명주기 함수가 필요한 구조의 컴포넌트를 만들 때 사용한다.

import React from 'react';

class MyComponent extends React.Component {
	constructor(props) { // 생성함수
		super(props);
	}
	
	componentDidMount() { // 상속받은 생명주기 함수
	}
	
	render() { // 상속받은 화면 출력 함수, 클래스형 컴포넌트는 render() 필수
		return <div>Hello, {this.props.name}</div>;
	}
}

export default MyComponent; //다른 JS파일에서 불러올 수 있도록 내보내주기

함수형 컴포넌트가 사용하기 더 쉽기 때문에 주로 함수형 컴포넌트를 사용하고, 함수형 컴포넌트로 하지 못하는 작업을 처리할 때가 있는데 이때 클래스형 컴포넌트를 활용한다.

 

map

map()이란? 

리액트에서 동적인 배열을 렌더링해야 할 때는 자바스크립트 배열 내장함수인 map()을 사용하여 일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열로 변환해준다. map() 함수는 배열안에 있는 각 원소를 변환할때 원소들을 이용하여 새로운 배열을 만들어주는 역할을 한다. 보통 반복문을 대체하여 사용한다.

 

for문과 map 비교

 

for문

const numbers = [1, 2, 3]
for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i])
}

map

const numbers = [1, 2, 3];
const listItems = numbers.map((number, idx) => {
    console.log(number);
});

이러한 map에 대해 더 자세히 알아보자면

 - arr.map(callbackFunction, [thisArg])
 - arr.map(callbackFunction(currenValue, index, array), thisArg)

위의 두가지 방법으로 사용할 수 있다.

callbackFunction : 새로운 배열의 요소를 생성하는 함수로 세가지 인수를 갖는다.

 - currenValue : 현재 배열값

 - index : 현재 배열값 내의 인덱스 값

 - array : 현재 배열

thisArg : 콜백 함수 내부에서 사용할 this 컨퍼런스를 설정

 

props(프로퍼티)

- 프로퍼티, props(properties의 줄임말) 라고 한다.
- 상위 컴포넌트가 하위 컴포넌트에 값을 전달할때 사용한다.
- 프로퍼티는 수정할 수 없다는 특징이 있다.(자식입장에선 읽기 전용인 데이터이다.)

프로퍼티에 문자열을 전달할 때는 큰따옴표(" ")를, 문자열 외의 값을 전달할 때는 중괄호({ })를 사용 한다.

 

ex) 1개의 props 넘기기

 

app.js (문자열은 큰따옴표( " " ) 를 사용하여 값을 전달) 

import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';

function app() {
  return (
    <div>
      <Header />
      <Main name="동덩"/>
      <Footer />
    </div>
  );
}

export default app;

index.js

import React from 'react';

function index(props) {
    return (
        <div>
            <main>
                <h1>안녕하세요. {props.name} 입니다.</h1>
            </main>
        </div>
    );
}

export default index;

위와 같은 방법으로 값을 넘겨줄 수 있다.

 

숫자를 넘겨줄때는 {}를 사용한다.

app.js

import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';

function app() {
  return (
    <div>
      <Header />
      <Main name={9} color="red"/>
      <Footer />
    </div>
  );
}

export default app;

 

프로퍼티의 Type

- 프로퍼티의 자료형을 미리 선언할 수 있다.
- 리액트 엔진이 프로퍼티로 전달하는 값을 효율적으로 알 수 있고, 버그예방에도 도움이 된다.
- 리액트에서 제공하는 prop-types를 이용하여 각각의 자료형을 선언하면 된다.

 

프로퍼티의 기본값 및 필수값 설정

1) 기본값 설정

 - 컴포넌트에 props 기본값을 설정하고 싶은 경우 defaultProps를 설정하면 된다.

ex) Main.js (name 프로퍼티가 없는 경우, '디폴트'라는 값을 사용 하게 처리)

import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.

function Main({name, color}) {
    return (
        <div>
            <main>
                <h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
            </main>
        </div>
    );
}

// 프로퍼티 타입 지정
Main.propTypes = {
  name: PropTypes.string
}

// 프로퍼티 기본값 지정
Main.defaultProps = {
  name: '디폴트'
}

export default Main;

app,js

import React, { Component } from 'react';
import Header from './component/Header';
import Footer from './component/Footer';
import Main from './component/Main';

function app() {
  return (
    <div>
      <Header />
      <Main color="blue"/>
      <Footer />
    </div>
  );
}

export default app;

 

2) 필수값 설정

- 디폴트 설정을 하지 않는 경우 해당 프로퍼티를 필수 프로퍼티로 선언 할 수도 있다.

ex) index.js (isRequired 를 통한 필수값 설정)

import React from 'react';
import PropTypes from 'prop-types' // 프로퍼티 타입을 지정해주기 위해 사용 한다.

function index({name, color}) {
    return (
        <div>
            <main>
                <h1 style={{color}}>안녕하세요. {name} 입니다.</h1>
            </main>
        </div>
    );
}

// 프로퍼티 타입 지정 및 필수값 설정
Main.propTypes = {
  name: PropTypes.string.isRequired,
}

export default index;

 

LTS 버전 : 안정적이고 신뢰되는 버전 

최근 버전은 모듈이 호환이 안되는 경우가 많다.

 

EC2는 명령어를 통해 설치를 해야한다.

데이터 베이스는 전부다 올리면 안된다. > gitignore을 통해 올리지 않는다.

 

JWT

를 하기 전에 알아야하는 개념은 OAuth에 대해 알아야한다.

OAuth(Open Authorization)

- 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 어플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는 접근 위임을 위한 개방형 표준 

- 즉, 서드파티 어플리케이션이 사용자의 계정에 접근할 수 있는 권한을 부여하기 위한 프로토콜

 

현재는 OAuth 2.0을 사용하고 있다.

 

- JWT는 웹 애플리케이션에서 정보를 안전하게 전송하기 위한 간단한 방법

- 인증된 사용자를 식별하거나 데이터에 서명을 하여 변조를 방지하는 데 사용

- 모두가 열어봐서 확인할 수 있기 때문에 중요한 정보(EX 비밀번호)는 담으면 안된다.

- 암호화는 되어 있지만 언제든지 해석할 수 있다.

 

JWT 구성

- Header

- Payload

- Signature : 위의 두개의 조합에 비밀 키를 사용해 생성

 

작동 방식

주요함수

sign : 서버측에서 JWT를 생성할 때 사용

jwt.sign(payload, secretOrPrivateKey, [options, callback])

verify : 클라이언트나 서버에서 받은 JWT의 유효성을 검증할 때 사용

jwt.verify(token, secretOrPrivateKey, [option, callback])

사용하기

npm i jsonwebtoken

 

jwt 해보기

npm init -y

npm i express jsonwebtoken

으로 express와 jsonwebtoken을 설치하고 아래와 같이 적은 후

import express from 'express';
import jwt from 'jsonwebtoken';
const app = express();
const SECRET = 'secretkey'

app.use(express.urlencoded({extended:true}))
app.use(express.json())

app.post('/login', (req, res)=>{
    const { id } = req.body;
    const token = jwt.sign({id}, SECRET);
    console.log(token);
})

app.listen(8080, ()=>{
    console.log('연결')
});

서버를 연다 그 이후엥 포스트 맨에서 객체 형태로 보내면

vscode에 다음과 같은 문장이 온다 이를 jwt에 입력하면 어떤 것을 받았는지 확인할 수 있다.

 

토큰을 보내는 방법

저기서 토큰에 받은 토큰을 보내면 된다. 전부다 받을려면 

req.headers로 더 많은 정보를 맏을 수 있고, 토큰 값만 받을려면

app.post('/verify', (req, res) => {
    console.log(req.headers.authorization);
    const auth = req.headers.authorization;
    const token = auth.split(' ');
});

이와 같이 입력하고 다시 보내면 된다.

 

jwt 를 검증하는 코드

app.post('/verify', (req, res) => {
    console.log(req.headers.authorization);
    const auth = req.headers.authorization;
    const token = auth.split(' ');
    if( token[0] === 'Bearer') {
        jwt.verify(token[1], SECRET, (err, decoded) => {
            if( err ) {
                return res.send({result : false, message : '검증 실패'});
            }
            res.send({result : true, user : decoded});
        });
        // 여기서 바로 옆 애를 변수 선언하고 리턴을 할 경우 트라이캐치문으로 받아야하기 때문에 콜백함수 형태로 사용한다
    }else {
        res.send({ result : false, message: '올바른 인증 방식이 아닙니다.' })
    }
});

err의 명확한 상태값을 보내주기 위해선 

.status(오류 상황에 대한 숫자)

를 적으면 된다.

 

 

서버배포

인스턴스 생성 -> 인증키 ppk로 다운로드 (pem은 맥 전용) -> 탄력적 ip 할당 -> 만든 인스턴스에 연결 -> putty로 퍼블릭 ip 입력 후 포트 22에 연결 -> SSH의 크리덴션로 들어가 인증키 입력하여 open -> ubuntu 입력하여 연결

 

nginx 설치

sudo apt-get update -> 관리자 업데이트 apt-get 라잌 npm 

sudo apt-get install nginx -> nginx 설치

sudo systemctl start nginx -> 안되면 실행해보기

그래도 안되는데 어떻게 해야하지...알고보니까 보안 그룹의 인바운드 규칙 설정으로 http 규칙 생성을 안해서 그랬던 거였다. 미리 그걸 했으면 좋았을텐데..

 

대음 연 서버에 나의 프로젝트 넣는법

sudo vi /etc/nginx/sites-available/원하는이름.conf

이후 입력하는 방법 i 누르면 입력상태로 바뀜

i 입력하고 위와 같이 입력 그 후 esc 누르면 입력 커서 사라짐

-> :wq

하고 파일 이동

cd /etc/nginx/sites-available

 

디폴트 파일 옮기기

sudo cp -r /etc/nginx/sites-available/ /etc/nginx/sites-avail-origin

 

사용할 파일의 디폴트 파일 삭제하기

 디폴트 파일의 역할이 뭘까..?

sudo rm /etc/nginx/sites-available/default

 

nginx에는 test.conf 파일이 sites-available과 sites-enabled 두 곳에 있어야한다.

sudo ln  -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled/test.conf

 

nginx가 서버를 열고 파일을 찾을 때, sites-available과 sites-enabled에서 파일을 찾기 때문에 그곳으로 파일을 옮기고, 디폴트 파일을 삭제하는 것이다. 

 

디포트 파일은 우리가 nginx를 설치하고 퍼블릭 ip로 검색을 했을때 나오는 페이지이다. 그렇게 때문에 디폴트를 지워야 우리가 원하는 파일을 연결할 수 있다.

 

enabled의 디폴트 파일 백업

sudo cp -r /etc/nginx/sites-enabled/ /etc/nginx/sites-enabled-origin

 

enabled의 디폴트 파일 삭제

sudo rm /etc/nginx/sites-enabled/default

 

설정이 제대로 되어있는지 확인

sudo nginx -t

 

noginx 재시작

sudo systemclt restart nginx

 

이렇게 한 후에 타력적 ip를 치면 

이 화면이 뜨는데 정상적인 화면이다. 디폴트 파일을 지워줬고 아무것도 없기 때문이다.

 

cd ~

git -version

깃 버전확인

깃 클론하기

git clone '자기프로젝트 레파지토리 주소'

 

 

GitHub - nodesource/distributions: NodeSource Node.js Binary Distributions

NodeSource Node.js Binary Distributions. Contribute to nodesource/distributions development by creating an account on GitHub.

github.com

여기서 Node.js LTS에서 Using ubuntu bash까지 복붙해서 실행

Node.js 설치

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash

sudo apt-get install -y nodejs 

버전 확인하기 

 

pm2 설치 (nginx에서의 nodemon

sudo npm install -g pm2

 

설치 후에 서버를 연결할 폴더까지 이동해서 npm install 하기

 

cd ~

 

ls -al

 

cd /home

 

sudo chmod 711 ubuntu/ 권한 변경

 

서버를 열 파일로 가서 pm2 start index.js

 

하면 연결 성공!

 

데이터베이스 연결하는법

aws의 RDS에서 데이터베이스를 만들고 엔드포인트를 원래 mysql 연결하는 url에 입력하면 된다.

 


정리하기

 

default파일 백업하기
sudo cp -r /etc/nginx/sites-available/ /etc/nginx/sites-available-origin
sudo cp -r /etc/nginx/sites-enabled/ /etc/nginx/sites-enabled-origin
 
 
default파일 삭제하기
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default
 
새로운 conf파일 생성
sudo vi /etc/nginx/sites-available/test.conf
 
conf파일 만들기(백엔드)
server {
          listen 80;
          server_name 아이피주소;
          location / {
                    proxy_pass http://127.0.0.1:포트;
           }
}
 

위에서 적었던건 리액트 할때 즉, 프론트엔드를 할때 이용하는 거라고 한다. 미리 준비해서 알려줬다면 좋았을거 같다.

그리고 이럴경우 

이런 에러가 뜨는데 이는 권한이 허용이 안되서 그렇다고 한다 이럴때는 시작할때 앞에 sudo를 치거나

저장을 할때 :w !sudo tee % > /dev/null 이렇게 작성하면 된다고한다.

 
 
심볼릭 파일만들기
sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled/test.conf
 
설정확인
sudo nginx -t
ok가 떠야함!!
 
nginx 재시작
sudo systemctl restart nginx
 
500에러시 권한 변경
cd ~
cd /home
sudo chmod 711 ubuntu/

 

오늘은 너무 돌아가는 거 같았다 분명 우리가 따라가지 못하는 점도 있지만 미리 백엔드 전용으로 test.conf 파일을 만드는 법을 알려주셨으면 오늘 하루종일 nginx로 서버 배포를 하는 과정만 진행하지는 않았을 것이라 생각한다. 정리해주신 부분을 처음에 알려주고, 사용되는 리눅스 용어는 어떤 기능을 하는지 vi는 정확히 어떤 것이며, 심볼릭 링크는 무엇인지 nginx를 실행하기 위한 흐름이 어떤지를 한 번  더 정리해주셨다면 정말 좋았을 것 같다.

 

 

 

 

 

 

 

 

 

usestate

>> let [글제목, b] = useState(['내용1', '내용2', ...]);

 

Warning 메세지는 앱을 실행하는데에는 큰 문제가 없는 메세지이다. 이를 없애는 방법은 코드의 맨 위에

/* eslint-disable */ 

를 사용하면 된다 (Lint 기능을 끈다.)

 

- 좋아요 버튼& 갯수 UI 만들기

좋아요 옆에 들어가는 숫자를 state로 만들자

let [좋아요, c] = useState(0);

 

클릭했을때 원하는 기능을 실행하기 위해선 onClick을 사용하면된다. 이를 보통 이벤트 리스너라고 한다.

onClick은 태그 바로 옆에 선언해서 사용할 수 있다. onClick = {함수이름}을 넣어서 사용할 수 있다.

 함수 이름 안에 그냥 함수를 넣어도 된다. ( function()이나 ()=>를 넣어도 된다.)

- state를 변경하는 법

좋아요 = 좋아요 + 1 등호를 이용해 바꿀 수  없다.

이럴때는 state 변경 함수를 써야한다.

state를 변경하면 html이 재랜더링이 된다.

이를 사용하는 방법은 따봉변경(원하는 기능 적기)

위의 경우에는

이렇게 하면 좋아요 이모티콘을 누를때마다 이모티콘 옆의 숫자가 증가한다.

 

state를 변경할때는 무조건 변경함수를 이용해야한다.

 

array object state 변경하는법

이런 방법으로 글제목을 바꿀 수 있다 하지만 이렇게 사용하면 확장성이 부족함으로 

위와 같이 인덱싱 방법으로 하는 것이 더 빠르다. 

하지만 array나 object를 다룰 때는 원본을 보존하는 것이 좋기 때문에 원본은 보존하는 것이 좋다. 그렇기 때문에 내용을 수정할 복사본을 따로 만들어 사용할 수 있다.

여기서 복사본 [...글제목]에서 글제목 앞에 ...을 붙여서 위와 같이 만들어야만 변경이 된다. 

이렇게 해야하는 두가지 이유가 있는데

첫 번째는 기존 state의 값과 신규 state의 값이 같을 경우 변경을 해주지 않는 state 변경함수의 특징 때문이다. 

두 번째는 array/object 담을때 다음과 같이 let arr = [1, 2, 3] 처럼 지정할 경우 1,2,3을 가리키는 주소만 지정되기 때문에 내용이 바뀌지 않는다 그렇게 때문에 ...을 사용해야지 데이터를 직접 수정할 수 있다.

 

여기서 글제목은 array 데이터가 아니라 그 저장 공간의 주소 혹은 위치를 가르키는 화살표라고 생각할 수 있다.

그래서 copy == 글제목을 비교하면 항상 같다고 나온다.

 

결론적으로 ...은 괄호를 벗기고 그 안의 데이터를 가져오는 것이다.

 

 

+ Recent posts