[TIL] Day27 #React #JSX

Beanxxยท2022๋…„ 6์›” 2์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
27/120
post-thumbnail

[TIL] Day27
[SEB FE] Day27

โ˜‘๏ธย React

Front-end ๊ฐœ๋ฐœ์„ ์œ„ํ•œ JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ‘‰ย React๋Š” "ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ์œ„ํ•œ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ฝ”๋“œ ๋ฌถ์Œ"์ธ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ์ˆ ์  ๋ถ„๋ฅ˜์— ๋”ฐ๋ผ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๊ณ , ๊ธฐ๋Šฅ ๋ณ„๋กœ ์ฝ”๋“œ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ธธ ๊ถŒ์žฅ!

  1. ์„ ์–ธํ˜•(Declarative): ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋ช…์‹œ์ ์œผ๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ JSX๋ฅผ ํ™œ์šฉํ•œ ์„ ์–ธํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ง€ํ–ฅ
  2. ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜: ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌํ•˜๋ฉด ์„œ๋กœ ๋…๋ฆฝ์ ์ด๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ๋Šฅ ์ž์ฒด์— ์ง‘์ค‘ํ•˜์—ฌ ๊ฐœ๋ฐœ ๊ฐ€๋Šฅ (์œ ์ง€๋ณด์ˆ˜, ์œ ๋‹› ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ์— ํŽธ๋ฆฌ)
  3. ๋ฒ”์šฉ์„ฑ(๋‹ค์–‘ํ•œ ๊ณณ์—์„œ ํ™œ์šฉ ๊ฐ€๋Šฅ): ๋ฆฌ์•กํŠธ๋Š” ๊ธฐ์กด ํ”„๋กœ์ ํŠธ์—๋„ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

๐Ÿ“Žย JSX(JavaScript XML)

React์—์„œ UI๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ๋ฒ•์œผ๋กœ JS๋ฅผ ํ™•์žฅํ•œ ๋ฌธ๋ฒ• โ†’ React Element ์ƒ์„ฑ

โœ‹ย JSX โ‰  HTML (HTML ๋ฌธ๋ฒ•์„ ์ผ๋ถ€ ์ฐจ์šฉํ–ˆ์ง€๋งŒ, ๋‹ค๋ฅธ ๋ฌธ๋ฒ• ์‚ฌ์šฉ)
๐Ÿ‘‰ย JSX๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด JS๋งŒ์œผ๋กœ๋„ markup ํ˜•ํƒœ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ DOM์— ๋ฐฐ์น˜ ๊ฐ€๋Šฅ

  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” JS ์ฝ”๋“œ๊ฐ€ ์•„๋‹˜
    โ†’ So, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” JS ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์–ด์•ผ ํ•จ โ‡’ Babel

  • Babel: JSX๋ฅผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” JS๋กœ ์ปดํŒŒ์ผ โ†’ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ JS๋ฅผ ์ฝ๊ณ  ํ™”๋ฉด์— ๋ Œ๋”๋ง

  • JS ๋ฌธ๋ฒ•๊ณผ HTML ๋ฌธ๋ฒ•์„ ๋™์‹œ์— ์ด์šฉํ•ด ๊ธฐ๋Šฅ๊ณผ ๊ตฌ์กฐ๋ฅผ ํ•œ๋ˆˆ์— ํ™•์ธ ๊ฐ€๋Šฅ
    โ†’ ๊ตฌ์กฐ์™€ ๋™์ž‘์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ํ•œ ๋ญ‰์น˜๋กœ ์ ์€ ์ฝ”๋“œ์…‹์„ ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ํ•จ

โœ‹ย JSX ์—†์ด๋„ React ์š”์†Œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ , ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๋‹จ์  ์กด์žฌ


