[TIL] Day27
[SEB FE] Day27
Front-end ๊ฐ๋ฐ์ ์ํ JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๐ย React๋ "ํ๋์ ๊ธฐ๋ฅ ๊ตฌํ์ ์ํ ์ฌ๋ฌ ์ข ๋ฅ์ ์ฝ๋ ๋ฌถ์"์ธ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐ์ ํ๊ธฐ ๋๋ฌธ์, ๊ธฐ์ ์ ๋ถ๋ฅ์ ๋ฐ๋ผ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ์ง ์๊ณ , ๊ธฐ๋ฅ ๋ณ๋ก ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ๊ธธ ๊ถ์ฅ!
- ์ ์ธํ(Declarative): ํ๋์ ํ์ผ์ ๋ช ์์ ์ผ๋ก ์์ฑํ ์ ์๊ฒ JSX๋ฅผ ํ์ฉํ ์ ์ธํ ํ๋ก๊ทธ๋๋ฐ ์งํฅ
- ์ปดํฌ๋ํธ ๊ธฐ๋ฐ: ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ๋ฉด ์๋ก ๋ ๋ฆฝ์ ์ด๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ๊ธฐ๋ฅ ์์ฒด์ ์ง์คํ์ฌ ๊ฐ๋ฐ ๊ฐ๋ฅ (์ ์ง๋ณด์, ์ ๋ ํ ์คํธ ํ๊ธฐ์ ํธ๋ฆฌ)
- ๋ฒ์ฉ์ฑ(๋ค์ํ ๊ณณ์์ ํ์ฉ ๊ฐ๋ฅ): ๋ฆฌ์กํธ๋ ๊ธฐ์กด ํ๋ก์ ํธ์๋ ์ ์ฐํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ
React์์ UI๋ฅผ ๊ตฌ์ฑํ ๋ ์ฌ์ฉํ๋ ๋ฌธ๋ฒ์ผ๋ก JS๋ฅผ ํ์ฅํ ๋ฌธ๋ฒ โ React Element ์์ฑ
โย JSX โ HTML (HTML ๋ฌธ๋ฒ์ ์ผ๋ถ ์ฐจ์ฉํ์ง๋ง, ๋ค๋ฅธ ๋ฌธ๋ฒ ์ฌ์ฉ)
๐ย JSX๋ฅผ ์ฌ์ฉํ๋ฉด JS๋ง์ผ๋ก๋ markup ํํ์ ์ฝ๋๋ฅผ ์์ฑํ์ฌ DOM์ ๋ฐฐ์น ๊ฐ๋ฅ
๋ธ๋ผ์ฐ์ ๊ฐ ๋ฐ๋ก ์คํํ ์ ์๋ JS ์ฝ๋๊ฐ ์๋
โ So, ๋ธ๋ผ์ฐ์ ๊ฐ ์ดํดํ ์ ์๋ JS ์ฝ๋๋ก ๋ณํํด์ฃผ์ด์ผ ํจ โ Babel
Babel
: JSX๋ฅผ ๋ธ๋ผ์ฐ์ ๊ฐ ์ดํดํ ์ ์๋ JS๋ก ์ปดํ์ผ โ ๋ธ๋ผ์ฐ์ ๊ฐ JS๋ฅผ ์ฝ๊ณ ํ๋ฉด์ ๋ ๋๋ง
JS ๋ฌธ๋ฒ๊ณผ HTML ๋ฌธ๋ฒ์ ๋์์ ์ด์ฉํด ๊ธฐ๋ฅ๊ณผ ๊ตฌ์กฐ๋ฅผ ํ๋์ ํ์ธ ๊ฐ๋ฅ
โ ๊ตฌ์กฐ์ ๋์์ ๋ํ ์ฝ๋๋ฅผ ํ ๋ญ์น๋ก ์ ์ ์ฝ๋์
์ ์ปดํฌ๋ํธ
๋ผ๊ณ ํจ
โย JSX ์์ด๋ React ์์๋ฅผ ๋ง๋ค ์ ์์ง๋ง ์ฝ๋๊ฐ ๋ณต์กํด์ง๊ณ , ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๋ ๋จ์ ์กด์ฌ
opening tag
& closing tag
๋ก ๊ฐ์ธ์ฃผ์ด์ผ ํจ<div>
<div>
<h1>Hello</h1>
</div>
<div>
<h2>World</h2>
</div>
</div>
className
์ผ๋ก ํ๊ธฐ โย ๋ง์ฝ class๋ก ์์ฑํ๋ค๋ฉด React์์ ์ด๋ฅผ HTML ํด๋์ค ์์ฑ ๋์ JS ํด๋์ค๋ก ๋ฐ์๋ค์ด๊ธฐ ๋๋ฌธ์ ์ฃผ์!<div className="colors">Hello!</div>
{}
) ์ด์ฉfunction App() {
const name = "soobin";
return (
<div>
Hello, {name}!
</div>
);
}
function Hello() {
return <div>Hello!</div>;
}
function HelloWorld() {
return <Hello/>;
}
<div>
{(1+1 === 2) ? (<p>์ ๋ต</p>) : (<p>์ค๋ต</p>)}
</div>
map()
ํจ์ ์ด์ฉmap()
ํจ์ ์ฌ์ฉ์, ๋ฐ๋์ โkeyโ
JSX ์์ฑ ์ฝ์
key
๋ก ์ฌ์ฉ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>
);
}
- ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ๋ ๊ฐ์ ๊ณ ์ ์ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ผ๋ฉด์ UI์ ํ ๋ถ๋ถ์ ๋ด๋น
- ํ๋์ ๊ธฐ๋ฅ ๊ตฌํ์ ์ํ ์ฝ๋ ๋ชจ์์ง
- ํด๋์ค ํํ๋ก๋ ํํ ๊ฐ๋ฅ
์ปดํฌ๋ํธ ๊ธฐ๋ฐ ๊ฐ๋ฐ์ ์น ์ ํ๋ฆฌ์ผ์ด์
์์ ๊ฐ ๊ธฐ๋ฅ ๋ณ๋ก ํ๋์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋๋ก ๊ถ์ฅ
โ ์ปดํฌ๋ํธ ๊ฐ ์์กด์ฑ์ด ๋ฎ์์ง๊ณ ๋
๋ฆฝ์ ์ผ๋ก ์๋
์ปดํฌ๋ํธ ๋จผ์ ์์ฑ์ํจ ํ, ๋ ์ด์์์ ๋ฐ๋ผ ์ ๋์ ์ผ๋ก ์ปดํฌ๋ํธ ์์น๋ฅผ ๋ณ๊ฒฝํ๋ ์ํฅ์ ๊ฐ๋ฐ(Bottom-up) ๋ฐฉ์์ ์ ํฉ
๊ธฐ์กด์ ํด๋์คํ ์ปดํฌ๋ํธ ์ฃผ๋ก ์ฌ์ฉ โ ์ต๊ทผ์ ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋ง์ด ์ฌ์ฉ
React SPA๋ฅผ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ ์ ์๋๋ก ๋ง๋ค์ด์ง ํด ์ฒด์ธ
// React project ์์ฑ
npx create-react-app <project-name>
โย ๋ชจ๋ ์ปดํฌ๋ํธ ์์ ํญ์ root ์ญํ ์ ํ๋ ์ต์์ ์ปดํฌ๋ํธ ์กด์ฌ (ex. <App>
)
// 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>
);
// 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ํด๋ณด๊ธฐ