Coding/Today I Learned (148)

08
13

따로 배울땐 몰랐어요...다 합쳐야 한다는 것

1. Redux?

  • React에서 state를 사용할 때 상위에 있는 부모에서 자식으로 점점 state를 props로 전달하게 된다. 이때, 만약 컴포넌트가 너무 많아서 한 10개쯤 거쳐서 전달해야 한다면? 너무 복잡해서 고통스러울 것이다. 유지보수도 마찬가지이다.
  • 이런 state를 어디서든 접근 가능한 하나의 저장소에 저장해서 어떤 컴포넌트에서든 접근할 수 있게 만든 것이다.
  • 그 저장소는 꼭 지정된 함수를 이용해 수정할 수 있게 하면 state가 실수로 수정되는 경우도 없을 것이다. 마치 setState 함수처럼 말이다.

2. 생긴 모양을 구분해서 동작원리를 살펴보자.

  • store : 우리가 만든 정보가 저장되는 공간.
    • state : 진짜 우리가 저장한 정보 (절때 직접 접근은 불가능)
    • reducer : state값을 바꿀 수 있는 함수.
    • dispatch : 2개의 값(지금 state와 action)을 reducer에 전달하고 subscribe를 호출해 준다.
      • action : UI에서 일어난 일들의 여러 가지 타입을 가진다. 이때 맞는 타입을 찾아 가공하고 가공한 데이터를 dispatch로 전달한다.
    • subscribe : reder함수를 '구독' 한다. state값이 바뀔 때마다, reder함수를 호출시켜준다. 
    • getState : render에서 UI정보를 받아서 state에 전달해 주며, 값이 다른 함수들에 의해 변경된 후에 다시 render로 바뀐 값들을 보내서 우리가 보는 화면을 만들어 준다. 즉, state에 접근할 수 있는 정상적인 방법이다.
  • render : UI를 만들어주는 그 렌더되어서 우리가 직접 보는 코드. 

출처: https://www.youtube.com/watch?v=F_NLNBOqZrQ&list=PLuHgQVnccGMB-iGMgONoRPArZfjRuRNVc&index=5 (생활코딩 Redux-2.3)

3. Redux로 시간여행을 하자!

  • Redux Devtools을 이용하면, 모든 state의 변경 상황을 다 알 수 있다. git 쓸 때처럼, 변화가 생긴 어떠한 상황으로도 돌아갈 수 있으며, 어떤 상황이 변경되었는지도 다 알 수 있기 때문에 매우 편리하다.

https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en 

 

Redux DevTools

Redux DevTools for debugging application's state changes.

chrome.google.com

 

4. 각 Redux 함수의 생김새

  • Reducer, Action
function reducer(oldState, action) {
	if(action.type === 'create') {
    	// type의 종류는 다양하다. 여기에서는 뭔가 input내용을 추가한다 던지 하는 create
        // 무언가 조작 되겠지?
    } 
}

let store = Redux.createStore(reducer) 
// 위의 코드가 store를 만들고 reducer까지 함께 만들어 주는 코드이다.

 

  • Render, Subscribe