โœ”๏ธย JSX ๋ฌธ๋ฒ•

  • ์—ฌ๋Ÿฌ Element๋ฅผ ์ž‘์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ, ์ตœ์ƒ์œ„์—์„œ opening tag & closing tag๋กœ ๊ฐ์‹ธ์ฃผ์–ด์•ผ ํ•จ
    <div>
    	<div>
    		<h1>Hello</h1>
    	</div>
    	<div>
    		<h2>World</h2>
    	</div>
    </div>
  • Element Class ์‚ฌ์šฉ ์‹œ, className์œผ๋กœ ํ‘œ๊ธฐ โœ‹ย ๋งŒ์•ฝ class๋กœ ์ž‘์„ฑํ•œ๋‹ค๋ฉด React์—์„  ์ด๋ฅผ HTML ํด๋ž˜์Šค ์†์„ฑ ๋Œ€์‹  JS ํด๋ž˜์Šค๋กœ ๋ฐ›์•„๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์˜!
    <div className="colors">Hello!</div>
  • JS ํ‘œํ˜„์‹ ์‚ฌ์šฉ์‹œ, ์ค‘๊ด„ํ˜ธ({}) ์ด์šฉ
    function App() {
    	const name = "soobin";
    
    	return (
    		<div>
    			Hello, {name}!
    		</div>
    	);
    }
  • ์‚ฌ์šฉ์ž ์ •์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ โœ‹ย ๋งŒ์•ฝ ์†Œ๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•œ๋‹ค๋ฉด ์ผ๋ฐ˜์ ์ธ HTML ์—˜๋ฆฌ๋จผํŠธ๋กœ ์ธ์‹
    function Hello() {
    	return <div>Hello!</div>;
    }
    
    function HelloWorld() {
    	return <Hello/>;
    }
  • ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง์—๋Š” ์‚ผํ•ญ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ ( if๋ฌธ โŒย )
    <div>
    	{(1+1 === 2) ? (<p>์ •๋‹ต</p>) : (<p>์˜ค๋‹ต</p>)}
    </div>
  • ์—ฌ๋Ÿฌ HTML element ํ‘œ์‹œ์‹œ, map() ํ•จ์ˆ˜ ์ด์šฉ
    • map() ํ•จ์ˆ˜ ์‚ฌ์šฉ์‹œ, ๋ฐ˜๋“œ์‹œ โ€˜keyโ€™ JSX ์†์„ฑ ์‚ฝ์ž…
      • ๋ฐ์ดํ„ฐ์˜ ID๋ฅผ key๋กœ ์‚ฌ์šฉ
      • ๋ณ€ํ•˜์ง€ ์•Š๊ณ , ์˜ˆ์ƒ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์œ ์ผํ•œ ID๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ํ•ญ๋ชฉ์˜ index๋ฅผ key๋กœ ์‚ฌ์šฉ
      • key ์†์„ฑ ์œ„์น˜๋Š” map() ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์— ์žˆ๋Š” ์ฒซ element์—
    โœ‹ย map() ํŠน์„ฑ: ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋ฅผ ํŠน์ • ๋…ผ๋ฆฌ(ํ•จ์ˆ˜)์— ์˜ํ•ด ๋‹ค๋ฅธ ์š”์†Œ๋กœ ์ง€์ •(map)
    function Blog() {
    	const content = posts.map((post) =>
    		<div key={post.id}>
    			<h2>{post.title}</h2>
    			<p>{post.content}</p>
    		</div>
    	);
    
      // return ์•ˆ์— ๋‹จ์ผ ์š”์†Œ ์กด์žฌ์‹œ () ์ƒ๋žต ๊ฐ€๋Šฅ
    	// ๋‘ ๊ฐœ ์ด์ƒ์˜ ์š”์†Œ ์กด์žฌ์‹œ ()๋กœ ๊ฐ์‹ธ์ฃผ์–ด์•ผ ํ•จ
    	return (
    		<div>
    			{content}
    		</div>
    	);
    }

๐Ÿ“Žย Component

  • ๊ฐ๊ฐ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐ์ž ๊ณ ์œ ์˜ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด์„œ UI์˜ ํ•œ ๋ถ€๋ถ„์„ ๋‹ด๋‹น
  • ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ์œ„ํ•œ ์ฝ”๋“œ ๋ชจ์Œ์ง‘
  • ํด๋ž˜์Šค ํ˜•ํƒœ๋กœ๋„ ํ‘œํ˜„ ๊ฐ€๋Šฅ
  • ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ ๊ธฐ๋Šฅ ๋ณ„๋กœ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋„๋ก ๊ถŒ์žฅ
    โ‡’ ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ์˜์กด์„ฑ์ด ๋‚ฎ์•„์ง€๊ณ  ๋…๋ฆฝ์ ์œผ๋กœ ์ž‘๋™

    • ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ์‹œ, ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š” ์—†์Œ
    • ์›ํ•˜๋Š” ์ˆ˜์ • ์‚ฌํ•ญ์— ๋งž์ถฐ ์ปดํฌ๋„ŒํŠธ ์œ„์น˜๋งŒ ์ˆ˜์ •ํ•ด์ฃผ๊ฑฐ๋‚˜ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ โ†’ ํšจ์œจ์ ์ธ ๊ฐœ๋ฐœ ๊ฐ€๋Šฅ
  • ์ปดํฌ๋„ŒํŠธ ๋จผ์ € ์™„์„ฑ์‹œํ‚จ ํ›„, ๋ ˆ์ด์•„์›ƒ์— ๋”ฐ๋ผ ์œ ๋™์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ƒํ–ฅ์‹ ๊ฐœ๋ฐœ(Bottom-up) ๋ฐฉ์‹์— ์ ํ•ฉ

  • ๊ธฐ์กด์—” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ ์ฃผ๋กœ ์‚ฌ์šฉ โ†’ ์ตœ๊ทผ์—” ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉ


๐Ÿ“Žย Create React App

React SPA๋ฅผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ง„ ํˆด ์ฒด์ธ

// React project ์ƒ์„ฑ
npx create-react-app <project-name>

โœ‹ย ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ ์œ„์—” ํ•ญ์ƒ root ์—ญํ• ์„ ํ•˜๋Š” ์ตœ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ ์กด์žฌ (ex. <App>)



โœ”๏ธย JSX ์˜ˆ์‹œ

