Giter VIP home page Giter VIP logo

fe_growing's Introduction

Hello, I'm HyunJu๐Ÿ‘

Hits

โœจ Front-end Stack โœจ



โœจ Cowork tools โœจ


Anurag's GitHub stats Top Langs

fe_growing's People

Contributors

leemember avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

rheehot

fe_growing's Issues

โญ๏ธ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€ ํด๋ฆญ ์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ id ๊ฐ’์— ๋งž์ถฐ ์ฝ˜ํ…์ธ  ๋งตํ•‘๋˜๊ธฐ

๊ฒŒ์‹œํŒ ์ž‘์—…์‹œ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€ ํด๋ฆญํ•˜๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ id๊ฐ’์— ๋งž์ถฐ ์ฝ˜ํ…์ธ  ๋งตํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•

๐Ÿ“ api ์ฃผ์†Œ๋„

[mock.js]

server.get('/api/v1/cms/notice/detail/:boardID')`

๐Ÿ“ ๊ฒŒ์‹œํŒ ์ƒ์„ธ ํŽ˜์ด์ง€

import { useParams } from 'react-router';

// ์ƒ์„ธ ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ  ๋‚ด์šฉ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด์„œ useParams๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
// useParams๋Š” react-router์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋‹ค.

const path: BoradProps = useParams();
const [notice, setNotice] = useState<string>('');

useEffect(() => {
  if (path.boardID) {
   try {
      const getNotice = async () => {
       const data = await ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฉ”์„œ๋“œ.get(`/api/v1/cms/notice/detail/:${boardID}`);
       setNotice(data.data);
    }
     
   // ๐Ÿ’› api ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
    getNotice();
   } catch (error) {
      console.log('error---->', error);
    }
 }
},[path]);

๐Ÿ“ ๋ผ์šฐํ„ฐ

import { Route } from 'react-router';

<Route exact path={'menu/board-view/:boardID'} component={BoardView} />

๋ผ์šฐํŠธ ํ•  ์ฃผ์†Œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’๋„ boardID ์ด ๋™์ผํ•œ ๊ฐ’์œผ๋กœ ํ•ด์ฃผ์–ด์•ผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

โญ๏ธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์€ ๋™์ผํ•ด์•ผ ๋œ๋‹ค! ๊ฐ€ ์ƒ์„ธํŽ˜์ด์ง€ ๋งŒ๋“œ๋Š” ๋ฐ ํฌ์ธํŠธ๋‹ค. โญ๏ธ

๐Ÿ [์ธํ…”๋ฆฌ์ œ์ด] Prettier ์ ์šฉํ•˜๊ธฐ (์ €์žฅํ•˜๋ฉด ์ž๋™์œผ๋กœ ์ด์˜๊ฒŒ ์ •๋ ฌ)

์„ค์ •

  1. Preferences > Plugins > Prettier๋ฅผ ๊ฒ€์ƒ‰ํ•ด์„œ ์„ค์น˜ ํ›„ ์žฌ๋ถ€ํŒ…

์„ค์น˜

npm install --save-dev --save-exact prettier
๋˜๋Š”
yarn add --dev --exact prettier

๊ฒฝ๋กœ์ง€์ •

JavaScript ๊ธฐ์ค€์œผ๋กœ,
Preferences > Languages & Frameworks > JavaScript > Prettier > Prettier package์—์„œ prettier ๊ด€๋ จ๋œ ๊ฒฝ๋กœ๋ฅผ ์„ ํƒ
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-08-29 แ„‹แ…ฉแ„’แ…ฎ 4 19 03

module.exports = {
  bracketSpacing: false, // ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์˜ ๊ด„ํ˜ธ ์‚ฌ์ด์˜ ๊ณต๊ฐ„
  jsxBracketSameLine: true, // JSX ์š”์†Œ์˜ ๋งˆ์ง€๋ง‰ ๋ผ์ธ์— '>' ํŠน์ˆ˜๊ธฐํ˜ธ๋ฅผ ๊ฐ™์€ ๋ผ์ธ|๋‹ค์Œ ๋ผ์ธ
  singleQuote: true, // ์ฟผํ…Œ์ด์…˜ ๋งˆํฌ๋ฅผ 1๊ฐœ|2๊ฐœ
  trailingComma: 'all', // ๋์— ','๋ฅผ ๋ถ™์ž„('es5'(๊ธฐ๋ณธ), 'none', 'all' 3๊ฐœ์˜ ์˜ต์…˜)
  tabWidth: 2, // ํƒญ์˜ ๋„“์ด
};

๋” ๋งŽ์€ ์˜ต์…˜๋“ค

https://prettier.io/docs/en/options.html

ํ•ด๋‹น ๊ฒฝ๋กœ์— ์žˆ์„ ๋•Œ๋งŒ ์ ์šฉ๋˜๋„๋ก (current link)

import { Outlet, useLocation } from 'react-router-dom'; ๋ฆฌ์•กํŠธ ๋ผ์šฐํŠธ ๋”์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” useLocation์€ window.location์„ ์˜๋ฏธํ•œ๋‹ค.

์ด๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ์ด๋Ÿฌํ•˜๋‹ค.

  • hash
  • pathname
  • search
  • state
    const useLink = currentLocation.pathname.split('/')[1];

pathname์€ /project/ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’ ์ด๋ ‡๊ฒŒ ์ถœ๋ ฅ ๋˜๋Š”๋ฐ, / ์ด ์ง๋Œ€๊ธฐ ๊ธฐ์ค€์œผ๋กœ ๋‹จ์–ด๋“ค์„ ์ชผ๊ฐ  ํ›„ ๋ฐฐ์—ดํ™”์‹œ์ผœ์„œ ๊ฑฐ๊ธฐ์„œ project๊ฐ€ ์žˆ๋Š” ๊ฐ’์„ ๋ฝ‘์•„๋‚ด๋ฉด ๋œ๋‹ค.

์‹ค์ œ๊ฐ’ -> ["", "project", "ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’"] ์ด๋ ‡๊ฒŒ ์ถœ๋ ฅ๋ผ ๋‚˜์˜จ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’์€ project์ด๊ธฐ ๋•Œ๋ฌธ์— const useLink = currentLocation.pathname.split('/')[1]; ์ด๋ ‡๊ฒŒ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด๋‹ค. [1]

์กฐ๊ฑด์‹

const sameLink = (bgImgLink: string) => {
        switch (bgImgLink) {
            case 'project':
            case 'document':
            case 'member':
            case 'faq':
                return false;
            default:
                return true;
        }
    };

project, document, member, faq ๋‹จ์–ด๊ฐ€ ๋“ค์–ด๊ฐ„ ๋งํฌ์—๋Š” wrap์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•„์„œ, switch ๋ฌธ์œผ๋กœ ํ•ด๋‹น ๋งํฌ์ผ ๋•Œ๋Š” split์œผ๋กœ ์ชผ๊ฐ  ํ˜„์žฌ ์œ„์น˜๋ฅผ ๋„ฃ์–ด์„œ return ์‹œ false์œผ๋กœ ์ถœ๋ ฅ๋˜์ง€ ์•Š๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” wrap์ด๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ ์šฉ๋˜๋„๋ก default ๊ฐ’์„ ture๋กœ ํ•ด์ฃผ์—ˆ๋‹ค.

๐Ÿ˜ ์ ์šฉํ•œ ํƒœ๊ทธ

<div className={cx('ctnbody', sameLink(useLink) && 'wrap')}>
      <Outlet />
 </div>

์ด์ฒ˜๋Ÿผ sameLink ๋ผ๋Š” ํ•จ์ˆ˜์— useLink ๋ผ๋Š” ์ชผ๊ฐ  ํ‚ค์›Œ๋“œ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ์–ด์„œ ๊ทธ๊ฒŒ ํ•ฉ๋‹นํ•˜๋‹ค๋ฉด wrap์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ ์šฉ ํ•˜๊ฑด ๋ง๊ฑด ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

๊ฒฐ๊ณผ

project, document ... ๋“ฑ๋“ฑ์„ ์ œ์™ธํ•œ ๋‚˜๋จธ์ง€ ํŽ˜์ด์ง€๋“ค์€ wrap์ด๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์ ์šฉ๋๋‹ค.

์œ„ ์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „ ์‹ค์ˆ˜ํ–ˆ๋˜ ๊ฒƒ๋“ค.

OR ์—ฐ์‚ฐ์ž์ธ || ๋ฅผ ์‚ฌ์šฉํ•ด์„œ

<div className={cx('ctnbody', sameLink('project' || 'member' || 'faq') && 'wrap')}>
      <Outlet />
 </div>

์ด๋ ‡๊ฒŒ ํ–ˆ์—ˆ๋Š”๋ฐ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ๊ฐ’๋งŒ ์ธ์ •๋๋‹ค. ๊ทธ๋ž˜์„œ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์•ˆ๋‚˜์™”์Œ. ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฒŒ ํ•˜๋ ค๋ฉด switch ๋ฌธ์œผ๋กœ ์กฐ๊ฑด์‹์„ ์ œ๋Œ€๋กœ ๊ฑธ์–ด์„œ ์ž‘์—…ํ•ด์•ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค.

์ฐธ๊ณ ํ•˜๊ธฐ : https://ko.javascript.info/nullish-coalescing-operator

๐Ÿ˜‡ ๋ฆฌ์•กํŠธ CRA ์ƒ์—์„œ ํ•ซ๋ฆฌ๋กœ๋“œ ์„ค์ •

ํ•ซ ๋ฆฌ๋กœ๋“œ ์„ค์ •ํ•˜๊ธฐ

  • ์ €์žฅํ•˜๋ฉด ์•Œ์•„์„œ ์ž๋™์œผ๋กœ ๋ฐ˜์˜๋œ๋‹ค.

$npm i react-hot-loader ์„ค์น˜ํ•˜๊ธฐ

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Board1 from './pages/board1';
import Board2 from './pages/board2';
import { hot } from 'react-hot-loader';

const App = () => {
    return (
        <Router>
            <Routes>
                <Route path="/" element={<Board1 />} />
                <Route path="/board2" element={<Board2 />} />
            </Routes>
        </Router>
    );
};

export default hot(module)(App);

๐Ÿ’ฉ ๋ฆฌ์•กํŠธ ํด๋ง Polling ํ•˜๋Š” ๋ฐฉ๋ฒ• !

โœจ ๋ฆฌ์•กํŠธ ํด๋ง Polling ํ•˜๋Š” ๋ฐฉ๋ฒ•

์•„๋ž˜์™€ ๊ฐ™์ด api ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ setState์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

       const domesticState = async (dayParams: {}) => {
        const rankApi = await fetcher(METHOD.GET, `/domestic/rank?toDate=${dayParams}`);
        const globalKrwApi = await fetcher(METHOD.GET, `/domestic/total?toDate=${dayParams}`);
        const coinListApi = await fetcher(METHOD.GET, `/domestic/coinList?toDate=${dayParams}`);

        setRankList(rankApi.data);
        setGlobalKrw(globalKrwApi.data);
        setCoinList(coinListApi.data);
    };

 useEffect(() => {
        let polling = setInterval(() => {
            domesticState(todayCall);
        }, 60000);

        if (clickDay.replaceAll('-', '') !== todayCall) {
            clearInterval(polling);
            domesticState(changeDay);
        } else {
            domesticState(changeDay);
        }

        // ํŽ˜์ด์ง€์— ๋ฒ—์–ด๋‚  ๊ฒฝ์šฐ polling X
        return () => {
            clearInterval(polling);
        };
    }, [clickDay]);

๊ทธ๋ฆฌ๊ณ  setInterval ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฃผ๊ธฐ ์‹œ๊ฐ„์„ ๋„ฃ๊ณ  (60000 = 1๋ถ„)
1๋ถ„์— ํ•œ ๋ฒˆ์”ฉ api๋ฅผ ์ƒˆ๋กญ๊ฒŒ call ์‹œํ‚ด์œผ๋กœ์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๋™๋˜๋Š” api๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋งŒ์ผ์— ์กฐ๊ฑด์— ๋”ฐ๋ผ polling์„ ๋ฉˆ์ถ”์–ด์•ผ ํ•œ๋‹ค๋ฉด if๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ clearInterval๋ฅผ ํ•ด์ค€๋‹ค.
clearInterval๋ฅผ ํ•ด์ค„ ๋•Œ๋Š” setInterval๋กœ id๊ฐ’์„ ๋„ฃ์–ด์„œ ์ค‘์ง€์‹œ์ผœ์ค€๋‹ค !

๐Ÿ“๊ทธ๋ฆฌ๊ณ  useEffect๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํŽ˜์ด์ง€๊ฐ€ ๋ฒ—์–ด๋‚ ๋•Œ willdidmount
๋์„ ๋•Œ๋ฅผ ์ƒ๊ฐํ•ด์„œ๋„ retrun๋ฌธ ์•ˆ์—๋‹ค๊ฐ€ clearInterval์„ ํ•ด์ค€๋‹ค.

๐ŸšŒ ๋ฐ์ดํ„ฐ fetching์‹œ config ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ

๐ŸŸก Axios

Axios๋Š” Promise ๊ธฐ๋ฐ˜์œผ๋กœ XHRHttpRequests ์š”์ฒญ์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ œ

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })

์—ฌ๊ธฐ์„œ {} ์•ˆ์— ์žˆ๋Š” ๊ฒƒ์ด params ์ด๋‹ค.


fetcher ๋ผ๋Š” ๋ชจ๋“ˆ ์ƒ์„ฑ

import axios from 'axios';
import { METHOD } from './type';

const apis = axios.create({
    baseURL: `${process.env.REACT_APP_CMS_URL}`, // ๊ธฐ๋ณธ ์„œ๋ฒ„ ์ฃผ์†Œ ์ž…๋ ฅ
});

const fetcher = async (method: METHOD, url: string, params?: any) => {
    try {
        // ๐Ÿ“ method = get, post, put, delete ์—ฌ๋ถ€ & url = baseURL ๋’ค์— ์˜ฌ api ์ฃผ์†Œ & params ๋Š” config
        const res = await apis[method](url, {params});
        return res.data;
    } catch (error: any) {
        console.log('error-->', error);
        return error;
    }
};

export default fetcher;

fetcher ๋ผ๋Š” ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์–ด์„œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์„ ๋„ฃ์–ด ๋ฐ›์•„์˜ค๋Š”๋ฐ, ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ’์— params ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ config ์˜ ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค.


params ์‚ฌ์šฉ

const res = await fetcher(METHOD.GET, `/api/v1/cms/notices`, {
            pageNo: boardInfo.pageNumber,
            pageSize: boardInfo.size,
            categoryId: boardInfo.categoryId
        });

fetcher ๋ผ๋Š” ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ์ด๋‹ค. ์„ธ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ฐ”๋กœ config ์—ญํ• ์„ ํ•˜๋Š”๋ฐ, ์ด config๋Š” api ์ฃผ์†Œ์ธ /api/v1/cms/notices์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์—ญํ• ์„ ํ•ด์ค€๋‹ค. /api/v1/cms/notices?pageNo=${boardInfo.pageNumber}?pageSize=${boardInfo.size}?categoryId=${boardInfo.categoryId} ๋ผ๊ณ  ๋ณด๋ฉด๋œ๋‹ค.

config ํƒ€์ž… AxiosRequestConfig

axios.get(url: string, config?: AxiosRequestConfig<any> | undefined)

์ด๋Ÿฐ์‹์œผ๋ฃจ ์ง€์ •ํ•˜์—ฌ

const res = await axios.get('https://fake-api.kindacode.com/tutorials', {
        params: {
          paramOne: 'one',
          paramTwo: 'two',
          paramThree: 'three',
          foo: 1,
          bar: 2,
        },
      });

์ด๋ ‡๊ฒŒ config ๊ฐ’์„ ๋„˜๊ฒจ ์ค„ ์ˆ˜๋„์žˆ๋‹ค. ๋„˜๊ฒจ์ค„ ๋•Œ๋Š” params ๋ผ๋Š” ๋ช…๋ช…์œผ๋กœ ๋„˜๊ฒจ์ค˜์•ผํ•œ๋‹ค.
์ € ์œ„์—์žˆ๋Š” ๋‚ด์šฉ๊ณผ

https://fake-api.kindacode.com/tutorials?paramOne=one&paramTwo=two&paramThree=three&foo=1&bar=2

์ด url์€ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ’์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

์ฐธ๊ณ  : https://www.kindacode.com/snippet/axios-passing-query-parameters-in-get-post-requests/

๐Ÿง [React] react-moment, moment.js ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์‹œ๊ฐ„

moment.js

  • ์‹œ๊ฐ„์ด ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์กฐ์ž‘ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํŽธ๋ฆฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝ ๋˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ๋ผ๋ฉด ์‚ฌ์šฉํ•ด๋ณผ๋งŒ ํ•˜๋‹ค.
  • moment์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์„ค๋ช…๋ฒ•์€ ๋งจ ์•„๋ž˜์— ๊ธฐ์žฌ ์˜ˆ์ •

์„ค์น˜

$npm i moment

์„ ์–ธ

import moment from 'moment';
import 'moment/locale/ko';

ํ˜„์žฌ ์‹œ๊ฐ„

const nowTime = moment().format('YYYY-MM-DD HH:mm:ss');
console.log('ํ˜„์žฌ ์‹œ๊ฐ„', nowTime);

์ด ์ƒํƒœ๋ผ๋ฉด F5 ํ‚ค๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ๋งŒ ์‹œ๊ฐ„์ด ๋ณ€๊ฒฝ๋œ๋‹ค.

setInterval ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ๋ฐ˜์˜ํ•˜๊ธฐ

  • ์‹ค์‹œ๊ฐ„์œผ๋กœ ์‹œ๊ฐ„์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ ์‹œํ‚ฌ ๋•Œ๋Š” setInterval์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.
  • ๋‹ค๋งŒ, ๋ฆฌ์•กํŠธ ํ›…์—์„œ setInterval์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ฐธ๊ณ  https://overreacted.io/making-setinterval-declarative-with-react-hooks/

๊ฐ„๋žต ์„ค๋ช…ํ•˜๋ฉด, ๋‹ค์†Œ ์ง๊ด€์ ์ด์ง€ ์•Š๋‹ค.

  useInterval(() => {
    // Your custom logic here
    setCount(count + 1);
  }, 1000);

์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๋” ์ถ”์ฒœํ•œ๋‹ค. ์™œ๋ƒ๋ฉด, ์ด๊ฒƒ๊ณผ setInterval์˜ ์ฐจ์ด์ ์€ ์ธ์ˆ˜๊ฐ€ '๋™์ '์ด๋‹ค.

  • ์•„๋ฌดํŠผ ์ด๋Ÿฐ ๋ณตํ•ฉ์ ์ธ ์ด์œ ์™€ ์„ฑ๋Šฅ์ƒ์˜ ์ด์Šˆ ๋•Œ๋ฌธ์— ์ปค์Šคํ…€ hook์„ ์ƒ์„ฑํ•˜์—ฌ setInterval์„ ์‚ฌ์šฉํ•  ์ˆ˜ ๊ฐ€ ์žˆ๋‹ค.

์ปค์Šคํ…€ use Hooks setInterval

// useInterval.js ์ž‘์„ฑ
import { useRef, useEffect } from "react";

export default function useInterval(callback, delay) {
    const savedCallback = useRef();

    useEffect(() => {
      // useEffect์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ์ฝœ๋ฐฑ์„ ํ˜„์žฌ Ref๋กœ ์„ ์–ธํ•ด์ค€๋‹ค.
      savedCallback.current = callback;
    });

    useEffect(() => {
      function tick() {
        savedCallback.current();
      }
        // useEffect์— Ref์˜ current๋ฅผ setInterval๋ฅผ delay ์‹œ๊ฐ„๋™์•ˆ ํ•ด์ค€๋‹ค.
      let id = setInterval(tick, delay);
      // ์–ธ๋งˆ์šดํŠธ๋˜๊ธฐ์ „ clearInterval์„ ํ•ด์ค€๋‹ค.
      return () => clearInterval(id);
    }, [delay]);
  }

๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ, react-use์˜ useInterval ์‚ฌ์šฉํ•˜๊ธฐ

๐Ÿ“import { useInterval } from 'react-use';

const LiveTimeContainer = () => {
  const [realTime, setRealTime] = useState(Date.now());

  // useInterval
  ๐Ÿ“useInterval(() => {
    setRealTime(Date.now());
  }, 1000);

  return <div>{seconds}</div>
}

์ฐธ๊ณ  https://haranglog.tistory.com/10

๐Ÿ—ž ์–•์€๋ณต์‚ฌ ๊นŠ์€๋ณต์‚ฌ ๊ฐœ๋…

4. ์–•์€๋ณต์‚ฌ ๊นŠ์€๋ณต์‚ฌ ๊ฐœ๋…

๐ŸŽˆ4-1. ์–•์€๋ณต์‚ฌ (shallow copy)๋ž€ ?

์–•์€๋ณต์‚ฌ

const obj1 = { a : b, b : 2 };
const obj2 = obj1;
 
console.log( obj1 === obj2 ); // true
console.log(obj1); // {a: 1, b: 2}
console.log(obj2); // {a: 1, b: 2}

์ด ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๋Œ€์ž…ํ•˜๋Š” ๊ฒฝ์šฐ ์ฐธ์กฐ์— ์˜ํ•œ ํ• ๋‹น์ด ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ ๋‘˜์€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ (์ฃผ์†Œ)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ด๊ฒƒ์„ ์–•์€ ๋ณต์‚ฌ๋ผ๊ณ  ํ•œ๋‹ค.

๐ŸŽˆ4-2. ๊นŠ์€ ๋ณต์‚ฌ (Deep copy)๋ž€ ?

๊นŠ์€๋ณต์‚ฌ

const dog = {a: 1, b: 2};
const cat = {...dog};
cat.a = 100;
console.log(dog === cat) // false
console.log(cat.a) // 1

...(spread) ์—ฐ์‚ฐ์ž๋ฅผ ํ†ตํ•ด ๋ธ”๋ก ์•ˆ์— dog์˜ ์†์„ฑ์„ ๋ณต์‚ฌํ•˜๋ฉฐ cat์— ํ• ๋‹นํ•˜์˜€๋‹ค. ์ด์ œ dog์™€ cat์€ ๋‹ค๋ฅธ ์ฃผ์†Œ๋ฅผ ๊ฐ–๊ฒŒ ๋˜์—ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์ฐธ์กฐ๊ฐ€ ๋‹ค๋ฅธ ๊ฒƒ.

๐ŸŸก ์ ˆ๋Œ€๊ฒฝ๋กœ ../../ ์ด๋Ÿฐ๊ฑฐ ์—†์ด ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ๊น”๋”ํ•˜๊ฒŒํ•˜๊ธฐ

ํŒŒ์ผ import ํ•ด์˜ฌ ๋•Œ ํŒŒ์ผ ๊ฒฝ๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋–จ์–ด์ง€๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•.

import fetcher from 'lib/api';
import { METHOD } from 'lib/type';
// jsconfig.json ๋˜๋Š” tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "src"
  }
}

โค๏ธโ€๐Ÿ”ฅ ๋งํฌ ๋ณต์‚ฌํ•˜๊ธฐ

https://abangpa1ace.tistory.com/255

๐Ÿ’™ document.execCommand (deprecated)

export const clip = (): void => {
  let url = '';
  const textarea = document.createElement("textarea");
  document.body.appendChild(textarea);
  url = window.document.location.href;
  textarea.value = url;
  textarea.select();
  document.execCommand("copy");
  document.body.removeChild(textarea);
}
  • url ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • textarea๋Š” ์ž„์‹œ๋กœ ์ƒ์„ฑํ•˜๋Š” textarea ์š”์†Œ๋ฅผ ๊ฐ€๋ฅดํ‚จ๋‹ค. ์ด๋ฅผ body์— ์ถ”๊ฐ€ํ•œ๋‹ค.(appendChild)
  • url์— ํ˜„์žฌ ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•œ๋‹ค.(window.document.location.href) ๊ทธ๋ฆฌ๊ณ , textarea์˜ value์— ์ด url ๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค.
  • textarea๋ฅผ ์„ ํƒํ•œ๋‹ค.(select) ๊ทธ ๋‹ค์Œ์—, execCommand('copy') ๋ฉ”์„œ๋“œ๋กœ ํด๋ฆฝ๋ณด๋“œ์— ๋ณต์‚ฌํ•œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ, ๋ถˆํ•„์š”ํ•œ textarea ๋ฅผ removeChild() ๋กœ ์ง€์›Œ์ค€๋‹ค.

ํ˜„์žฌ ๋งํฌ ์œ„์น˜

const url = document.URL;

๐Ÿ’“ useRef element (์š”์†Œ) ์žก์„ ๊ฒฝ์šฐ

useRef๋กœ ์—˜๋ฆฌ๋จผํŠธ ์žก์„ ๊ฒฝ์šฐ์—๋Š”

$elSlide ์ด๋ ‡๊ฒŒ ๋‹ฌ๋Ÿฌํ‘œ์‹œ๋ž‘ el๋กœ ๋„ค์ด๋ฐ ์ง€์ •ํ•˜๊ธฐ
์—˜๋ฆฌ๋จผํŠธ ํฌ์ปค์Šค ๋ฟ๋งŒ ์•„๋‹Œ ๊ทธ๋ƒฅ ๋ณ€์ˆ˜ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”

const variable = useRef&lt;{
   // ์Šฌ๋ผ์ด๋“œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฉˆ์ถ”๊ธฐ ์œ„ํ•œ ๊ณ ์œ  id๊ฐ’
   slideStop: number,
   // ์Šฌ๋ผ์ด๋“œ ์ „์ฒด๋„ˆ๋น„ - ์œ ์ € ๋””๋ฐ”์ด์Šค ๋„ˆ๋น„ = slide ๊ฐ€์žฅ ๋ X ์ง€์ 
   slideWidth: number,
   // ์Šฌ๋ผ์ด๋“œ X๊ฐ’ ์œ„์น˜
   slideCurrent: number,
   // ๋ฉ”์ธ Top10 ์ด๋‹ˆ?
   bTopTenMain: boolean
}>({
   slideStop: 0,
   slideWidth: 0,
   slideCurrent: 1,
   bTopTenMain: type === TopTenType.Main
});

์ด๋ ‡๊ฒŒ ๋ฌถ์–ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ.
boolearn ๊ฐ’์ด๋ฉด b๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋„ค์ด๋ฐ์œผ๋กœ ์ง“๊ธฐ
์™ ๋งŒํ•˜๋ฉด const ์‚ฌ์šฉํ•˜๊ธฐ. ๊ทธ๋ฆฌ๊ณ  ํƒ€์ž… ์ง€์ • ๊ผญ ํ•˜๊ธฐ
์ฃผ์„์€ ๋””ํ…Œ์ผํ•˜๊ฒŒ ์ ์„์ˆ˜๋ก ์ข‹๋‹ค.

๋˜‘๊ฐ™์€ && ์—ฐ์‚ฐ์ž๊ฐ€ ์ค‘๋ณต๋ผ์„œ ์‚ฌ์šฉํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ์—๋Š”

if() ์“ฐ๊ธฐ

ํƒ€์ž…์ •์˜ํ•  ๋•Œ any๋Š” ์“ฐ์ง€๋ง๊ธฐ. ํ•˜์ง€๋งŒ ๋ชจ๋‹ฌ์ผ ๊ฒฝ์šฐ๋Š” ์–ด์ฉ” ์ˆ˜ ์—†์Œ.

โœจ ์ž๋™ ์Šฌ๋ผ์ด๋“œ ๊ตฌํ˜„์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ์‹ (requestAnimationFrame)

ํšŒ์‚ฌ ์—…๋ฌด ์ž‘์—…ํ•˜๋ฉด์„œ ๊ฐ€์ƒ์ž์‚ฐ ์ฝ”์ธ ์ธ๊ธฐ TOP 10 ์˜ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ๋“ค์ด ์ž๋™ ์Šฌ๋ผ์ด๋“œ๋˜๋Š” ์ž‘์—…์„ ํ–ˆ๋‹ค.

์กฐ๊ฑด

  • ์Šฌ๋ผ์ด๋“œ ์Šคํฌ๋กค ํ–ˆ์„ ๊ฒฝ์šฐ ์Šฌ๋ผ์ด๋“œ ์ผ์‹œ์ •์ง€
    (1) ๋งˆ์šฐ์Šค ๋˜๋Š” ํ„ฐ์น˜ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ฉˆ์ถ”๊ณ  ๋• ์„ ๋•Œ 2์ดˆ๋’ค์— ์žฌ์‹คํ–‰
    (2) ์Šคํฌ๋กค ๋„ˆ๋น„ ๋๊นŒ์ง€ ๋„๋‹ฌํ–ˆ์„ ๊ฒฝ์šฐ ์Šฌ๋ผ์ด๋“œ ์ •์ง€
    (3) ์Šฌ๋ผ์ด๋“œ๋Š” ์ถ”์ฒœ ํŽ˜์ด์ง€๋ผ๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ๋งŒ ๋™์ž‘ํ•˜๊ณ  ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ๋Š” ๋ฏธ๋™์ž‘
    (4) ์Šฌ๋ผ์ด๋“œ๋Š” X์ถ• ๊ธฐ์ค€ ์ขŒ์šฐ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์›€์ง์ผ ์ˆ˜ ์žˆ๋„๋ก

์ฒซ ๋ฒˆ์งธ ๋ฐฉ์‹ (๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์Šคํฌ๋กค๋ง ๋˜๋„๋ก)

์ž๋™ ์Šฌ๋ผ์ด๋“œ ๊ตฌํ˜„์— ๋Œ€ํ•œ ๊ตฌ๊ธ€๋ง ์˜ˆ์ œ๋“ค์„ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ CSS์˜ translateX ์ขŒํ‘œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์Šฌ๋ผ์ด๋“œ ๋™์ž‘๋˜๋„๋ก ์ž‘์—…ํ•ด๋ดค๋‹ค.
๋จผ์ € ์ฒซ ํŽ˜์ด์ง€ ์ง„์ž…ํ•  ๋•Œ๋Š” ์Šฌ๋ผ์ด๋“œ ์‹œ์ž‘์ ์ธ 0๊ณผ ๊ฐ€์ƒ์ž์‚ฐ์˜ li ๊ฐ’ ๋„ˆ๋น„๋งŒํผ ์›€์ง์ด๊ธฐ ์œ„ํ•ด useState๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ์„ ์–ธํ–ˆ์Œ

const [currentPos, setCurrentPos] = useState<number>(0); // ์‹œ์ž‘์  0,   ๋ณ€๊ฒฝ๋  ์œ„์น˜๊ฐ’
  • ์Šฌ๋ผ์ด๋“œ ์Šคํฌ๋กค ํ–ˆ์„ ๊ฒฝ์šฐ ์Šฌ๋ผ์ด๋“œ ์ •์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ useEffect๋กœ ์ œ์–ด
    ๊ทธ๋ž˜์„œ slideEvent์ด๋ผ๋Š” ์Šฌ๋ผ์ด๋“œ ์ •์ง€์‹œ์ผœ์ฃผ๋Š” ์ด๋ฒคํŠธ ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ์„ ์–ธํ•ด๋†“๊ณ ,
    ์Šคํฌ๋กค์„ ํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ ์Šฌ๋ผ์ด๋“œ ์ •์ง€ 1๋ฒˆ ์ž‘์—…์„ ํ•ด์คฌ๋‹ค.

  • slideEvent ํ•จ์ˆ˜์—๋‹ค setTimeout์„ ์‚ฌ์šฉํ•ด์„œ ์ผ์ •์‹œ๊ฐ„์„ ์ฃผ๊ณ  ๋ฌดํ•œ๋ฃจํ”„ ๋Œ๊ฒŒํ•ด์„œ ์Šฌ๋ผ์ด๋“œ ๋™์ž‘๋˜๊ฒŒ ํ–ˆ๋‹ค.

useEffect(() => {
   $elSlide.current.addEventListener('scroll', slideEvent);
 
   return () => {
      if ($elSlide.current) {
         $elSlide.current.removeEventListener('scroll', slideEvent);
      }
   };
}, []);

๊ทธ๋ฆฌ๊ณ  ul ํƒœ๊ทธ์˜ ์Šคํฌ๋กค ๋„ˆ๋น„๋ฅผ useRef๋กœ ์ธก์ •ํ•ด์„œ ๋ณด๊ธฐ์— 2๋ฒˆ ์ž‘์—…ํ–ˆ๋‹ค.
x์ถ•์˜ ์Šคํฌ๋กค ๋„ˆ๋น„ ๋ฉ”์„œ๋“œ = element.current.scrollWidth
์œ ์ € ๋””๋ฐ”์ด์Šค ๋„ˆ๋น„ = element.current.clientWidth

<ul xss=removed>
    <li></li>
    <li></li>
    <li></li>
    
    (...)
</ul>

๊ทธ๋ฆฌ๊ณ  ์œ„์ฒ˜๋Ÿผ useRef๋กœ ์žก์€ ul ํƒœ๊ทธ์— ์ง์ ‘์ ์œผ๋กœ ์Šคํƒ€์ผ์„ ์ค˜์„œ currentPos ์ƒํƒœ๋ฅผ ์ œ์–ดํ–ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์ด ๋„ˆ๋น„ ์ธก์ •์„ ์ด์šฉํ•ด์„œ ์Šคํฌ๋กค์ด ๋˜๋ฉด์„œ x์ถ•์˜ ์Šคํฌ๋กค์ด ์ „์ฒด ๋„ˆ๋น„์˜ ๋์— ๋„๋‹ฌํ–ˆ์„ ๊ฒฝ์šฐ
slideEvent ์ด ์ด๋ฒคํŠธ ํ•จ์ˆ˜์—๋‹ค๊ฐ€ clearTimeout ๋ฉ”์„œ๋“œ๋กœ setTimeout ์œผ๋กœ ๋™์ž‘๋˜๋Š” ๊ฒƒ์„ ์Šฌ๋ผ์ด๋“œ ๋ฉˆ์ถ”๊ฒŒ ํ•จ
๊ทธ๋ฆฌ๊ณ  clearTimeout ํ•  ๋•Œ๋Š” ์ด๊ฒƒ๋„ useRef๋กœ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค„ ๊ณ ์œ  ์•„์ด๋”” ๊ฐ’์„ ์„ ์–ธํ•ด์•ผํ•œ๋‹ค.

const slideId = useRef&lt;{timeId: number}>({timeId: 0})
์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. ๊ทธ๋ž˜์„œ ์ด slideId๋ฅผ setTimeout์„ ๊ฑธ์–ด์ฃผ๋Š” ๊ณณ์—๋‹ค๊ฐ€ ๋Œ€์ž…ํ•˜๊ณ , clearTimeoutํ•  ๋•Œ๋Š”
clearTimeout(slideId) ํ•ด์„œ ํ•˜๋ฉด setTimeout ๊ฑธ์–ด์ค€ ๋™์ž‘๋“ค์ด ๋ฉˆ์ถ˜๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์›๋ž˜๋Š” ๋”ฑ๋”ฑํ•˜๊ฒŒ ์›€์ง์˜€๋Š”๋ฐ ์Šคํƒ€์ผ ์ชฝ์—๋‹ค๊ฐ€

transition: 5s;
transition-timing-function: linear;

์œ„์™€ ๊ฐ™์€ ์†์„ฑ์„ ๋„ฃ์œผ๋‹ˆ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์›€์ง์˜€๋‹ค.

๋ฉ”์ธํ™”๋ฉด์—๋Š” ์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋ฏธ๋™์ž‘ํ•˜๊ณ , ์ถ”์ฒœ ํ™”๋ฉด์—์„œ๋Š” ์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋™์ž‘๋˜๊ฒŒ ํ•˜๋ ค๋ฉด ์ด๊ฒƒ๋„ useEffect ์—๋‹ค๊ฐ€ ์กฐ๊ฑด๋ฌธ์„ ๊ฑธ์–ด์„œ main ํƒ€์ž…์ด ์•„๋‹Œ ๊ฒฝ์šฐ (=์ถ”์ฒœ ํŽ˜์ด์ง€ํ™”๋ฉด)์— ๋งŒ ์Šฌ๋ผ์ด๋“œ ๋™์ž‘๋˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ํ˜ธ์ถœํ•ด์คŒ์œผ๋กœ์„œ 3๋ฒˆ ์ž‘์—…๋„ ์™„๋ฃŒํ–ˆ๋‹ค,

๐Ÿ˜‡ ๊ทธ๋ž˜์„œ ๋‹ค ์ž‘์—…์™„๋ฃŒํ•˜๊ณ  ๋‚˜๋‹ˆ ์ผ์–ด๋‚œ ์ด์Šˆ

์ด๋ ‡๊ฒŒ translate๋ฅผ ์ œ์–ดํ•˜๋ฉด์„œ ์ž‘์—…ํ•˜๋‹ˆ ์Šคํฌ๋กค์ด ์•ˆ๋˜๋Š” ํ˜„์ƒ์ด ์ƒ๊ฒผ๋‹ค.
์™œ๋ƒ๋ฉด ์ด๋ฏธ translateX๊ฐ’์ด ์ง€๋‚˜๋ฒ„๋ ธ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค ;;;

๐Ÿ™ ์•„๋ฌดํŠผ ์Šคํฌ๋กค์˜ ์ „์ฒด ๋„ˆ๋น„๊นŒ์ง€ ๋„๋‹ฌํ–ˆ์„ ๋•Œ ๋ฉˆ์ถ”๊ณ  ์Šคํฌ๋กค์ด ๋˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ
ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

requestAnimationFrame , cancelAnimationFrame, scrollTo (scrollLeft) 

์œ„์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ–ˆ๋‹ค.

requestAnimationFrame ๋ž€ ?

  • ๋งˆ์น˜ setTimeout๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•ด์ฃผ๋Š”๋ฐ ์ตœ์ ํ™”๋œ ์†๋„๋กœ ๋ถ€๋“œ๋Ÿฌ์šด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ํ‘œํ˜„ํ•˜๋ฉด์„œ ์„ฑ๋Šฅ์€ ์ตœ๋Œ€ํ•œ ํ™•๋ณดํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์ค€๋‹ค. setTimeout ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฃผ๋ ค๋ฉด ๋ณ„๋„๋กœ ์Šคํƒ€์ผ๋„ ์ค˜์•ผํ–ˆ๋Š”๋ฐ ์ด ๋ฉ”์„œ๋“œ๋Š”
    ์ด ๋ฉ”์„œ๋“œ ์ž์ฒด์—์„œ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ํ‘œํ˜„๋„ ํ•ด์ฃผ๋‹ˆ ใ„ฑใ…‡ใ„ท์ž„

๐Ÿ‘‹ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ์ด๋ ‡๋‹ค.

const fnSlideRender = () => {
   if (!$elSlide.current) {
      return;
   }
 
   // ์Šฌ๋ผ์ด๋“œ X๊ฐ’ ์œ„์น˜ 0.3px์”ฉ ์›€์ง์ด๊ธฐ
   variable.current.slideCurrent += 0.3;
 
   // ์Šคํฌ๋กค X์ถ• ํ˜„์žฌ ์œ„์น˜ (scrollLeft)
   $elSlide.current.scrollLeft = variable.current.slideCurrent;
 
   // ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘ ์‹œํ‚ค๊ธฐ
   variable.current.slideStop = requestAnimationFrame(fnSlideRender);
 
   // X์ถ• ๋„ˆ๋น„ ๋๊นŒ์ง€ ๋„๋‹ฌ ์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ฉˆ์ถ”์–ด
   // ํ˜„์žฌ ์Šฌ๋ผ์ด๋“œ x๊ฐ’์ด (์Šคํฌ๋กค ์ „์ฒด ๋„ˆ๋น„ - ์œ ์ € ๋””๋ฐ”์ด์Šค ๋„ˆ๋น„) ๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ํฌ๋ฉด
   if (variable.current.slideCurrent >= variable.current.slideWidth) {
      cancelAnimationFrame(variable.current.slideStop);
   }
};

๊ธฐ๋Šฅ ์ถ”๊ฐ€

  • ์Šคํฌ๋กค ๋˜๋Š” ํ„ฐ์น˜๋กœ ์ธํ•ด ๋ฉˆ์ถฐ์ง„ ์ฝ”์ธ ์Šฌ๋ผ์ด๋“œ๊ฐ€ 2์ดˆ ํ›„์— ๋‹ค์‹œ ์›€์ง์ด๋„๋ก ํ•˜๊ธฐ

๐Ÿ‘… ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

const variable = useRef&lt;{
   // ๋ฉˆ์ถ˜ ์Šฌ๋ผ์ด๋“œ 2์ดˆ ๋’ค ์žฌ์‹คํ–‰
   timeOutRePlay: NodeJS.Timeout | 0
}>({
   timeOutRePlay: 0
});

(...)
 
const fnSameEvent = () => {
   cancelAnimationFrame(variable.current.slideStop);
 
   // setTimeout ์ด๋ฒคํŠธ๊ฐ€ 2๋ฒˆ ๊ฑธ๋ฆฌ์ง€ ์•Š๋„๋ก
   variable.current.timeOutRePlay && clearTimeout(variable.current.timeOutRePlay);
 
   // ๋ฉˆ์ถ˜ ์Šฌ๋ผ์ด๋“œ 2์ดˆ ๋’ค ์žฌ์‹คํ–‰
   variable.current.timeOutRePlay = setTimeout(() => {
      // ๋ฉˆ์ถฐ์ง„ ๊ณณ left ์œ„์น˜
      variable.current.slideCurrent = $elSlide.current?.scrollLeft || 0;
 
      // ์Šฌ๋ผ์ด๋“œ ์‹คํ–‰
      variable.current.slideStop = requestAnimationFrame(fnSlideRender);
   }, 2000);
}

setTimeout์œผ๋กœ 2์ดˆ ํ›„์— ์žฌ์‹คํ–‰ ๋˜๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  clearTimeout์„ ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด id๊ฐ’์„ ๋ฐ›์•„์™€์•ผ ํ•˜๋Š”๋ฐ useRef์—๋‹ค๊ฐ€ timeOutRePlay ๋ผ๋Š” ๊ฐ’์„ ์ €์žฅํ•ด์„œ clearTimeoutํ•  ๋•Œ ์ด์™€๊ฐ™์€ ๊ฐ’์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ clear ์‹œ์ผฐ๋‹ค.

๐Ÿณ๏ธ (warning)warning ๋ฐœ์ƒ

// addEventListener
const slideStopEvent = (eventName: string) => {
   $elSlide.current && $elSlide.current.addEventListener(eventName, fnSameEvent, { passive: true });
};
 
// removeEventListener
const slideStopCleanUp = (eventName: string) => {
        $elSlide.current && $elSlide.current.removeEventListener(eventName, fnSameEvent);
    };

addEventListener๋ฅผ ํ•ด์ค„ ๋•Œ ์ฝ”๋“œ ์•ˆ์— passive: true๋ฅผ ์„ ์–ธํ•ด์ค˜์•ผ ํ•œ๋‹ค.

๊ทธ ์ด์œ ๋Š” passive ์˜ต์…˜์˜ ๊ธฐ๋ณธ ๊ฐ’์€ ํ•ญ์ƒ FALSE๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ์ธํ•ด ํ„ฐ์น˜ ์ด๋ฒคํŠธ ๋“ฑ ์ผ๋ถ€ ์ด๋ฒคํŠธ์˜ ์ˆ˜์‹ ๊ธฐ๊ฐ€ ์Šคํฌ๋กค์„ ์ฒ˜๋ฆฌ ์ค‘์ธ ๋ธŒ๋ผ์šฐ์ € ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์ƒ๊ธด๋‹ค. ๋”ฐ๋ผ์„œ ์Šคํฌ๋กค ์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ถ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ๋ฌธ์„œ ๋ ˆ๋ฒจ ๋…ธ๋“œ์ธ window, document, touchstart, touchmove ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ๋Š” passive์˜ ๊ธฐ๋ณธ ๊ฐ’์„ true๋กœ ๋ฐ”๊ฟ”์„œ ์ ์šฉํ•œ๋‹ค.

์ด passive ์ด๋ฒคํŠธ ์ˆ˜์‹ ๊ธฐ๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ทจ์†Œํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กคํ•  ๋•Œ ๋ธŒ๋ผ์šฐ์ €์˜ ๋ Œ๋”๋ง์„ ๋ฐฉํ•ดํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋ฉ”์ธ์Šค๋ ˆ๋“œ๋ž€ ?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ ์‹คํ–‰์ด๋‚˜ ๋ธŒ๋ผ์šฐ์ € ๋ Œ๋”๋ง์„ ๋งก๋Š” ๋“ฑ ๋ธŒ๋ผ์šฐ์ €์˜ ์ฃผ๋œ ๋™์ž‘์ด ์ˆ˜ํ–‰๋˜๋Š” ๊ณณ์ด๋‹ค.

๐Ÿ”ฅ ์ž๋™ ์Šฌ๋ผ์ด๋“œ ๋ถ€๋“ค๊ฑฐ๋ฆผ ํ˜„์ƒ

๋‹ค๋ฅธ ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ์—์„œ๋Š” ์•„๋ฌด๋Ÿฐ ํ˜„์ƒ์ด ์—†์—ˆ์ง€๋งŒ ํŠน์ • ํ•ธ๋“œํฐ์ธ <์•„์ดํฐ 10>์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ์˜€๋‹ค.
์ด๋Ÿฌํ•œ ํ˜„์ƒ์€ setInterval์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœํ•˜์—ฌ ๋ฐœ์ƒํ•œ ๊ฒƒ์ž„. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ 1์ดˆ์— 60ํ”„๋ ˆ์ž„์„ ์ฐ์–ด๋‚ด๊ฒŒ ๋œ๋‹ค.
์ฆ‰ 1ํ”„๋ ˆ์ž„์„ ์ฐ์–ด๋‚ด๋Š”๋ฐ 16.6ms๋ฅผ ์ดˆ๊ณผํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ ๋ฆฌํ”Œ๋กœ์šฐ ํ˜„์ƒ์ด ์ผ์–ด๋‚œ๋‹ค.
๋ฆฌํ”Œ๋กœ์šฐ ํ˜„์ƒ์ด๋ž€ ๋ธŒ๋ผ์šฐ์ € ๋ Œ๋”๋งํ•˜๋Š” ๊ณผ์ •์—์„œ [๋ ˆ์ด์•„์›ƒ - ํŽ˜์ธํŠธ - ํ•ฉ์„ฑ] ์ด๋Ÿฐ ๊ณผ์ •์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์ด๊ฐ™์€ ํ˜„์ƒ ๋•Œ๋ฌธ์— ํ™”๋ฉด์ด ๋ฒ„๋ฒ…๊ฑฐ๋ฆฌ๋Š” ์ด์Šˆ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ตœ์ ํ™” ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ์ธ requestAnimationFrame ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๋‹น ์ด์Šˆ๋ฅผ ํ•ด๊ฒฐํ•ด ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋Š” ๋ธŒ๋ผ์šฐ์ € ๋ฆฌ์†Œ์Šค์™€ ์ปดํ“จํ„ฐ์˜ CPU ์„ฑ๋Šฅ์„ ๊ณ ๋ คํ•˜์—ฌ 1์ดˆ๋‹น ํ”„๋ ˆ์ž„ ์ˆ˜๋ฅผ ์กฐ์ ˆํ•ด์ฃผ์–ด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ตœ์ ํ™” ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฅผ ํ†ตํ•ด FPS (๋ชจ๋‹ˆํ„ฐ ์ฃผ์‚ฌ์œจ) ์ œ์–ดํ•จ์œผ๋กœ์จ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘ํžˆ ๋ถ€๋“ค๊ฑฐ๋ฆผ ํ˜„์ƒ์ด ์‚ฌ๋ผ์กŒ๋‹ค.
๊ทธ๋ž˜์„œ ์•„์ดํฐ10 ์—์„œ๋„ ์ฝ”์ธ๋ฆฌ์ŠคํŠธ์˜ ์ž๋™ ์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋ Œ๋”๋ง ๋˜๋„๋ก ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋จ

์ฐธ๊ณ ์ž๋ฃŒ : https://curryyou.tistory.com/520

๐Ÿ“… datePicker ์‚ฌ์šฉ์‹œ ์˜ค๋Š˜ ๋‚ ์งœ ์ดํ›„, ๋ฏธ๋ž˜ ๋‚ ์งœ disable ์ฒ˜๋ฆฌ

antd ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜์˜€๊ณ  ์ปดํฌ๋„ŒํŠธ๋Š” datePicker ์‚ฌ์šฉํ–ˆ๋‹ค.
์˜ค๋Š˜ ๋‚ ์งœ ์ดํ›„๋กœ ๋ฏธ๋ž˜ ๋‚ ์งœ๋ฅผ ํด๋ฆญํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋น„ํ™œ์„ฑํ™” ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์€
์•„๋ž˜์™€๊ฐ™์ด ์ž‘์—…ํ•˜๋ฉด ๋œ๋‹ค.

<DatePicker
                onChange={onChange}
                className="dataInput"
                defaultValue={moment(today, 'YYYY-MM-DD')}
                ๐Ÿ‘‰disabledDate={(current: any) => {
                    const start: any = moment('2020-01-01', 'YYYY-MM-DD');
                    return current < start || current > moment();
                }}
            />

๊ฒฐ๊ณผ๋ฌผ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-08-16 แ„‹แ…ฉแ„’แ…ฎ 6 30 20

A ๋‚ ๋ถ€ํ„ฐ ~ B ๋‚ ๊นŒ์ง€๋งŒ ํ—ˆ์šฉํ•˜๊ณ  ๊ทธ ์™ธ์—๋Š” ๋‹ซ์•„ ๋ฒ„๋ฆฌ๊ธฐ

์ฝ”๋“œํŽœ ์˜ˆ์ œ ์ฝ”๋“œ

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { DatePicker } from 'antd';

function disabledYear(current) {
  // return current.year() === 2021; // disabling 2021
  // return current.year() !== 2021; // disabling everything besides 2021
  // return current.year() !== (new Date).getFullYear(); // disabling everything besides current year
  // return current.year() > 2021; // disabling everything further than 2021
  return current.year() < 2021; // disabling everything in the past before 2021
  return [2018, 2019].includes(current.year()); // disabling 2018 and 2019
}

ReactDOM.render(
  <div>
    <DatePicker format="YYYY-MM-DD" disabledDate={disabledYear} />
  </div>,
  document.getElementById('root')
);

๐Ÿ˜ต ์‹ค์ œ ๊ตฌํ˜„ํ•ด๋ณธ ์ฝ”๋“œ

<DatePicker
                onChange={onChangeDate}
                className="dataInput"
                format="YYYY-MM-DD"
                disabledDate={(current: any) => {
                    return current.year() < 2020 || current >= moment().subtract(1, 'days').toDate();
                }}
            />

์ฐธ๊ณ  https://stackoverflow.com/questions/46358603/disable-date-and-time-for-antd-datepicker
https://ant.design/components/date-picker/#header

๐Ÿ•น [์ธํ…”๋ฆฌ์ œ์ด] ํด๋” ์•ˆ ๋ณด์ด๊ณ  ํŒŒ์ผ๋งŒ ๋ณด์ด๋Š” ๋ฒ„๊ทธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๋ฒ„๊ทธ ์ƒํ™ฉ

ํŒŒ์ผ์€ ๋ณด์ด๋‚˜ ํด๋”๊ฐ€ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  1. File -> Project Structure ํด๋ฆญ

  1. Modules ํด๋ฆญ

  1. +์„ ๋ˆŒ๋Ÿฌ Import Module ํด๋ฆญ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ž์‹ ์˜ ํ”„๋กœ์ ํŠธ Root ํด๋”๋ฅผ ์„ ํƒ -> Next ํด๋ฆญ

  1. OK ํด๋ฆญ

๋ ~~

์ด ๋ฐฉ๋ฒ•์ด ์•ˆ๋œ๋‹ค๋ฉด ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— .idea ํด๋”๋ฅผ ์‚ญ์ œํ–ˆ๋‹ค๊ฐ€ ์žฌ์‹คํ–‰ ํ•  ๊ฒฝ์šฐ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

โ˜ ๏ธ react ๋ฐ˜๋ณต๋ฌธ For๋กœ JSX ๋ฆฌํ„ดํ•˜๊ธฐ

โ˜ ๏ธ react for ๋ฌธ์œผ๋กœ JSX ๋ฆฌํ„ดํ•˜๊ธฐ

const arrDealList = () => {
        const list = []; // ๐Ÿ‘‰ ๋‹ด์•„๋‚ผ ๋ณ€์ˆ˜

        // ๐Ÿ‘‰ ์‹ค์ œ ๋ฐฐ์—ด ๋ณ€์ˆ˜ ์„ ์–ธํ•ด์•ผํ•จ _ ๋ฐฐ์—ด์˜ ๊ธธ์ด๋งŒํผ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ๋ฆฌ์ž.
        for (let i = 0; i < domeRankList.length; i++) {
            list.push(<DealList rankName={domeRankList[i]} listName={coinList[i]} key={i} />);
        }
        // ๐Ÿ‘‰ ๋ฆฌํ„ด !
        return list;
    };

JSX

 return (
        <div className="domestic__coinlist">
            <Division coinName={coinList[0]} />
            {arrDealList()}  // ๐Ÿ‘‰ ๋ฆฌํ„ด ๋œ ํ•จ์ˆ˜ ์„ ์–ธํ•˜์—ฌ list ๋ฟŒ๋ ค์ฃผ๊ธฐ
            (...)
        </div>
    )   

Redux๋ž€..? mobx์™€ ๋น„๊ต์„ค๋ช…

๋ฐœํ‘œ์‹์œผ๋กœ ๋งํ•˜๊ธฐ

๋ฆฌ๋•์Šค์˜ ํŠน์ง•

  • action, dispatch, reducer, store๊ฐ€ ์žˆ๋‹ค.
  • action : action์€ state๋ฅผ ๋ฐ”๊พธ๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ฐ˜๋“œ์‹œ typeํ•„๋“œ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • dispatch : action์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์œผ๋กœ action ๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š”๋‹ค.
  • reducer : ๋ณ€ํ™”๋ฅผ ์ผ์œผํ‚ค๋Š” ํ•จ์ˆ˜๋กœ action์˜ ๊ฒฐ๊ณผ๋กœ ์ƒํƒœ๋ฅผ ์–ด๋–ค ์‹์œผ๋กœ ๋ฐ”๊ฟ€์ง€ ๊ตฌ์ฒด์ ์œผ๋กœ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„
  • store : ๋ฆฌ๋•์Šค๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ค‘์•™ ์ €์žฅ์†Œ ์ด๋ฉฐ, ๋‹จ ํ•œ ๊ฐœ๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ƒํƒœ๋ฅผ ์ฝ์„ ๋•Œ๋Š” getState() ์ƒํƒœ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ๋Š” dispatch()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ํ๋ฅด๊ฒŒ ํ•œ๋‹ค.
  • ์ƒํƒœ๋ฅผ ์ „์—ญ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋Š ์ปดํฌ๋„ŒํŠธ์— ์ƒํƒœ๋ฅผ ๋‘ฌ์•ผํ• ์ง€ ๊ณ ๋ฏผํ•  ํ•„์š”๊ฐ€ ์—†๊ฒŒ ํ•œ๋‹ค.
  • ์ƒํƒœ๊ด€๋ฆฌ์—์„œ ๋ถˆ๋ณ€์„ฑ ์œ ์ง€๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. immer.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ถˆ๋ณ€์„ฑ ์œ ์ง€๋ฅผ ๋”ฐ๋กœ ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.
  • flux ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋”ฐ๋ฅธ๋‹ค. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์‹œ redux-saga๋‚˜ redux-thunk๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ํ•„์ˆ˜์ด๋‹ค.
  • flux ๊ตฌ์กฐ๋ž€ ? ๋‹จ๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ฐ€์ง€๋Š” ๊ตฌ์กฐ๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ๋ฅด๊ณ , ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์œผ๋ฉด ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘๋˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋˜์–ด์žˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ํ๋ฆ„์€ dispatch -> store -> view ์ˆœ์„œ์ด๋‹ค. view์—์„œ ์ž…๋ ฅ์ด ๋ฐœ์ƒํ•˜๋ฉด ์•ก์…˜์„ ํ†ตํ•ด ๋””์ŠคํŒจ์น˜๋กœ ํ–ฅํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์—ฌ๋Ÿฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋‹ˆ ๋Ÿฌ๋‹์ปค๋ธŒ๊ฐ€ ๋†’์€ ํŽธ
  • ์•ก์…˜ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ ์ž‘์„ฑ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์ด ๋งŽ๊ณ  ์ปดํฌ๋„ŒํŠธ์™€ ์Šคํ† ์–ด๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ํ•„์ˆ˜์ ์ธ ๋ถ€๋ถ„๋“ค์ด ์žˆ์–ด์„œ ์ฝ”๋“œ๋Ÿ‰์ด ์ƒ๋Œ€์ ์œผ๋กœ ๋งŽ์•„์ง„๋‹ค.
import produce from "immer";

// ๐Ÿ‘‰ ์ดˆ๊ธฐ์ƒํƒœ ์ •์˜
const initialState = {
  movies: [],

  loadMovieLoading: false,
  loadMovieDone: false,
  loadMovieError: null,
};

// ํ™”๋ฉด ๋กœ๋”ฉ ๐Ÿ‘‰ ํƒ€์ž…์ •์˜
export const LOAD_MOVIES_REQUEST = "LOAD_MOVIES_REQUEST";
export const LOAD_MOVIES_SUCCESS = "LOAD_MOVIES_SUCCESS";
export const LOAD_MOVIES_FAILURE = "LOAD_MOVIES_FAILURE";

// ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜ ํ˜„์žฌ ์ƒํƒœ (์ฆ‰, ์ดˆ๊ธฐ์ƒํƒœ)
// ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜ ์•ก์…˜์ด ์ผ์–ด๋‚˜์•ผ ๋  ์ƒํƒœ (dispatch)
// ๐Ÿ‘‰ ๋ฆฌ๋“€์„œ
const movies = (state = initialState, action) =>
  produce(state, (draft) => {
    switch (action.type) {
      case LOAD_MOVIES_REQUEST: {
        draft.loadMovieLoading = true;
          draft.loadMovieDone = false;
        break;
      }
      case LOAD_MOVIES_SUCCESS: {
        draft.movies = draft.movies.concat(action.data);
        draft.loadMovieLoading = false;
        draft.loadMovieDone = true;
        break;
      }
      case LOAD_MOVIES_FAILURE: {
        draft.loadMovieError = action.error;
        break;
      }

      default:
        return state;
    }
  });

  export default movies;

middleware ์ ์šฉ

import axios from "axios";
import { all, fork, call, put, takeLatest, delay } from "redux-saga/effects";

import {
  LOAD_MOVIES_REQUEST,
  LOAD_MOVIES_SUCCESS,
  LOAD_MOVIES_FAILURE,
} from "../reducers/movies";

function loadMoviesAPI() {
  return axios.get("https://yts-proxy.now.sh/list_movies.json?sort_by=rating");
}

function* loadMainPosts() {
  try {
    console.log("saga Movies");
    const result = yield call(loadMoviesAPI);
    yield delay(1000);

    yield put({
      type: LOAD_MOVIES_SUCCESS,
      data: result.data,
    });
  } catch (err) {
    console.error(err);
    yield put({
      type: LOAD_MOVIES_FAILURE,
      error: err.response.data,
    });
  }
}

function* watchLoadMainPosts() {
  yield takeLatest(LOAD_MOVIES_REQUEST, loadMainPosts);
}

export default function* postSaga() {
  yield all([fork(watchLoadMainPosts)]);
}

/*
  ๐Ÿ“ fork : ํ•จ์ˆ˜ํ˜ธ์ถœ(๋น„๋™๊ธฐ)
  ๐Ÿ“ call : ํ•จ์ˆ˜ํ˜ธ์ถœ(๋™๊ธฐ)
  ๐Ÿ“ put : ์•ก์…˜ dispatch
  ๐Ÿ“ takeLatest : ์•ก์…˜์ด dispatch๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋‹ค๋ ค์„œ dispatch๋ ๋•Œ generator๋ฅผ ํ˜ธ์ถœ (๋งจ ๋’ค์—๊บผ๋งŒ)
  ๐Ÿ“ takeEvery : ์•ก์…˜์ด dispatch๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋‹ค๋ ค์„œ dispatch๋ ๋•Œ generator๋ฅผ ํ˜ธ์ถœ (์ „๋ถ€)
*/

๋ฆฌ๋•์Šค๋Š” ์ด๋Ÿฌํ•œ ํ”Œ๋กœ์šฐ๋ฅผ ์ง€๋‹Œ๋‹ค.

๐Ÿฃ ๋ฐ์ดํ„ฐ๊ฐ€ proxy ํ˜•ํƒœ๋กœ ๊ฐ’์ด ์ถœ๋ ฅ ๋  ๊ฒฝ์šฐ toJS()

mobx๋กœ get ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ์กฐํšŒ ํ•  ๋•Œ,
์ฝ˜์†” ๋กœ๊ทธ๋กœ ์ฐ์–ด๋ณด๋‹ˆ Proxy {0: ... } ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ์ด ๋  ๊ฒฝ์šฐ์— ํ•ด๊ฒฐํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.

toJS(๋ฐ์ดํ„ฐ๊ฐ’);

์ด๋ ‡๊ฒŒ ํ˜ธ์ถœํ•˜๋ฉด Proxy๊ฐ€ ๋ฒ—๊ฒจ์ง€๊ณ  ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฐ’์ด ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

๐Ÿค– Rendering HTML // ๋ Œ๋”๋ง๋œ DOM๋…ธ๋“œ์— dangerouslySetInnerHTMLํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘์ ์œผ๋กœ HTML์„ ์‚ฝ์ž…

๋ Œ๋”๋ง๋œ DOM๋…ธ๋“œ์— dangerouslySetInnerHTMLํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ
์ง์ ‘์ ์œผ๋กœ HTML์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋งํฌ๋“ค์€ ๋ฏธ๋ฆฌ ๊ฒ€์‚ฌํ•˜์—ฌ ๋ฐฉ์ง€ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
dangerouslySetInnerHTML prop์— ์ง€์ •๋˜๊ธฐ ์ „์— ๋ชจ๋“  ๊ฐ’๋“ค์„
dompurify์™€ ๊ฐ™์€ sanitization library๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ sanitizeํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

import purify from "dompurify";

(...)

<div dangerouslySetInnerHTML={{ __html:purify.sanitize(data) }} />

๋”ฐ๋ผ์„œ ์ปจํ…์ธ ๋ฅผ DOM nodes์˜ ์ง์ ‘์ ์œผ๋กœ ๋„ฃ์œผ๋ ค DOM์— ์ ‘๊ทผํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.
dangerouslySetInnerHTML ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ dompurify๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ HTML์ด ์‚ฝ์ž…๋˜๊ธฐ ์ „ sanitizeํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿคฒ Recoil ์‚ฌ์šฉ๋ฒ• (index ์ž‘์—…์— ์ ์šฉํ•ด๋ณด๋ฉด์„œ ๋Š๋‚€์  ๋“ฑ๋“ฑ..)

Recoil

์ฐธ๊ณ  : https://recoiljs.org/ko/

ํŠน์ง•

  • ๋ฆฌ์ฝ”์ผ์€ ํŽ˜์ด์Šค๋ถ์—์„œ ์ง์ ‘ ๋งŒ๋“  ์ƒํƒœ๊ด€๋ฆฌ์ด๋‹ค.
  • ์˜ค์ง ๋ฆฌ์•กํŠธ๋ฅผ ์œ„ํ•œ ์ƒํƒœ๊ด€๋ฆฌ์ด๋‹ค
  • ์ธํ„ฐํŽ˜์ด์Šค ๋ฌธ๋ฒ•์€ hook ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋œ๋‹ค.
  • atom๊ณผ selector๋งŒ์„ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ์ด๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ˜ถโ€๐ŸŒซ๏ธ Atoms๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ์˜ ๋‹จ์œ„๋‹ค.

๐Ÿ˜ถโ€๐ŸŒซ๏ธ Selectors๋Š” atoms ์ƒํƒœ๊ฐ’์„ ๋™๊ธฐ ๋˜๋Š” ๋น„๋™๊ธฐ ๋ฐฉ์‹์„ ํ†ตํ•ด ๋ณ€ํ™˜ํ•œ๋‹ค.

atoms

const fontSizeState = atom({
  key: 'fontSizeState',
  default: 14,
});
  • key : ๊ณ ์œ ํ•œ ํ‚ค๊ฐ€ ํ•„์š”

  • default : React ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ์ฒ˜๋Ÿผ ๊ธฐ๋ณธ๊ฐ’๋„ ๊ฐ€์ง„๋‹ค.

  • ์ปดํฌ๋„ŒํŠธ์—์„œ atom์„ ์ฝ๊ณ  ์“ฐ๋ ค๋ฉด useRecoilState๋ผ๋Š” ํ›…์„ ์‚ฌ์šฉํ•œ๋‹ค. React์˜ useState์™€ ๋น„์Šทํ•˜์ง€๋งŒ ์ƒํƒœ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์— ๊ณต์œ ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

๐Ÿ‘ป IntelliJ + git (์ปค๋ฐ‹๋‚ด์—ญ ๋Œ๋ฆฌ๊ธฐ, ๋ธŒ๋Ÿฐ์น˜ ์ฒดํฌ์•„์›ƒ)

1. IntelliJ + git

์ด์ „์— ์ปค๋ฐ‹ ๋‚ด์—ญ์œผ๋กœ ๋˜๋Œ๋ฆฌ๊ธฐ
ํ„ฐ๋ฏธ๋„ ์ฐฝ ์—ฌ๋Š” ๊ณณ์—์„œ git ํด๋ฆญ โ†’ ์ž‘์—…ํ•œ ๋ธŒ๋Ÿฐ์น˜์˜ ์ž‘์—… ๋‚ด์—ญ (ํŠธ๋ฆฌ) ๋ณด๋ฉด ๋˜๋Œ๋ฆฌ๊ณ ์ž ํ•˜๋Š” ์ปค๋ฐ‹๋‚ด์—ญ์— ์šฐํด๋ฆญ โ†’ Reset Current Branch to here ํด๋ฆญ โ†’ Hard ์„ ํƒํ•˜๊ณ  Reset ํด๋ฆญ ํ•˜๋ฉด ๋œ๋‹ค.

2. ๋‹ค๋ฅธ ๋ธŒ๋Ÿฐ์น˜ ์ฒดํฌ์•„์›ƒ ํ•˜๊ธฐ

์ƒ๋‹จ nav๋ฐ”์—์„œ git ํด๋ฆญ โ†’ Fetch ํด๋ฆญ โ†’ Fetch ์„ฑ๊ณต์ ์œผ๋กœ ๋œจ๋ฉด ํ•˜๋‹จ ์˜ค๋ฅธ์ชฝ์— ๋ธŒ๋Ÿฐ์น˜๋ช… ํด๋ฆญ โ†’ ๊ทธ๋Ÿผ ๋“œ๋กญ๋ฆฌ์ŠคํŠธ์— ๋กœ์ปฌ ๋ธŒ๋Ÿฐ์น˜๋ž‘ remote ๋ธŒ๋Ÿฐ์น˜๊ฐ€ ์žˆ์Œ โ†’ remote ๋ธŒ๋Ÿฐ์น˜์— ์žˆ๋Š” ๋ธŒ๋Ÿฐ์น˜ ์ฒดํฌ์•„์›ƒ ํ•ด์™€์•ผํ•œ๋‹ค.

โ˜๏ธŽ react์—์„œ innerHTML ์‚ฌ์šฉํ•˜๊ธฐ

๋ฆฌ์•กํŠธ์—์„œ HTML ์ฝ”๋“œ๋ฅผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ธฐ์กด์— JS์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅด๋‹ค.
๊ธฐ์กด์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” innerHTML๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋„ฃ์–ด์ค€๋‹ค๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ–ˆ์ง€๋งŒ ๋ฆฌ์•กํŠธ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์—…์„ ํ•ด์•ผ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

import React from 'react';

export default () => {
   const htmlCode = "<div>์•ˆ๋…•</div>";
   return <div dangerouslySetInnerHTML={{ __html: htmlCode }}>{htmlCode}</div>;
}

๋ฆฌ์•กํŠธ์—์„œ๋Š” dangerouslySetInnerHTML={{ __html: htmlCode }} ์ด์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ถ”๊ฐ€ํ•ด์ค˜์•ผํ•œ๋‹ค.

๐ŸŸ  ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•

const [htmlCode, setHtmlCode] = useState<string>('');

useEffect(() => {
  try {
    const getNotice = async () => {
      const data = await httpService.get('๋ฐ์ดํ„ฐ ์ฃผ์†Œ');
      // ๋ณ€๊ฒฝ ๋  ์ƒํƒœ๊ด€๋ฆฌ์— data.content ๋„ฃ๊ธฐ
      setHtmlCode(data.data.content);
   };
  getNotice();
  } catch (error) {
    console.log('error-->', error);
 }
},[])

0519 bigNumber. js ์‚ฌ์šฉ๋ฒ•

๐ŸŽˆ ํŠน์ง•

  • Javascript์—์„œ ์ •์ˆ˜๋Š” ์ตœ๋Œ€ 15 ์ž๋ฆฌ๊นŒ์ง€ ์ •ํ™•ํ•˜๋‹ค
  • ์ •๋ฐ€๋„ ์†์‹ค์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด 10์ง„์ˆ˜ ๊ฐ’์„ ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์—ด๋กœ ์ง๋ ฌํ™”
  • Big number๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ
  • ๋น ๋ฅด๊ณ  ์ž‘์œผ๋ฉฐ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • 8KB ์ถ•์†Œ ๋ฐ gzip

์ˆซ์ž์—์„œ BigNumber๋ฅผ ์ƒ์„ฑํ•  ๋•Œ BigNumber๋Š” toString()๊ธฐ๋ณธ ์ด์ง„ ๊ฐ’์ด ์•„๋‹Œ ์ˆซ์ž์˜ 10์ง„์ˆ˜ ๊ฐ’์—์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ›„์ž๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ˆซ์ž toString(2)๊ฐ’์„ ์ „๋‹ฌํ•˜๊ณ  ๊ธฐ์ˆ˜ 2๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

BigNumber๋ฅผ ์“ฐ๋Š” ์ด์œ ๋Š” ํฐ ๋‹จ์œ„์˜ ์ˆ˜๋ฅผ ์ฒœ๋‹จ์œ„(1,000)๋กœ ํ‘œ๊ธฐํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

new BigNumber(Number.MAX_VALUE.toString(2), 2)

npm install bignumber.js

์˜ˆ๋ฅผ๋“ค์–ด ํฐ ์ˆ˜๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์“ฐ๋Š”๋ฐ ๋ณดํ†ต ๊ธˆ์•ก์ ์ธ ๊ฒƒ์— ๋Œ€ํ•ด ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
๋ณ€๋™๋ฅ  ๋“ฑ๋ฝํ•  ๋•Œ ๋น„๊ต ๊ธฐ์ค€์„ ์žก๊ณ  BigNumber ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฉ”์„œ๋“œ์ค‘ isGreaterThan์€ 0๋ณด๋‹ค ๊ฐ’์ด ํด ๊ฒฝ์šฐ ์‚ฌ์šฉ.
isLessThan์€ 0๋ณด๋‹ค ๊ฐ’์ด ์ž‘์„ ๊ฒฝ์šฐ๋ฅผ ๋น„๊ตํ•˜์—ฌ ์“ด๋‹ค.

๊ทธ๋ž˜์„œ ์ฃผ์‹์ฐฝ ๊ฐ™์€๋ฐ๋‹ค ๋“ฑ๋ฝํ‘œ์‹œํ•  ๋•Œ up & dwon ์ž‘์—…์‹œ className์„ ์ ์šฉํ•ด์„œ ๋นจ๊ฐ„์ƒ‰ ํŒŒ๋ž€์ƒ‰์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
0์ผ ๋•Œ๋Š” ๊ฒ€์ •์ƒ‰์œผ๋กœ ์ ์šฉ์‹œ์ผœ์•ผ ๋จ.

{new BigNumber(Math.abs(oRowData.chgRate)).toFormat()}%

์‹ค์ œ view ๋‹จ์—์„œ ํ‘œ๊ธฐ๋  ๊ฐ’์€ ์‹ค์ œ ๋ณ€๋™๋ฅ ๋กœ ๋ณด์—ฌ์ค€๋‹ค.

๐ŸŽˆ isEqual

์ด๊ฒƒ์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ isEqual(๋งค๊ฐœ๋ณ€์ˆ˜1, ๋งค๊ฐœ๋ณ€์ˆ˜2) ๋กœ ์“ฐ์ด๋Š”๋ฐ,
๋งค๊ฐœ๋ณ€์ˆ˜ 1๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜ 2๊ฐ€ ์„œ๋กœ ๊ฐ™๋‹ˆ? ๋ผ๋Š” ๋œป์œผ๋กœ ์“ฐ๋Š” ๋ฉ”์„œ๋“œ๋‹ค.

isEqual ์˜ˆ์ œ

if (_.isEqual(oCoinData, oldRowData)) {
   oldRowData.current = oCoinData;
   setRowData(oCoinData);
}

โญ๏ธ props๋กœ ํ•จ์ˆ˜ ๋ฐ์ดํ„ฐ๋„ ๋‚ด๋ ค๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

์ฐธ๊ณ ์ž๋ฃŒ
https://github.com/MikeMcl/bignumber.js

๐Ÿ”ป ๋ฆฌ๋ˆ…์Šค ์œ ์šฉํ•œ ํ„ฐ๋ฏธ๋„ ๋ช…๋ น์–ด

๋ชจ๋“  ํŒŒ์ผ๋“ค ๋‹ค๋ฅธ ํด๋”์— ์˜ฎ๊ธฐ๊ธฐ

ํŒŒ์ผ ์ด๋™ ๋ช…๋ น์–ด, ์–ด๋–ค ํŒŒ์ผ ์˜ฎ๊ธธ๊ฒƒ์ธ์ง€, ์–ด๋””์— ์˜ฎ๊ธธ๊ฒƒ ์ธ์ง€.

 mv * ../

ํ˜„์žฌ ๊ฒฝ๋กœ์— ์–ด๋–ค ํŒŒ์ผ๋“ค์ด ์žˆ๋Š”์ง€

ls

์—ฌ๊ธฐ์„œ ์ˆจ๊ธด ํŒŒ์ผ๊นŒ์ง€ ๋ณด๊ณ ์‹ถ๋‹ค๋ฉด ?

ls -al

๐Ÿ”— ๊ฐœ๋ฐœํ•  ๋•Œ ๋„์›€๋˜๋Š” ๊ฒŒ์‹œ๊ธ€ (React, JS)

[์งค๋ง‰๊ธ€] Custom Hooks์„ ๋งŒ๋“ค์–ด๋ณด์ž!

https://velog.io/@kysung95/%EC%A7%A4%EB%A7%89%EA%B8%80-Custom-Hooks%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90


mobx ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์˜ˆ์ œ๋กœ ์•Œ์•„๋ณด๊ธฐ

https://kyounghwan01.github.io/blog/React/mobx/async/#async-await-runinaction


[React] ๋ถ€๋ชจ-์ž์‹ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๋ฐฉ๋ฒ•

https://technicolour.tistory.com/56


๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ(React Router) - URL Parameters, Query Parameters (+URLSearchParams)

https://velog.io/@wiostz98kr/TIL51-l-React-Router-3%ED%83%84


๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„

https://keating.vercel.app/2020-06-09-dark-mode/


์ตœ๊ทผ ๊ฒ€์ƒ‰์–ด ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

https://velog.io/@hoon_dev/%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%A1%9C-%EC%B5%9C%EA%B7%BC-%EA%B2%80%EC%83%89%EC%96%B4-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%B4%EB%B3%B4%EA%B8%B0


Toast UI (react ๋ฐ JS ๊ด€๋ จ ์ง€์‹ ๋ชจ์Œ)

https://ui.toast.com/posts/ko/react


[์งค๋ง‰๊ธ€] useRef๊ฐ€ ๋ญ”๊ฐ€์š”?

https://velog.io/@kysung95/%EC%A7%A4%EB%A7%89%EA%B8%80-useRef%EA%B0%80-%EB%AD%94%EA%B0%80%EC%9A%94#useref%EB%A1%9C-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B0%A9%EC%A7%80


[React] useEffect ๋ฅผ ์ด์šฉํ•ด ์Šคํฌ๋กค ๊ฐ์ง€

https://velog.io/@dltmdwls15/React-useEffect-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B0%90%EC%A7%80


[JS] ํŽ˜์ด์ง€ ๋‚ด ํŠน์ • ์œ„์น˜๋กœ ์Šคํฌ๋กค ์ด๋™ํ•˜๊ธฐ

https://gurtn.tistory.com/127


Element.getBoundingClientRect() DOMRect์š”์†Œ์˜ ํฌ๊ธฐ์™€ ๋ธŒ๋ผ์šฐ์ € ๋ทฐํฌํŠธ์— ์ƒ๋Œ€์ ์ธ ์œ„์น˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณต ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

https://kyounghwan01.github.io/blog/JS/JSbasic/getBoundingClientRect/#%E1%84%80%E1%85%AE%E1%84%86%E1%85%AE%E1%86%AB


06. useEffect Hook

https://2oneweek.dev/frontend/react/006.%20Hook%20-%20useEffect/


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ด๋ฒคํŠธ ๋ฉ”์„œ๋“œ addEventListner ๋“ฑ๋“ฑ

https://chlolisher.tistory.com/10


componentDidMount ์™€ useEffect

https://velog.io/@ryong9rrr/componentDidMount-%EC%99%80-useEffect


[JS] ๐Ÿ“š window.open / close (์ƒˆ์ฐฝ ์—ด๊ธฐ/๋‹ซ๊ธฐ) ์‚ฌ์šฉ๋ฒ• ๐Ÿ’ฏ ์ •๋ฆฌ

https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-windowopen-%EC%A0%95%EB%A6%AC

๐Ÿงโ€โ™€๏ธ Kakao ์†Œ์…œ ์—ฐ๋™ API ์ž‘์—…ํ•  ๋•Œ

๐Ÿงโ€โ™€๏ธ Kakao ์†Œ์…œ ์—ฐ๋™ API ์ž‘์—…ํ•  ๋•Œ

src/react-app-env.d.ts ํŒŒ์ผ์—๋‹ค๊ฐ€

interface Window {
   Kakao : any;
}

์ด๋Ÿฐ์‹์œผ๋กœ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š”

const kakao = window.Kakao;

์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  public/index.html ํŒŒ์ผ์—

<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>

์ด๋ ‡๊ฒŒ ์ƒ๋‹จ์—๋‹ค ์„ ์–ธํ•ด์ฃผ์–ด์•ผ ์นด์นด์˜ค ์†Œ์…œ ๊ณต์œ ํ•˜๊ธฐ ๊ฐ€๋Šฅ.
๐Ÿ’๐Ÿปโ€โ™€๏ธ ๊ทธ๋ฆฌ๊ณ  ๋ฐ˜๋“œ์‹œ ํ‚ค๊ฐ’์ด ์žˆ์–ด์•ผํ•œ๋‹ค.
ํ‚ค๊ฐ’์€ ์นด์นด์˜ค developer ์— ๊ฐ€์„œ ์•ฑ ๋“ฑ๋กํ•˜๋ฉด ํ‚ค ๊ฐ’ ์–ป์–ด์˜ค๊ธฐ ๊ฐ€๋Šฅํ•˜๋‹ค.

JavaScript ํ‚ค : f661d4bba439f1455cefe8dfdfaa2b4513ee04 ํ‚ค๊ฐ’์€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒจ๋จน์Œ.
์ด๊ฑธ env ํ™˜๊ฒฝ ํŒŒ์ผ์—๋‹ค๊ฐ€ ์„ ์–ธํ•ด์„œ ๊ฐ–๋‹ค ์“ฐ๋ฉด๋œ๋‹ค.

  • ๐Ÿ“ .env
REACT_APP_KAKAO_KEY=f661d4bba439f1aaaaa455cefe82b4513ee04

์š”๋Ÿฐ์‹ ! ๊ฐ–๋‹ค ์“ธ ๋•Œ๋Š” kakao.init(process.env.REACT_APP_KAKAO_KEY ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด ๋œ๋‹ค.

๐ŸŒš ๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„์— ์•Œ์•„์•ผ ํ•  ์ง€์‹๋“ค

๐ŸŒš ๋‹คํฌ๋ชจ๋“œ ๊ตฌํ˜„์— ์•Œ์•„์•ผ ํ•  ์ง€์‹๋“ค

๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•˜๊ณ  ํ…Œ๋งˆ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‹คํฌ๋ชจ๋“œ ๋˜๋Š” ๋ผ์ดํŠธ๋ชจ๋“œ๋กœ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

<Helmet>
   <html data-theme={mobx ์ƒํƒœ๊ด€๋ฆฌ์—์„œ ์ €์žฅํ•œ ํ…Œ๋งˆ์˜ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ด} />;
</Helmet>

JSX ์ƒ์—์„œ๋Š” ์ด๋ผ๋Š” react-helmet ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹คํฌ๋ชจ๋“œ ํ…Œ๋งˆ์˜ ์„ค์ •๋œ ์ƒํƒœ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

๐ŸŒค react-helmet ํŠน์ง•

  1. ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์„ ์ง€์›ํ•œ๋‹ค. (์ฆ‰ SPA์˜ ๋‹จ์ ์„ ๊ทน๋ณตํ•ด์คŒ)
  2. ๋ฉ”ํƒ€ ํƒœ๊ทธ๋ฅผ ๊ฐ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. SEO(๊ฒ€์ƒ‰์—”์ง„์ตœ์ ํ™”) ๊ฐ€๋Šฅ. ์ด๊ฒŒ ์ค‘์š”ํ•œ ์ด์œ ๋Š” ํฌ๋กค๋Ÿฌ๊ฐ€ ์ฝ๊ธฐ ์‰ฝ๋„๋ก ๋ฉ”ํƒ€ํƒœ๊ทธ๋ฅผ ์„ค์ •ํ•˜์—ฌ ์‚ฌ์ดํŠธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๐ŸŒš localStorage

4๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค (setItem, getItem, clear, remove)

  • setItem : ์Šคํ† ๋ฆฌ์ง€์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ฃผ๋Š”๋ฐ, ๋ฐ˜๋“œ์‹œ key์™€ value๋กœ๋„ ์ด๋ฃจ์–ด์ง„๋‹ค. (๊ฐ์ฒด ๋ฐ์ดํ„ฐ ๋˜ํ•œ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค)
    ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋‹ซํ˜€๋„ ๊ทธ๋Œ€๋กœ ์œ ์ง€๊ฐ€ ๋œ๋‹ค.
    ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€์™€ ์ฐจ์ด์ ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ remove๋‚˜ clear๋ฅผ ํ•˜๊ธฐ ์ „๊นŒ์ง€ ์‚ญ์ œ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.
    setItem์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์€ string์ด๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ธŒ์ ํŠธ๋กœ ๋˜์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ ๊ฐ’์„ JSON.stringity๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ string ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์กฐํšŒ๋ฅผ ํ•  ๋•Œ๋Š” ๊ฐ์ฒดํ˜•์œผ๋กœ ๋ถˆ๋Ÿฌ ์™€์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— stringํ™” ๋œ ํƒ€์ž…์„ ๋‹ค์‹œ JSON.parse๋กœ object์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์กฐํšŒ(get)ํ•œ๋‹ค.

โœจ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ ๋ฉ”์„œ๋“œ ์ข…๋ฅ˜

// JSON ์œผ๋กœ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ
localStorage.setItem('key', JSON.stringity({ a: value }));
 
// JSON์œผ๋กœ ์Šคํ† ๋ฆฌ์ง€ ๋ฐ์ดํ„ฐ ์กฐํšŒ
JSON.parse(localStorage.getItem('key'));
 
// key์— ํ•ด๋‹นํ•˜๋Š” ์Šคํ† ๋ฆฌ์ง€๋งŒ ์‚ญ์ œ
localStorage.remove('key')
 
// ๋ชจ๋“  ์Šคํ† ๋ฆฌ์ง€ ์‚ญ์ œ
localStorage.clear('key')

๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽค Hooks ์ข…๋ฅ˜์— ๋”ฐ๋ฅธ ์‚ฌ์šฉ์„ค๋ช…๋ฒ•

hook์ด๋ž€ ?

  • ๋ฆฌ์•กํŠธ ๋ฒ„์ „ 16.8์— ๋„์ž…๋œ ๊ธฐ๋Šฅ

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ

๐Ÿ– useState

์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ์— ์‚ฌ์šฉํ•˜๋Š” ๊ฐ’์ด๋‹ค.
์ƒํƒœ์— ๋ณ€ํ™”๋ฅผ ์ค€๋‹ค.

const [color, setColor] = useState<string>('red');
  • useState ์‚ฌ์šฉ ์˜ˆ
const [color, setColor] = useState<string>('red');
 
const handleChange = () => {
    setColor('pink');
}
 
return (
    &lt;>
        &lt;button onClick={handleChange}&gt;
            ์ปฌ๋Ÿฌ ๋ณ€๊ฒฝ
        &lt;/button&gt;
 
 
        <div xss=removed>์ปฌ๋Ÿฌ๋ณ€๊ฒฝ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ƒ‰๊น”์ด ๋ณ€ํ•ด์š”</div>
    &lt;/>
)

๐Ÿ– useEffect

๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๊ณ  ๋‚œ ๋’ค์— ๋ Œ๋”๋ง์ด ๋œ๋‹ค.
๋น„๋™๊ธฐ๋กœ ํ˜ธ์ถœํ•ด์ค€๋‹ค.

  • useEffect ์‚ฌ์šฉ ์˜ˆ
useEffect(() => {
         
        ๊ฐ์‹œ ๋Œ€์ƒ์ด ๋ณ€ํ•˜๋ฉด ๋™์ž‘ ํ•  ์ฝœ๋ฐฑ
 
    return () => {
 
 
    }
},[๊ฐ์‹œ๋Œ€์ƒ])
  • useEffect ์‚ฌ์šฉ ์˜ˆ
// ์ฒซ ๋ Œ๋”๋ง ํ›„ ์‹คํ–‰๋œ๋‹ค
useEffect(() => {       
   ์ฝœ๋ฐฑ
},[])
 
 
// ํŽ˜์ด์ง€์—์„œ ๋– ๋‚  ๋•Œ ์‹คํ–‰
useEffect(() => {       
    return ()=> {
        console.log('bye~')
    }
},[])

 
// ๊ฐ์‹œ๋Œ€์ƒ์ด ๋ณ€ํ•˜๋ฉด ๋™์ž‘๋˜๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜
useEffect(() => {       
    ์ฝœ๋ฐฑ
},[๊ฐ์‹œ ๋Œ€์ƒ])
 
useEffect(() => {       
    consoloe.log(๊ฐ์‹œ ๋Œ€์ƒ)
    return ()=> {
        console.log('bye~')
    }
},[๊ฐ์‹œ ๋Œ€์ƒ])

๐Ÿ– useLayoutEffect

๋™๊ธฐ๋กœ ํ˜ธ์ถœํ•ด์ค€๋‹ค.
๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๊ธฐ๋„ ์ „์— ์‹คํ–‰ํ•ด์ค€๋‹ค.

  • useLayoutEffect ์‚ฌ์šฉ ์˜ˆ
useLayoutEffect(() => {
     
    return () => {
 
 
    }
},[])

๋งŒ์•ฝ ์ด useLayoutEffect ์•ˆ์— ์—ฐ์‚ฐ๋Ÿ‰์ด ๋งŽ์€ ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค๋ฉด ์‚ฌ์šฉ์ž์˜ ํ™”๋ฉด์€ ๋ฒ„๋ฒ…์ž„์„ ๋Š๋‚„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๊ณ  ๋‚œ ๋’ค์— ๋ Œ๋”๋ง์„ ํ•ด์ฃผ๋Š” useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋ฉ”๋ชจ์ œ์ด์…˜ ํ›…

๐Ÿ– useCallback

๋ Œ๋”๋ง ์„ฑ๋Šฅ์„ ์œ„ํ•ด ์‚ฌ์šฉ

  • ์ธํ„ฐํŽ˜์ด์Šค
useCallback(() => {
    ์ฝœ๋ฐฑํ•จ์ˆ˜
},[์˜์กด์„ฑ])
// ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋œ๋‹ค
const hyunju = () => { }
 
// ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.
const hyunju = callback(() => {
 
 
},[])
 
// a๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๋งค๋ฒˆ ์ƒˆ๋กญ๊ฒŒ ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.
const hyunju = callback(() => {
 
},[a])

DOM์— ์ง์ ‘ ์ ‘๊ทผํ•˜์ž !

๐Ÿ– useRef

DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด ๋” ์š”์†Œ์— ํฌ์ปค์Šค๋ฅผ ์ค„ ๋•Œ ์‚ฌ์šฉ
๋ Œ๋”๋ง๊ณผ ๋ฌด๊ด€ํ•œ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.
์–ด๋–ค ๊ฐ’์ด๋“  ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
useState ์ฒ˜๋Ÿผ ์ดˆ๊ธฐ๊ฐ’๋„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋‹ค.

  • ์ธํ„ฐํŽ˜์ด์Šค
const TextInput = () => {   
    const inputRef = useRef<HTMLInputElement>(null);
     
    useEffect(() => {
     inputRef.current.focus();
    }, [])
 
    return (
    &lt;>
        &lt;input type="text" ref={inputRef} /&gt;
        &lt;button&gt;์ €์žฅ&lt;/button&gt;
    &lt;/>
  )
}

โค๏ธโ€๐Ÿ”ฅ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ window.localStorage

Window.localStorage

์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ. ์ €์žฅํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋ธŒ๋ผ์šฐ์ € ์„ธ์…˜ ๊ฐ„ ๊ณต์œ ๋œ๋‹ค.
๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€๋Š” ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์˜ ๋ฐ์ดํ„ฐ๋Š” ๋งŒ๋ฃŒ๋˜์ง€ ์•Š๊ณ , ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€์˜ ๋ฐ์ดํ„ฐ๋Š” ํŽ˜์ด์ง€ ์„ธ์…˜์ด ๋๋‚  ๋•Œ, ์ฆ‰ ํŽ˜์ด์ง€๋ฅผ ๋‹ซ์„ ๋•Œ ์‚ฌ๋ผ์ง„๋‹ค.

myStorage = window.localStorage;

์ถ”๊ฐ€

localStorage.setItem('ํ‚ค', '๊ฐ’');

์ฝ๊ธฐ

const cat = localStorage.getItem('ํ‚ค');

์ œ๊ฑฐ

localStorage.removeItem('myCat');

๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ ์ „์ฒด ์ œ๊ฑฐ

localStorage.clear();

๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€๋Š” ๋ฌธ์ž์—ด๋งŒ ๋ฐ›์•„์˜ค๊ธฐ ๋•Œ๋ฌธ์— number ๊ฐ’์„ ๋ฐ›์•„์˜ค๊ณ  ์‹ถ๋‹ค๋ฉด

Number(localStorage.getItem("counter");

์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด์ค˜์•ผํ•œ๋‹ค.

โ—๏ธ HTTP ์ฃผ๋กœ ๋ฐœ์ƒ๋˜๋Š” ์—๋Ÿฌ์ฝ”๋“œ

200 ์„ฑ๊ณต
400 Bad Request,์ž˜๋ชป๋œ ์š”์ฒญ์œผ๋กœ์จย ๋ฌธ๋ฒ•์ƒ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์–ด์„œย ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ
ex) ์ž˜๋ชป์ž…๋ ฅํ•œ url์ธ๊ฒฝ์šฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„!
404 Not Found,ํด๋ผ์ด์–ธํŠธ๊ฐ€ย ์š”์ฒญํ•œ ๋ฌธ์„œ๋ฅผ ์ฐพ์ง€๋ชปํ•œ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•จ
ex) urlํ™•์ธ์ด๋‚˜ ์บ์‹œ์‚ญ์ œ ํ•ด๋ณผ๊ฒƒ!
405 Method not allowed,๋ฉ”์†Œ๋“œ ํ—ˆ์šฉ์•ˆ๋จ, Request๋ผ์ธ์— ๋ช…์‹œ๋œย ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํ•ด๋‹น ์ž์›์˜ ์ด์šฉ์ด ํ—ˆ์šฉ๋˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•จ.ย (ํŽ˜์ด์ง€๋Š” ์กด์žฌํ•˜๋‚˜, ๊ทธ๊ฑธ ๋ชป๋ณด๊ฒŒ ๋ง‰๊ฑฐ๋‚˜ ๋ฆฌ์†Œ์Šค๋ฅผ ํ—ˆ์šฉ์•ˆํ•จ)
ex) ์ฃผ๋กœ ๋ฉ”์†Œ๋“œ ๋งค์นญ์ด ์•ˆ๋ ๋•Œ ์ผ์–ด๋‚จ
415 ์ง€์›๋˜์ง€ ์•Š๋Š” ํ˜•์‹์œผ๋กœ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ํ•ด์„œย ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์— ๋Œ€ํ•œ ์Šน์ธ์„ ๊ฑฐ๋ถ€ํ•œ ์˜ค๋ฅ˜๋ฅผย ์˜๋ฏธํ•œ๋‹ค.
ex) ContentType, Content Encoding ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค
500 ์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๋Š”ย ์›น ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์‚ฌํ•ญ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์„ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•จ
505 HTTP Version Not Supported

๐Ÿ’ฟ ๋กค๋ง

๊ณต์ง€์‚ฌํ•ญ์— ๊ฒŒ์‹œ๋ฌผ์ด ๋กค๋ง๋˜๋Š” ์ž‘์—…์„ ํ–ˆ์—ˆ๋‹ค.

ํ•˜๋Š” ๋ฐฉ๋ฒ•

๐ŸŽ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง

  const [idx, setIdx] = useState(0);
  const idxRef = useRef(0);
  const [pressRelease, setPressRelease] = useState<MainPost[]>([]);

  (...)

  const getMainPressRelease = async () => {
        try {
            const res = await axios.get("/api/v1/cpc/main/board/list?board_master_id=CPC_PRESS_RELEASE&size=6");
            const resMobile = await axios.get("/api/v1/cpc/main/board/list?board_master_id=CPC_PRESS_RELEASE&size=1");
            setPressRelease(res.data);
            setPressReleaseMobile(resMobile.data);
            console.log(res.data);
        } catch (error) {
            console.log(error);
        }
    };

 // api ๋ฐ์ดํ„ฐ ๊ฐ€๋™์‹œํ‚ค๊ธฐ
  useEffect(() => {
        getMainPressRelease();
    }, []);

// ๐Ÿ’ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด๋‹ค.
  useEffect(() => {
        // ๋กค๋ง๋˜๋„๋ก setInterval์„ ์„ ์–ธ.
        const timer = setInterval(() => {
            const rolling = Number(idxRef.current) + 1;
            idxRef.current = rolling % 5; // ๊ฒŒ์‹œ๋ฌผ ๊ฐฏ์ˆ˜
            setIdx(idxRef.current);
            console.log(idxRef.current);
        }, 3000);

      // ๋ฌผ๋ก  clearInterver๋„ ์„ค์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.
        return () => {
            console.log("clean interval");
            clearInterval(timer);
        };
    }, [ pressRelease.length]);

๐ŸŽ view ๋‹จ (=JSX)

return (
 <ul className={styles.article_list}>
                                    {contents.map((item: MainPost) => (
                                        <div key={item.id} style={{ transform: `translateY(-${28.8 * idx}px)`, transition: idx === 0 ? "" : "1s all" }}>
                                            <li>
                                                <Link className={styles.a} to={`/boardView/CPC_NOTICE/${item.id}`}>
                                                    <span className={styles.title}>{item.title}</span>
                                                    <span className={styles.date}>{moment(item.create_date).format("YYYY-MM-DD")}</span>
                                                </Link>
                                            </li>
                                        </div>
                                    ))}
                                </ul>
)

๐ŸŽ CSS ์Šคํƒ€์ผ

.article_list {
        font-size: 18px);
        line-height: 1.3;
        height: 50px;
        overflow: hidden;
}

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋ฉด ์™„์„ฑ !

https://safe.bithumbsystems.com/ --> ํ•ด๋‹น ์‚ฌ์ดํŠธ ๋ฉ”์ธ ๋ถ€๋ถ„์— ๊ณต์ง€์‚ฌํ•ญ์ด๋ž‘ ๋ณด๋„์ž๋ฃŒ ๋ถ€๋ถ„ ๋กค๋ง๋˜๋Š” ๋ถ€๋ถ„ ๊ตฌํ˜„ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

๐Ÿคต๐Ÿปโ€โ™€๏ธ ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ๊ณผ์ •๋“ค (env... build... ์–ด์ฉŒ๊ณ )

๐Ÿคต๐Ÿปโ€โ™€๏ธ ๋ฐฐํฌ๋ฅผ ์œ„ํ•œ ๊ณผ์ •๋“ค

์ „์—ญ ์„ค์ •๊ณผ ๊ฐ™์€ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด env ํŒŒ์ผ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์•ฑ์˜ ๋ฒ„์ „ ์ •๋ณด ๋˜๋Š” api ์ฃผ์†Œ์™€ ๊ฐ™์€ ์ •๋ณด๋ฅผ ์ „์—ญ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

$npm i env-cmd

์„ค์น˜!

image

  1. env ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • ๋ณ€์ˆ˜๋ช…์€ ๋ฌด์กฐ๊ฑด REACT_APP_๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.
env ํŒŒ์ผ

REACT_APP_SERVER_API=http://localhost:8080

์ด๋Ÿฐ์‹์œผ๋กœ ์ƒ์šฉํ•˜๋Š”๋ฐ ์‹ฑ๊ธ€ ์ฟผํ„ฐ๋Š” ํ•„์š”์—†๋‹ค.
๋ถˆ๋Ÿฌ์„œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ด์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

const serverAPI = process.env.REACT_APP_SERVER_API

.env ํŒŒ์ผ์€ ๊ฐœ๋ฐœํ™˜๊ฒฝ๊ณผ ๋ฐฐํฌ์— ๋”ฐ๋ผ ๋‹ค์ˆ˜์˜ ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์ž๋ฉด ์ด๋ ‡๊ฒŒ.

.env-dev
.env-production
.env-local
.env-test
.env

์•ฑ ๋นŒ๋“œ์— ๋”ฐ๋ผ์„œ ์ ์šฉ๋˜๋Š” ํŒŒ์ผ ์šฐ์„ ์ˆœ์œ„๋Š” ์ด์™€ ๊ฐ™๋‹ค.

pagakage.json ํŒŒ์ผ์† script ๋ถ€๋ถ„

npm start: .env-dev, .env
npm run build: .env-production, .env
npm test: .env-test, .env

๋ชจ๋“  env ํŒŒ์ผ์€ ์ค‘์ฒฉ์ด ๋˜๊ณ  ์™ผ์ชฝ ํŒŒ์ผ์ด ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๊ฐ€์žฅ ๋†’๋‹ค.
์ด ๋ง์€ ์ฆ‰์Šจ ๋˜‘๊ฐ™์€ ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ๊ฒฝ์šฐ ์šฐ์ธก์˜ .envํŒŒ์ผ์˜ ๊ทœ์น™์ด ๊ฐ€์žฅ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ์Œ.
๋’ค๋Šฆ๊ฒŒ ์„ ์–ธํ•  ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ

"scripts": {
    "start": "react-scripts start",
    "build": "env-cmd -f .env react-scripts  build",
    "build:prod": "env-cmd -f .env.production react-scripts  build && move build ./build_prod",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },

๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ ๋กœ์ปฌ ๊ฐœ๋ฐœ .env.local

.env.local ํŒŒ์ผ์€ .env๋ฅผ ๋ฎ์–ด ์“ฐ๋Š” ํŒŒ์ผ๋กœ test ํ™˜๊ฒฝ ์™ธ์˜ ๋ชจ๋“  ํ™˜๊ฒฝ์—์„œ ๋กœ๋”ฉ๋œ๋‹ค.

๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ ๊ฐœ๋ฐœํ™˜๊ฒฝ .env.development

$ npm run start
$ yarn start

๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ ์„œ๋ฒ„ ๋ฐฐํฌ์‹œ .env.production

.env.production ํŒŒ์ผ์€ ๋ฐฐํฌ ํ™˜๊ฒฝ ์‹œ ์‚ฌ์šฉ๋˜๋ฉฐ, ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ์น˜๋ฉด ์ž๋™์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ๋งŒ์•ฝ, .env.production.local์ด ์žˆ๋‹ค๋ฉด, .env.production์„ ๋ฎ์–ด์“ด๋‹ค.

$ npm run build 
$ yarn build

๐Ÿ‘จ๐Ÿปโ€โœˆ๏ธ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ .env.test

$ npm run test
$ yarn test

๐Ÿ“’ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํŠน์ง• 1 (๊ธฐ์ˆ  ๋ฉด์ ‘์šฉ ์ด๋ก )

๐Ÿ“’ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„ (๋™์ž‘ํ•˜๋Š” ๊ณผ์ •)

๋ธŒ๋ผ์šฐ์ € ์ž์ฒด์— ๋‚ด์žฅ๋˜์–ด์žˆ๋Š” JS ์—”์ง„์ด ํ•„์š”ํ•˜๋‹ค. ์ด๊ฒƒ์ด ๋™์ž‘ํ•˜๋Š” ์‹œ๊ฐ„์„ ๋Ÿฐํƒ€์ž„์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ ๋Ÿฐํƒ€์ž„ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ฝ”๋“œ๋ฅผ ํ•œ ์ค„ ํ•œ ์ค„ ์ฝ๊ณ  ๋ฒˆ์—ญํ•ด์„œ ์‹คํ–‰์„ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๋ผ๊ณ  ํ•œ๋‹ค. ๋ณดํ†ต ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ์‹์€ ์ž๋ฐ”๋กœ ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ  ์‹คํ–‰ํ•˜๊ธฐ ์ „ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์ปดํŒŒ์ผ๋ง ํ•˜์—ฌ ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

๐Ÿ“• ECMAScirpt?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ํ•„์š”ํ•˜๊ณ  ๊ฐ๊ฐ์˜ ๋ธŒ๋ผ์šฐ์ € ๋งˆ๋‹ค ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์—”์ง„์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ๊ทธ ๋ฒ„์ „ ๋ณ„๋กœ ์ž‘๋™๋˜๋Š” ๊ฒƒ๋„ ๋‹ค ๋‹ค๋ฅด๋‹ค.
๋ฒ„์ „ 5์—์„œ strict mode์™€ getter, setter๊ฐ€ ์ถ”๊ฐ€๋๋‹ค.
์ด๋ ‡๋“ฏ ๋ฒ„์ „์ด ์ƒˆ๋กœ์›Œ์ง€๋ฉด ์ถ”๊ฐ€๋œ ๊ฒƒ ๊ธฐ๋Šฅ๋“ค๋„ ๊ฐ๊ธฐ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•œ๋‹ค.

๋ฐ”๋ฒจ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฒ„์ „ ์‹ ๊ฒฝ ์•ˆ์“ฐ๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํŠน์ง•

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ€๋ณ๊ณ  ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์ด์šฉํ•ด์„œ ๋Ÿฐํƒ€์ž„ ์‹œ ํ•œ ์ค„ ํ•œ ์ค„ ๋ฒˆ์—ญํ•œ๋‹ค.
์ผ๊ธ‰ ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์–ธ์–ด์ด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์žˆ๋Š” ์–ด๋–ค ๊ณณ์ด๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ”„๋กœํ† ํƒ€์ž…์„ ๋ฒ ์ด์Šค๋กœ ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๋ฉ€ํ‹ฐ ํŽ˜๋Ÿฌ๋‹ค์ž„์ด๋‹ค. ์ ˆ์ฐจ์ง€ํ–ฅ์œผ๋กœ๋„ ๊ฐ€๋Šฅํ•˜๊ณ  ๊ฐ์ฒด์ง€ํ–ฅ์œผ๋กœ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์‹ฑ๊ธ€ ์“ฐ๋ ˆ๋“œ๊ณ , ๋‹ค์ด๋‚˜๋ฏนํ•œ ์–ธ์–ด์ด๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด ์ž์ฒด๋งŒ์œผ๋กœ๋Š” ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š๋‹ค.
๋ธŒ๋ผ์šฐ์ €์— ๋ฌด์–ธ๊ฐ€๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์™ธ๋ถ€ํ™˜๊ฒฝ์— ์ถœ๋ ฅ ํ•  ๋งŒํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ํ•˜๋ ค๋ฉด ํ†ต์‹ ์„ ํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
์ด์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ธŒ๋ผ์šฐ์ €์— ๋™์ž‘ํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด ํ”„๋ก ํŠธ์—”๋“œ ์ง€์‹์ด ์žˆ์–ด์•ผํ•œ๋‹ค.

๐ŸŒ ๋ธŒ๋ผ์šฐ์ €

  • ํŠน์ •ํ•œ UI ์š”์†Œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” DOM API
  • ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ต์‹  ํ•ด์ค„ ๋„คํŠธ์›Œํฌ API
  • ์˜ค๋””์˜ค์™€ ๋น„๋””์˜ค๋ฅผ ์ œ๊ณตํ•ด์ฃผ๋Š” ์˜ค๋””์˜ค ๊ด€๋ จ๋œ API
  • ์ฝ˜์†”๋กœ๊ทธ์— ๊ด€๋ จ๋œ API

์ด์™€ ๊ฐ™์€ ์ง€์‹๋“ค๋„ ํ•„์š”ํ•˜๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ทธ๋ƒฅ ์–ธ์–ด์ผ ๋ฟ์ด๋‹ค.
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž˜ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์™€ ๋…ธ๋“œ JS๋ฅผ ๋„˜๋‚˜๋“ค๋ฉฐ ํ”„๋ก ํŠธ์™€ ๋ฐฑ์—”๋“œ๋„ ๋Šฅ์ˆ™๋Šฅ๋ž€ํ•˜๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

โ˜˜๏ธ ํฌ๋กฌ(Chrome) ๋””๋ฒ„๊ทธ ๋จนํ†ต์‹œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

PC์™€ MO๋ฒ„์ „ ๊ฐ™์ด ์ž‘์—…ํ•˜๋Š” ๋ฐ˜์‘ํ˜• ์›น ํ”„๋กœ์ ํŠธ ์ž‘์—… ์ค‘์— ์ผ์–ด๋‚œ ๊ฒฝ์šฐ๋‹ค.
localhost:3000์—์„œ pc๋กœ ๋ดค์„ ๋•Œ๋Š” ์ž˜ ๋ณด์ด๋Š”๋ฐ, ๊ฐœ๋ฐœ์ž๋„๊ตฌ์—์„œ ๋ชจ๋ฐ”์ผ๋กœ ๋ณ€๊ฒฝ ํ›„ ์ƒˆ๋กœ๊ณ ์นจํ•˜๋ฉด
๋ชจ๋ฐ”์ผ ๋ฒ„์ „์œผ๋กœ ๋งž์ถคํ˜• ๋ผ์„œ ์ž˜ ๋‚˜์™€์•ผํ•˜๋Š”๋ฐ ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ์ด ์‹คํŒจ๋๋‹ค๋Š” ํฌ๋กฌ ๋‹ค์ด๋…ธ์™€ ํ•จ๊ป˜ ์—๋Ÿฌ ๋ฌธ๊ตฌ๊ฐ€ ๋–ณ๋‹ค.

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ ํฌ๋กฌ ๋””๋ฒ„๊ทธ ๋จนํ†ต์ด๋ผ๊ณ  ํ•œ๋‹ค.
๋˜ ๋‹ค๋ฅธ ์˜ˆ๋กœ๋Š” console.log('text')๋ผ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์–ด๋„ ์ฝ˜์†”์ฐฝ์— ๋ฉ”์‹œ์ง€๊ฐ€ ๋œจ์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ณผ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.
๋ฒ„ํŠผ์— ์ด๋ฒคํŠธ๋ฅผ ์ค˜๋„ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰์ด ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.

ํฌ๋กฌ ๋””๋ฒ„๊ทธ ๋จนํ†ต ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

์„ค์ •๋“ค์„ ์›์ƒ๋ณต๊ตฌ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-08-05 แ„‹แ…ฉแ„’แ…ฎ 12 17 24

์ด์™€๊ฐ™์ด ํ†ฑ๋‹ˆ๋ฐ”ํ€ด(=setting)๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋””๋ฒ„๊ทธ ๋ชจ๋“œ ์„ค์ •์ฐฝ์œผ๋กœ ์ „ํ™˜๋œ๋‹ค.
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-08-05 แ„‹แ…ฉแ„’แ…ฎ 12 18 13

Restore defaults and reload ๋ผ๋Š” ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋œ๋‹ค.
๋ฌด์Šจ ์˜๋ฏธ๋ƒ๋ฉด ๋ชจ๋“  ํฌ๋กฌ ๋””๋ฒ„๊ทธ ์„ค์ •๋“ค์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋˜๋Œ๋ฆฌ๋ฉด ๋œ๋‹ค๋Š” ์˜๋ฏธ๋‹ค. (= ํฌ๋กฌ ๋””๋ฒ„๊ทธ ์„ค์ • ์ดˆ๊ธฐํ™”)
์ด๋ ‡๊ฒŒ ํ•˜๊ณ ๋‚˜๋‹ˆ ํฌ๋กฌ ๋””๋ฒ„๊ทธ ๋จนํ†ต, ๋ฉˆ์ถค ํ˜„์ƒ์„ ์‚ฌ๋ผ์ง€๊ณ  ์ œ๋Œ€๋กœ ์ž˜ ์ž‘๋™ ๋˜๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๐Ÿ’ [JS]์ˆซ์ž ๊ฐ–๊ณ  ๋†€์•„๋ณด์ž. ์†Œ์ˆ˜์  ๋ฐ˜์˜ฌ๋ฆผํ•˜๋Š” ๋ฐฉ๋ฒ• ๋“ฑ๋“ฑ ์™ธ

๋ชฉ์ฐจ

  1. toFixed() ํ•จ์ˆ˜
  2. Math.round() ํ•จ์ˆ˜
  3. Math.floor() ํ•จ์ˆ˜
  4. Math.ceil() ํ•จ์ˆ˜
  5. toPrecision() ํ•จ์ˆ˜

1. toFixed() ํ•จ์ˆ˜

์†Œ์ˆ˜ ์ž๋ฆฟ์ˆ˜๋กœ ๋ฐ˜์˜ฌ๋ฆผ๋œ ์ˆซ์ž๋ฅผ ๋ฌธ์ž์—ด ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

(123.678).toFixed();
// 124

(123.678).toFixed(1);
// 123.7

2. Math.round() ํ•จ์ˆ˜

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์ˆ˜๋กœ ๋ฐ˜์˜ฌ๋ฆผ๋œ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Math.round(123.456);
// 123

Math.round(123.678);
// 124

Math.round(123.9191);
// 124

3. Math.floor() ํ•จ์ˆ˜

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์ˆ˜๋กœ ๋‚ด๋ฆผ๋œ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜

Math.floor(123.456);
// 123

Math.floor(123.678);
// 123

4. Math. ceil() ํ•จ์ˆ˜

๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์ˆ˜๋กœ ์˜ฌ๋ฆผ๋œ ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜

Math.ceil(123.456);
// 124

Math.ceil(123.678);
// 124

5.toPrecision() ํ•จ์ˆ˜

์ „๋‹ฌ๋œ ๊ฐ’๋งŒํผ ํ‘œํ˜„ํ•  ์ˆ˜์˜ ๊ธธ์ด๋ฅผ ์ œํ•œํ•˜๋ฉฐ, ์ˆซ์ž๋ฅผ ๋ฌธ์ž์—ด ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜

์ด๋ฐ–์— ๋‹ค์–‘ํ•œ ์ˆซ์ž๊ด€๋ จ ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-08-17 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 11 32 27

์ฐธ๊ณ 
https://developer-talk.tistory.com/304
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/random

๐ŸŠ ๋ชจ๋ฐ”์ผ์ผ ๋•Œ ํ…์ŠคํŠธ ๊ธด๊ฑฐ ... ์ฒ˜๋ฆฌ

๐ŸŠ ๋ชจ๋ฐ”์ผ์ผ ๋•Œ ํ…์ŠคํŠธ ๊ธด๊ฑฐ ... ์ฒ˜๋ฆฌ

JSX ์ฝ”๋“œ

    {
          item.title!.length<25
          ? <span className={`${styles.title} ${styles.shorts}`}>{item.title}</span>
          : <span className={styles.title}>{item.title}</span>
      }

์ด๋ ‡๊ฒŒ ํ…์ŠคํŠธ ๊ธธ์ด๋กœ ์ธก์ •ํ•ด์„œ ์Šคํƒ€์ผ์„ ์ฃผ๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

CSS

 .title {
              ๐Ÿ“ display: inline-block;
              ๐Ÿ“ white-space: nowrap;
              ๐Ÿ“ overflow: hidden;
              ๐Ÿ“ text-overflow: ellipsis;
              ๐Ÿ“ width: 58% !important;
              &.shorts {
                  width: 55% !important;
                  text-overflow: clip;
              }
          }

์ด๋ ‡๊ฒŒ width ๊ฐ’์„ ์ฃผ๊ณ  ... ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๐Ÿ“ ๋กœ ํ‘œ๊ธฐํ•ด๋†ˆ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-09-28 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 11 28 16

[JS] User Agent ๋ธŒ๋ผ์šฐ์ € ์ •๋ณด ์–ป๊ธฐ (ํฌ๋กฌ์ธ์ง€ ์•„๋‹Œ์ง€ ์ฒดํฌํ•˜๊ธฐ)

๐Ÿ‘‰ ํ˜„์žฌ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์–ด๋–ค ๊ฒƒ์ธ์ง€ ์•Œ๊ธฐ ์œ„ํ•ด userAgent๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

userAgent๋ž€ ?

๋ธŒ๋ผ์šฐ์ €์— ๋Œ€ํ•œ ์‹๋ณ„ ์ฝ”๋“œ๋กœ ์‚ฌ๋žŒ์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด "์ฃผ๋ฏผ ๋“ฑ๋ก์ฆ" ๊ณผ ๊ฐ™์€ ๊ฒƒ ์‹๋ณ„๋˜๋Š” ๊ฒƒ์€ ์ปดํ“จํ„ฐ(๋‹จ๋ง๊ธฐ)์— ๋Œ€ํ•œ OS ์ •๋ณด, ๋ธŒ๋ผ์šฐ์ € ๋ฒ„์ „, ๋ ˆ์ด์•„์›ƒ ์—”์ง„ ์ข…๋ฅ˜ ๋“ฑ ๋‹ด์•„์„œ ํ•ญ์ƒ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•  ๋•Œ ์ ‘์†์ž ์ •๋ณด๋ฅผ ๋œปํ•œ๋‹ค.

์ฝ”๋“œ์˜ˆ์ œ

var userAgent = window.navigator.userAgent;
var isChrome = userAgent.indexOf('Chrome');
var isChromeMobile = userAgent.indexOf('CriOS');
var isSamsungBrowser = userAgent.indexOf('SamsungBrowser');
var isWindows = userAgent.indexOf('Windows NT');
var isEdge = userAgent.indexOf('Edge');
var isIE = userAgent.indexOf('Trident');

์ด๋Ÿฐ ๋Š๋‚Œ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๊ณ , IF๋ฌธ์œผ๋กœ ์ž‘์—…ํ•  ๋•Œ๋Š”

var isChrome = userAgent.indexOf('Chrome');

// ํฌ๋กฌ์ผ๊ฒฝ์šฐ
if(isChrome > -1) {

}

// ํฌ๋กฌ์ด ์•„๋‹ ๊ฒฝ์šฐ
if(isChrome === -1) {

}

์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. if๋ฌธ์œผ๋กœ ์ ์ ˆํ•˜๊ฒŒ ์ปค์Šคํ…€ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด๋จ.

Navigator ๋ž€?

Navigator ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์‚ฌ์šฉ์ž ์—์ด์ „ํŠธ์˜ ์ƒํƒœ์™€ ์‹ ์› ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ์Šคํฌ๋ฆฝํŠธ๋กœ ํ•ด๋‹น ์ •๋ณด๋ฅผ ์งˆ์˜ํ•  ๋•Œ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํŠน์ • ํ™œ๋™์— ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


Navigator.userAgent.indexOf('๋ธŒ๋ผ์šฐ์ €๋ช…')

if(navigator.userAgent.indexOf('SamsungBrowser') > -1){
     
}

๐Ÿ‘‰ ์ฐธ๊ณ ์ž๋ฃŒ
codepen ์˜ˆ์‹œ
https://codepen.io/zineeworld/pen/oJyZOq
[JS] User Agent ๋ธŒ๋ผ์šฐ์ € ์ •๋ณด ์–ป๊ธฐ (ํฌ๋กฌ์ธ์ง€ ์•„๋‹Œ์ง€ ์ฒดํฌํ•˜๊ธฐ)
https://zinee-world.tistory.com/512
https://developer.mozilla.org/ko/docs/Web/API/Window/navigator#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80_%ED%98%B8%ED%99%98%EC%84%B1
Window.navigator MDN
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90-%EC%A0%91%EC%86%8D%ED%95%98%EB%8A%94-%EA%B8%B0%EA%B8%B0%EB%AA%A8%EB%B0%94%EC%9D%BC%ED%83%9C%EB%B8%94%EB%A6%BFPC-%EA%B5%AC%EB%B6%84%ED%95%98%EA%B8%B0

๐Ÿ“• ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ํŠน์ง• 2 (๋ณ€์ˆ˜์— ๋Œ€ํ•œ ๋ชจ๋“ ๊ฒƒ)

๐ŸŽฝ ๋ฉ”๋ชจ๋ฆฌ

  • ํ•˜๋“œ๋””์Šคํฌ / ๊ณ„์‚ฐํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์—ฐ์‚ฐCPU / ๋ฉ”๋ชจ๋ฆฌ
  • ๋ฉ”๋ชจ๋ฆฌ ์…€์€ 1byte๋กœ ๋งŒ๋“ค์–ด์ ธ์žˆ๋‹ค.
  • ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋™ํ•˜๋Š”๋ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ฝ”๋“œ, ๋ณ€์ˆ˜ ๋ฐ์ดํ„ฐ, ์‹คํ–‰์ˆœ์„œ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ์Šคํƒ, ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌถ์–ด๋†“์€ ๊ฐ์ฒด heap ์ด ํ•„์š”ํ•˜๋‹ค.

๐Ÿ˜’ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰

  1. ์ž…๋ ฅ
  2. ์ฒ˜๋ฆฌ ---> ํ”„๋กœ์„ธ์Šค
  3. ์ถœ๋ ฅ ---> ์Šคํ† ๋ฆฌ์ง€ ๊ฐ™์€ ๊ณณ์— ์ €์žฅ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
    โญ๏ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์žˆ์–ด์„œ ์ž…๋ ฅ ์ฒ˜๋ฆฌ ์ถœ๋ ฅ ๊ฐ€์žฅ ์ค‘์š” ! โญ๏ธ
    ์ œ์ผ ๊ธฐ๋ณธ์ ์ธ ๊ฒƒ์€ ์ฒ˜๋ฆฌ๋‹ค.
    ์ฒ˜๋ฆฌ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ€์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

๐Ÿง ๋ณ€์ˆ˜๋ž€ ?

  • ๊ฐ’์„ ์ €์žฅํ•˜๋Š” ๊ณต๊ฐ„์„ ์˜๋ฏธ
  • ์ž๋ฃŒ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฆ„์ด ์ฃผ์–ด์ง„ ๊ธฐ์–ต ์žฅ์†Œ๋‹ค.
  • let, const ๊ฐ™์€ ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ€์ˆ˜ ์„ ์–ธ let a;
  • ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด ? let a = 0;
  • let์€ ๊ฐ’์„ ์žฌํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. a = 1; ์ด์ฒ˜๋Ÿผ ๊ฐ’์„ ์žฌํ• ๋‹นํ•จใ…Žใ…Ž
    ๊ทธ๋Ÿฌ๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์–ด๋”˜๊ฐ€์— 0์ด๋ผ๋Š” ๊ฐ’์ด ์ €์žฅ๋˜์–ด ์žˆ๋‹ค. ๊ทธ๋Ÿผ ์ด์ œ ๋ฉ”๋ชจ๋ฆฌ ์…€์— ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋“ค์ด ๋“ค์–ด์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ € ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์€ a๋ผ๊ณ  ํ•œ๋‹ค. ๋ณ€์ˆ˜์ด๋ฆ„์ด๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ํ•˜๊ณ  ์‹๋ณ„์ž๋ผ๊ณ  ๋ถ€๋ฅด๊ธฐ๋„ ํ•œ๋‹ค.

๐Ÿคฉ ๋ณ€์ˆ˜ ์ด๋ฆ„ ์ง“๊ธฐ

  • ์ €์žฅ๋œ ๊ฐ’์„ ์ž˜ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” ์˜๋ฏธ ์žˆ๋Š” ์ด๋ฆ„
  • ๊ตฌ์ฒด์ ์ผ ์ˆ˜๋ก ์ข‹๋‹ค.
  • ์˜ˆ์•ฝ์–ด(ํ‚ค์›Œ๋“œ)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ex) if, for, functinon, import ๋ญ ์ด๋Ÿฐ ๊ฒƒ๋“ค
  • ๋ผํ‹ด๋ฌธ์ž(0-9, a-z, A-Z), _, ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„, camelCase (๋‹จ์–ด๊ฐ€ 2๊ฐœ ์ผ ๋•Œ), ํ•œ๊ตญ์–ด๋Š” ์“ฐ์ง€๋ง๊ธฐ
  • ์ˆซ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ์‹๋„ ์•ˆ๋œ๋‹ค.
  • ํŠน์ˆ˜๋ฌธ์ž๋„ ์•ˆ๋œ๋‹ค. (_, $ ์ด 2๊ฐ€์ง€ ์ œ์™ธ)
  • ์ด๋ชจ์ง€ ์‚ฌ์šฉ๋„ ์•ˆ๋œ๋‹ค.
  • ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ์˜์–ด๋กœ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค.
  • ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ณ€์ˆ˜๋ฅผ 1,2,3 ์ˆซ์ž๋กœ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ๋„ ์•ˆ์ข‹๋‹ค.

๐Ÿคฌ ๋‚˜์œ์˜ˆ์ œ

// ๋‚˜์œ ์˜ˆ
let number = 20;

// ์ข‹์€ ์˜ˆ
let myAge = 20;

์ด๋Ÿฐ์‹์œผ๋กœ ๊ตฌ์ฒด์ ์œผ๋กœ ์ด๋ฆ„์„ ์ง“๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•œ๋‹ค.

๐Ÿ˜ณ ๋ฐ์ดํ„ฐ ํƒ€์ž…

์›์‹œํ˜•(๋‹จ์ผ ๋ฐ์ดํ„ฐ)๊ณผ ๊ฐ์ฒดํ˜•(๋ณตํ•ฉ ๋ฐ์ดํ„ฐ)์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๋‹จ์ผ ๋ฐ์ดํ„ฐ (number, string, boolean, null, undefined, symbol) ๋ณตํ•ฉ ๋ฐ์ดํ„ฐ (object, array, function)

(1) ์ˆซ์žํ˜•

  • ์ •์ˆ˜, ์Œ์ˆ˜, ์‹ค์ˆ˜, 2์ง„์ˆ˜, 8์ง„์ˆ˜, 16์ง„์ˆ˜ ๋ชจ๋‘ ๋ณ€์ˆ˜์— ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.
let integer = 123; // ์ •์ˆ˜
let negative = -123; // ์Œ์ˆ˜
let double = 1.23; // ์‹ค์ˆ˜

let binary = 0b1111011; // 2์ง„์ˆ˜
let octal = 0o173; // 8์ง„์ˆ˜
let hex = 0x7b; // 16์ง„์ˆ˜

๋งŒ์ผ ์ˆซ์ž๋ฅผ ์ถœ๋ ฅํ•  ๋•Œ ์ถœ๋ ฅ๊ฐ’์ด infinity๋‚˜ -infinity ๊ฐ’์ด ๋‚˜์˜ค๋ฉด ์•ˆ๋œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์ˆซ์ž์™€ ํ…์ŠคํŠธ๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๊ณ„์‚ฐ์‹์„ ๋‚ธ๋‹ค๋ฉด NaN์ด๋ผ๋Š” ๊ฐ’์ด ์ถœ๋ ฅ๋œ๋‹ค.

(2) ๋ฌธ์ž์—ด

  • string์„ ์˜๋ฏธํ•œ๋‹ค. "" ์Œ๋”ฐ์˜ดํ‘œ๋‚˜ '' ์‹ฑ๊ธ€๋”ฐ์˜ดํ‘œ๋กœ๋„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” `` ๊บฝ์„ธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž์—ด์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  • ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด : `` ๊บฝ์„ธ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž์—ด๊ณผ ๊ฐ์ฒด๋ฅผ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์„ ๋งํ•œ๋‹ค. ex) '์•ˆ๋…•!', ${title} ์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

(3) ๋ถˆ๋ฆฌ์–ธ ํƒ€์ž… (boolean)

  • ์ฐธ true / ๊ฑฐ์ง“ false ์— ๋”ฐ๋ฅธ ๊ฒฐ๊ณผ๊ฐ’์„ ์–ป๋Š”๋‹ค.
let isFree = ture; // ์ฐธ์ธ ๊ฐ’
let isActivated = false; // ๊ฑฐ์ง“์ธ ๊ฐ’

console.log(!!0); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!-0); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!''); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!null); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!undefined); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!Nan); // flase ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

console.log(!!1); // true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!-1); // true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!'text'); // true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!{}); // true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.
console.log(!!Infinity); // true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

๋Š๋‚Œํ‘œ 2๊ฐœ๋ฅผ ๋ถ™ํžˆ๋ฉด ๊ฐ’์„ true๋‚˜ flase๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋Š๋‚Œํ‘œ 2๊ฐœ + ํ……ํ…… ๋นˆ ์• ๋“ค์€ false ๊ฐ’์ด ๋‚˜์˜ค๊ณ  ๋Š๋‚Œํ‘œ 2๊ฐœ + ๋ฌด์–ธ๊ฐ€๊ฐ€ ์žˆ๋Š” ์• ๋“ค์€ true ๊ฐ’์ด ๋‚˜์˜จ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

(4) null๊ณผ undefined ํƒ€์ž…

  • ์ด ๋‘˜์€ ๋น„์Šทํ•œ ๊ฒƒ ๊ฐ™์ง€๋งŒ ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๋‹ค๋ฅด๋‹ค.
  • value : ๋ญ”๊ฐ€ ์žˆ์Œ
  • null : ๋ญ”๊ฐ€ ์—†์Œ
  • undefined : ์•„๋ฌด๊ฒƒ๋„ ํ™•์ •๋˜์–ด์žˆ์ง€ ์•Š์Œ.
let title; // ์•„์ง ํ™œ์„ฑํ™” ๋œ ๋ฌด์–ธ๊ฐ€๊ฐ€ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ๋ชจ๋ฅด๋Š” ์ƒํƒœ
title = null; // ํ™œ์„ฑํ™”๋œ ๋ฌด์–ธ๊ฐ€๊ฐ€ ์—†๋Š” ์ƒํƒœ

๊ทธ๋ž˜์„œ null์„ ํ• ๋‹นํ•˜๋ฉด object๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค.
ํ•˜์ง€๋งŒ undefined๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ™•์ •๋˜์ง€ ์•Š์€ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฝ˜์†”๋กœ๊ทธ์— ์ถœ๋ ฅํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๊ทธ๋Œ€๋กœ undefined๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

typeof

  • ์–ด๋–ค ํƒ€์ž…์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํ‚ค์›Œ๋“œ

๋ณตํ•ฉ๋ฐ์ดํ„ฐ์ธ ๊ฐ์ฒด๋ฅผ ์•Œ์•„๋ณด์ž. Object

  • ์ƒํƒœ๋‚˜ ํ–‰๋™์„ ๋ฌถ์–ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
{ key : value }

์ด๋ ‡๊ฒŒ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

์•ฑ์— ๋ฉ”๋ชจ๋ฆฌ ์ƒ์— data์™€ stack์—๋Š” ์›์‹œํ˜• ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  heap์กด์—๋Š” ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค.

let apple = {
  name: 'apple',
  color: 'red',
  display: '๐ŸŽ'
}

์ด๋ ‡๊ฒŒ ์ƒ๊ธด ๊ฒƒ์„ ๊ฐ์ฒด๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿฅฏ ๊ฐ’๊ณผ ์ฐธ์กฐ์˜ ์ฐจ์ด

let a = 1;
let b = a; // 1

b=2; // ์žฌํ• ๋‹น์‹œ ? ์ด์ œ 2๊ฐ€ ๋œ๋‹ค.
  • ์ด ์›๋ฆฌ๋ฅผ copy by value ๋ผ๊ณ  ๋งํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ๋™์ž‘์ด ๊ฐ์ฒด๋กœ ๊ฐ€๋ฉด ๋‹ฌ๋ผ์ง„๋‹ค

let apple = {
   name : 'apple'
}
let orange = apple; 
  • ์˜ค๋ Œ์ง€์— ์• ํ”Œ์„ ํ• ๋‹นํ•œ๋‹ค๋ฉด ? ์ € ์ฃผ์†Œ๊ฐ’์ด ๋ณต์‚ฌ๋˜์–ด ํ• ๋‹น๋œ๋‹ค.
  • ์ด ์›๋ฆฌ๋ฅผ copy by reference ๋ผ๊ณ  ๋งํ•œ๋‹ค.
apple.name = 'orange'

๋ผ๊ณ  ๋ฐ”๊พธ๋ฉด name์ด ๋™์ผํ•˜๊ฒŒ orange๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค.

๐Ÿฅจ ์ •๋ฆฌ

  • ์›์‹œํƒ€์ž…์€ ๊ฐ’์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ๋œ๋‹ค.
  • ๊ฐ์ฒดํƒ€์ž…์€ ์ฐธ์กฐ๊ฐ’(๋ฉ”๋ชจ๋ฆฌ์ฃผ์†Œ, ๋ ˆํผ๋Ÿฐ์Šค)์ด ๋ณต์‚ฌ๋˜์–ด ์ „๋‹ฌ๋œ๋‹ค.

์ƒ์ˆ˜ ๋ณ€์ˆ˜ const

  • let์€ ์žฌํ• ๋‹น์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • const ์žฌํ• ๋‹น์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
let a = 1;
a = 2; // ---> ๊ฐ€๋Šฅ

const text = 'hello';
text='bye'; // ---> ๋ถˆ๊ฐ€.
  • ์ƒ์ˆ˜๋Š” ํ•ญ์ƒ ๋Œ€๋ฌธ์ž๋กœ ์‚ฌ์šฉํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • ์žฌํ• ๋‹น ๋ถˆ๊ฐ€๋Šฅํ•œ ์ƒ์ˆ˜๋ณ€์ˆ˜ ๋˜๋Š” ๋ณ€์ˆ˜
const MAX_FRUITS = 5;

const apple = {
  name: 'apple',
  color: 'red',
  display: '๐ŸŽ'
}

ํ•˜์ง€๋งŒ ๊ฐ์ฒด์— ์žˆ๋Š” ๋‚ด์šฉ๋ฌผ๋“ค์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

apple.name = 'orange'; // ์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๋ฉด
console.log(apple); // ๊ฒฐ๊ณผ๊ฐ’์ด ๋ฐ”๋€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์–˜๋„ค ๋“ค์ด ๊ฐ€๋ฅดํ‚ค๊ณ  ์žˆ๋Š” ํŠน์ •ํ•œ object ๋‚ด๋ถ€๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ํƒ€์ž… ํ™•์ธํ•˜๋Š” ๋ฒ• typeof

  • ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํ™•์ธํ•œ๋‹ค.
  • ๊ฐ’์„ ํƒ€์ž… ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜
let variable;
console.log(typeof variable); // undefined

variable = '';
console.log(typeof variable); // string

variable = 1;
console.log(typeof variable); // number

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋™์ ์œผ๋กœ ์‹คํ–‰๋  ๋•Œ ์–ด๋–ค ๊ฐ’์ด ํ• ๋‹น ๋๋Š๋ƒ์— ๋”ฐ๋ผ ํƒ€์ž…์ด ๊ฒฐ์ •๋œ๋‹ค.

๐Ÿ”Ž ๊ฒ€์ƒ‰ ๊ตฌํ˜„ ํ•˜๋ฉด์„œ ๋Š๋‚€์ 

๐Ÿ”Ž ๊ฒ€์ƒ‰ ๊ตฌํ˜„

(1) ์ตœ๊ทผ ๊ฒ€์ƒ‰ํ•œ ํ‚ค์›Œ๋“œ โ†’ ํ‚ค์›Œ๋“œ๋ฅผ ๊ฒ€์ƒ‰ ํ›„ ํ•ด๋‹น ์•„์ดํ…œ์„ ํด๋ฆญ ํ–ˆ์„ ๋•Œ ์ด๋ฒคํŠธ ๊ฑธ๊ธฐ

์ค‘๋ณต๋œ ๊ฒ€์ƒ‰์–ด๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์˜›๋‚  ๊ธฐ๋ก์€ ์ง€์›Œ์ง€๊ณ  ์ตœ์‹  ๊ธฐ๋ก์„ ์•ž์œผ๋กœ ๋‹น๊ธด๋‹ค.
๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ ๋‚ด์—ญ 10๊ฐœ ๊นŒ์ง€๋งŒ ๋ณด์—ฌ์ง€๋„๋ก ! 11๊ฐœ ์งธ๋ถ€ํ„ฐ ์‚ฌ๋ผ์ง€๊ณ  ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ๋‹ค.

์‚ฌ์šฉํ•œ ๋ฉ”์„œ๋“œ filter, _(lodash), unshift, pop, localstorage

์กฐ๊ฑด 1. ์ค‘๋ณต๋œ ๊ฒ€์ƒ‰์–ด๊ฐ€ ์žˆ๋‹ค๋ฉด

_ lodash

if (_.filter(๊ฒ€์ƒ‰๋œ ๋ฆฌ์ŠคํŠธ, ๊ฒ€์ƒ‰ํ•œ ํ‚ค์›Œ๋“œ).length > 0) {
    ...
}

๊ฒ€์ƒ‰๋œ ๋ฆฌ์ŠคํŠธ์— ๋‚ด๊ฐ€ ๊ฒ€์ƒ‰ํ•œ ํ‚ค์›Œ๋“œ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด 1 ์—†๋‹ค๋ฉด -1์ด๋‹ค. (indexOf) ๊ฐ™์€ ์—ญํ• ์„ ํ•ด์ค€๋‹ค.

๊ทธ๋Ÿฌ๋ฏ€๋กœ ์žˆ์„ ๊ฒฝ์šฐ 0๋ณด๋‹ค ํดํ…Œ๋‹ˆ ๋ถ€๋“ฑํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์กฐ๊ฑด์„ ๊ฑธ์–ด์ฃผ๊ณ  ๋ธ”๋ก์•ˆ์— ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด์งˆ ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ ๋กœ์ง์„ ์ƒ์„ฑํ•œ๋‹ค.

๐Ÿ“ filter

keywordList = keywordList.filter((item) => {
   // item์˜ ๊ฒ€์ƒ‰๋ช…๊ณผ ๋‚ด๊ฐ€ ํด๋ฆญํ•œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์•„์ดํ…œ์ด ๋‹ค๋ฅธ ์• ๋“ค์€ ์•ž์œผ๋กœ ๋ณด๋‚ด๊ธฐ
   return item.coin !== newCoinMarket.coin || item.market !== newCoinMarket.market;
});

// ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— ๋‚ด๊ฐ€ ํด๋ฆญํ•œ ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•ด์ฃผ์ž
keywordList.unshift(newCoinMarket);
}

filter์™€ map์€ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ES6 ๋ฌธ๋ฒ•์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ „์—ญ๋ณ€์ˆ˜๋กœ ์„ ์–ธ๋œ keywordList์˜ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๊ฐ’์„ ๋งŒ๋“ค์–ด์ฃผ๋Š”๋ฐ, ์ด์ฒ˜๋Ÿผ ๋ฐ˜ํ™˜๋œ ๊ฐ’์ด ํ˜„์žฌ ์žˆ๋˜ item์˜ coin๊ณผ ๋‚ด๊ฐ€ ์ฐพ๊ณ ์ž ํ•œ coin์ด ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ~ ( || (OR) ์—ฐ์‚ฐ์ž) market ๋˜ํ•œ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ์• ๋“ค์€ ์•ž์œผ๋กœ ๋ณด๋‚ด์ค€๋‹ค. (unShift) ์ด๋ ‡๊ฒŒ filter๋กœ ํ•˜์—ฌ๊ธˆ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์ด ๋งŒ๋“ค์–ด์ง„ keywordList ๋ฐฐ์—ด์— ๋‚ด๊ฐ€ ํด๋ฆญํ•œ ์•„์ดํ…œ์„ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•ด์คŒ์œผ๋กœ์„œ ์ตœ๊ทผ ๊ฒ€์ƒ‰ํ•œ ๊ฒ€์ƒ‰๋ช…์— ์ค‘๋ณต๋œ ์• ๋“ค์€ ํ•œ ๋ฒˆ์— ์ทจํ•ฉ๋ผ์„œ ์ตœ์‹  ๊ธฐ๋ก ์ˆœ์„œ๋กœ ์˜ฎ๊ฒจ์ง€๊ฒŒ ๋˜๊ณ  ์ค‘๋ณต๋œ ๊ฐ’๋“ค์€ ์•ž์œผ๋กœ ๊ฐ€๋ฉด์„œ new ๋ฐฐ์—ด๊ฐ’์ด ์ƒ๊ธฐ๋„๋ก ํ–ˆ๋‹ค.

๐Ÿ“ ์ž‘์—…ํ•˜๋ฉด์„œ ํ—ท๊ฐˆ๋ฆฐ ๊ฒƒ.

ํ™”์‚ดํ‘œํ•จ์ˆ˜์—์„œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ๋•Œ, function ํ•จ์ˆ˜์™€๋Š” ๋‹ฌ๋ฆฌ
const sum = (num1, num2) => num1 + num2 ์ด๋ ‡๊ฒŒ ๋ธ”๋ก ์—†์ด ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ๋ธ”๋ก์•ˆ์—์„œ๋Š” retrun์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

arrow ํ•จ์ˆ˜ return?

const sum = (num1, num2) => {
 return num1 + num2;
}

์กฐ๊ฑด 2. ์ค‘๋ณต๋œ ์•„์ดํ…œ์ด ์—†์„ ๊ฒฝ์šฐ โ†’ ๋ณด์—ฌ์งˆ ์ˆ˜ ์žˆ๋Š” ์•„์ดํ…œ์€ ์ตœ๋Œ€ 10๊ฐœ ์ฒ˜๋ฆฌ

unShift๋กœ ๋ฆฌ์ŠคํŠธ์— ์•„์ดํ…œ ์ถ”๊ฐ€ํ•˜๊ธฐ

์กฐ๊ฑด 3. 10๊ฐœ๊ฐ€ ์ดˆ๊ณผ ๋์„ ๊ฒฝ์šฐ ?

  • ๋งˆ์ง€๋ง‰ ์ˆœ์„œ์— ์œ„์น˜ํ•œ ๋ฆฌ์ŠคํŠธ ์•„์ดํ…œ ์ œ๊ฑฐํ•˜๊ธฐ (pop)
  • ๊ทธ๋ฆฌ๊ณ  ์ƒˆ๋กœ์šด ์•„์ดํ…œ ์ตœ์‹  ์ˆœ์„œ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ (unShift)
  • ๊ฒฐ๋ก ์ ์œผ๋กœ ์ด๋ ‡๊ฒŒ ์กฐ๊ฑด๋ฌธ์„ ๊ฑฐ์นœ ์• ๋“ค์€ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅํ•ด์ค€๋‹ค.

๊ทธ๋ ‡๊ฒŒ ์ตœ๊ทผ ๊ฒ€์ƒ‰ํ•œ ๊ฐ€์ƒ์ž์‚ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์™„๋ฃŒ

(2) ๊ฒ€์ƒ‰ ํ•„ํ„ฐ๋ง

  1. ๊ฒ€์ƒ‰๋ช… (ํ•œ๊ธ€, ์˜์–ด)
    2.๊ฒ€์ƒ‰ํ•œ ํ‚ค์›Œ๋“œ์˜ ์‹ฌ๋ณผ๋ช…
  2. ํ•œ๊ธ€ ์ดˆ์„ฑ
  3. ์˜์–ด๋กœ '๊ฒ€์ƒ‰๋ช…' ์ž…๋ ฅํ•  ๋•Œ, ์ด 4๊ฐ€์ง€ ์กฐ๊ฑด์ด ์„ฑ๋ฆฝ๋ผ์„œ ๊ฒ€์ƒ‰์‹œ ์ฐพ๊ณ ์žํ•˜๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด ๋‚˜์™€์•ผํ•œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์–‘ํ•œ ๋กœ์ง์œผ๋กœ ์กฐ๊ฑด๋ฌธ์„ ๋งŒ๋“ค์–ด์„œ ์ž‘์—…ํ•ด๋ดค์œผ๋‚˜, ์‹œ๊ฐ„ ์ง€์—ฐ์œผ๋กœ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.
๊ฒ€์ƒ‰ํ•  ๋•Œ ํŠนํžˆ ๊ฐ€์žฅ ์–ด๋ ค์› ๋˜ ๊ฒƒ์ด ๋ฌด์—‡ ์ด๋ƒ๋ฉด ํ•œ๊ธ€ ๊ฒ€์ƒ‰ํ•  ๋•Œ๋Š” ์ดˆ์„ฑ, ์ข…์„ฑ, ์ค‘์„ฑ ๊ทธ๋ฆฌ๊ณ  ์ž์Œ๊ณผ ๋ชจ์Œ์ด ์žˆ๊ณ  '์ป'์„ ์ž…๋ ฅํ•ด๋„ ์ด๋”๋ฆฌ์›€์ด๋ผ๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด ๋‚˜์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‘๋ฒŒ์‹๋„ ๊ณ ๋ คํ•ด์„œ ํ•ด์•ผํ•œ๋‹ค. ๊ทผ๋ฐ ๊ทธ๊ฒƒ์„ ์ „๋ถ€ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ํ•œ๊ธ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์—ˆ๋‹ค. โ†’ hangul.js ์ฐธ๊ณ ํ•˜๊ธฐ

hangul.js์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ๋„ ๋‹ค์–‘ํ•˜๋‹ค !

(3) ์ž…๋ ฅ๋œ ํ‚ค์›Œ๋“œ๋งŒ ์ƒ‰๊น”์ž…ํžˆ๊ธฐ (ํ•˜์ด๋ผ์ดํ„ฐ)

ํ˜„์žฌ ๋‚ด๊ฐ€ ์ž…๋ ฅํ•œ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ํ•˜์ด๋ผ์ดํ„ฐ ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋„ indexOf, split, splice, join ๋“ฑ๋“ฑ ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ๋“ค์„ ์ž˜ ํ™œ์šฉํ•ด์•ผ๋˜๋Š”๋ฐ
ํ•˜๋‹ค๊ฐ€ ๊ตฌ์กฐ์š”์ฒญํ–ˆ๋‹ค. ์•”ํŠผ ๋ฐฐ์—ด ์ชผ๊ฐœ๊ณ  ๋ถ™ํžˆ๊ณ  ํ•˜๋Š” ๋Šฅ๋ ฅ๋„ ๋ถ€์กฑํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ๋”ฐ๋กœ ์—ฐ์Šตํ•ด๋ณด์ž !

[ios] scorll smooth ๋น„ํ˜„์ƒ

ios์—์„œ๋Š” ์Šคํฌ๋กค์ด ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์›€์ง์ด์ง€ ์•Š๋Š” ํ˜„์ƒ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค.

์ฐธ๊ณ  : https://github.com/magic-akari/seamless-scroll-polyfill
https://joonfluence.tistory.com/entry/IOS-Chrome-Safari%EC%97%90%EC%84%9C-Smooth-Scroll%EC%9D%B4-%EC%95%88%EB%90%A0-%EB%95%8C-%ED%95%B4%EA%B2%B0%EB%B2%95

CSS

html {
 scroll-behavior: smooth;
}

JS

 document.getElementById(์•„์ด๋””).scrollIntoView({
   behavior: 'smooth',
 });

๐Ÿช ์ฟ ํ‚ค๋ž€ ?

์ฟ ํ‚ค๋ž€?

์ฟ ํ‚ค๋Š” ํด๋ผ์ด์–ธํŠธ(๋ธŒ๋ผ์šฐ์ €) ๋กœ์ปฌ์— ์ €์žฅ๋˜๋Š” ํ‚ค์™€ ๊ฐ’์ด ๋“ค์–ด์žˆ๋Š” ์ž‘์€ ๋ฐ์ดํ„ฐ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.
์‚ฌ์šฉ์ž ์ธ์ฆ์ด ์œ ํšจํ•œ ์‹œ๊ฐ„์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์œ ํšจ ์‹œ๊ฐ„์ด ์ •ํ•ด์ง€๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ์ธ์ฆ์ด ์œ ์ง€๋œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ฟ ํ‚ค๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ƒํƒœ ์ •๋ณด๋ฅผ ๋กœ์ปฌ์— ์ €์žฅํ–ˆ๋‹ค๊ฐ€ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์ด์–ธํŠธ์— 300๊ฐœ๊นŒ์ง€ ์ฟ ํ‚ค์ €์žฅ ๊ฐ€๋Šฅ, ํ•˜๋‚˜์˜ ๋„๋ฉ”์ธ๋‹น 20๊ฐœ์˜ ๊ฐ’๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ, ํ•˜๋‚˜์˜ ์ฟ ํ‚ค๊ฐ’์€ 4KB๊นŒ์ง€ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
Response Header์— Set-Cookie ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ฟ ํ‚ค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋”ฐ๋กœ ์š”์ฒญํ•˜์ง€ ์•Š์•„๋„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ Request์‹œ์— Request Header๋ฅผ ๋„ฃ์–ด์„œ ์ž๋™์œผ๋กœ ์„œ๋ฒ„์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

์ฟ ํ‚ค์˜ ๊ตฌ์„ฑ ์š”์†Œ

์ด๋ฆ„ : ๊ฐ๊ฐ์˜ ์ฟ ํ‚ค๋ฅผ ๊ตฌ๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„
๊ฐ’ : ์ฟ ํ‚ค์˜ ์ด๋ฆ„๊ณผ ๊ด€๋ จ๋œ ๊ฐ’
์œ ํšจ์‹œ๊ฐ„ : ์ฟ ํ‚ค์˜ ์œ ์ง€์‹œ๊ฐ„
๋„๋ฉ”์ธ : ์ฟ ํ‚ค๋ฅผ ์ „์†กํ•  ๋„๋ฉ”์ธ
๊ฒฝ๋กœ : ์ฟ ํ‚ค๋ฅผ ์ „์†กํ•  ์š”์ฒญ ๊ฒฝ๋กœ
์ฟ ํ‚ค์˜ ๋™์ž‘ ๋ฐฉ์‹

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ์š”์ฒญ
์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค๋ฅผ ์ƒ์„ฑ
HTTP ํ—ค๋”์— ์ฟ ํ‚ค๋ฅผ ํฌํ•จ ์‹œ์ผœ ์‘๋‹ต
๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ์ฟ ํ‚ค ๋งŒ๋ฃŒ ๊ธฐ๊ฐ„์ด ์žˆ๋‹ค๋ฉด ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณด๊ด€ํ•˜๊ณ  ์žˆ์Œ
๊ฐ™์€ ์š”์ฒญ์„ ํ•  ๊ฒฝ์šฐ HTTP ํ—ค๋”์— ์ฟ ํ‚ค๋ฅผ ํ•จ๊ป˜ ๋ณด๋ƒ„
์„œ๋ฒ„์—์„œ ์ฟ ํ‚ค๋ฅผ ์ฝ์–ด ์ด์ „ ์ƒํƒœ ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝ ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์ฟ ํ‚ค๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ์ฟ ํ‚ค๋ฅผ HTTP ํ—ค๋”์— ํฌํ•จ์‹œ์ผœ ์‘๋‹ต

์ฟ ํ‚ค์˜ ์‚ฌ์šฉ ์˜ˆ

๋ฐฉ๋ฌธ ์‚ฌ์ดํŠธ์—์„œ ๋กœ๊ทธ์ธ ์‹œ, "์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ €์žฅํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?"
์‡ผํ•‘๋ชฐ์˜ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ธฐ๋Šฅ
์ž๋™๋กœ๊ทธ์ธ, ํŒ์—…์—์„œ "์˜ค๋Š˜ ๋” ์ด์ƒ ์ด ์ฐฝ์„ ๋ณด์ง€ ์•Š์Œ" ์ฒดํฌ, ์‡ผํ•‘๋ชฐ์˜ ์žฅ๋ฐ”๊ตฌ๋‹ˆ

๐Ÿ‘‹ hooks ์˜ˆ, ์ข‹์€ ์ฝ”๋“œ ์ž‘์„ฑ๋ฐฉ์‹

01. ์ถ”์ฒœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ ์ž‘์„ฑ๋ฒ•

ํƒ€์ž… ์ •์˜๋Š” ๋งจ ์œ„์—
์—ฐ๊ด€ ๋œ ๊ธฐ๋Šฅ์˜ useState์™€ useEffect๋Š” ๋ฌถ์–ด์„œ ๋‘๊ธฐ
๋ณต์žกํ•œ ์ฝ”๋“œ๋Š” hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ

02. ์†์„ฑ๊ฐ’ ํƒ€์ž… ์ •์˜ํ•˜๊ธฐ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋™์  ํƒ€์ž… ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์— ์ •์  ํƒ€์ž… ์–ธ์–ด์ธ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
ํƒ€์ž… ์˜ค๋ฅ˜๋ฅผ ์‚ฌ์ „์— ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ•จ์ˆ˜์— ๋Œ€ํ•œ ํƒ€์ž…์€ ์ฃผ์„์œผ๋กœ ๋‹ฌ์•„๋‘๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. (๋ฐ˜ํ™˜๊ฐ’์— ๋Œ€ํ•ด์„œ๋„...)
ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์—†์„ ๋•Œ์—๋Š” prop-types๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์„œ ์†์„ฑ๊ฐ’ ํƒ€์ž…์„ ์ •์˜

03. ๊ฐ€๋…์„ฑ์„ ๋†’์ด๋Š” ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง ๋ฐฉ๋ฒ•

์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์ด๋ž€ ? ์„ ํƒ์ ์œผ๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

๐Ÿ‘Ž ์•ˆ์ข‹์€ ์˜ˆ

์‚ผํ•ญ์—ฐ์‚ฐ์ž

{isLogin ? (
    <div>
        <p>{name}๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”</p>
    </div>
    ) : null}

์‚ผํ•ญ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ์˜ ์ข‹์€์˜ˆ

๐Ÿ‘ ๊ฐœ์„ ๋œ ์ฝ”๋“œ

์ข€ ๋” ๊ฐœ์„ ๋œ ์ฝ”๋“œ

{isLogin && (
    <div>
        <p>{name}๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”</p>
    </div>
}

&& (AND) ์—ฐ์‚ฐ์ž

const num = 'ab' && 0 && 2;
// result
 
const num = 'ab' && 2 && 3;
// result

๊ฑฐ์ง“์„ ๋งŒ๋‚˜๊ฑฐ๋‚˜ ๋งˆ์ง€๋ง‰๊นŒ์ง€ ํ‰๊ฐ€๋  ๋•Œ ๊ทธ ๊ฒƒ์ด ๋‹ต์ด๋œ๋‹ค.

๐Ÿ‘Ž ์•ˆ์ข‹์€ ์˜ˆ

<div>
    {cash && <p>{cash}์› ๋ณด์œ  ์ค‘</p>} // ----&gt; 0์ผ ๊ฒฝ์šฐ
    {memo && <p>{200 - memo.length}์ž ์ž…๋ ฅ ๊ฐ€๋Šฅ</p>} // ----&gt; '' ๋นˆ ๋ฌธ์ž์—ด์ผ ๊ฒฝ์šฐ
</div>

๐Ÿ‘ ๊ฐœ์„ ๋œ ์ฝ”๋“œ

์•„๋ž˜์™€ ๊ฐ™์ด ๋ช…ํ™•ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธฐ

<div>
    {cash !== null && <p>{cash}์› ๋ณด์œ  ์ค‘</p>} // ----&gt; 0์ผ ๊ฒฝ์šฐ
    {memo !== null && <p>{200 - memo.length}์ž ์ž…๋ ฅ ๊ฐ€๋Šฅ</p>} // ----&gt; '' ๋นˆ ๋ฌธ์ž์—ด์ผ ๊ฒฝ์šฐ
</div>

|| (OR) ์—ฐ์‚ฐ์ž

const v1 = 'ab' || 0;
// result
 
const v2 = '' || 0 | 3;
// result

์ฒ˜์Œ์œผ๋กœ ์ฐธ์„ ๋งŒ๋‚  ๋•Œ ๊ฐ’์ด ๋œ๋‹ค.

?? nullish ๋ฐฉ์‹

const msg = null ?? 'hello';
const msg = undefined ?? 'hello';

null ์ด๋‚˜ undefined๊ฐ€ ์•„๋‹Œ ๊ฐ’์„ ์ถœ๋ ฅํ•ด์ค€๋‹ค.

false๋กœ ์ทจ๊ธ‰ํ•˜๋Š” ๊ฐ’

0
-0
NaN
' ' (๋นˆ ๋ฌธ์ž์—ด)
null
undefined
false

04. ์žฌ์‚ฌ์šฉ์„ฑ์„ ๊ณ ๋ คํ•œ ์ปดํฌ๋„ŒํŠธ ๊ตฌ๋ถ„๋ฒ•

โ†’ ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ํ•˜์ž

๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ž€ ?

๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ์ฝ”๋“œ๋ผ๋ฆฌ ๋ชจ์€๋‹ค. (ex. UI๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ, ์„œ๋ฒ„ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ, DB๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฝ”๋“œ)
์—ฐ๊ด€๋œ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ํด๋”๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•œ๋‹ค.

์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹์€ ์ปดํฌ๋„ŒํŠธ

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์—†๋‹ค.
์ƒํƒฏ๊ฐ’์ด ์—†๋‹ค.

05. useEffect ์‹ค์ „ ํ™œ์šฉ๋ฒ•

  • ์˜์กด์„ฑ ๋ฐฐ์—ด ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•
useEffect(() => {
        (...)
    },[์˜์กด์„ฑ ๋ฐฐ์—ด])

์˜์กด์„ฑ ๋ฐฐ์—ด์— ๋‹ด๊ธด ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ ๋  ๊ฒฝ์šฐ ๋ถ€์ˆ˜ ํšจ๊ณผ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋จ
API ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•  ๋•Œ, useCallback ์˜์กด์„ฑ ๋ฐฐ์—ด์— ๊ฐ’์ด ์—†์–ด๋„ ์ƒˆ๋กœ์šด ๊ฐ’ ์ƒ์„ฑํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ

function Profile&#40;{ userId }&#41; {
    const [user, setUser] = useState();
 
 
    useEffect(() => {
        (...)
    },[user])
}
useCallback(() => {
    ํ•จ์ˆ˜
}, [๋ณ€๊ฒฝ๋ ํ•จ์ˆ˜])

๊ฐ€์žฅ ๋ฒ ์ŠคํŠธ ๋ฐฉ๋ฒ•

if๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ ๋ถ„๊ธฐ์ฒ˜๋ฆฌํ•˜์—ฌ api ํ˜ธ์ถœ ์‹คํ–‰ ์‹œ์ ์„ ๊ด€๋ฆฌํ•œ๋‹ค.

  1. async await๋ฅผ ๋ถ€์ˆ˜ํšจ๊ณผ ํ•จ์ˆ˜์— ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ
useEffect(async () => {
     const data = await fetchUser(A,B);
},[])

๋ถ€์ˆ˜ํšจ๊ณผ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’์€ ํ•ญ์ƒ ํ•จ์ˆ˜ ํƒ€์ž…์ด์–ด์•ผ ํ•œ๋‹ค.
async await ํ•จ์ˆ˜๋Š” promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜.

(1) useEffect ์•ˆ์—๋‹ค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

useEffect(() => {
    async function test () {
       const data = await fetchUser(A,B);
    }
},[])

(2) ํ•จ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ

async function test () {
       const data = await fetchUser(A,B);
    }
 
 
useEffect(() => {
    test()
},[])

06. ๋ Œ๋”๋ง ์†๋„๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•

๋ฆฌ์•กํŠธ์—์„œ ์ตœ์ดˆ ๋ Œ๋”๋ง ํ›„, ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‹œ ๋ Œ๋”๋ง์„ ํ•˜๋Š”๋ฐ ์ด์™€ ๊ฐ™์€ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์นœ๋‹ค.

์ด์ „ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋ฅผ ์žฌ์‚ฌ์šฉํ• ์ง€ ํŒ๋‹จํ•œ๋‹ค.
์ปดํฌ๋„ŒํŠธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
๊ฐ€์ƒ ๋”๋ผ๋ฆฌ ๋น„๊ตํ•ด์„œ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์‹ค์ œ ๋”์— ๋ฐ˜์˜ํ•œ๋‹ค.

React.Memo

์ปดํฌ๋„ŒํŠธ์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ง‰์•„์ค€๋‹ค.

function MyComponent(view){
    // ...
}

React.memo(MyComponent, view);
์†์„ฑ๊ฐ’๊ณผ ๋น„๊ตํ•ด์„œ ๊ฐ™๋‹ค๋ฉด ์ฐธ์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ด์ „์˜ ๊ฐ’์„ ์žฌ์‚ฌ์šฉ์„ ํ•œ๋‹ค.

์†์„ฑ๊ฐ’๊ณผ ๋น„๊ตํ•˜์—ฌ ๋‹ค๋ฅด๋‹ค๋ฉด ๊ฑฐ์ง“์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ’์„ ๋‹ค์‹œ ๋ฆฌ๋ Œ๋”๋ง ํ•ด์ค€๋‹ค.

useMemo : ๊ฐ’์„ ๋ฉ”๋ชจ์ œ์ด์…˜
useCallback : ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจ์ œ์ด์…˜

git ์œ ์šฉํ•œ ๋ช…๋ น์–ด ๋ชจ์Œ์ง‘

Git Cheat Sheet

Set up

Git Config

๋ชจ๋“  ๊ตฌ์„ฑ ๋ณด๊ธฐ

git config --list #show all the settings in gitconfig

ํŽธ์ง‘ํ•  ๊ตฌ์„ฑ ์—ด๊ธฐ

git config --global -e #open .gitconfig file

๊ธฐ๋ณธ ํŽธ์ง‘๊ธฐ ์„ค์ •

git config --global core.editor "code --wait" # set default text editor for git 

์‚ฌ์šฉ์ž ์„ค์ •

git config --global user.name "name" #set user.name
git config --global user.email "email" #set user.email
git config user.name #check user.name
git config user.email #check user.email

์ž๋™ CRLF ์„ค์ •

git config --global core.autocrlf true #for Windows
git config --global core.autocrlf input #for Mac

Git Aliases

git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status

Help

Git official site

https://git-scm.com/docs

See help

git config --help #detail
git config -h #short

Basic

Git ์ดˆ๊ธฐํ™”

git init #initialise git 
rm -rf .git #delete .git 

์ž‘์—… ํŠธ๋ฆฌ ์ƒํƒœ ํ‘œ์‹œ

git status #full status
git status -s #short status

Ignoring Files

Add files that should be ignored in .gitignore in project directory

For example:

# ignore all .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in any directory named build
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory and any of its subdirectories
doc/**/*.pdf

Staging files

git add a.txt #stage a.txt file
git add a.txt b.txt #stage a.txt, b.txt files
git add *.txt #stage all files ends with .txt 
git add * #stage all files except deleted files and files that begin with a dot
git add . #stage everything 

Modifying files

Removing files

rm file.txt #delete file
git add file.txt #add to staging area
git rm file.txt # removes file from working directory and staging area
git rm --cached file.txt #removes from staging area only
git clean -fd #removes all untracked files

Moving files

git mv from.txt to.txt
git mv from.text /logs/from.text

Viewing the Staged/Unstaged changes

git status #full status
git status -s #short status
git diff #changes in working directory
git diff --staged #changes in staging area
git diff --cached #same as --staged

Visual Diff Tool

Open .gitconfig and add below

[diff]
    tool = vscode
[difftool "vscode"]
    cmd = code --wait --diff $LOCAL $REMOTE

Run Git Diff tool

git difftool

Commit

git commit #commit stagged files
git commit -m "Commit message" #commit stagged files with commit message
git commit -am "Commit message" #commit all files with commit message

Log ยท History

See history

git log #list of commits 
git log --patch #shows the difference introduced in each commit
git log -p #same as --patch
git log --state #abbreviated states for each commit
git log --oneline #oneline
git log --oneline --reverse #oneline, from the oldest to the newest 

Log Formatting

git log --pretty=oneline #same as --oneline
git log --pretty=format:"%h - %an %ar %s" #formatting
git log --pretty=format:"%h %s" --graph #show graph
git log --graph --all --pretty=format:'%C(yellow)[%ad]%C(reset) %C(green)[%h]%C(reset) | %C(white)%s %C(bold red){{%an}}%C(reset) %C(blue)%d%C(reset)' --date=short

Log Filtering

git log -2 #shows only the last n commits
git log --author="ellie" 
git log --before="2020-09-29"
git log --after="one week ago"
git log --grep="message" #finds in commit messages
git log -S="code" #finds in the code
git log file.txt #logs only for file.txt

History of a file

git log file.txt #history of file.txt
git log --state file.txt #shows statistics
git log --patch file.txt #show the changes

HEAD ยท Hash code

git log HEAD
git log HEAD~1
git log hash

Viewing a commit

git show HEAD #shows the last commit
git show hash #shows the given commit
git show hash:file.txt 

Comparing

git diff hash1 hash2 #all changes between two commits
git diff hash1 hash2 file.txt #changes to file.txt only

Tagging

Creating

git tag v1.0.0 #lightweight tag on latest commit
git tag v1.0.0 hash #lightweight tag on the given commit
git show v.0.0 #shows the tag
git tag -a v.1.0.0 -m "message" #annotated tag

Listing

git tag #all the tags
git tag -l "v1.0.*" #search certain tags

Deleting

git tag -d v1.0.0 #delete the given tag

Syncing with Remote

git push origin v1.0.0 #sharing the given tag with remote
git push origin --tags #sharing all the tags
git push origin --delete v1.0.0 #delete a remote tag 

Checking out Tags

git checkout v1.0.0 #checkout certain tag
git checkout -b branchName v1.0.0 #create a new bracnh with the given tag 

Branch

Creating branch

git branch testing #create a new branch called testing
git checkout testing #switches to testing branch
git switch testing #same as the above
git checkout -b testing #create and switch to testing 
git switch -C testing #same as the above

Managing Branch

git branch #simple listing of all branches
git branch -r #sees the remote branches
git branch --all #list including remote branches
git branch -v #sees the last commit on each branch
git branch --merged #sees merged branches
git branch --no-merged #sees not merged branches
git branch -d testing #deletes the branch
git push origin --delete testing
git branch --move wrong correct #rename
git push --set-upstream origin correct #push new name

Comparing

git log branch1..branch2 #all the commits between branch1 and branch2
git diff branch1..branch2 #all the changes between branch1 and branch2

Merge

git merge featureA #merges featureA branch into the current one
git merge --squash featureA #suqash merge, only one commit
git merge --no-ff featureA #creates a merge commit 
git merge --continue 
git merge --abort
git mergetool #opens merge tool 

Merge tool Config

[merge]
    tool = vscode
[mergetool]
	keepBackup = false
[mergetool "vscode"]
    cmd = code --wait $MERGED
[mergetool "p4merge"]
    path = "/Applications/p4merge.app/Contents/MacOS/p4merge"

Rebasing

git rebase master #rebase current branch onto the master
git rebase --onto master service ui #take commits of the ui branch forked from the service branch and move them to master

Cherry picking

git cherry-pick hash #applies the given commit 

Stashing

Saving

git stash push -m "message" #make a new stash
git stash #same as above
git stash --keep-index #stash but keep them in the staging area
git stash -u #--include-untracked 

Listing

git stash list #see all the stashes
git stash show hash #see the given stash
git stash show hash -p #see the given stash with details 

Applying

git stash apply hash #applies the given stash
git stash apply #applies the latest stash
git stash apply --index #apply the stated changes
git stash pop #apply and drop 
git stash branch branchName #apply stash in a new branch

Deleting

git stash drop hash #deletes the given stash
git stash clear #deletes all the stashes

Undo

Local Changes

Unstaging a staged file

git reset HEAD file.txt

Unmodifying a modified file

git checkout -- file.txt

Discarding local changes

git restore --staged file.txt #unstaging a staged file
git restore file.txt #unmodifying a modified file
git restore . #unmodifying all modified files in the directory
git clean -fd #removes all untracked files

Restoring file from certain commit

git restore --source=hash file.txt
git restore --source=HEAD~2 file.txt

Commit

Amending the last commit

git commit --amend

Reset

git reset --soft HEAD # ์ค€๋น„ ์˜์—ญ์—์„œ ์ปค๋ฐ‹ ๋ฐ ์œ ์ง€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
git reset --mixed HEAD # ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์ปค๋ฐ‹ ๋ฐ ์œ ์ง€ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
git reset --hard HEAD # ์ปค๋ฐ‹์„ ์ œ๊ฑฐํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š์Œ

Undo action - reflog

git reflog
git reset --hard hash

Revert

git revert hash # ์ง€์ •๋œ ์ปค๋ฐ‹์„ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค.
git revert HEAD~1 
git revert --no-commit hash # ์ปค๋ฐ‹ ๋˜๋Œ๋ฆฌ๊ธฐ ์—†์ด ์ง€์ •๋œ ์ปค๋ฐ‹์„ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค.

Interactive Rebasing

git rebase -i HEAD~2
git rebase --continue
git rebase --abort

Remote

git clone URL #cloning
git remote -v #shows all the remote URLs
git remote add name URL #add a new remote with name

Inspecting

git remote
git remote show 
git remote show origin

Syncing with remotes

git fetch #pulls down all the data from remote 
git fetch origin #same as the above
git fetch origin master #pulls down only master branch
git pull #fetch and merge
git pull --rebase #use rebase when pulling instead of merge
git push
git push origin master 

Renaming or Removing

git remote rename sec second
git remote remove second

Tools

Basic Debugging

git blame file.txt

Bisect

git bisect start
git bisect good hash
git bisect good 
git bisect bad
git bisect reset

Config

[alias]
	s = status
	l = log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %Cgreen(%cr) %C(magenta)<%an>%Creset'
	up = !git fetch origin master && git rebase origin/master
	co = checkout
	ca = !git add -A && git commit -m 
	cad = !git add -A && git commit -m "."
	c = commit
	b = branch
  list = stash list
  save = stash save 
	pop = stash pop
	apply = stash apply
	rc = rebase โ€”continue
	get = "!f(){ git fetch && git checkout $1 && git reset --hard origin/$1; };f"
	new = "!f(){ git co -b ellie-$1 origin/master && git pull; };f"
	st = status
	hist = log --graph --all --pretty=format:'%C(yellow)[%ad]%C(reset) %C(green)[%h]%C(reset) | %C(white)%s %C(bold red){{%an}}%C(reset) %C(blue)%d%C(reset)' --date=short

๐Ÿ“ฒ ํ…Œ์ŠคํŠธํฐ ๋””๋ฒ„๊น… ํ•˜๋Š” ๋ฐฉ๋ฒ•

๊ณตํ†ต : ํœด๋Œ€ํฐ ์ผ€์ด๋ธ”์„ ์—ฐ๊ฒฐํ•œ๋‹ค.
์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ์ค€ ์œˆ๋„์šฐ์—, ์•„์ดํฐ์ผ ๊ฒฝ์šฐ์—๋Š” ๋งฅ์—๋‹ค๊ฐ€ ์—ฐ๊ฒฐํ•ด์•ผํ•œ๋‹ค.

๐Ÿ“ฒ ์•ˆ๋“œ๋กœ์ด๋“œ ๋””๋ฒ„๊น… ๋ฐฉ๋ฒ•

โญ์ด ์ฃผ์†Œ๋กœ ์ ‘๊ทผํ•˜๊ธฐ -> chrome://inspect/#devices

chrome inspect ํด๋ฆญํ•ด์„œ ํ™•์ธํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“ฒ ์•„์ดํฐ ๋””๋ฒ„๊น… ๋ฐฉ๋ฒ•

์‚ฌํŒŒ๋ฆฌ ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.
โญSafari -> ์ƒ๋‹จํƒญ์—์„œ Develope -> ์•„์ดํฐ ์–ด์ฉŒ๊ณ  ์ €์ฉŒ๊ณ  -> ๋””๋ฒ„๊น… ํด๋ฆญ

์•„์ดํฐ ์„ค์ • -> ์‚ฌํŒŒ๋ฆฌ -> ๊ณ ๊ธ‰ -> ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ, ์›น์†์„ฑ ํ™œ์„ฑํ™”


๋””๋ฒ„๊น… ํ™”๋ฉด์—์„œ ํƒญ [Sources]์— ๋“ค์–ด๊ฐ€์„œ [Search] ์— ์žˆ์„๋งŒํ•œ ๋‚ด์šฉ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๋” ๋นจ๋ฆฌ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋””๋ฒ„๊น… ๊ฑธ ์†Œ์Šค ์ฝ”๋“œ์—๋‹ค๊ฐ€ ๋ธŒ๋ ˆ์ดํฌ ํฌ์ธํŠธ (๋งˆ์ปค) ์žก๊ณ  ๋””๋ฒ„๊น… ํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“ฒ ๋””๋ฒ„๊น… ์‹คํ–‰ ์‹œํ‚ค๋Š” ๋‹จ์ถ•ํ‚ค

ctrl + enter

๋‹ค์Œ ํ”Œ๋กœ์šฐ์— ๋””๋ฒ„๊น… ํƒ€๋Š”์ง€ ํ™•์ธํ• ๋ ค๋ฉด F10 ๋ˆŒ๋Ÿฌ์„œ ํ•œ์ค„ ํ•œ์ค„ ๋‹ค์Œ ์ฝ”๋“œ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿšฉ react ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ ํˆดํŒ ๋งํ’์„  ๋„์šฐ๋ฉด์„œ ๋ฐฐ์šด์  ์ •๋ฆฌ

react ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ SIMPLE ์„œ๋น„์Šค ํˆดํŒ ๋งํ’์„  ๋„์šฐ๋ฉด์„œ ๋ฐฐ์šด์  ์ •๋ฆฌ

// ์Šคํฌ๋กค ์ด๋ฒคํŠธ์™€ ํด๋ฆญ ์ด๋ฒคํŠธ ์‹คํ–‰์‹œ ๋งํ’์„  ์‚ฌ๋ผ์ง€๋„๋ก
useEffect(() => {
   window.addEventListener('scroll', handleScroll);
   window.addEventListener('click', handleScroll);
   return () => {
      window.removeEventListener('scroll', handleScroll);
      window.removeEventListener('click', handleScroll);
   };
}, []);
 
// ์Šคํฌ๋กค, ํด๋ฆญ ์ด๋ฒคํŠธ
const handleScroll = (e) => {
   // ์Šคํฌ๋กค ์‹œ, ์•„๋ฌด๊ณณ ํด๋ฆญ์‹œ simpleTip ๋งํ’์„  ์‚ฌ๋ผ์ง€๊ฒŒ
   if (window.scrollY >= 100 || onModal && (!el.current || !el.current?.contains(e.target))){
      setOnModal(false)
   }
};

useEffect๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋ž‘ click ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ handleScroll ์ด๋ผ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋™์ž‘๋˜๋„๋ก ํ–ˆ๋‹ค.
๊ทธ๋ž˜์„œ useEffect ๊ธฐ๋Šฅ๋‚ด์— ์žˆ๋Š” retrun ๊ฐ’์„ ํ†ตํ•ด cleanup ์ž‘์—…๊นŒ์ง€ ํ–ˆ๋‹ค. (removeEventListener == ์ด๋ฒคํŠธ๋ฅผ ์ง€์›Œ์ฃผ๋Š”)

๊ทธ๋ฆฌ๊ณ  ์„œ๋น„์Šค ํˆดํŒ ๋งํ’์„ ์ด ์‚ฌ๋ผ์ง€๋Š” ์กฐ๊ฑด์€ 2๊ฐ€์ง€๋‹ค

  1. ์Šคํฌ๋กค ์‹œ
  2. ์•„๋ฌด ๊ณณ ํด๋ฆญํ•  ๋•Œ

๊ทผ๋ฐ ์ž‘์—…ํ•˜๋ฉด์„œ ๋ฌธ์ œ์ ์ด ๋ฌด์—‡์ด๋ƒ๋ฉด,
๋ฉ”์ธํŽ˜์ด์ง€์— ์ฒซ ๋ฒˆ์งธ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ๋‹ฌ์„ ํด๋ฆญํ•˜์—ฌ ๋‹ซ๊ฒŒ ๋  ๊ฒฝ์šฐ, ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์ด ์ผ์–ด๋‚˜์„œ ๋งํ’์„ ๊นŒ์ง€ ๋™์‹œ์— ์‚ฌ๋ผ์ง„๋‹ค.
๊ทธ๋ž˜์„œ ์ฒซ ๋ฒˆ์งธ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ๋‹ฌ์„ ๋‹ซ์„ ๋•Œ์— close ๋˜๋Š” ์ด๋ฒคํŠธ ์ชฝ์—๋‹ค๊ฐ€ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์„ ์•„๋ž˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ง‰์•„์ฃผ์—ˆ๋‹ค.

event.stopPropagation()
์„ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿฅ ์ด๋ฒคํŠธ ๋ฒ„๋ธ”๋ง์ด๋ž€ ?

์ด๋ฒคํŠธ๊ฐ€ ์—ฐ์†ํ•˜์—ฌ ๋ฐœ์ƒํ•˜๋Š” ๋ฒ„๋ธ” ํ˜„์ƒ์„ ์˜๋ฏธํ•œ๋‹ค.
์ž์‹ ์—˜๋ฆฌ๋จผํŠธ์—์„œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ, ๋ถ€๋ชจ ์—˜๋ฆฌ๋จผํŠธ์— ๊ฐ™์€ ์ด๋ฒคํŠธ๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์ด๋ฒคํŠธ์— ํ• ๋‹น๋œ ๊ธฐ๋Šฅ๋„ ํ•จ๊ป˜ ์‹คํ–‰๋œ๋‹ค.
๊ทธ๋ž˜์„œ ์ด ๊ฐ™์€ ํ˜„์ƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ๋Š” e.stopPropagation() ์„ ์‚ฌ์šฉํ•ด์„œ ๋ง‰์•„์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿค– Lodash (ps.๋ฐฐ์—ด์•ˆ์˜ ๊ฐ์ฒด๋“ค์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์ข‹์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

๐Ÿค– Lodash

lodash๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ธ๊ธฐ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜ ์ž…๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ฐฐ์—ด ์•ˆ์˜ ๊ฐ์ฒด๋“ค์˜ ๊ฐ’์„ ํ•ธ๋“ค๋ง ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ ์œผ๋กœ ์ธํ•ด JS ์˜ ๋ณต์žกํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ํ•„์š” ์—†์ด lodash ๋กœ ํ•˜์—ฌ๊ธˆ ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ฝ”๋“œ๋Ÿ‰๋„ ์ค„์—ฌ์ฃผ๊ณ  ๋น ๋ฅธ ์ž‘์—…์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค !

โญ๏ธ ํŠนํžˆ front-end ํ™˜๊ฒฝ์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์„ค์น˜ ๋ช…๋ น์–ด

$ yarn i --save lodash
$ yarn i --save @types/lodash

์‚ฌ์šฉ๋ฒ•

import _ from 'lodash';

(...)

_.(๋ฐฐ์—ด๋ณ€์ˆ˜)

lodash๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

  • ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์„ฑ๋Šฅ์ด ๋ณด์žฅ๋˜์–ด์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
  • ํผํฌ๋จผ์Šค ์ธก๋ฉด์—์„œ native๋ณด๋‹ค ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๊ฐ€์ง
  • npm์ด๋‚˜ ๊ธฐํƒ€ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ ์„ค์น˜ํ•˜์—ฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ‘จ๐Ÿผโ€๐Ÿณย ๋ช‡ ๊ฐ€์ง€ ์œ ์šฉํ•œ ๋ฉ”์„œ๋“œ example

1. ์›ํ•˜๋Š” index ๊ฐ’ ๊ตฌํ•˜๊ธฐ

var myFriend = [
 {name:'kys',job:'developer',age:27},
 {name:'cys',job:'webtoons man',age:27},
 {name:'yhs',job:'florist',age:26},
 {name:'chj',job:'nonghyup man',age:27},
 {name:'ghh',job:'coffee man',age:27},
 {name:'ldh',job:'kangaroo father',age:27},
 {name:'hsy',job:'monk',age:27},
];

// ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋‚˜์ด๊ฐ€ 26์ธ ๊ฐ์ฒด๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ๋‚˜์˜ค๋Š” index ๋ฐ˜ํ™˜
_.findIndex(myFriend, (friend) => {
  return friend.age === 26;
});

2. ๋‹ค์ฐจ์› ๋ฐฐ์—ด ๋‚ด ์š”์†Œ ์ถœ๋ ฅ

_.flatten(arraym[isDeep])

์‚ฌ์šฉ๋ฒ•

_.flatten([1, [2, 3, [4]]], true);
// โ†’ [1, 2, 3, 4]

๊ธฐ์กด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ž‘ ๋น„๊ต

  • ์ด๊ฒŒ ์–ผ๋งˆ๋‚˜ ํŽธ๋ฆฌํ•œ์ง€ lodash ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ์ฝ”๋“œ์™€ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

JSON

const myFriend = [
	{'name':'๋ผ์ง€'},
	{'name':'๋งˆ๋ผํƒ•'},
	{'name':'๊ณฑ์ฐฝ'},
	{'name':'ํ† ์ด์Šคํ† ๋ฆฌ'}
]

๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽ“ย lodash ์‚ฌ์šฉ์ „ vs ์‚ฌ์šฉํ›„

myFriend.map((item) => {
	return {
		item.name
	}
}
_.map(mayFriend, 'name')

โœจย ๊น”๋” ๊ทธ์ž์ฒด โœจ

Lodash ๊ณต์‹๋ฌธ์„œ

[Lodash](https://lodash.com/)

  • ์ˆ˜๋งŽ์€ ๋ฉ”์„œ๋“œ๋“ค์„ ์ œ๊ณตํ•ด์ฃผ๋‹ˆ ๊ณต์‹๋ฌธ์„œ ๋ณด๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜์„ธ์š” ๐Ÿ™ƒ๐Ÿ‘

โค๏ธโ€๐Ÿฉน SNS ์†Œ์…œ ๊ณต์œ ํ•˜๊ธฐ ์ž‘์—…ํ•˜๊ธฐ

๐Ÿ’ž SNS ์†Œ์…œ ๊ณต์œ ํ•˜๊ธฐ ์ž‘์—…

  • ํŽ˜์ด์Šค๋ถ
  • ํŠธ์œ„ํ„ฐ
  • ๋ผ์ธ
  • ์นด์นด์˜ค
  • ํ…”๋ ˆ๊ทธ๋žจ
const url = encodeURI(window.location.href);

// Facebook
const shareFacebook = () => {
  window.open("http://www.facebook.com/sharer/sharer.php?u=" + url);
}

// Twitter
const shareTwitter = () => {
  window.open("https://twitter.com/intent/tweet?url=" +  url)
}

// ๋ผ์ธ

// ํ…”๋ ˆ๊ทธ๋žจ
const shareTelegram = () => {
  window.open("https://telegram.me/share/url?url=" + url);
}

์นด์นด์˜ค๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฆ„

  • ๊ฐœ๋ฐœ์ž ๋“ฑ๋ก, ํ‚ค ๋ฐœ๊ธ‰, ์ „์—ญ ์„ค์ • ๋“ฑ์ด ํ•„์š”ํ•˜๋‹ค.

(1) ์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ๋“ฑ๋ก ๋ฐ ํ‚ค ๋ฐœ๊ธ‰
๋จผ์ €, ์นด์นด์˜ค ๊ฐœ๋ฐœ์ž ํŽ˜์ด์ง€์— ์ ‘์†ํ•˜์—ฌ ๊ฐœ๋ฐœ์ž ๊ณ„์ •์œผ๋กœ ๊ฐ€์ž…ํ•œ๋‹ค. (๋งํฌ : developers.kakao.com/)

  • ๋‚ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์ด๋™ํ•ด์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

image

  • ์—ฌ๊ธฐ์„œ ์„ค์ •ํ•˜๋Š” ์•ฑ ์•„์ด์ฝ˜, ์•ฑ ์ด๋ฆ„์€ ์นด์นด์˜คํ†ก ๊ณต์œ ์‹œ์— ๋…ธ์ถœ๋˜๋Š” ์‚ฌ์ง„ ๋ฐ ํƒ€์ดํ‹€์ด ๋œ๋‹ค.
  • ์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™”๋ฉด์œผ๋กœ ์ง„์ž…ํ•˜๋ฉด, ๋ฐœ๊ธ‰๋ฐ›์€ ์•ฑ ํ‚ค๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ, Javascript ํ‚ค๋ฅผ ํ”„๋กœ์ ํŠธ์— ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.
    ๋˜ํ•œ, ํ”Œ๋žซํผ ๋ฉ”๋‰ด์— ๊ฐ€์„œ ์ ์šฉํ•  ์‚ฌ์ดํŠธ์˜ ๋„๋ฉ”์ธ์„ ๋“ฑ๋กํ•ด์ค€๋‹ค!

์ฐธ๊ณ ์ž๋ฃŒ : https://abangpa1ace.tistory.com/255

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.