function render() {
	let state = store.getState(); 
    document.querySelector('#app').innnerHTML = "
    	<h1>Hello World!</h1>
    " } 
        
store.subscribe(render);

 

  • Dispatch
<form onsubmit= "
	store.dispatch({type: "create", payload:{title: title, desc: desc}}) 
" />

 

COMMENT
 
08
12

누르면 스토리북 홈페이지로 이동합니다.

1. Storybook?

  • 일명, 컴포넌트 탐색기
  • 모든 컴포넌트들을 각각 따로 한꺼번에 보면서 테스트해 보는 일을 할 수 있다. 진짜 우리 컴퓨터에 있는 '탐색기'를 생각하면 된다.

2. 굳이 왜 사용하죠?

  • 그렇다. 안 써도 된다. 하지만 쓰면 더 행복해진다.
  • 프로젝트를 완성시켜 놓고 컴포넌트에 어떤 부분을 수정하려고 하면 어디 있는지 찾는 일부터, 혹시나 있을 예상 하지 못한 결과를 프로젝트 안이 아닌 밖에서 미리 해 보고 적용할 수 있다.
  • 다른 개발자나 디자이너들과 협업을 할 때도 확실히 보여줄 수 있기 때문에 편리하다!

3. 기본 셋팅

  • npx degit chromaui/intro-storybook-react-template taskbox로 기본 프로젝트를 설치한다. 리액트로 돌아가기 때문에 리액트 앱을 하나 설치하는 샘이다.
  • cd taskbox로 들어가 실행한다.
  • npx -p @storybook/cli sb init으로 현재 만들고 있는 프로젝트에서도 설치가 가능하다.

4. 어떻게 사용할까?

  • Vs 코드로 실행시켜서 components폴더를 만든다.
  • 안에 각각의 원하는 컴포넌트의 폴더를 만들어 그 안에 js파일을 만든다.
  • 그리고 작업 후에 다시 스토리북 react파일을 npm run storybook로 실행시켜 보면, 만든 ui를 볼 수 있다.
  • Backpack UI에 다양한 대모가 있다. 참고하면 고수들의 작업물을 따라 만들 수 있을 것이다.

https://storybook.js.org/tutorials/intro-to-storybook/react/ko/get-started/

 

React를 위한 Storybook 튜토리얼

Storybook을 개발 환경에 설치해봅시다

storybook.js.org

https://storybook.js.org/docs/react/get-started/examples

 

Example Storybooks

Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular

storybook.js.org

  • 위의 두 가지 사이트를 잘 돌아본다면 더 편하게 사용할 수 있을 것이다.
COMMENT
 
08
09

거의 '마약' 같습니다. 하지만 안심하세요! 합법입니다!!

1. Styled Components?

  • JS파일 안에서 간단하게 CSS작업을 할 수 있게 된다.
  • 파일이 하나뿐이라고?? => 용량이 적다 + 직관적이다 + 작성할 때 빠르다.
  • className도 많이 사용하지 않기 때문에 중복이나 오타를 막을 수 있고, 어떤 부분이 잘 못 되어 있는지 찾기 편해서 유지 보수도 편하다.

2. 어떻게 사용할 수 있을까?

  • npm install --save styled-components으로 설치한다.
import styled from "styled-components";

const Text = styled.h2`
  font-size: 5em;
  margin: 1em;
  color: #d90429;
`;

const BackGround = styled.section`
  padding: 5em;
  background: #d9ed92;
`;

export default function App() {
  return (
    <BackGround>
      <Text>Hello Styled Components!</Text>
    </BackGround>
  );
}

위 코드를 Sandbox에서 만들었다.

3. Props 사용하기

  • 컴포넌트를 재활용 할 때 사용할 수 있다.
  • 이때, props로 주어진 style이 우선으로 적용된다.
  • props 자체로 style이 직접 적용되어서 className은 역시 필요 없다!
  • 다른 속성이나 수치도 줄 수 있기 때문에 state 없이, 애니메이션 스피드 적용에도 탁월하다.
  • useRef를 이용하면 이벤트 이후, 일어나는 리 렌더링에 대해 데이터를 방어할 수 있다. 예를 들어, 동영상 재생, 멈춤 버튼을 눌렀을 때 페이지가 렌더링 된다면, 동영상은 계속 시작점으로 돌아가 버려서 똑바로 재생될 수 없을 것이다. 이때, 재생, 멈춤 버튼을 useRef로 사용하면 재생, 멈춤 버튼이 눌릴 때, 그 버튼의 동작만 하고 렌더링은 되지 않기 때문에 잘 작동하게 된다.
import styled from "styled-components";

const Text = styled.h2`
  font-size: 3em;
  margin: 10px;
  color: #d90429;
  text-shadow: ${(props) => (props.shadow ? '5px 5px 10px #f72585' : 'none')}
    `;

const BackGround = styled.section`
  padding: 0.5px;
  background: #d9ed92;
`;

export default function App() {
  return (
    <BackGround>
      <Text>Hello Styled Components!</Text>
      <Text shadow>This is Shadow Text</Text>
    </BackGround>
  );
}

shadow를 props로 주어 그 부분만 그림자를 주었다.

 

COMMENT
 
08
08

누르면 Express API들을 확인 할 수 있는 공식문서로 이동합니다. 한번은 내용을 읽어보시는것을 강력히 추천드립니다. 번역기를 돌려도 좋습니다.

1. req.query

  • 요청에 따라 그에 맞는 라우터 경로의 매개 변수를 입력해 주면 그 값을 반환해준다.
  • URL에서 보면? 뒤에 존재하는 값을 'Querystring'라고 하고, 그것을 반환하는 것이다.
  • 하나의 라우터로 Querystring을 바꿔 주어서 비동기적으로 path값과 상관없이 다른 값을 줄 수 있다는 말이다!
// GET /search?q=tobi+ferret
console.dir(req.query.q)
// => 'tobi ferret'

2. req.params

  • 요청에 따라 그에 맞는 라우터 경로의 매개 변수를 입력해 주면 그 경로를 반환해 준다.
  • 말 그대로, URL 경로 부분을 얻을 수 있다.
  • req.path보다 더 주로 쓰인다. (req.body도 마찬가지)
// GET /user/tj
console.dir(req.params.name)
// => 'tj'

3. express.json();

  • 객체 형태의 데이터를 json형식으로 간단하게 바꿔주는 express에 딸린 기능.
  • 옛날에는 'body parser'라고 하면서, 거창하게 사용하였지만 express v4.16.0 이상이라면 저렇게 사용하면 된다.
const express = require("express");
const app = express();
const port = 3001;

app.use(express.json());

app.post("/", function(req, res) {
	console.log(req.body);
		res.send(req.body);
})

app.listen(port, () => {
  console.log(`[RUN] http://localhost:${port}`);
});

4. express.static();

  • html 문서를 서버에서 가져올 때 연결되어 있는 css나 js 파일은 함께 가져오지 않는다. 이때, 모든 파일들을 static으로 설정한 폴더 안에 넣어놓고 경로를 맞춰주면 모두 다 같이 딸려오게 된다.
const express = require("express");
const app = express();
const cors = require("cors");
const path = require("path");

const PORT = 5000;
const ip = "localhost";

app.use(express.static("public"));
app.use(express.json({ strict: false }));
app.use(cors());

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "../public", "index.html"));
});

app.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

// 서버가 데이터를 가공하는 부분은 생략.

5. express.path();

  • 경로를 굳이 쓰지 않아도 상대적 경로로 표현할 수 있다.
  • '__dirname'은 지금 서버가 실행되고 있는 폴더가 된다. 그곳부터 다시 찾아서 원하는 경로로 가면 된다.
  • 예시는 위에 static에서 사용되고 있기 때문에 생략한다!
COMMENT