// 1
let langs = ["JavaScript", "HTML", "Python"];
  // map() ํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ฒฐ๊ณผ๋ฅผ ๋ณ€์ˆ˜์— ๋‹ด์•„์คŒ
  let viewLangs = langs.map((it) => {
      return <p>{it}</p>;
    });
    
  return (
    <div>
      {viewLangs}
    </div>
  );
// 2
let langs = ["JavaScript", "HTML", "Python"];

  return (
	// ์ค‘๊ด„ํ˜ธ{} ์‚ฌ์šฉํ•ด์„œ JS๋ฅผ ๋‚ด๋ถ€์— ํ‘œํ˜„
	// ํ™”์‚ดํ‘œํ•จ์ˆ˜์—์„œ ์ค‘๊ด„ํ˜ธ{}๋ฅผ ์“ฐ๋ฉด return์ด ๊ผญ ์กด์žฌํ•ด์•ผ ํ•จ (์—†๋‹ค๋ฉด undefined return)
    <div>
       {langs.map((it) => { 
        return <p>{it}</p>;
      })} 
    </div>
  );
// 3
let langs = ["JavaScript", "HTML", "Python"];
  return (
	// ํ™”์‚ดํ‘œํ•จ์ˆ˜์—์„œ ()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด () ์•ˆ์˜ ๊ฐ’์ด return
    <div>
      {langs.map((it) => (
        <p>{it}</p>
      ))}
    </div>
  );
// X
let langs = ["JavaScript", "HTML", "Python"];
	
  let viewLangs = () =>  {
    return langs.map((it) => {
      return <p>{it}</p>;
    });
  };

  return (
	// viewLangs๊ฐ€ ํ™”์‚ดํ‘œ ํ•จ์ˆ˜ ํ‘œํ˜„์‹์œผ๋กœ ์„ ์–ธ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์—ฐ์‚ฐ์ž์ธ ()๋ฅผ ์จ์•ผ ์ž‘๋™
	// {viewLangs} (x)
    <div>
      {viewLangs()}  
    </div>
  );

โ˜‘๏ธย [Pair] React Twittler Intro

  • Using fontawesome
// index.html์— script tag๋กœ fontawesome url ์ง€์ • ํ›„ js ํŒŒ์ผ์—์„œ ์‚ฌ์šฉ

// index.html
<script src="https://kit.fontawesome.com/14d687cae1.js" crossorigin="anonymous"></script>

// App.js
<i className="far fa-comment-dots"></i>
// App.js ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋ชฝ๋•… ์ฝ”๋“œ ๋–„๋ ค๋„ฃ๊ธฐ 
import React from "react";
import "./App.css";
import { dummyTweets } from "./static/dummyData";

console.log(dummyTweets); // ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋”๋ฏธ ๋ฐ์ดํ„ฐ

const Sidebar = () => {
  return (
    <section className="sidebar">
      <h1>Twittler</h1>
      <i className="far fa-comment-dots"></i>
    </section>
  );
};

const Counter = () => {
  return (
    <div className="tweetForm__input">
      <div className="tweetForm__inputWrapper">
        <div className="tweetForm__count" role="status">
          <span>total: {dummyTweets.length}</span>
        </div>
      </div>
    </div>
  );
};

const Footer = () => {
  return <footer>by Beanxx</footer>;
};

const Tweets = () => {
  return (
    <ul className="tweets">
      {dummyTweets.map((tweet) => {
        const isParkHacker = tweet.username === "parkhacker";
        const tweetUserNameClass = isParkHacker
          ? "tweet__username tweet__username--purple"
          : "tweet__username";

        return (
          // ์œ„์—์„œ map() ์‚ฌ์šฉํ–ˆ์œผ๋ฏ€๋กœ key ์„ค์ •
          <li className="tweet" key={tweet.id}>
            <div className="tweet__profile">
              <img src={tweet.picture} alt="profile-img"></img>
            </div>
            <div className="tweet__content">
              <div className="tweet__userInfo">
                // class๊ฐ€ Line38์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— {} ์•ˆ์— ์ž‘์„ฑ
                <span className={tweetUserNameClass}>{tweet.username}</span>
                <span className="tweet__createdAt">{tweet.createdAt}</span>
              </div>
              <div className="tweet__message">{tweet.content}</div>
            </div>
          </li>
        );
      })}
    </ul>
  );
};

const Features = () => {
  return (
    <section className="features">
      <div className="tweetForm__container">
        <div className="tweetForm__wrapper">
          <div className="tweetForm__profile"></div>
          <Counter />
        </div>
      </div>
      <Tweets />
      <Footer />
    </section>
  );
};

const App = () => {
  return (
    <div className="App">
      <main>
        <Sidebar />
        <Features />
      </main>
    </div>
  );
};

export { App, Sidebar, Counter, Tweets, Features, Footer };

โœ… Component ๋ถ„๋ฆฌํ•ด์„œ ๊ตฌ์กฐ Refactoringํ•ด๋ณด๊ธฐ

profile
FE developer

0๊ฐœ์˜ ๋Œ“๊ธ€