sbyeol3 / articles Goto Github PK
View Code? Open in Web Editor NEWLearn.. Run.. ๐
Learn.. Run.. ๐
์๋ฌธ : 2021.01.18์ ์์ฑ๋ Tao of React - Software Design, Architecture & Best Practices
์ ๋ React๋ฅผ 2016๋ ๋ถํฐ ์ฌ์ฉํ์ง๋ง ์ฌ์ ํ ์ดํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ์ ๋์์ธ์ ๋ํ ๋ชจ๋ฒ์ ์ธ ์์๋ ํ ๊ฑด๋ ์์ต๋๋ค. ๋ง์ดํฌ๋ก ์์ค์ ๋ํ ๋ชจ๋ฒ ์ฌ๋ก๋ ์์ง๋ง ๋๋ถ๋ถ์ ํ๋ค์ ๊ฐ์ ์์ ๋ง์ ์ํคํ ์ณ๋ฅผ ๊ตฌ์ถํฉ๋๋ค. ๋ฌผ๋ก , ๋ชจ๋ ๋น์ฆ๋์ค์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉ๋ ์ ์๋ ์ต๊ณ ์ ์์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์์ฐ์ ์ธ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๋ฐ๋ผ์ผ ํ๋ ์ผ๋ฐ์ ์ธ ๊ท์น๋ค์ ์กด์ฌํฉ๋๋ค.
์ํํธ์จ์ด ์ํคํ ์ณ์ ๋์์ธ์ ๋ชฉ์ ์ ์ํํธ์จ์ด๋ฅผ ์์ฐ์ ์ด๊ณ ์ ์ฐํ๊ฒ ์ ์งํ๋ ๊ฒ์ ์์ต๋๋ค. ๊ฐ๋ฐ์๋ค์ ์ํํธ์จ์ด์ ํต์ฌ๋ถ๋ถ์ ์ฌ์์ฑํ์ง ์๊ณ ํจ๊ณผ์ ์ผ๋ก ์์ ํ๊ณ ์์ ํด์ผ๋ง ํฉ๋๋ค. ์ด ๊ธ์ ์ ์ ์ ๊ฐ ํจ๊ป ์ผํ๋ ํ์์ ๊ฝค ํจ๊ณผ์ ์ด๋ผ๊ณ ์ฆ๋ช ๋์๋ ์๋ฆฌ์ ๊ท์น๋ค์ ๋ชจ์์ง์ ๋๋ค.
์ปดํฌ๋ํธ, ์ดํ๋ฆฌ์ผ์ด์ ๊ตฌ์กฐ, ํ ์คํ , ์คํ์ผ๋ง, ์ํ ๊ด๋ฆฌ์ ๋ฐ์ดํฐ fetching ๋ฑ์ ๋ํ ์ฌ๋ก๋ค์ ๊ฐ๋ต์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค. ์์ ์ ์ผ๋ถ๋ ๊ตฌํ๋ณด๋ค๋ ์์น์ ์ง์คํ๊ณ ์ ์ง๋์น๊ฒ ๋จ์ํ๋์ด ์์ผ๋ ์ฐธ๊ณ ํ์ธ์.
์ด ๊ธ์ ๋ชจ๋ ๊ฒ์ ์ ๋์ ์ธ ๊ฒ์ด ์๋ ํ๋์ ์๊ฒฌ์ผ๋ก์ ๋ฐ์๋ค์ด๊ธธ ๋ฐ๋๋๋ค. ์ํํธ์จ์ด๋ฅผ ๋ง๋๋ ๋ฐ์๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์กด์ฌํฉ๋๋ค.
ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ์งํฅํ๋ผ - ๊ฐ๋จํ ํํ์ ๋๋ค. ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋, ์์ฑ์, ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ ์์ต๋๋ค. ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ๋๋ณด๋ค ๊ฐ๋ ์ฑ์ ์์ง ์์ผ๋ฉด์ ์ ์ ํํ์ผ๋ก ๊ฐ์ ๋ก์ง์ ํํํ ์ ์์ต๋๋ค. error boundary๊ฐ ํ์ํ ๊ฒ์ด ์๋๋ผ๋ฉด ์ด ๋ฐฉ์์ ๋ฐ๋ผ์ผ๋ง ํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ๋จธ๋ฆฟ ์์ ๊ฐ์งํด์ผ ํ ์ ์ ์ ์ธ ๋ชจ๋ธ์ด ํจ์ฌ ์์์ง ๊ฒ์ ๋๋ค.
// ๐ ํด๋์ค ์ปดํฌ๋ํธ๋ ์ฅํฉํฉ๋๋ค
class Counter extends React.Component {
state = {
counter: 0,
}
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.setState({ counter: this.state.counter + 1 })
}
render() {
return (
<div>
<p>counter: {this.state.counter}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
)
}
}
// ๐ ํจ์ํ ์ปดํฌ๋ํธ๊ฐ ์ฝ๊ธฐ๋ ์ฝ๊ณ ์ ์งํ๊ธฐ๋ ์ข์ฃ
function Counter() {
const [counter, setCounter] = useState(0)
handleClick = () => setCounter(counter + 1)
return (
<div>
<p>counter: {counter}</p>
<button onClick={handleClick}>Increment</button>
</div>
)
}
์ฌ๋ฌ๋ถ์ ์ปดํฌ๋ํธ์ ์คํ์ผ์ ์ผ๊ด๋๊ฒ ์ ์งํ์ธ์. ๊ฐ์ ์์น์ ํฌํผ ํจ์๋ฅผ ๋๊ณ , ๊ฐ์ ๋ฐฉ์์ผ๋ก exportํ๊ณ ๋์ผํ ๋ค์ด๋ฐ ํจํด์ ๋ฐ๋ฅด์ธ์.
์ด๋ค ์ ๊ทผ ๋ฐฉ์์ด ๋ค๋ฅธ ๋ฐฉ์๋ณด๋ค ๋์ ์ ์ ์์ต๋๋ค. ํ์ผ ์๋์์ exportํ๋ ์ง, ์ปดํฌ๋ํธ ์ ์์์ ๋ฐ๋ก ํ๋ ์ง ์๊ด์์ต๋๋ค.
ํ๋๋ฅผ ๊ณจ๋ผ ๊ทธ ๋ฐฉ์์ ๊ณ ์ํ์ธ์.
์ฌ๋ฌ๋ถ์ ์ปดํฌ๋ํธ์ ํญ์ ์ด๋ฆ์ ์ง์ด์ฃผ์ธ์. ์ด๋ ๋์ค์ ์ฌ๋ฌ๋ถ์ด ์๋ฌ ์คํ์ ์ถ์ ํ๊ฑฐ๋ React Dev tools๋ฅผ ์ฌ์ฉํ ๋ ๋์์ด ๋ฉ๋๋ค.
๋ํ ํ์ผ ๋ด์ ์ปดํฌ๋ํธ ์ด๋ฆ์ด ์๋ค๋ฉด ์ฌ๋ฌ๋ถ์ด ๊ฐ๋ฐํ ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฐพ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค.
์ปดํฌ๋ํธ์ ๋ํด ํด๋ก์ ธ๋ฅผ ๊ฐ์ง ํ์ ์๋ ํฌํผ ํจ์๋ ๋ฐ๊นฅ์ผ๋ก ์ฎ๊ฒจ์ผ ํฉ๋๋ค. ์ด์์ ์ธ ์์น๋ ์ปดํฌ๋ํธ๊ฐ ์ ์๋ ๊ณณ๋ณด๋ค ๋จผ์ ๋์ค๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋์ผ ์์์๋ถํฐ ์๋๋ก ํ์ผ์ ์ฝ๊ธฐ๊ฐ ์ข๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด ๋ฃฐ์ ์ปดํฌ๋ํธ๋ฅผ ๊นจ๋ํ๊ฒ ํด์ฃผ๋ฉฐ ์ปดํฌ๋ํธ ๋ด์์ ํ์ํ ๊ฒ๋ง ๋จ๊ฒจ๋ก๋๋ค.
// ๐ ํด๋ก์ ธ๋ฅผ ์ ์งํ ํ์ ์๋ ๋ณต์กํ ํจ์๋ฅผ ํผํ์ธ์.
function Component({ date }) {
function parseDate(rawDate) {
...
}
return <div>Date is {parseDate(date)}</div>
}
// ๐ ํฌํผํจ์๋ ์ปดํฌ๋ํธ ์์ ๋์ธ์
function parseDate(date) {
...
}
function Component({ date }) {
return <div>Date is {parseDate(date)}</div>
}
์ฌ๋ฌ๋ถ์ ์ ์ํ ํจ์ ๋ด์ ์ ์ ์์ ํฌํผํจ์๋ฅผ ์ ์งํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ๊ฐ๋ฅํ ํ ํฌํผ ํจ์๋ ๋ฐ์ผ๋ก ์ฎ๊ฒจ๋๊ณ ์ธ์๋ก ์ํ๊ฐ์ ์ ๋ฌํ์ธ์.
๋ก์ง์ ์
๋ ฅ๊ฐ์ ์์กดํ๋ ์์ํจ์๋ก ๊ตฌ์ฑํ๋ ๊ฒ์ด ๋ฒ๊ทธ๋ฅผ ์ฐพ๊ธฐ๊ฐ ์ฉ์ดํ๋ฉฐ ํ์ฅ์ฑ์ด ์ข์ต๋๋ค.
// ๐ ํฌํผ ํจ์๊ฐ ์ปดํฌ๋ํธ์ ์ํ์์ ์ฝํ๋ฉด ์ ๋ฉ๋๋ค.
export default function Component() {
const [value, setValue] = useState('')
function isValid() {
// ...
}
return (
<>
<input
value={value}
onChange={e => setValue(e.target.value)}
onBlur={validateInput}
/>
<button
onClick={() => {
if (isValid) {
// ...
}
}}
>
Submit
</button>
</>
)
}
// ๐ ํฌํผํจ์๋ ๋ฐ์ผ๋ก ๋นผ์ ํ์ํ ๊ฐ๋ง ์ ๋ฌํ์ธ์.
function isValid(value) {
// ...
}
export default function Component() {
const [value, setValue] = useState('')
return (
<>
<input
value={value}
onChange={e => setValue(e.target.value)}
onBlur={validateInput}
/>
<button
onClick={() => {
if (isValid(value)) {
// ...
}
}}
>
Submit
</button>
</>
)
}
๋ค๋น๊ฒ์ด์
, ํํฐ, ๋ชฉ๋ก์ ๋ํ ๋งํฌ์
์ ํ๋์ฝ๋ฉํ์ง ๋ง์ธ์. ๋์ ๊ฐ์ฒด ๋ฐฐ์ด์ ์ฌ์ฉํ์ฌ ์์ดํ
์ ์ํํ์ธ์.
์ฆ, ํ ๊ณณ์์๋ง ๋งํฌ์
๊ณผ ์์ดํ
์ ๋ณ๊ฒฝํ๋ฉด ๋ฉ๋๋ค.
// ๐ ํ๋์ฝ๋ฉ๋ ๋งํฌ์
์ ๊ด๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
function Filters({ onFilterClick }) {
return (
<>
<p>Book Genres</p>
<ul>
<li>
<div onClick={() => onFilterClick('fiction')}>Fiction</div>
</li>
<li>
<div onClick={() => onFilterClick('classics')}>
Classics
</div>
</li>
<li>
<div onClick={() => onFilterClick('fantasy')}>Fantasy</div>
</li>
<li>
<div onClick={() => onFilterClick('romance')}>Romance</div>
</li>
</ul>
</>
)
}
// ๐ loop์ ๊ฐ์ฒด ๋ฐฐ์ด์ ์ฌ์ฉํ์ธ์
const GENRES = [
{
identifier: 'fiction',
name: Fiction,
},
{
identifier: 'classics',
name: Classics,
},
{
identifier: 'fantasy',
name: Fantasy,
},
{
identifier: 'romance',
name: Romance,
},
]
function Filters({ onFilterClick }) {
return (
<>
<p>Book Genres</p>
<ul>
{GENRES.map(genre => (
<li>
<div onClick={() => onFilterClick(genre.identifier)}>
{genre.name}
</div>
</li>
))}
</ul>
</>
)
}
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ props๋ฅผ ๋ฐ๊ณ ๋งํฌ์
์ ๋ฆฌํดํ๋ ํจ์์ผ ๋ฟ์
๋๋ค. ์ปดํฌ๋ํธ๋ ๋์ผํ ์ํํธ์จ์ด ์ค๊ณ ์์น์ ์ค์ํฉ๋๋ค.
ํจ์๊ฐ ๋๋ฌด ๋ง์ ์ผ์ ํ๋ค๋ฉด, ๋ก์ง์ ์ผ๋ถ๋ฅผ ๊บผ๋ด์ ๋ค๋ฅธ ํจ์๋ฅผ ํธ์ถํ๋๋ก ํ๋ ๊ฒ์ฒ๋ผ ์ปดํฌ๋ํธ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
๋๋ฌด ๋ง์ ๊ธฐ๋ฅ์ ํ๋ ์ปดํฌ๋ํธ๋ผ๋ฉด ์์ ์ปดํฌ๋ํธ๋ค๋ก ์ชผ๊ฐ์ ํธ์ถํ๋๋ก ํ์ธ์.
๋งํฌ์
์ ์ด๋ ๋ถ๋ถ์ด ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ๊ฑฐ๋ ์กฐ๊ฑด๋ฌธ์ ์ฌ์ฉํ์ฌ ๋ณต์กํ๋ค๋ฉด ๋ฐ์ผ๋ก ๋นผ๋์ธ์.
์ปค๋ฎค๋์ผ์ด์
๊ณผ ๋ฐ์ดํฐ๋ฅผ ์ํ props์ callback์ ์์กดํ์ธ์. ์ฝ๋์ ๋ผ์ธ์ ๊ฐ๊ด์ ์ธ ์ฒ๋๊ฐ ์๋๋๋ค.
๋์ ์ ์ฑ
์๊ฐ๊ณผ ์ถ์์ฑ์ ๋ํด ์๊ฐํด๋ณด์ธ์.
๋ ๋ช ํํ๊ฒ ํด์ผ ํ ๋ ์ฝ๋ ๋ธ๋ก์ ์ด๊ณ ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ธ์. ๋งํฌ์ ์ ๋ก์ง์ ์ผ๋ถ์ด๋ฏ๋ก ๋ช ํํ๊ฒ ํ ๋ ์ฃผ์์ ์์ฑํ์ธ์.
function Component(props) {
return (
<>
{/* If the user is subscribed we don't want to show them any ads */}
{user.subscribed ? null : <SubscriptionPlans />}
</>
)
}
ํ ์ปดํฌ๋ํธ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๊ณ ํด์ ์ ์ฒด UI๊ฐ ๊นจ์ง๋ฉด ์๋ฉ๋๋ค. ์ฌ๊ฐํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ํ์ด์ง๋ฅผ ํต์งธ๋ก ๋ด๋ฆฌ๊ฑฐ๋ ๋ฆฌ๋ค์ด๋ ํธํ๊ฒ ๋๋ ๊ฒฝ์ฐ๋ ๋๋ฌธ ์ผ์ ๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์คํฌ๋ฆฐ์์ ์๋ฌ๊ฐ ๋ฐ์ํ ๋ถ๋ถ๋ง ์จ๊ธฐ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ํจ์์์ ์ฌ๋ฌ try/catch ๋ฌธ์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์ต์์ ๋ ๋ฒจ์ด ์๋๋๋ผ๋ ์ฌ์ฉํ๊ณ ์ ํ๋ ๊ณณ์ Error boundary๋ฅผ ๋์ธ์.
๋ณ๊ฐ๋ก ์กด์ฌํ ์ ์๋ ์คํฌ๋ฆฐ์ element๋ฅผ ๊ฐ์ธ๋ฉด ์ด์ด์ง๋ ์ฅ์ ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
function Component() {
return (
<Layout>
<ErrorBoundary>
<CardWidget />
</ErrorBoundary>
<ErrorBoundary>
<FiltersWidget />
</ErrorBoundary>
<div>
<ErrorBoundary>
<ProductList />
</ErrorBoundary>
</div>
</Layout>
)
}
๋๋ถ๋ถ์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ํจ์์ผ ๋ฟ์
๋๋ค. props๋ฅผ ๋ฐ์ ๋งํฌ์
์ ๋ฆฌํดํ์ฃ . ์ผ๋ฐ ํจ์์์ ์ธ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ธ์๊ฐ ์ง์ ์ ๋ฌ๋๋ฏ๋ก ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์๋ ๋์ผํ ์๋ฆฌ๋ฅผ ์ ์ฉํ๋ฉด ๋ฉ๋๋ค. ์ด๋์๋ props
๋ฅผ ๋ฐ๋ณตํ ํ์๊ฐ ์์ต๋๋ค.
props๋ฅผ ๋น๊ตฌ์กฐํํ์ง ์๋ ์ด์ ๋ ์๋ง ์ธ๋ถ์์ ์จ ๊ฒ๊ณผ ๋ด๋ถ ์ํ๋ฅผ ๊ตฌ๋ถ์ง๊ธฐ ์ํจ์ผ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ฐ ํจ์์์ ์ธ์์ ๋ณ์์ ๊ตฌ๋ถ์ด ๋ฐ๋ก ์์ง ์์ต๋๋ค. ๋ถํ์ํ ํจํด์ ๋ง๋ค์ง ๋ง์ธ์.
// ๐ ์ปดํฌ๋ํธ ์ด๋์์๋ ์ง props๋ฅผ ๋ฐ๋ณตํ์ง ๋ง์ธ์
function Input(props) {
return <input value={props.value} onChange={props.onChange} />
}
// ๐ props๋ฅผ ๋น๊ตฌ์กฐํํ์ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์
function Component({ value, onChange }) {
const [state, setState] = useState('')
return <div>...</div>
}
์ปดํฌ๋ํธ๊ฐ ๋ฐ๋ props์ ๊ฐ์๊ฐ ๋ช๊ฐ์ฌ์ผ ํ๋์ง์ ๋ํ ์ง๋ฌธ์ ์ฃผ๊ด์ ์ ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ง๋ props์ ์๋ ์ปดํฌ๋ํธ๊ฐ ํ๋ ๊ฒ๊ณผ ์๊ด ์์ต๋๋ค. ๋ ๋ง์ด props๋ฅผ ์ ๋ฌํ ์๋ก ์ปดํฌ๋ํธ์ ์ฑ ์๋ ํจ๊ป ์ปค์ง๋๋ค. props๊ฐ ๋๋ฌด ๋ง๋ค๋ฉด ์ด๋ ์ปดํฌ๋ํธ๊ฐ ๋๋ฌด ๋ง์ ์ผ์ ํ๋ค๋ ์ ํธ์ ๋๋ค.
์ ๋ 5๊ฐ ์ด์์ props๋ฅผ ๋ฐ๋๋ค๋ฉด ์ปดํฌ๋ํธ๋ฅผ ๋๋์ด์ผ ํ ์ง๋ฅผ ์๊ฐํด ๋ด
๋๋ค. ์ผ๋ถ์ ๊ฒฝ์ฐ์์ ๋ง์ ๋ฐ์ดํฐ๊ฐ ํ์ํ ์๋ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด input ํ๋๋ ๋ง์ props๋ฅผ ๋ฐ์์ผ ํฉ๋๋ค. ๋ค๋ฅธ ๊ฒฝ์ฐ์์๋ ๋๋์ด์ผ ํ๋ค๋ ์ ํธ๊ฐ ๋๊ธฐ๋ ํฉ๋๋ค.
์ฃผ์ : ์ปดํฌ๋ํธ๊ฐ ๊ฐ์ง๋ props๊ฐ ๋ง์ ์๋ก ๋ฆฌ๋ ๋๋ง๋์ด์ผ ํ ์ด์ ๋ ๋ง์์ง๋๋ค!
props์ ์์ ์ค์ด๋ ๋ฐฉ๋ฒ ์ค ํ๋๋ ์์๊ฐ ๋์ ์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฆ, ์ด๋ฉ์ผ, ์ค์ ๋ฑ์ ๋ฐ๋ก ์ ๋ฌํ๋ ๊ฒ ๋์ ์ ๋ฌถ์ด์ ๊ฐ์ฒด๋ก ์ ๋ฌํ ์ ์์ฃ . ์ด๋ ์ฌ์ฉ์๊ฐ ์ถ๊ฐ์ ์ธ ๊ฐ์ ์ ๋ฌํ ๋ ๋ณ๊ฒฝํด์ผ ํ๋ ๋ถ๋ถ์ ์ค์ฌ์ค๋๋ค.
ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฅผ ๋ ์ฝ๊ฒ ํด์ค๋๋ค.
// ๐ ๊ด๋ จ๋ ๊ฐ์ด๋ผ๋ฉด ํ๋์ฉ ์ ๋ฌํ์ง ๋ง์ธ์
<UserProfile
bio={user.bio}
name={user.name}
email={user.email}
subscription={user.subscription}
/>
// ๐ ๋์ ์ ๊ฐ์ฒด๋ก ๋ฌถ์ด ๋ณด๋ด์ธ์
<UserProfile user={user} />
์ผ๋ถ ์ํฉ์์ ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ์ํด ๋จ๋ฝ ์ฐ์ฐ์(&&
)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ญํจ๊ณผ๋ฅผ ๋ณ์ ์ ์์ผ๋ฉฐ ์ฌ๋ฌ๋ถ์ UI์ ์์น์๋ 0
์ด ๋ณด์ผ ์ ์์ต๋๋ค. ์ด๋ฐ ์ํฉ์ ํผํ๊ธฐ ์ํด ์ผํญ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ธ์. ๋ค๋ง ์ข ๋ ์ฅํฉํด์ง ์ ์์ต๋๋ค.
๋จ๋ฝ ์ฐ์ฐ์๋ ์ฝ๋์ ์์ ์ค์ฌ์ฃผ๊ณ ์ด๋ ์์ฃผ ์ข์ต๋๋ค. ์ผํญ ์ฐ์ฐ์๋ ๋ ๋ณต์กํ์ง๋ง ์๋ชป๋ ์ฌ์ง๋ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ ๋ค๋ฅธ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฒ ๋๋๋ผ๋ ๋ณ๊ฒฝ์ฌํญ์ด ์ ์ต๋๋ค.
// ๐ ๋จ๋ฝ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ง์ํ์ธ์
function Component() {
const count = 0
return <div>{count && <h1>Messages: {count}</h1>}</div>
}
// ๐ ๋์ ์ผํญ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ธ์
function Component() {
const count = 0
return <div>{count ? <h1>Messages: {count}</h1> : null}</div>
}
์ผํญ ์ฐ์ฐ์๋ ํ ๋จ๊ณ๋ฅผ ์ง๋๊ฐ๊ฒ ๋๋ฉด ์ฝ๊ธฐ ์ด๋ ค์์ง๋๋ค. ๊ณต๊ฐ์ ์ ์ฝํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋๋ผ๋ ์ฌ๋ฌ๋ถ์ ์๋๋ฅผ ๋ถ๋ช ํ ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
// ๐ JSX์์ ์ค์ฒฉ๋ ์ผํญ ์ฐ์ฐ์๋ ์ฝ๊ธฐ ์ด๋ ต์ต๋๋ค.
isSubscribed ? (
<ArticleRecommendations />
) : isRegistered ? (
<SubscribeCallToAction />
) : (
<RegisterCallToAction />
)
// ๐ ์ปดํฌ๋ํธ ๋ด์ ๋์ธ์
function CallToActionWidget({ subscribed, registered }) {
if (subscribed) {
return <ArticleRecommendations />
}
if (registered) {
return <SubscribeCallToAction />
}
return <RegisterCallToAction />
}
function Component() {
return (
<CallToActionWidget
subscribed={subscribed}
registered={registered}
/>
)
}
map
ํจ์๋ฅผ ์ฌ์ฉํ๋ ค ์์ดํ
์ ๋ฐฐ์ด์ ์ํํ๋ ๊ฒ์ ํํ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋ฌ ๋งํฌ์
์ ๊ฐ์ง ์ปดํฌ๋ํธ ๋ด์์ ์ถ๊ฐ์ ์ธ ์ฌ๋ฐฑ์ด๋ map
๋ฌธ๋ฒ์ ๊ฐ๋
์ฑ์ ํด์นฉ๋๋ค. map
์ผ๋ก ์ํํด์ผ ํ๋ค๋ฉด ๋งํฌ์
์ด ๋ง์ง ์๋๋ผ๋ ๊ทธ ๋ถ๋ถ์ ๋ฐ๋ก ๋นผ์ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ์ธ์. ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ ์์ธํ ๋ถ๋ถ์ ์ ํ์์์ด ๋ฐฐ์ด์ ๋ํ๋ด๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์ปดํฌ๋ํธ์ ์ฃผ ์ญํ ์ด ๋ณด์ฌ์ฃผ๊ธฐ๋ผ๋ฉด ๋งํฌ์ ์ ๋ฃจํ๋ฅผ ๋๊ธฐ๋ง ํ์ธ์. ์ปดํฌ๋ํธ๋ง๋ค ํ๋์ ๋งคํ์ ๋๋๋ก ํ์ธ์. ๋งํฌ์ ์ด ๋๋ฌด ๊ธธ์ด์ง๊ฑฐ๋ ๋ณต์กํด์ง๋ค๋ฉด ๋ฐ๋ก ๋นผ๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
// ๐ ๋ฐ๋ณต๋ฌธ๊ณผ ๋ค๋ฅธ ๋งํฌ์
์ ๊ฐ์ด ๋์ง ๋ง์ธ์.
function Component({ topic, page, articles, onNextPage }) {
return (
<div>
<h1>{topic}</h1>
{articles.map(article => (
<div>
<h3>{article.title}</h3>
<p>{article.teaser}</p>
<img src={article.image} />
</div>
))}
<div>You are on page {page}</div>
<button onClick={onNextPage}>Next</button>
</div>
)
}
// ๐ ๋ฐฐ์ด์ ๋ํ ์ปดํฌ๋ํธ๋ฅผ ๋ฐ๋ก ๋นผ์ธ์
function Component({ topic, page, articles, onNextPage }) {
return (
<div>
<h1>{topic}</h1>
<ArticlesList articles={articles} />
<div>You are on page {page}</div>
<button onClick={onNextPage}>Next</button>
</div>
)
}
๊ธฐ๋ณธ prop ๊ฐ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ์ปดํฌ๋ํธ์ defaultProps
๋ฅผ ๋๋ ๊ฒ์
๋๋ค. ์ด๋ ์ปดํฌ๋ํธ ํจ์์ ์ธ์ ๊ฐ์ด ํจ๊ป ์์ง ์๋ค๋ ๊ฒ์ ์๋ฏธํ๊ธฐ๋ ํฉ๋๋ค. props๋ฅผ ๋น๊ตฌ์กฐํํ ๋ ๊ธฐ๋ณธ๊ฐ์ ๋ฐ๋ก ํ ๋นํ๋ ๊ฒ์ ์งํฅํ์ธ์. ์ด๋ ์ฝ๋๋ฅผ ์์์๋ถํฐ ์ฝ๊ธฐ ํธํ๊ฒ ํ๋ฉฐ ์ ์์ ๊ฐ์ ํจ๊ป ๋ก๋๋ค.
// ๐ default props๋ฅผ ํจ์ ๋ฐ์ ์ ์ํ์ง ๋ง์ธ์
function Component({ title, tags, subscribed }) {
return <div>...</div>
}
Component.defaultProps = {
title: '',
tags: [],
subscribed: false,
}
// ๐ ์ธ์ ๋ชฉ๋ก์ ํจ๊ป ๋์ธ์
function Component({ title = '', tags = [], subscribed = false }) {
return <div>...</div>
}
์ปดํฌ๋ํธ๋ ๋ก์ง์ผ๋ก๋ถํฐ ๋งํฌ์
์ ๋ถ๋ฆฌํ๊ณ ์ถ์ ๋ ๊ฐ์ ์ปดํฌ๋ํธ ๋ด์ ๋งํฌ์
ํจ์๋ฅผ ๋์ง ๋ง์ธ์. ์ปดํฌ๋ํธ๋ ํจ์์ผ ๋ฟ์
๋๋ค.
์ด๋ ๊ฒ ํจ์๋ฅผ ์ ์ํ๊ฒ ๋๋ฉด ๋ถ๋ชจ ํจ์ ๋ด์์ ๋ฅ์ง๋ฅผ ํธ๋ ์
์
๋๋ค. ์ด๋ ๋ถ๋ชจ์ ์ํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ชจ๋ ์ ๊ทผํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ์.
์ปดํฌ๋ํธ ๋ด์์ ํจ์๊ฐ ํ๋ ์ผ์ด ์์์๋ ๋ด๋ถ์ ์๋ค๋ฉด ์ฝ๋์ ๊ฐ๋
์ฑ์ ํด์น๊ฒ ๋ฉ๋๋ค.
๋งํฌ์ ์ปดํฌ๋ํธ๋ก ์ฎ๊ธฐ๊ณ ์ด๋ฆ์ ์ง๊ณ ํด๋ก์ ธ ๋์ ์ props๋ก ์ ๋ฌํ์ธ์.
// ๐ ์ค์ฒฉ๋๋๋ก ๋ ๋ํจ์๋ฅผ ๋ง๋ค์ง ๋ง์ธ์
function Component() {
function renderHeader() {
return <header>...</header>
}
return <div>{renderHeader()}</div>
}
// ๐ ๊ฐ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ์ธ์
import Header from '@modules/common/components/Header'
function Component() {
return (
<div>
<Header />
</div>
)
}
ํ์
์คํฌ๋ฆฝํธ์ never
๋ ๋ค๋ฅธ ํ์
๋ค๋งํผ ์์ฃผ ํํ๊ฑฐ๋ ๋ฌด์ํ ์ ์๋ ํ์
์ด ์๋๊ธฐ ๋๋ฌธ์ ๊ทธ๋ค์ง ํ๋ฐํ๊ฒ ๋
ผ์๋๋ ํ์
์ด ์๋๋๋ค. ์ฌํ๋ ํ์
์ ๋ค๋ฃจ๊ฑฐ๋ ๊น๋ค๋ก์ด ํ์
์๋ฌ ๋ฉ์์ง๋ฅผ ์ฝ์ ๋๋ ๋ฑ์ฅํ๊ธฐ ๋๋ฌธ์ ์ด๊ธ์๋ค์ ์๋ง never
ํ์
์ ๋ฌด์ํ๊ณ ๋ ํ์
์คํฌ๋ฆฝํธ๋ฅผ ์ธ ์ ์์ต๋๋ค.
never
ํ์
์ ํ์
์คํฌ๋ฆฝํธ์์ ๊ฝค ์ข์ ์ ์ฆ ์ผ์ด์ค๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋, ๊ทธ๋งํผ ์ฌ๋ฌ๋ถ๋ค์ด ์กฐ์ฌํด์ผ ํ๋ ์ํ๋ค๋ ๊ฐ๊ณ ์์ต๋๋ค.
์ด ๊ธ์์๋ ๋ค์ ๋ด์ฉ์ ๋ค๋ฃน๋๋ค.
never
ํ์
์ ์๋ฏธ์ ํ์์ฑnever
ํ์
์ ์์ฉ๊ณผ ์ํnever
ํ์
๊ณผ ์ด๊ฒ์ ๋ชฉ์ ์ ์๋ฒฝํ๊ฒ ์ดํดํ๊ธฐ ์ํด์๋, ํ์
์ด๋ ๋ฌด์์ธ์ง ๊ทธ๋ฆฌ๊ณ ํ์
์์คํ
์์ ํ์
์ด ์ด๋ค ์ญํ ์ ํ๋์ง ๋จผ์ ์ดํดํด์ผ ํฉ๋๋ค.
ํ์
์ ๊ฐ๋ฅํ ๊ฐ๋ค์ ์งํฉ๊ณผ ๊ฐ์ต๋๋ค. ์๋ฅผ ๋ค์ด string
ํ์
์ ๊ฐ๋ฅํ ๋ฌธ์์ด์ ๋ฌดํ์งํฉ์ ๋ํ๋
๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ณ์์ string
ํ์
์ด๋ผ๊ณ ๋ถ์ฌ์ค ๋, ๊ทธ ๋ณ์๋ ๋ฌธ์์ด ์งํฉ ๋ด์์๋ง ๊ฐ์ ๊ฐ์ง ์ ์๊ฒ ๋ฉ๋๋ค.
let foo: string = 'foo'
foo = 3 // โ ์ซ์๋ ๋ฌธ์์ด ์งํฉ์ ์ํ์ง ์์ต๋๋ค.
ํ์
์คํฌ๋ฆฝํธ์์ never
๋ ๊ฐ๋ค์ ๊ณต์งํฉ์ ์๋ฏธํฉ๋๋ค. ์ค์ ๋ก ๋๋ค๋ฅธ ์ ๋ช
ํ ์๋ฐ์คํฌ๋ฆฝํธ ํ์
์์คํ
์ธ Flow์์๋ never
์ ๋์ผํ ํ์
์ empty๋ผ๊ณ ๋ถ๋ฅธ๋ต๋๋ค.
์งํฉ์ ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ never
๋ any
ํ์
์ ํฌํจํ์ฌ ์ ๋๋ก(never ใ
) ์ด๋ ํ ๊ฐ๋ ๊ฐ์ง ์ ์์ต๋๋ค. never
๊ฐ ๋๋๋ก ๊ฑฐ์ฃผ ๋ถ๊ฐ๋ฅํ ํ์
(uninhabitable type) ๋๋ ๋ฐ๋ฅ ํ์
(bottom type)์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ด์ ์
๋๋ค.
declare const any: any
const never: never = any // โ 'any' ํ์
์ 'never'์ ํ ๋นํ ์ ์์ต๋๋ค.
๋ฐ๋ฅ ํ์
์ TypeScript Handbook์์ ์ ์ํ ๋จ์ด์
๋๋ค. ์ ๋ ์๋ธํ์ดํ์ ์ดํดํ๋ ๋ฐ ์ฌ์ฉํ๋ ํ์
๊ณ์ธต ํธ๋ฆฌ์์ never
๋ฅผ ๋์ง ์๋ ๊ฒ ๋ ์ดํดํ๊ธฐ ์ฝ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
๋ค์ ๋
ผ๋ฆฌ์ ์ธ ์ง๋ฌธ์, '์ never
ํ์
์ด ํ์ํ๊ฐ?' ์
๋๋ค.
์ซ์ ์์คํ ์์ ์๋ฌด๊ฒ๋ ๊ฐ์ง์ง ์์๋ค๋ ๊ฒ์ ๋ํ๋ด๊ธฐ ์ํด ์ฐ๋ฆฌ๊ฐ 0์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ, ํ์ ์์คํ ๋ ๋ถ๊ฐ๋ฅํจ์ ๋ํ๋ด๋ ํ์ ์ด ํ์ํฉ๋๋ค. "๋ถ๊ฐ๋ฅํจ"์ด๋ ๋จ์ด ์์ฒด๊ฐ ๋ชจํธํฉ๋๋ค. ํ์ ์คํฌ๋ฆฝํธ์์ "๋ถ๊ฐ๋ฅํจ"์ ๋ค์ํ ๋ฐฉ์์ผ๋ก ๋ํ๋ฉ๋๋ค.
process.exit
์ฒ๋ผ)
void
์ ํผ๋ํ์ง ๋ง์ธ์. void
๋ ํธ์ถ์์๊ฒ ์ ์ฉํ ๋ฌด์ธ๊ฐ๋ฅผ ๋ฆฌํดํ์ง ์๋๋ค๋ ์๋ฏธ์
๋๋ค.promise
์ fulfilled๋ ๊ฐ์ ํ์
const p = Promise.reject('foo') // const p: Promise<never>
๋ง์
, ๊ณฑ์
์์ 0์ด ๋์ํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํ๊ฒ, never
ํ์
์ union ํ์
๊ณผ intersection ํ์
์์ ์ฌ์ฉ๋๋ ํน๋ณํ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋๋ค.
never
์ ํฉ์งํฉ์ ํ๊ฒ ๋๋ฉด never
๋ ์ ์ธ๋ฉ๋๋ค. ์ด๋ค ์ซ์์ 0์ ๋ํ์ ๋ ๊ทธ ์ซ์๊ฐ ๊ทธ๋๋ก์ธ ๊ฒ๊ณผ ๊ฐ์ ์๋ฆฌ์
๋๋ค.
type Res = never | string // string
never
์ intersection ํ๊ฒ ๋๋ฉด ๋ค๋ฅธ ํ์
์ ์ค๋ฒ๋ผ์ด๋ฉํฉ๋๋ค. ์ด๋ค ์ซ์์ 0์ ๊ณฑํ๋ฉด 0์ด ๋๋ ๊ฒ์ฒ๋ผ ๋ง์
๋๋ค.
type Res = never & string // never
never
ํ์
์ด ๊ฐ์ง๋ ๋ ๊ฐ์ง ๋์/ํน์ฑ์ ๋์ค์ ๋ณด๊ฒ ๋ ๋ช๋ช ๊ฐ์ฅ ์ค์ํ ์ ์ฆ ์ผ์ด์ค์ ๊ธฐ๋ฐ์ ๋ง๋ จํด์ค๋๋ค.
์๋ง ์ฌ๋ฌ๋ถ๋ค์ ์ค์ค๋ก never
๋ฅผ ๋ง์ด ์ฌ์ฉํ์ง ์์๊ฒ ์ง๋ง, ์ด๋ฏธ ๊ฝค ์ ์ฌ์ฉ๋๋ ์ ์ฆ ์ผ์ด์ค๋ค์ด ์กด์ฌํฉ๋๋ค.
์ด๋ค ๊ฐ์ never
ํ์
์ ํ ๋นํ ์ ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๋ ๋ค์ํ ์์ฉ์ ์ํด ํจ์์ ์ ํ์ ๊ฐํ๋ ๋ฐฉ์์ผ๋ก never
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ค ํจ์๊ฐ ์ค์ง never
ํ์
์ธ ํ๋์ ๋งค๊ฐ๋ณ์๋ง ๋ฐ๋๋ค๋ฉด ๊ทธ ํจ์๋ never
๊ฐ ์๋ ๊ฐ๊ณผ ํจ๊ป ํธ์ถ๋ ์ ์์ต๋๋ค.
function fn(input: never) {}
// `never`๋ง ํ์ฉ
declare let myNever: never
fn(myNever) // โ
// ๋ค๋ฅธ ๊ฑธ ์ ๋ฌํ๋ฉด ํ์
์๋ฌ ๋ฐ์
fn() // โ 'input`์ ๋ํ ์ธ์๊ฐ ์ฃผ์ด์ง์ง ์์.
fn(1) // โ number ํ์
์ never์ ํ ๋นํ ์ ์์
fn('foo') // โ string ํ์
์ never์ ํ ๋นํ ์ ์์
// ์ฌ์ง์ด any๋ ๋ถ๊ฐ๋ฅ
declare let myAny: any
fn(myAny) // โ any ํ์
์ never์ ํ ๋นํ ์ ์์
์ด๋ฌํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ switch๋ฌธ๊ณผ if-else๋ฌธ์์ ์์ ํ ์ผ์นํ๋๋ก ๋ณด์ฅํ ์ ์์ต๋๋ค. ๋จ์ ํ์
์ ๋ฐ๋์ never
ํ์
์ด๋ฏ๋ก default ์ผ์ด์ค๋ก never
ํ์
์ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๊ฒฝ์ฐ๊ฐ ์ปค๋ฒ๋ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ค์๋ก ์ผ์นํ๋ ํญ๋ชฉ์ ๋๋ฝํ๋ฉด ํ์
์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค.
function unknownColor(x: never): never {
throw new Error("unknown color");
}
type Color = 'red' | 'green' | 'blue'
function getColorName(c: Color): string {
switch(c) {
case 'red':
return 'is red';
case 'green':
return 'is green';
default:
return unknownColor(c); // Argument of type 'string' is not assignable to parameter of type 'never'
}
}
VariantA
๋๋ VariantB
๋ฅผ ๊ฐ์ง๋ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋ ํจ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค. ๊ทธ๋ฌ๋ ์ฌ์ฉ์๊ฐ ๋ ์ ํ์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ํฌํจํ๋ ํ์
์ ์ ๋ฌํด์๋ ์๋๋ ๊ฒฝ์ฐ์
๋๋ค.
ํ๋ผ๋ฏธํฐ๋ก ์ ๋์จ ํ์
์ธ VariantA | VariantB
์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ์
์คํฌ๋ฆฝํธ์์ ํ์
ํธํ์ฑ์ ๊ตฌ์กฐ์ ์ธ ์๋ธํ์ดํ์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ํจ์์ ํ๋ผ๋ฏธํฐ์ ํ์
๋ณด๋ค ๋ ๋ง์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ํ์ฉ๋์ง ์์ต๋๋ค. (๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ ๋ฌํ์ง ์๋ ํ)
type VariantA = {
a: string,
}
type VariantB = {
b: number,
}
declare function fn(arg: VariantA | VariantB): void
const input = {a: 'foo', b: 123 }
fn(input) // TypeScript๊ฐ ์๋๋ค๊ณ ํ์ง ์์ง๋ง ์ฐ๋ฆฌ๋ ์ด๋ฅผ ํ์ฉํ์ง ์์์ผ ํฉ๋๋ค.
์์ ์ฝ๋ ์ค๋ํซ์์ ํ์
์คํฌ๋ฆฝํธ๋ ํ์
์๋ฌ๋ฅผ ๋ฐ์์ํค์ง ์์ต๋๋ค.
never
๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ ๋ถ๋ถ์ ์ผ๋ก ๊ตฌ์กฐ์ ํ์ดํ์ ๋ถ๊ฐ๋ฅํ๊ฒ ํ๊ณ ์ฌ์ฉ์๋ค์ด ๋ ํ๋กํผํฐ๋ฅผ ๋ค ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ์ง ๋ชปํ๊ฒ ํ ์ ์์ต๋๋ค.
type VariantA = {
a: string
b?: never
}
type VariantB = {
b: number
a?: never
}
declare function fn(arg: VariantA | VariantB): void
const input = {a: 'foo', b: 123 }
fn(input) // โ Types of property 'a' are incompatible
๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ ์ฅํ๋ Cache
์ธ์คํด์ค๋ฅผ ์์ฑํ๋ค๊ณ ํด๋ด
์๋ค.
type Read = {}
type Write = {}
declare const toWrite: Write
declare class MyCache<T, R> {
put(val: T): boolean;
get(): R;
}
const cache = new MyCache<Write, Read>()
cache.put(toWrite) // โ
allowed
์ด๋ ํ ์ด์ ๋ ์ง ๊ฐ์ get
๋ฉ์๋๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ read-only ์บ์๋ฅผ ๊ฐ์ง๊ณ ์ถ์ด์ง ์๋ ์์ต๋๋ค. put
๋ฉ์๋ ์ธ์์ never
ํ์
์ ์ถ๊ฐํ๊ฒ ๋๋ฉด ํจ์ ๋ด๋ถ๋ก ์ด๋ ํ ๊ฐ์ด๋ ๋ฐ์ ์ ์๊ฒ ๋ฉ๋๋ค.
declare class ReadOnlyCache<R> extends MyCache<never, R> {}
// Now type parameter `T` inside MyCache becomes `never`
const readonlyCache = new ReadOnlyCache<Read>()
readonlyCache.put(data) // โ Argument of type 'Data' is not assignable to parameter of type 'never'.
๋ถ๊ฐ์ ์ผ๋ก
never
ํ์ ๊ณผ๋ ๊ด๋ จ์์ง๋ง, ์ด๋ ํ์ ํด๋์ค์ ์ข์ ์์๊ฐ ์๋ ์ ์์ต๋๋ค. ์ ๋ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ ๋ฌธ๊ฐ๊ฐ ์ฌ์ค ์๋๊ธฐ ๋๋ฌธ์ ๊ฐ์ ์์์ ํ๋จํด์ฃผ์๊ธธ ๋ฐ๋๋๋ค.
์กฐ๊ฑด ํ์
๋ด์์ ์ถ๊ฐ์ ์ธ ํ์
๋ณ์๋ฅผ ์์ฑํ๊ธฐ ์ํด infer
๋ฅผ ์ฌ์ฉํ ๋ ์ฐ๋ฆฌ๋ ๋ชจ๋ infer
ํค์๋์ ๋ฐ๋์ else ๋ถ๊ธฐ๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
type A = 'foo';
type B = A extends infer C ? (
C extends 'foo' ? true : false// inside this expression, C represents A
) : never // ์ด ๋ถ๊ธฐ์ ์ ๋ฟ์ ์ ์๊ฒ ์ง๋ง ์๋ตํ ์ ์์ต๋๋ค
์
extends infer
์ฝค๋ณด๊ฐ ์ ์ฉํ๊ฐ์?
์ด์ ์ ์์ฑํ ๊ธ์์ "๋ก์ปฌ (ํ์ ) ๋ณ์"๋ฅผ ์ ์ธํ๋ ๋ฐฉ์๊ณผ ํจ๊ปextends infer
๋ฅผ ์ธ๊ธํ์์ต๋๋ค. ์์ง ์ฝ์ง ์์๋ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ถ๊ฐ๋ฅํ ๋ถ๊ธฐ๋ฅผ ๋ํ๋ด๋ ๊ฒ ์ธ์๋, never
๋ ์กฐ๊ฑด ํ์
์์ ์์น์๋ ํ์
์ ๋ถ๋ฆฌํด๋ด๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด์ ์๋ ์๊ธฐํ๋ฏ์ด, ์ ๋์จ ๋ฉค๋ฒ๋ก์จ never
๋ฅผ ์ฌ์ฉํ๋ฉด ์๋์ ์ผ๋ก ์ ๊ฑฐ๋๋ค๊ณ ํ์ต๋๋ค. ์ฆ, ์ ๋์จ ํ์
์์ never
๋ ์ธ๋ชจ๊ฐ ์๋ ๊ฒ์ด์ฃ .
์ด๋ค ๊ธฐ์ค์ ์ ๊ธฐ๋ฐ์ผ๋ก ์ ๋์จ ํ์
์์ ์ ๋์จ ๋ฉค๋ฒ๋ฅผ ์ ํํ๋ ์ ํธ๋ฆฌํฐ ํ์
์ ์์ฑํ ๋ never
ํ์
์ ์ธ๋ชจ์์์ else ๋ถ๊ธฐ์ ์๋ฒฝํ ํ์
์ ๋๊ฒ๋ ๋ง๋ค์ด์ค๋๋ค.
foo
๋ฌธ์์ด ๋ฆฌํฐ๋ด์ ๊ฐ์ง๋ name
ํ๋กํผํฐ๋ฅผ ์ถ์ถํ๊ณ , ๊ทธ ์ธ์๋ ํํฐ๋งํ๋ ์ ํธ๋ฆฌํฐ ํ์
์ธ ExtractTypeByName
์ ์์ฑํ๋ค๊ณ ํด๋ณผ๊น์.
type Foo = {
name: 'foo'
id: number
}
type Bar = {
name: 'bar'
id: number
}
type All = Foo | Bar
type ExtractTypeByName<T, G> = T extends {name: G} ? T : never
type ExtractedType = ExtractTypeByName<All, 'foo'> // the result type is Fo
์ค์ ๋ก ์ด๋ป๊ฒ ๋์ํ๋์ง ์์ธํ ์ดํด๋ด ์๋ค.
๋ค์์ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ๊ฒฐ๊ณผ ํ์ ์ ํ๊ฐํ๊ณ ๊ฐ์ ธ์ค๋ ๊ฐ ๋จ๊ณ๋ค์ ๋๋ค.
type ExtractedType = ExtractTypeByName<All, Name>
โฌ๏ธ
type ExtractedType = ExtractTypeByName<Foo | Bar, 'foo'>
โฌ๏ธ
type ExtractedType = ExtractTypeByName<Foo, 'foo'> | ExtractTypeByName<Bar, 'foo'>
type ExtractedType = Foo extends {name: 'foo'} ? Foo : never
| Bar extends {name: 'foo'} ? Bar : never
โฌ๏ธ
type ExtractedType = Foo | never
never
๋ฅผ ์ ๊ฑฐํฉ๋๋ค.type ExtractedType = Foo | never
โฌ๏ธ
type ExtractedType = Foo
ํ์
์คํฌ๋ฆฝํธ์์ ํ์
์ ๋ถ๋ณ์
๋๋ค. ๊ฐ์ฒด ํ์
์์ ์ด๋ค ํ๋กํผํฐ๋ฅผ ์ ๊ฑฐํ๊ณ ์ ํ๋ค๋ฉด ์ด๋ฏธ ์กด์ฌํ๋ ํ์
์ ๋ณํํ๊ณ ํํฐ๋งํ์ฌ ์๋ก์ด ํ์
์ ๋ง๋ค์ด์ผ๋ง ํฉ๋๋ค. ๋งคํ๋ ํ์
์ ํค๋ฅผ ์กฐ๊ฑด๋ถ๋ก ๋ค์ never
๋ก ๋งคํํ ๋, key๋ ํํฐ๋ง๋ฉ๋๋ค.
๊ฐ์ฒด์ ๊ฐ ํ์
์ ๋ฐ๋ผ ๊ฐ์ฒด ํ์
ํ๋กํผํฐ๋ฅผ ํํฐ๋งํ๋ Filter
ํ์
์ ๋ํ ์์์
๋๋ค.
type Filter<Obj extends Object, ValueType> = {
[Key in keyof Obj
as ValueType extends Obj[Key] ? Key : never]
: Obj[Key]
}
interface Foo {
name: string;
id: number;
}
type Filtered = Filter<Foo, string>; // {name: string;}
ํจ์์ ๋ฆฌํด ๊ฐ์ never
๋ผ๊ณ ํ์
์ ์ง์ ํ๋ค๋ ๊ฒ์, ํจ์๊ฐ ์คํ์ด ์ข
๋ฃ๋์์ ๋ ์ ๋ ํธ์ถ์์๊ฒ ์ ์ด๊ถ์ ๋ฆฌํดํด์ฃผ์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ํ์
์ ์ขํ๊ธฐ ์ํ ์ ์ด ํ๋ฆ ๋ถ์์์ ์ด ์ ์ ์์ฉํ ์ ์์ต๋๋ค.
ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ์๋ฌด๊ฒ๋ ๋ฆฌํดํ์ง ์์ ์ ์์ต๋๋ค: ๋ชจ๋ ์ฝ๋ ๊ฒฝ๋ก๋ง๋ค ์์ธ๋ฅผ throwํ๋ ๊ฒฝ์ฐ, ๋ฌดํ ๋ฃจํ์ ๋น ์ง๋ ๊ฒฝ์ฐ,
process.exit
๊ณผ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ์ํด ์ข ๋ฃ๋๋ ๊ฒฝ์ฐ
๋ค์ ์ฝ๋ ์ค๋ํซ์์, never
ํ์
์ ๋ฆฌํดํจ์๋ฅผ ์ฌ์ฉํ์ฌ foor
๋ผ๋ union ํ์
์์ undefined
๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
function throwError(): never {
throw new Error();
}
let foo: string | undefined;
if (!foo) {
throwError();
}
foo; // string
๋๋ ||
๋ ??
์ฐ์ฐ์ ์ดํ์ throwError
๋ฅผ ํธ์ถํ ์๋ ์์ต๋๋ค.
let foo: string | undefined;
const guaranteedFoo = foo ?? throwError(); // string
never
์ ์์ฉ ์ฌ๋ก๋ณด๋ค๋ ํ์
์คํฌ๋ฆฝํธ ์ธ์ด์ ๋์/ํน์ง์ ๋ ๊ฐ๊น๋ค๊ณ ๋๊ปด์ง ์๋ ์์ต๋๋ค. ๊ทธ๋ผ์๋, ์ด ์ ์ ์ฌ๋ฌ๋ถ์ด ๋ง์ฃผ์น ์๋ ์๋ ๋ช ๊ฐ์ง ์ํธ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ดํดํ๋ ๋ฐ ์์ฃผ ์ค์ํฉ๋๋ค.
๊ณต์กดํ ์ ์๋ ํ์
๋ค๋ผ๋ฆฌ ๊ต์งํฉ ์ฐ์ฐ์ ํ๋ฉด never
ํ์
์ ์ป์ ์ ์์ต๋๋ค.
type Res = number & string // never
๋ํ, ์ด๋ ํ์
์ด๋ ์ง never
๋ก ๊ต์งํฉ ์ฐ์ฐ์ ํ๋ฉด never
๋ฅผ ์ป๊ฒ ์ฃ .
type Res = number & never // never
type Foo = {
name: string,
age: number
}
type Bar = {
name: number,
age: number
}
type Baz = Foo & Bar // {name: never, age: number}
๋ค์ ์์์์๋ ์ ์ฒด ํ์
์ธ Baz
๊ฐ never
๋ก ์ขํ์ง๋๋ฐ boolean
์ ํ๋ณ ํ๋กํผํฐ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. (true | false
์ ์ ๋์จ)
type Foo = {
name: boolean,
age: number
}
type Bar = {
name: number,
age: number
}
type Baz = Foo & Bar // never
์ด PR์์ ๋ ์ดํด๋ณด์ธ์.
์ฌ๋ฌ๋ถ์ด ๋ช
์์ ์ผ๋ก never
๋ผ๊ณ ํ์
์ ์ง์ ํ์ง ์์ผ๋ฉด, ์์์น ๋ชปํ never
ํ์
๊ณผ ํจ๊ป ์๋ฌ ๋ฉ์์ง๋ฅผ ๋ง์ฃผํ๊ฒ ๋ ์๋ ์์ต๋๋ค. ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์
์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ๊ฐ ํ์
๋ค์ ๊ต์ฐจํ๊ธฐ ๋๋ฌธ์
๋๋ค. ํ์
์ ์์ ์ฑ์ ์งํค๊ณ ๊ฑด์ ์ฑ(soundness)์ ๋ณด์ฅํ๊ธฐ ์ํด ์๋ฌต์ ์ผ๋ก ์ํ๋๋ ์์
์
๋๋ค.
๋ค์ ์์๋ ์ด์ ์ ๋คํ์ ์ธ ํจ์์ ํ์ ์ ๋ํด ์์ฑํ ํฌ์คํ ์์ ์ฌ์ฉํ ์์์ ๋๋ค.
type ReturnTypeByInputType = {
int: number
char: string
bool: boolean
}
function getRandom<T extends 'char' | 'int' | 'bool'>(
str: T
): ReturnTypeByInputType[T] {
if (str === 'int') {
// generate a random number
return Math.floor(Math.random() * 10) // โ Type 'number' is not assignable to type 'never'.
} else if (str === 'char') {
// generate a random char
return String.fromCharCode(
97 + Math.floor(Math.random() * 26) // โ Type 'string' is not assignable to type 'never'.
)
} else {
// generate a random boolean
return Boolean(Math.round(Math.random())) // โ Type 'boolean' is not assignable to type 'never'.
}
}
์ด ํจ์๋ ์ ๋ฌ๋ฐ๋ ์ธ์์ ๋ฐ๋ผ ์ซ์, ๋ฌธ์์ด, ๋ถ๋ฆฌ์ธ์ ๋ฆฌํดํฉ๋๋ค. ๋ฆฌํด ๊ฐ์ ํด๋นํ๋ ํ์
์ ๊ฐ์ ธ์ค๊ธฐ ์ํด ReturnTypeByInputType[T]
๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๋ฆฌํด๋ฌธ์์ Type X is not assignable to type 'never'
๋ผ๋ ํ์
์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ถ๊ธฐ์ ๋ฐ๋ผ X
๋ string, number, boolean์ด ๋ฉ๋๋ค.
ํ์
์คํฌ๋ฆฝํธ๋ ์ฐ๋ฆฌ ํ๋ก๊ทธ๋จ์ด ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ๊ฐ๋ฅ์ฑ์ ์ค์ฌ์ฃผ๊ธฐ ์ํด ๋์์ ์ฃผ๋ ค๊ณ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ๊ฐ ๋ฆฌํด ๊ฐ์ ReturnTypeByInputType[T]
์ ํ ๋นํ ์ ์์ด์ผ ํ๋๋ฐ, ์ด ๊ฐ์ ๋ฐํ์ ๋ number, string, boolean์ด ๋ ์ ์์ต๋๋ค.
๋ฆฌํด ํ์
์ด ๋ชจ๋ ๊ฐ๋ฅํ ReturnTypeByInputType[T]
์ ํ ๋นํ ์ ์๋ค๊ณ ๋ณด์ฅํ ์ ์์ ๋ ํ์
์์ ์ฑ์ด ์ง์ผ์ง๋๋ค. ์ฆ number, string, boolean์ intersecion์ผ ๋๊ฐ ๊ทธ๋ฐ ๊ฒฝ์ฐ์ง๋ง ์ด๋ ์๋ก ๊ณต์กดํ ์ ์๋ ํ์
์ด๊ธฐ ๋๋ฌธ์ never
๊ฐ ๋๋ ๊ฒ์ด์ฃ . ๊ทธ๋์ ์๋ฌ ๋ฉ์์ง์ never
๋ฅผ ๋ณด๊ฒ ๋๋ ๊ฒ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด, ์ฌ๋ฌ๋ถ์ ํ์ ๋จ์ธ(type assertions) (๋๋ ํจ์ ์ค๋ฒ๋ก๋ฉ)์ ์ฌ์ฉํด์ผ๋ง ํฉ๋๋ค.
return Math.floor(Math.random() * 10) as ReturnTypeByInputType[T]
return Math.floor(Math.random() * 10) as never
๋ค๋ฅธ ๋ถ๋ช ํ ์์๊ฐ ์์ ์ ์์ต๋๋ค.
function f1(obj: { a: number, b: string }, key: 'a' | 'b') {
obj[key] = 1; // Type 'number' is not assignable to type 'never'.
obj[key] = 'x'; // Type 'string' is not assignable to type 'never'.
}
obj[key]
๋ ๋ฐํ์์ key
์ ๊ฐ์ ๋ฐ๋ผ string ๋๋ number๊ฐ ๋ฉ๋๋ค. ์ด๋ฌํ ์ ์ฝ์กฐ๊ฑด์ด ๋ํด์ง ํ์
์คํฌ๋ฆฝํธ๋ ํ์
์ ์์ ์ฑ์ ์ํด string๊ณผ number ๋ ํ์
๋ชจ๋ ๊ณต์กด๊ฐ๋ฅํ ๊ฐ๋ง ์ฐ๊ฒ๋ ํฉ๋๋ค. ๊ทธ๋์ ๋ ํ์
์ ๊ต์ฐจ๋ ํ์
์ธ never
ํ์
์ด ์ ๋ฌ๋๋ ๊ฒ์
๋๋ค.
์ด๋ค ํ์
์ด never
์ด์ด์ผ ํ๋์ง ํ์ธํ๋ ๊ฒ๋ณด๋ค never
์ธ์ง ํ์ธํ๋ ๊ฒ์ด ๋ ์ด๋ ต์ต๋๋ค. ๋ค์ ์ฝ๋ ์์๋ฅผ ๋ด
์๋ค.
type IsNever<T> = T extends never ? true : false
type Res = IsNever<never> // never ๐ง
Res
๋ true
๋๋ false
๊ฐ ๋ ๊น์? ๋๋๊ฒ๋ ๋ ๋ค ์ ๋ต์ด ์๋๋๋ค. ์ค์ ๋ก๋ never
๊ฐ ๋ฉ๋๋ค.
์ ๋ ์ด๊ฑธ ์ฒ์ ์ ํ์ ๋ ์ ์ ์ด ๋๊ฐ๋ ๋ฏ ํ์ต๋๋ค. Ryan Cavanaugh๊ฐ ์ฌ๊ธฐ์ ์ด๋ฅผ ์ค๋ช ํด์ฃผ์์ต๋๋ค.
์์ฝ์ ํด๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
never
๋ ๋น ์ ๋์จ์
๋๋ค.never
๊ฐ ๋ฉ๋๋ค.์ฌ๊ธฐ์ ์ ์ผํ ํด๊ฒฐ์ฑ ์ ์์์ ์ผ๋ก ํฉ์น๋ ๊ฒ์ ์ ํํ๊ณ ํํ๋ก ํ์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ธ๋ ๊ฒ์ ๋๋ค.
type IsNever<T> = [T] extends [never] ? true : false;
type Res1 = IsNever<never> // 'true' โ
type Res2 = IsNever<number> // 'false' โ
์ด๋ ์ค์ ๋ก ํ์ ์คํฌ๋ฆฝํธ ์์ค ์ฝ๋์ ์ผ๋ถ์ด๋ฉฐ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ์ด ์ฝ๋๋ฅผ ์ธ๋ถ์ ๋ ธ์ถ์ํค๋ฉด ๋ ์ข์ ๋ฏ ํฉ๋๋ค.
์ด ๊ธ์์ ์ ๋ง ๋ง์ ๊ฒ์ ๋ค๋ฃจ์๋ค์.
never
ํ์
์ ์ ์์ ๋ชฉ์ ์ ๋ํด ๋ค๋ค์ต๋๋ค.never
๊ฐ ๋น ํ์
์ธ ์ ์ ํ์ฉํ์ฌ ํจ์์ ์ ์ฝ์ฌํญ ์ถ๊ฐํ๊ธฐnever
๊ฐ ๋ํ๋๋ ์ด์ ์ ๋ํด์๋ ๋ค๋ค์์ฃ never
ํ์
์ธ์ง ํ์ธํ๋ ๋ฐฉ๋ฒ๊น์ง ์ดํด๋ดค์ต๋๋ค.์ด ๊ธ์ ๋ฆฌ๋ทฐํด์ฃผ๊ณ ์์ฃผ ์์คํ ํผ๋๋ฐฑ์ ๋จ๊ฒจ์ค ์น๊ตฌ Josh์๊ฒ ๊ฐ์ฌ์ ์ธ์ฌ๋ฅผ!
์๋ฌธ : https://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ฌธ์์ด, ์ซ์ ๋๋ ๋ถ๋ฆฌ์ธ ์์ํ์ ๋ค์ ์ฌ์ฉํ ๋๋ง๋ค ์ฌ๋ฌ๋ถ์ ๊ฐ์ฒด์ ๊ทธ๋ฆผ์์ ๊ฐ์์ ์จ๊ฒจ์ง ์ธ๊ณ์ ๋ค์ด๊ฐ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ ๋กํ์ฆ์ ์ท์ฅ์ ๋จผ์ง๋ฅผ ํธ์ด๋ด๊ณ ๊ณ์ ์ฝ์ด๋ณด์ธ์.
๊ฐ์ฒด๋ ์์ฑ๋ค์ ์งํฉ์
๋๋ค. ํ๋์ ์์ฑ์ ๊ฐ์ฒด๋ ์์ํ์
์ ์ฐธ์กฐํ ์ ์๊ณ , ์์ ํ์
์ ๊ฐ๋ค๋ก ์์ฑ์ ๊ฐ์ง ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ์์ ํ์
์ ๋ค์ฏ ๊ฐ์ง๊ฐ ์์ต๋๋ค. undefined
, null
, boolean
, string
๊ทธ๋ฆฌ๊ณ number
์
๋๋ค. ๊ทธ ์ธ์ ๋ชจ๋ ๊ฒ๋ค์ ๊ฐ์ฒด์
๋๋ค. ์์ํ์
boolean, string, number๋ ๊ทธ๋ค์ ๊ฐ์ฒด์ ๋์๋๋ ๊ฒ๋ค์ ๊ฐ์ธ์ง ์๋ ์์ต๋๋ค. ์ด ๊ฐ์ฒด๋ค์ ๊ฐ Boolean
, String
, Number
์์ฑ์์ ์ธ์คํด์ค๋ค์
๋๋ค.
typeof true; //"boolean"
typeof Boolean(true); //"boolean"
typeof new Boolean(true); //"object"
typeof (new Boolean(true)).valueOf(); //"boolean"
typeof "abc"; //"string"
typeof String("abc"); //"string"
typeof new String("abc"); //"object"
typeof (new String("abc")).valueOf(); //"string"
typeof 123; //"number"
typeof Number(123); //"number"
typeof new Number(123); //"object"
typeof (new Number(123)).valueOf(); //"number"
"abc".length
๋ ๊ฐ์ ๋ฐํํ ๊น?์๋ฐ์คํฌ๋ฆฝํธ๋ ์์ ํ์ ๊ณผ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ๊ฐ์ ๋ณํํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์์ ๋ฌธ์์ด ๊ฐ์ length๋ผ๋ ํ๋กํผํฐ์ ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ ๋ฌธ์์ด ๊ฐ์ฒด๋ก ๊ฐ์ ๋ณํ๋ฉ๋๋ค. ๋ฌธ์์ด ๊ฐ์ฒด๋ ์ฐฐ๋์ ์๊ฐ์๋ง ์ฌ์ฉ๋๊ณ ๋ฐ๋ก ๊ฐ๋น์ง ์ฝ๋ ์ ์ ์ํด ์์ง๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ฐฐ๋์ ์ด ์๋ช ์ฒด๋ฅผ ๊ฐ๋ฌ ๋ถ์์ ํด๋ณผ ๊ฒ๋๋ค.
String.prototype.returnMe= function() {
return this;
}
var a = "abc";
var b = a.returnMe();
a; //"abc"
typeof a; //"string" (still a primitive)
b; //"abc"
typeof b; //"object"
์๋ฏธ์๋ ๋ง์ ์กฐ์ฌ๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฐ๋ฆฌ๋ b๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ b๊ฐ ์กด์ฌํ๋ ํ ๊ฐ์ฒด๊ฐ ์์ฐ์ค๋ฝ๊ฒ ์์ง๋๋ ๊ฒ์ ๋ฐฉํดํ์ฌ ๋ง์์ต๋๋ค. ํ์ด์ ๋ฒ ๋ฅดํฌ๋ ์ด์์์ต๋๋ค. ๐ (strict mode์์๋ ์ด๋ ๊ฒ ์ก์ ์ ์์ต๋๋ค.)
๋ค์ ์์๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ๋ฐฉํดํ์ง ์๊ณ ๊ฐ์ฒด์ ์ ํ์ ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
Number.prototype.toString = function() {
return typeof this;
}
(123).toString(); //"object"
์ด๋ฌํ ๋ฐฉ๋ฒ์ ํตํด ์์ํ์ ์ ๊ฐ์์ ๊ฐ์ฒด ์์ฑ์๊ฐ ์ ์ํ ๋ฉ์๋๋ฅผ ํฌํจํ ๋ชจ๋ ํ๋กํผํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
์ฃผ๋ก ๊ทธ๋ ์ต๋๋ค. ์ด๋ฌํ ์ ํ์ ๊ฐ์ฒด๋ค์ ๋จ์ง ๋ํผ์ ์ญํ ์ ํ๋ฉฐ ๊ทธ๋ค์ ๊ฐ์ ๊ฐ์ฒด๋ค์ด ๊ฐ์ธ๊ณ ์๋ ์์ํ์ ์ ๋๋ค. ํ์ํ ๋๋ ์์ ๋ค์ ๊ฐ์ผ๋ก ๊ฐ์ ๋ณํ๋๊ธฐ๋ ํฉ๋๋ค. ์ด ๊ธ์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// ์์๊ฐ์ผ๋ก ๊ฐ์ ๋ณํ๋๋ ๊ฐ์ฒด 1
var Twelve = new Number(12);
var fifteen = Twelve + 3;
fifteen; //15
typeof fifteen; //"number" (primitive)
typeof Twelve; //"object"; (still object)
//์์๊ฐ์ผ๋ก ๊ฐ์ ๋ณํ๋๋ ๊ฐ์ฒด 2
new String("hippo") + "potamus"; //"hippopotamus"
// ๋ณํ๋์ง ์๋ ๊ฐ์ฒด ('typeof' ์ฐ์ฐ์๋ ์ฌ์ ํ ๊ฐ์ฒด๋ก ๋์ํ๊ธฐ ๋๋ฌธ)
typeof new String("hippo") + "potamus"; //"objectpotamus"
์ฌํ๊ฒ๋ ๋ถ๋ฆฌ์ธ ๊ฐ์ฒด๋ ๊ทธ๋ ๊ฒ ์ฝ๊ฒ ๋ณํ๋์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ถ๋ฆฌ์ธ ๊ฐ์ฒด๋ ๊ฐ์ด null ์ด๋ undefined๊ฐ ์๋๋ผ๋ฉด true๋ก ํ๊ฐ๋ฉ๋๋ค.
if (new Boolean(false)) {
alert("true???");
}
์ผ๋ฐ์ ์ผ๋ก ๋ถ๋ฆฌ์ธ ๊ฐ์ฒด์ ๊ฐ์ ๋ช ์์ ์ผ๋ก ์์ฒญํด์ผ ํฉ๋๋ค. ๋ค์์ ๊ฐ์ด "truthy"ํ์ง "falsy"ํ์ง ๊ฒฐ์ ํ๋๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
var a = "";
new Boolean(a).valueOf(); //false
ํ์ง๋ง ์ค์ ๋ก๋ ์ด๋ ๊ฒ ํ๋ ๊ฒ์ด ๋ ์ฝ์ต๋๋ค.
var a = Boolean("");
a; // false
๋๋ ์ด๋ ๊ฒ์.
var a = "";
!!a; //false
๊ทธ๋ ์ง ์์ต๋๋ค.
var primitive = "september";
primitive.vowels = 3;
primitive.vowels; //undefined;
์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์์ ํ์ ์ ํ๋กํผํฐ๋ฅผ ํ ๋นํ๋ ๊ฒ์ ๊ฐ์งํ๋ค๋ฉด ์์ ํ์ ์ ๊ฐ์ฒด๋ก ๊ฐ์ ํ๋ณํ์์ผฐ์ ๊ฒ๋๋ค. ๊ทธ๋ฌ๋ ์์ ์์์ฒ๋ผ ์๋ก์ด ๊ฐ์ฒด๋ ์ฐธ์กฐ๊ฐ์ด ์๊ณ ์ฆ์ ๊ฐ๋น์ง ์ฝ๋ ์ ์ ์ํด ์์ง๋ฉ๋๋ค.
๋ค์์ ์ค์ ๋ก ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ์ค๋ช ํ๊ธฐ ์ํ ์๋ ์ฝ๋์ ๋๋ค.
var primitive = "september";
primitive.vowels = 3;
// ์์ฑ๋ ์๋ก์ด ๊ฐ์ฒด์ ํ๋กํผํฐ ์
(new String("september")).vowels = 3;
primitive.vowels;
// ๋ ๋ค๋ฅธ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ณ ์ด ๊ฐ์ฒด์์ ํ๋กํผํฐ๋ฅผ ์ฐพ์
(new String("september")).vowels; //undefined
๋ณด์๋ค์ํผ, ์ด๋ฌํ ์ฝ๋๋ ์ธ๋ชจ์์ ๋ฟ ์๋๋ผ ๋ญ๋น์ ๋๋ค.
ํ๋กํผํฐ๋ฅผ ํ ๋นํ๋ ๊ฒ์ ์์ํ์ ๊ณผ ๋ฌ๋ฆฌ ๊ฐ์ฒด๊ฐ ๊ฐ์ง๋ ์ ์ผํ ์ฅ์ ์ด์ง๋ง ์ด๋ง์ ๋ ๊ฝค ์์ฌ์ค๋ฝ์ต๋๋ค. ๋ฌธ์์ด, ๋ถ๋ฆฌ์ธ, ๋๋ฒ๋ ๊ตฌ์ฒด์ ์ด๊ณ ์ ์ ์๋ ๋ชฉ์ ์ ๊ฐ์ง๋ฉฐ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ๊ฒ์ ์ฌ๋๋ค์ ํผ๋์ค๋ฝ๊ฒ ํ ๊ฒ์ ๋๋ค. ๋ํ ์์ ํ์ ์ ๋ถ๋ณ๊ฐ์ด๋ฏ๋ก ๊ฐ์ฒด ๋ํผ์ ํ๋กํผํฐ๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
var me = new String("Angus");
me.length = 2; //(error in strict mode)
me.length; //5 (not 2 - thanks @joseanpg)
me.valueOf(); "Angus"
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์์ํ์ ์ ์ ์ดํดํ๊ณ ์์ํ์ ์ ์ฌ์ฉํ ๋ ์ด๋ค ์ผ๋ค์ด ์ผ์ด๋๋์ง ์ดํดํ๋ ๊ฒ์ ์ธ์ด๋ฅผ ๋ ์ ์ดํดํ๋๋ฐ ์์ฃผ ์ค์ํ ๋จ๊ณ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด ๊ธ์ด ๋์์ด ๋์๊ธธ ๋ฐ๋๋๋ค.
์๋ฌธ : 2021.01.18์ ์์ฑ๋ Tao of React - Software Design, Architecture & Best Practices
์ด๋ค ์ต์ ํ๋ฅผ ํ๊ธฐ ์ ์ ์ต์ ํ์ ๋ํ ์ด์ ๊ฐ ์๋์ง ํ์ธํ์ธ์. ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํฅ์ ์ฃผ์ง ์์์๋ ๋งน๋ชฉ์ ์ผ๋ก ์ข์ ์ฌ๋ก๋ฅผ ๋ฐ๋ผํ๋ ๊ฒ์ ๋ ธ๋ ฅ์ ํ๋นํ ๋ฟ์ ๋๋ค. ์ค์ํ ๊ฑธ ์๋ ๊ฒ๋ ํ์ํฉ๋๋ค๋ง, ์ฑ๋ฅ ์ด์ ์ ๊ฐ๋ ์ฑ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ ์ฐ์ ์ผ๋ก ํด์ผ ํฉ๋๋ค. ์ ์ฐ์ฌ์ง ์ฝ๋๊ฐ ๊ฐ์ ํ๊ธฐ ์ฝ์ต๋๋ค.
์ฌ๋ฌ๋ถ์ ์ฑ์ ์ฑ๋ฅ๋ฌธ์ ๊ฐ ์์ ๋ ๋ฌธ์ ์ ์์ธ์ ์ธก์ ํ๊ณ ๋ฌด์์ธ์ง ํ์ธํ์ธ์. ๋ฒ๋ค ์ฌ์ด์ฆ๊ฐ ๊ฑฐ๋ํ๋ค๋ฉด ๋ฆฌ๋ ๋๋ง ํ์๋ฅผ ์ค์ฌ๋ ์์ฉ์ด ์์ต๋๋ค. ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ์ผ๋จ ์๋ฉด ๋ฌธ์ ์ ์ํฅ ์์์ ๋ฐ๋ผ ์์ ํด์ผ ํฉ๋๋ค.
๋ธ๋ผ์ฐ์ ์ ์ ๋ฌ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์์ ์ดํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ๊ฐ์ฅ ์ฃผ์ํ ์์์ ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฑ์ด ์์ฒญ ๋น ๋ฅด๋๋ผ๋ 4MB์ JS ์ฝ๋๋ฅผ ๋ก๋ํด์ผ ํ๋ค๋ฉด ์๋ฌด๋ ์ฌ๋ฌ๋ถ์ ์ฑ์ด ๋น ๋ฅธ ๊ฒ์ ์์ง ๋ชปํ ๊ฒ๋๋ค. ํ๋์ ๋ฒ๋ค์ ์ ๋ฌํ์ง ๋ง๊ณ ์ฌ๋ฌ๋ถ์ ์ฑ์ route ์์ค์ผ๋ก ์ชผ๊ฐ๋๋ก ํ์ธ์. ๊ฐ๋ฅํ ์ต์ํ์ JS ์ฝ๋๋ฅผ ์ ๋ฌํ๋๋ก ํด์ผ ํฉ๋๋ค.
๋ฐฑ๊ทธ๋ผ์ด๋๋ก ๋ก๋ํ๊ฑฐ๋ ์ฌ์ฉ์๊ฐ ๋ค๋ฅธ ๋ฒ๋ค์ด ํ์ํ ๋ ๋ก๋ํฉ๋๋ค. ์ด๋ค ๋ฒํผ์ด PDF๋ฅผ ๋ค์ด๋ก๋ํ๋ ๊ฒ์ ํธ๋ฆฌ๊ฑฐํ๋ค๋ฉด, ๋ฒํผ์ด hover๋์์ ๋ PDF ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ค์ด๋ก๋ํ๋๋ก ์ง์ฐ์ํฌ ์ ์์ต๋๋ค.
๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ํ์๋ฅผ ์ค์ด๋ ๊ฒ์ ์ข์ ์๋์ ๋๋ค. ๋ค๋ง, ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ์ฌ๋ฌ๋ถ์ ์ฑ์ ์์ฒญ๋ ์ํฅ์ ๋ฏธ์น๋ ๊ฒฝ์ฐ๊ฐ ๊ฑฐ์ ์๋ค๋ ๊ฒ์ ์ ์ํ์ธ์. ๊ฐ์ฅ ํํ ์กฐ์ธ์ props๋ก ์ฝ๋ฐฑ ํจ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์ง์ํ๋ ๊ฒ์ ๋๋ค. ๊ฐ ์๋ก์ด ํจ์๊ฐ ์์ฑ๋ ๋๋ง๋ค ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฝ๋ฐฑํจ์๋ก ์ธํด ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๊ฒช์ ์ ์ ์์๊ณ , ์ฌ์ค ๊ทธ๊ฒ์ด ์ ๊ฐ ์ ๊ทผํ๊ณ ์ ํ๋ ๋ฐฉ์์ ๋๋ค.
์ฌ๋ฌ๋ถ์ด ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ๊ฒช๊ณ ์๊ณ ํด๋ก์ ธ๊ฐ ์์ธ์ด๋ผ๋ฉด ํด๋ก์ ธ๋ฅผ ์ ๊ฑฐํ์ธ์. ๊ทธ๋ฌ๋ ์ฝ๋์ ๊ฐ๋ ์ฑ์ ํด์น๊ฑฐ๋ ๋ ์ฅํฉํ๊ฒ ๋ง๋ค์ง๋ ๋ง์ธ์. ๋ฐฐ์ด์ด๋ ๊ฐ์ฒด๋ฅผ ์๋๋ก ์ ๋ฌํ๋ ๊ฒ์ ๋น์ทํ ๊ฒฐ์ ๋๋ค. ์ฐธ์กฐ ์ฒดํฌ์ ์คํจํ๋ฉด ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ์ฃ . ๊ณ ์ ๋ ๋ฐฐ์ด์ ์ ๋ฌํ๊ณ ์ ํ๋ค๋ฉด, ์ปดํฌ๋ํธ ์ ์์ ์์ ๋ฐฐ์ด์ ์์๋ก ์ ์ธํจ์ผ๋ก์จ ๋์ผํ ์ธ์คํด์ค๊ฐ ์ ๋ฌ๋ ๊ฒ์ ๋๋ค.
React๋ก 2016๋
๋ถํฐ ์์
ํ๋ฉด์ ์ ์ปดํฌ๋ํธ์์ ์ค๋
์ท ํ
์คํธ๊ฐ ๋ฌธ์ ๋ฅผ ์บ์นํ ์ ์ ๋ฑ ํ ๋ฒ ์์ต๋๋ค. ์ธ์ ์์ด new Date()
๋ฅผ ํธ์ถํ์ฌ ํญ์ ํ์ฌ ๋ ์ง๋ก ๊ธฐ๋ณธ ์ค์ ๋์๋ ๊ฑฐ์ฃ . ๊ฒ๋ค๊ฐ ์ค๋
์ท์ ์ปดํฌ๋ํธ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ๋น๋ ์คํจ์ ์์ธ์ด ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ํฌํ๋ก์ฐ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ค๋
์ท์ ์ค๋ฅ๊ฐ ์๋์ง ํ์ธํ ํ ์ค๋
์ท์ ์
๋ฐ์ดํธํ๊ณ ๊ณ์ ์งํํฉ๋๋ค. ์คํดํ์ง ๋ง์ธ์. ์ค๋
์ท ํ
์คํธ๋ ์ข์ ์๋ํฐ ์ฒดํฌ์ง๋ง ์ปดํฌ๋ํธ ์์ค์ ํ
์คํธ๋ฅผ ์ํ ๋์ฒดํ์ด ๋ ์๋ ์์ต๋๋ค. ์ ๋ ์ค๋
์ท์ ์์ฑํ๋ ๊ฒ์กฐ์ฐจ๋ฅผ ์ง์ํฉ๋๋ค.
์ฌ๋ฌ๋ถ์ ํ ์คํธ๊ฐ ๊ฒ์ฆํด์ผ ํ๋ ๊ฒ์ ์ปดํฌ๋ํธ๊ฐ ์์๋๋ก ๋์ํ๋ ๊ฒ์ ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๊ธฐ๋ณธ๊ฐ์ props์ ์ ๋ฌ๋๋ props๋ก ์ฌ๋ฐ๋ฅด๊ฒ ๋ ๋๋๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ์ฃผ์ด์ง ์ธํ์ ๋ํด ํจ์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๋์ง๋ฅผ ๊ฒ์ฆํ์ธ์. ์คํฌ๋ฆฐ์์ ํ์ํ ๋ชจ๋ ๊ฒ๋ค์ ๊ฒ์ฆํ์ธ์.
์ํ๊ฐ ์๋ ์ปดํฌ๋ํธ๋ ์ด๋ฒคํธ์ ์๋ต์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ฉ๋๋ค. ์ด๋ฒคํธ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๊ณ ์ปดํฌ๋ํธ๊ฐ ๊ทธ์ ์ ์ ํ ๋ฐ์ํ๋์ง ํ์ธํ์ธ์. ํธ๋ค๋ฌ ํจ์๊ฐ ํธ์ถ๋๊ณ ์ ์ ํ ์ธ์๊ฐ ์ ๋ฌ๋๋์ง ๊ฒ์ฆํ์ธ์. ๋ํ ๋ด๋ถ ์ํ๊ฐ ์ ์ค์ ๋๋์ง ํ์ธํ์ธ์.
๊ธฐ๋ณธ์ ์ธ ํ ์คํธ๋ฅผ ๋ค๋ค๋ค๋ฉด, ์ฃ์ง ์ผ์ด์ค๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด ๋ช ๊ฐ์ง๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ๋น ๋ฐฐ์ด์ ์ ๋ฌํ์ ๋ ์ฒดํน์์ด ์ธ๋ฑ์ค๋ฅผ ์ ๊ทผํ์ง ์๋๋ก ํด์ผ ํฉ๋๋ค. API ํธ์ถ์์ ์๋ฌ๋ฅผ ๋ฐ์์์ผ ์ปดํฌ๋ํธ๊ฐ ํด๋น ์ค๋ฅ๋ฅผ ์ ์ฒ๋ฆฌํ๋์ง ํ์ธํฉ๋๋ค.
ํตํฉ ํ ์คํธ๋ ์ ์ฒด ํ์ด์ง๋ ํฐ ์ปดํฌ๋ํธ๋ฅผ ๊ฒ์ฆํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ถ์ํ๋ก์ ์ ์๋ํ๋์ง ํ์ธํ๋ ๊ฒ์ด์ฃ . ์ด ํ ์คํธ๋ ์ฑ์ด ์์๋๋ก ์ ์๋ํ๋ค๋ ์์ ๊ฐ์ ์ค๋๋ค. ์ปดํฌ๋ํธ ์์ฒด๋ก๋ ์ ์๋ํ๊ณ ์ ๋ ํ ์คํธ ๋จ์๋ก๋ ํ ์คํธ๋ฅผ ํต๊ณผํ ์ ์์ง๋ง ํตํฉ๋์์ ๋ ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค.
๋ง์ ์ฌ๋๋ค์ด ๋์ํ์ง ์๊ณ ์ฌ๋ฌ ๋ ผ๋์ ์ผ๊ธฐํ ์๊ฒฌ์ ๋๋ค. ์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ปดํฌ๋ํธ์ ๋ํ ๋ชจ๋ ๊ฒ๋ค์ ํํ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ Styled Components๋ Emotion๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ํธํฉ๋๋ค. ๊ด๋ฆฌํ ํ์ผ์ด ํ๋ ์ค์ด๋ค๋ฉฐ CSS ์ปจ๋ฒค์ ์ ๋ํด ์๊ฐํ ํ์๊ฐ ์์ต๋๋ค. ๋ฆฌ์กํธ์์ ๋ ผ๋ฆฌ ๋จ์๋ ์ปดํฌ๋ํธ์ด๋ฏ๋ก ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ๋ ๊ด์ ์์๋ ์ปดํฌ๋ํธ์ ๊ด๋ จ๋ ๋ชจ๋ ๊ฒ๋ค์ ์ปดํฌ๋ํธ๊ฐ ์์ ํด์ผ ํฉ๋๋ค.
์ฃผ์ : ์คํ์ผ์ ๋ํ ์๋ชป๋ ์ ํ์ ์์ต๋๋ค. SCSS, CSS ๋ชจ๋, Tailwind์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ. CSS-in-JS๋ ์ ๊ฐ ์ถ์ฒํ๋ ์ ๊ทผ ๋ฐฉ์์ผ ๋ฟ์ ๋๋ค.
CSS-in-JS ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ๋ ํ ํ์ผ์ ์ฌ๋ฌ ๊ฐ๋ฅผ ๊ฐ์ด ๋๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. ๊ฐ์ ํ์ผ์ ์ฌ์ฉํ๋ ์ผ๋ฐ ์ปดํฌ๋ํธ์ ๋์ผํ ํ์ผ์ ๋ณด๊ดํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ฌด ์คํ์ผ ์ฝ๋๊ฐ ๋๋ฌด ๊ธธ์ด์ง๊ฒ ๋๋ฉด ๋ถ๋ฆฌํด์ ์คํ์ผ์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ ๊ทผ์ฒ์ ๋๋ ๊ฒ์ด ์ข์ต๋๋ค. Spectrum๊ณผ ๊ฐ์ ์คํ ์์ค ํ๋ก์ ํธ์์ ์ด๋ฌํ ํจํด์ ๋ณผ ์ ์์ต๋๋ค.
๋ฆฌ์กํธ๋ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ ๋ฐ์ดํธํ๋ ๊ณ ์ง๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์์ต๋๋ค. ๊ฐ ํ์ API์ ํต์คํ๋ ๋น๋๊ธฐ ํจ์๋ค์ ์ ๊ณตํ๋ ์์ ๋ค๋ง์ ์๋น์ค์ ๊ด๋ จ๋ ์์ฒด ๊ตฌํ์ ๋ง๋ค์ด๋ด์ฃ . ์ด ๋ฐฉ์์ ์ ํํ๋ฉด ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ http ์๋ฌ๋ค์ ๋ค๋ฃจ๋ ๊ฒ๋ค์ ์ฐ๋ฆฌ๊ฐ ์ง์ ํด์ผ ํฉ๋๋ค. ์ด๋ ์ฅํฉํ ์ฝ๋๋ฅผ ๊ฐ์ง๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ํ์๋ก ํฉ๋๋ค. ์ง์ ๊ตฌํํ๋ ๋์ React Query๋ SWR๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ธ์. hook์ด๋ผ๋ ๊ด์ฉ์ ์ธ ๋ฐฉ์์ ํตํด ์๋ฒ์ ํต์ ํ๋ ๊ฒ์ ์ปดํฌ๋ํธ ๋ผ์ดํ์ฌ์ดํด์ ์์ฐ์ค๋ฌ์ด ๋ถ๋ถ์ผ๋ก ๋ง๋ญ๋๋ค. ๋ํ ์บ์ฑ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ๋ก๋ฉ๊ณผ ์๋ฌ ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ ๊ธฐ๋ฅ์ ๋ค๋ฃจ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ๋ํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ํ์๋ฅผ ์์ ์ค๋๋ค.
์ด ๊ธ์ ์ค๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ ผ์์ ๋ค์ ์ด์ด๋ณด๊ณ ์ ์์ฑํ๋ ๊ธ์ด ์๋๋๋ค. ๋จ ์๋ฐ์คํฌ๋ฆฝํธ ์คํ ๋ค๋ ์คํ์ผ์์ "์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ์ง ์๋" ๊ท์น์ ๊ฐ์ ํ๋์ง์ ๋ํ ๊ถ๊ธ์ฆ์ ์ฐธ์กฐ์ฉ์ผ๋ก์ ์์ฑํฉ๋๋ค.
์ฌ๋ฌ๋ถ๋ค์ด ์๋ ์ธ๋ฏธ์ฝ๋ก ์ฝ์
(ASI)์ ๋ํด ๊ฑฑ์ ํ์ง ์๊ณ "์ธ์ ๋ ์ธ๋ฏธ์ฝ๋ก ์ ์ธ ์ ์๋ค๋" ์๊ฐ์ ์์ ํ ์๋ชป๋์ต๋๋ค.
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์๋ค์ ๋ฐ๋์ ASI์ ๋ํด ์ดํดํด์ผ ํ๋ฉฐ, ์ธ๋ฏธ์ฝ๋ก ์ ํญ์ ๋ถ์ด๋๋ผ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ๋ค์ ์์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
function foo () {
return
{
bar: 1,
baz: 2
};
}
์ธ๋ฏธ์ฝ๋ก ์ ๋ฃ๋ ๊ฒ์ ์์๋ค ํ ์ง๋ผ๋ ๊ด์ฐฎ์ต๋๋ค. ASI๊ฐ ์๋์ฒ๋ผ ๋ณ๊ฒฝํฉ๋๋ค.
function foo () {
return; // <-- ASI๊ฐ ์ฌ๊ธฐ์ ์ธ๋ฏธ์ฝ๋ก ์ ์ถ๊ฐํ๊ณ ์ฌ๋ฌ๋ถ์ ๋ฒ๊ทธ๋ฅผ ์ป๊ฒ ๋์์ต๋๋ค!
{
bar: 1,
baz: 2
};
}
์ด๋ฐ ๊ฒฝ์ฐ๋ก ์ธํด ์ฌ๋๋ค์ด "ํญ์ ์ธ๋ฏธ์ฝ๋ก ์ ์ด๋ค๋ฉด" ์ด์ํ ASI์ ๋์์ผ๋ก๋ถํฐ ์์ ํ๋ค๋ ์คํด๋ฅผ ๋ณ๊ฒ ๋ฉ๋๋ค.
ASI๋ ์ฐ๋ฆฌ์ ํ์ ํจ๊ป ํฉ๋๋ค. ์ด์ ์ฌ๋ฌ๋ถ๋ค์ด ASI๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง์ ๋ํด ๋ฐฐ์ธ ์๊ฐ์ ๋๋ค. ๊ฑฑ์ ํ์ง ๋ง์ธ์. ASI๋ ECMAScript ์ธ์ด ํ์ค์ ์ ์ค๋ช ๋์ด ์์ผ๋ฉฐ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ ์ ํํ ๋์ผํ ๋ฐฉ์์ผ๋ก ๊ตฌํํฉ๋๋ค.
์ต์ํ์ผ๋ก ์๊ธฐ์น ๋ชปํ ASI์ ๋์์ ํ์ธํ๋ ์ฉ๋๋ก ๋ฆฐํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์. ESLint๋ ์์์น ๋ชปํ ASI์ ๋์์ ์ก์์ฃผ๋ no_unexpected_multiline
๊ท์น์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ํ ์ฌ๋ฌ๋ถ๋ค์ด ์ผ๋จ ๋ฆฐํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ๋ถ๋ค์ ์์ ํ๊ฒ ํด์ฃผ๋ฏ๋ก ์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ๋ ์ฌ์ฉํ์ง ์๋ ์ค์ํ์ง ์์ต๋๋ค.
"ํญ์ ์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ๋ผ"๋ ๊ทธ๋ ๊ฒ ๊ฐ๋จํ์ง ์์ต๋๋ค. ์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ์ง ์๋ ๋ง์ ์ฃ์ง ์ผ์ด์ค๋ค์ด ์กด์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด๋ด ์๋ค.
function foo () {
return 42; // ok
}; // <-- AVOID!
var foo = function () {
}; // ok
๊ทธ๋ฆฌ๊ณ ์ด๋ฐ ๊ฒฝ์ฐ๋ ์์ต๋๋ค.
class Foo {
constructor () {
if (baz) {
return 42; // ok
}; // <-- AVOID!
return 12; // ok
}; // <-- AVOID!
}; // <-- AVOID!
"์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ์ง ์๊ธฐ"๋ณด๋ค "์ธ๋ฏธ์ฝ๋ก ์ ํญ์ ์ฌ์ฉํ๋ ๊ฒ"์ ๋ ๋ง์ "์ฃ์ง ์ผ์ด์ค"๋ค์ ๋ช
์ฌํด์ผ ํฉ๋๋ค.
๋ง์ฝ ์ฌ๋ฌ๋ถ์ด "์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด" ํ ๊ฐ์ง์ ๊ท์น๋ง์ด ์กด์ฌํฉ๋๋ค. [
, (
, ```๋ก ๋ผ์ธ์ ์์ํ์ง ์๋๋ค.
๊ทธ๋ฐ ๊ฒฝ์ฐ์, ์ด๋ ๊ฒ ๋จ์ํ ;
๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
;[1, 2, 3].forEach(bar)
๊ทธ๋ฌ๋ ์ด๋ฐ ์์ผ๋ก ๋ง์ด ์ฝ๋๋ฅผ ์์ฑํ๋ ํธ์ด๋ผ๋ฉด, ๋ถํ์ํ๊ฒ ๋๋ํ ์ฝ๋๋ฅผ ์ฐ๊ณ ์๋ ๊ฒ์ผ์ง๋ ๋ชจ๋ฆ
๋๋ค.
์ด๋ ๊ฒ ์ฐ๋ ๊ฒ ๋ ๊ฐ๋จํ์ฃ .
const nums = [1, 2, 3]
nums.forEach(bar)
๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ด standard์ฒ๋ผ ๋ฆฐํฐ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ์์์น ๋ชปํ ASI๊ฐ ์๋ฌ๋ก ์๋ ค์ง๋ฏ๋ก ๊ธฐ์ตํ ํ์๊ฐ ์์ต๋๋ค.
์์ ๋งํฌ, ๊นํํ๋
export const productAsyncState = selector({
key: 'productAsyncState',
get: async ({get}) => {
const idx = get(productIdxState);
return idx > 0 ? await getProductDetail(idx) : null;
},
});
export const productAsyncState = selectorFamily({
key: 'productAsyncState',
get: ({idx}) => async ({get}) => {
return idx > 0 ? await getProductDetail(idx) : null;
},
});
-> ์ด๋ฐ ์์ผ๋ก ์์ฑํ๊ฒ ๋๋ฉด Suspense
๋ฅผ ์ด์ฉํ๋ผ๋ ์๋ฌ๊ฐ ๋ธ
Suspense
๋ก ๊ฐ์ธ์<ErrorBoundary>
๋ก ๊ฐ์ธ๊ฑฐ๋ useRecoilValueLoadable
์์ state๋ฅผ ํ์ฉ์บ์ฑ ์ปจํธ๋กค ํ ์ ์๋ ์คํ ๋ฒ์ ์ด ๋ฑ์ฅ! v.0.4
2021๋ 7์ 27์ผ์ ์์ฑ๋ Top 5 React Mistakes Web Developers Make์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค. ๐
์ต๊ทผ, ์ ๋ ํ์๋ค์ ๊ฐ๋ฅด์น๊ธฐ ์์ํ์ฌ ๊ฐ๋์ฉ ์์ฃผ ๋ณด์ด๋ ์ค์๋ค์ ๋ชจ์ ๋ณด์์ต๋๋ค.
์ง๊ธ ๋ชจ์ ๊ฒ๋ค์ ์ผ๋ถ๋ฅผ ์ฌ๋ฌ๋ถ๋ค๊ณผ ๊ณต์ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
๋ํ ๋ช๋ช ๋ถ๋ค๊ณผ ์ธํฐ๋ทฐ๋ฅผ ์งํํ ๋ ๋ณดํต ์ด ๋ชฉ๋ก์์ ์ผ๋ถ๋ฅผ ๊ณจ๋๊ณ , ์ธํฐ๋ทฐ์ด๋ถ๋ค๊ป ์ฝ๋์ ์๋ชป๋ ์ ์ ์ฌ์ญค๋ณด๊ธฐ๋ ํ์ต๋๋ค.
๋ชจ๋ ์์ ๋ ์ฝ๋๋ฆฌ๋ทฐ๋ ์ธํฐ๋ทฐ ๊ณผ์ ์์ ๊ฐ์ ธ์์ง๋ง ๋ฌธ์ ์ ์ง์คํ๊ณ ์ ๋จ์ํ์์ผฐ์์ ์๋ ค๋๋ฆฝ๋๋ค.
export const Component4: FC = () => {
const [value, setValue] = useState(0);
useEffect(() => {
setInterval(() => setValue((value) => value + 1), 1000);
}, []);
return <div>{value}</div>;
};
์ฐ๋ฆฌ๊ฐ ์ ์๋ฏ์ด, SPA ์ฑ์์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ ์ค์ํ ๋ฌธ์ ์ด๊ณ ๋ฐ๋์ ์ ๊ฒฝ์จ์ผ ํ ๋ฌธ์ ์
๋๋ค. ์ด ์ฝ๋๋ ๋ฉ๋ชจ๋ฆฌ ๋์์ ์ด์ ๋ฅผ ์๋ ค์ฃผ๋ ์ข์ ์์ ์ฝ๋์
๋๋ค. ์ผ๋ถ ๋ก์ง์ setInterval
ํจ์์ ๋์๊ณ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋ ํด๋น ํจ์๋ฅผ ํด๋ฆฌ์ดํ๋ ๊ฒ์ด ๋๋ฝ๋์์ต๋๋ค.
useEffect
์ ์ ๋ฌ๋๋ ํจ์๋ clean-up ํจ์๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์ณ์ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
export const Component4: FC = () => {
const [value, setValue] = useState(0);
useEffect(() => {
const interval =
setInterval(() => setValue((value) => value + 1), 1000);
return () => clearInterval(interval);
}, []);
return <div>{value}</div>;
};
clean-up ํจ์์์ ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋ ๋๋ง๋ค ์ธํฐ๋ฒ ํจ์๋ฅผ ์ ๋ฆฌํจ์ผ๋ก์จ ๋ฉ๋ชจ๋ฆฌ ๋์์ ์์ธ์ ์ ๊ฑฐํ์ต๋๋ค.
useEffect/useLayoutEffect
์์ ๋ฐ์ํ ์ ์๋ ๊ตฌ๋
์ ๋ํด ์ธ์ ๋ ๊ตฌ๋
์ ํด์ ํ๋ ๋ก์ง์ ์ ๊ณตํด์ผ ํฉ๋๋ค.
setInterval
์ด๋ ์์ผ ์ฐ๊ฒฐ๊ณผ ๊ฐ์ ์ด๋ค ๊ตฌ๋
์ด๋ ์ง ๋ง์
๋๋ค.
useState
ํ
์์ ์
๋ฐ์ดํธ๋๋ ์ํ์ ๊ด๋ จ๋๋ ํจ์๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํ์ง๋ง๋ผ์๋ก์ด ํ์๋ค์ด ํ๋ก์ ํธ ๊ตฌํ์ ์์ํ๊ธฐ ์ ์ ์ ๊ฐ ํญ์ ํ๋ ํ ๋ง๋๊ฐ ์์ต๋๋ค.
๋๋ฌด ์ด๋ฅธ ์ต์ ํ๋ ๋ชจ๋ ์ ์ ๊ทผ์์ด๋ค. - Donald Knuth
๊ทธ๋ฌ๋ ๋๋๋ก ํ์๋ค์ด ๊ฐ๋ฐ ๊ณผ์ ๊ณผ ์๋ก์ด ๊ฒ๋ค์ ์์๊ฐ๋ ๊ณผ์ ์์ ๋๋ฌด ์ด์ ์ ์์ ๋ถ๋๋ผ ์ด ๋ง์ ๊น๋จน๊ณค ํฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ๋ณด๊ฒ ๋ฉ๋๋ค.
const Component1:FC = () => {
const [users, setUsers] = useState<User[]>([]);
const setUserList = useCallback(setUsers, []);
return <Component2 setUserList={setUserList}/>
}
๊ทธ๋ฌ๋ ๋ฆฌ์กํธ๋ setState
ํจ์์ ๋์ผ์ฑ์ด ์์ ์ ์ด๊ณ ๋ฆฌ๋ ๋๋ง๋ ๋ ๋ณ๊ฒฝ๋์ง ์์ ๊ฑฐ๋ผ๊ณ ๋ณด์ฅํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ต์ ํ๋ ํ์ํ์ง ์์ต๋๋ค.
๋ค๋ฅธ ํํธ์ผ๋ก๋ ์ด๋ฐ ์ ๋ค์ ๊ณ ๋ฏผํ๊ณ ์๋ ๊ฒ์ ๋ฉ์ง ์ผ์ด๊ธฐ๋ ํฉ๋๋ค.
์๋์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋๋ก ํฉ์๋ค.
type User = {
name: string,
roles: string[]
}
type UserRolesProps = {
roles: string[],
deleteRole: (role: string) => void
}
const UserRoles: FC<UserRolesProps> = React.memo(({roles, deleteRole}) => {
console.log('Render User Roles');
return (
<div>
{roles.map((role, i) =>
<span key={i} onClick={() => deleteRole(role)}>{role}</span>
)}
</div>
);
});
export const User: FC = () => {
console.log('Render User component');
const [user, changeUser] = useState<User>({name: 'Peter', roles: ['admin']});
const deleteRole = (deletedRole: string) => {
changeUser((prevUser) => ({
...prevUser,
roles: prevUser.roles.filter(role => role !== deletedRole)
}));
};
const changeName = (name: string) => {
changeUser((prevUser) => ({...prevUser, name}));
};
return (
<div>
<input value={user.name} onChange={(e) => changeName(e.target.value)}/>
<UserRoles roles={user.roles} deleteRole={deleteRole}/>
</div>
);
};
์ฝ๋ ์์น ์์ ๋ณ๊ฒฝ
User ์ปดํฌ๋ํธ์ ์์ ์ปดํฌ๋ํธ ํ๋๊ฐ ์๋๋ฐ, UserRoles๋ ์ ์ ์ ์ญํ ์๋ง ์์กดํ๊ณ ์์ต๋๋ค. ๊ฐ๋ฐ์๊ฐ UserRole์ React.memo ํจ์๋ก ๊ฐ์ธ๊ณ ์๋ค๋ ๊ฒ์ ์ฃผ๋ชฉํ์ธ์. ์ฑ๋ฅ ์ด์๋ฅผ ์ ๊ฒฝ์จ์ props๊ฐ ๋ณ๊ฒฝ๋์ง ์์์ ๋ ํด๋น ์ปดํฌ๋ํธ๋ค์ ์
๋ฐ์ดํธํ๊ณ ์ถ์ง ์์ ๊ฒ์
๋๋ค.
๊ทธ๋ฐ๋ฐ ๋ฌธ์ ๋ deleteRole์ด ์ธ๋ผ์ธ prop์ด๊ณ ๋ฆฌ์กํธ๊ฐ User ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋งํ ๋ deleteRole ํจ์์ ์ ์ธ์คํด์ค๋ฅผ ๊ณ์ ์์ฑํ๋ค๋ ๊ฒ์ ๊ฐ๊ณผํ ๊ฒ์
๋๋ค. ์ฆ user.role์ด ๋ณ๊ฒฝ๋์ง ์์์ ๋ deleteRole์ ๊ฐ ํ์๋ง๋ค ์๋ก์ด ํจ์๋ฅผ ์ฐธ์กฐํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋์ React.memo์ ๊ฐ์ธ์ ธ ์๋ ์ปดํฌ๋ํธ๋ ์๋ฏธ๊ฐ ์์ด์ง๋๋ค.
์๋ง ์ฌ๋ฌ๋ถ๋ค๋ ์ด๋ฏธ ๋ต์ ์๊ณ ๊ณ์ค ๊ฒ๋๋ค. deleteRole ํจ์๋ฅผ useCallback ํจ์๋ก ๊ฐ์ธ๋ฉด ๋๋ ๊ฒ์ด์ฃ .
export const User: FC = () => {
// skipped for brevity
const deleteRole = useCallback((deletedRole: string) => {
changeUser((prevUser) => ({
...prevUser,
roles: prevUser.roles.filter(role => role !== deletedRole)
}));
}, []);
// skipped for brevity
};
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ๊ฒฐ๊ณผ์ ๋๋ค.
๋ฉด์ ์์ 1000ms๋ง๋ค ๊ฐ์ ์ฆ๊ฐ์ํค๋ ์นด์ดํฐ์ ๊ฐ๋จํ ๊ตฌํ์ ์์ฒญํ ์ ์ด ์์ต๋๋ค. ์ข ์ข ์ ๊ฐ ๋ณด๋ ์ฝ๋๋ฅผ ๋ณด์์ฃ .
function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <h1>{count}</h1>;
}
์ฌ๋ฌ๋ถ๋ ์์ํ๋ฏ์ด, ๋ผ์ธ 6์์ count ๊ฐ์ ํจ์ ํด๋ก์ ์์ ๊ฐ์ ธ์ค๋ฏ๋ก ํญ์ 0์ ๊ฐ์ ธ์ต๋๋ค. ๊ฐ 1000ms๋ง๋ค ๊ฐ์ ์ฆ๊ฐ์ํค๋ ค๊ณ ํจ์๋ ๋ง์
๋๋ค. ํ๋ฉด์์ ์ฐ๋ฆฌ๋ 0๊ณผ 1000ms ํ์๋ 1์ ๊ณ์ ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค. ์นด์ดํฐ๋ ์ ๋ ์ฆ๊ฐ์ํค์ง ์์ต๋๋ค.
๋ฆฌ์กํธ์์ ํจ์ํ ์ปดํฌ๋ํธ๊ฐ ์ค์ ๋ก ์ด๋ป๊ฒ ์๋ํ๋์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด์ฃ . code sandbox๋ฅผ ์ฐธ๊ณ ํ์ธ์
์ํ ๊ฐ ๋ณ๊ฒฝ์ ๋น๋๊ธฐ ์์ ์ฒ๋ผ ์ฒ๋ฆฌํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด๋ณด๊ฒ ์ต๋๋ค.
export default function Counter() {
let [count, setCount] = useState(0);
useEffect(() => {
let id = setInterval(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearInterval(id);
}, []);
return <h1>{count}</h1>;
}
setCount(count + 1)
๋์ ์ setCount((count) => count + 1
์ ์ฌ์ฉํ์ต๋๋ค.
์ด ๊ฐ์ ํจ์ ํด๋ก์ ๊ฐ ์๋ ์ด์ ์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ์ํ์์ ๊ฐ์ ธ์ค๋ ๊ฐ์
๋๋ค.
๋ค๋ฅธ ํฅ๋ฏธ๋ก์ด ์ผ์ด์ค๊ฐ ์์ต๋๋ค.
const Task02 = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount(count + 1);
setCount(count + 1);
}
return (
<div>
Count: {count}
<div>
<button onClick={onClick}>Increment twice</button>
</div>
</div>
)
}
๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ํ๊ฐ์ด 2๋ฒ ์ฆ๊ฐํ ๊ฑฐ๋ผ๊ณ ์์ํ์ง๋ง ์ค์ ๋ก๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ๊ฐ ๋ฒํผ์ ํด๋ฆญํ ๋ ์ค์ง 1๋ง ์ฆ๊ฐ๋ ๋ฟ์
๋๋ค.
React๋ ๊ฝค ๋๋ํด์ ๊ฐ ์์
์ ๋๊ธฐ์ ์ผ๋ก ์์ฑ์ํค์ง ์์ต๋๋ค. ๋ฐฐ์น์์ ์ฌ๋ฌ ์ํ๊ฐ ๊ฐฑ์ ์ ๋ชจ์ผ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก๋ ์๋์ฒ๋ผ ์๋ํฉ๋๋ค.
Object.assign(
prevState,
{ count: prevState.count + 1 },
{ count: prevState.count + 1 }
)
๊ทธ๋์ ์ฐ๋ฆฌ์ ์์๋๋ก ์๋ํ๋๋ก ํ๋ ค๋ฉด ๋น๋๊ธฐ ์์ ์ผ๋ก ์ทจ๊ธํ์ฌ ์๋์ฒ๋ผ ์์ ํด์ผ ํฉ๋๋ค.
const Task02 = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((count) => count + 1);
setCount((count) => count + 1);
}
return (
<div>
Count: {count}
<div>
<button onClick={onClick}>Increment twice</button>
</div>
</div>
)
}
๊ฒฝํ์ ์ผ๋ก ๋น์ถ์ด ๋ดค์ ๋ ๋ฆฌ์กํธ๊ฐ ์ํ๋ฅผ ๋๊ธฐ์ ์ผ๋ก ์
๋ฐ์ดํธํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๊ทธ๋์ ๋ง์ ๊ฒฝ์ฐ์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ง ์์ ์ ์์ผ๋ฉฐ ์ธ์ ๋ ๋น๋๊ธฐ์ ์ผ๋ก ์ํ ๊ฐฑ์ ์ ์ ์งํ ์๋ ์์ต๋๋ค.
์ด๋ React๊ฐ ๊ฐฑ์ ํ๋ ๋ฐฉ๋ฒ์ด๊ณ ์๋ฌด๋ ์ด์ ๋ํด ๋ฐ๋ํ์ง ์๊ฒ ๋๋ฌธ์
๋๋ค.
๋ฐฐ์ฐ๊ธฐ ์์ํ ๋ ์๋ง ์ฌ๋ฌ๋ถ์ ๋ฆฌ์กํธ๊ฐ ๋ช
๋ นํ๋ณด๋ค ์ ์ธํ ํ๋ก๊ทธ๋๋ฐ์ ๊ณ ์ํ๋ค๊ณ ๋ค์ผ์
จ์ ๊ฒ๋๋ค. ๋๋๋ก ๊ทธ ๋์ ์ฐจ์ด๋ฅผ ์ดํดํ๊ธฐ ์ํด ์ค์ ์ด ํ์ํฉ๋๋ค. ์ฌ์ ํ useRef ํ
์ ๋ง์ด ์ฌ์ฉํ๊ณ ์๋ค๋ฉด ์ฌ๋ฌ๋ถ์ ์๋ง ์ด ๊ท์น์ ์๋ฐํ๋ฉฐ ์ ์ธํ์์ ๋ช
๋ นํ ์ ๊ทผ๋ฒ์ผ๋ก ๊ด์ ์ด ๋ฐ๋ ๊ฒ์
๋๋ค.
๊ธด ์ฝ๋ ์ค๋ํซ์ ๋ณผ๊น์. codesandbox
export const App: FC = () => {
const inputGroupRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
const handleFocus = () => inputGroupRef.current!.classList.add(styles.active);
const handleBlur = () => inputGroupRef.current!.classList.remove(styles.active);
inputRef.current!.addEventListener('focus', handleFocus);
inputRef.current!.addEventListener('blur', handleBlur);
return () => {
inputRef.current!.removeEventListener('focus', handleFocus);
inputRef.current!.removeEventListener('blur', handleBlur);
}
}, []);
return (
<div className={styles.container}>
<div ref={inputGroupRef} className={styles.inputGroup}>
<label className={styles.label}>
Your name
</label>
<input
ref={inputRef}
className={styles.input}
type="text"
/>
<div className={styles.border}/>
</div>
</div>
)
};
์ด ์ฝ๋๋ ๊ฝค ๋ณ๋ก์ธ ๊ตฌํ์ด๋ค์. ์ฝ๋๋ฅผ ๋ณด๋ jQuery๊ฐ ๋ช
๋ นํ ๋ฐฉ์๊ณผ ํจ๊ป ์ด์์์๋ค๋ ๊ฒ์ด ์๊ฐ๋๋ค์.
์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๋ช
๋ นํ์ผ๋ก ๋ณ๊ฒฝ์ํค๋ฉฐ DOM ํธ๋์ง์
์ ํจ๊ณผ์ ์ผ๋ก ์ํํ๋ React์ ํ์ ์ฌ์ฉํ๊ณ ์์ง ์์ต๋๋ค.
๊ฐ๋ฐ์์ ์๋๋ ๊ฐ input๋ง๋ค ์ปดํฌ๋ํธ์ CSS ํด๋์ค๋ฅผ ๋ณ๊ฒฝ์ํค๊ณ ์ ํ๋ ๊ฒ์ด์๋๋ฐ์.
์ฐ๋ฆฌ๋ useRef์ ์ฌ์ฉ์ ์ ๊ฑฐํด์ ์ ์ธํ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์ฌ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
export const App: FC = () => {
const [isActive, changeState] = useState(false);
return (
<div className={styles.container}>
<div className={isActive ? '${styles.inputGroup} ${styles.active}' : styles.inputGroup}>
<label className={styles.label}>
Your name
</label>
<input
onFocus={() => changeState(() => true)}
onBlur={() => changeState(() => false)}
className={styles.input}
type="text"
/>
<div className={styles.border}/>
</div>
</div>
);
};
๊ฒฝํ์ ์ผ๋ก ์ฌ๋ฌ๋ถ์ ๊ฐ๋ฅํ๋ฉด ๋ ํผ๋ฐ์ค ํธ์ถ์ ์ฌ์ฉํ๋ ๊ฒ์ ํผํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด useRef ํ
์ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ์ ๋ํ 3๊ฐ์ง ์ข์ ์ด์ ์
๋๋ค.
์๋ฌธ '4 Essential Tips for Better Asynchronous Code in JavaScript'
์๋ก์ด ํ๋ก๊ทธ๋๋ฐ ๊ธฐ์ ์ ๋ฐฐ์ฐ๋ ๊ฒ์ ์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ "์๋ํ๋ ๊ฒ"์ ๋์ด "๋ ์" ์๋ํ๊ฒ ๋ง๋๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ํ ๋๊ฐ์ ์ดํ๋ฆฌ์ผ์ด์ ๋ง ๋ง๋ค์ด ๋ดค๊ฑฐ๋ callback, promise, async/await ๋ฑ์ผ๋ก ๋น๋๊ธฐ ํธ์ถ์ ํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์์์ง๋ผ๋ ๋น๋๊ธฐ ์ฝ๋๋ฅผ ์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์๊ฒ๋๋ ๊ฑด ์ธ์ ๋ ์ฌ๋ฌ๋ถ์๊ฒ ์ ์ฉํ๊ฒ ์ฐ์ผ ๊ฒ์ ๋๋ค.
์ ํฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ฑ๊ธ ์ค๋ ๋๋ฅผ ์ ๋ค๋ฃจ๊ณ ํจ์จ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ํ "๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ 201" ํ๊ณผ ํธ๋ฆญ์ ์์ ์ ํจ๊ป ๊ณต์ ๋๋ฆด ๊ฒ์ ๋๋ค. "์๊ฐ/์ฝ๋ฐฑ ์ง์ฅ์ ์์"์ ํผํ๊ณ ์ต๊ทผ์ ์ฌ์ฉ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋น๋๊ธฐ ํจํด์ ์ง์คํ๊ณ ์ ๋น๋๊ธฐ ์ฝ๋์ ์ญ์ฌ๋ฅผ ์์๋ณด๊ฒ ์ต๋๋ค.
๊ฐ await
์ async
ํจ์๋ก ๊ฐ์ธ๊ณ fakeFetch()
์ ๋ค๋ฅธ ์ด๋ค ๊ณณ์ ์ ์๋์ด ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
๊ฐ Promise๋ค์ fetchFile(file)
์ ์ฐ์๋ง์ GET ์์ฒญ์ ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ๋น ๋ฆ
๋๋ค. ๋ฐ๋ฉด์ await
์ promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ํจ์์ ์คํ์ ์ค๋จํฉ๋๋ค. ๋ถํ์ํ ๊ธฐ๋ค๋ฆผ์ ์ ๊ฑฐํ๊ณ , ๋ ๋น ๋ฅธ promise๋ฅผ ์ฌ์ฉํ๊ณ , ํ๋์ฉ ๋ณด๋ด์ง ์๊ณ ํ๋ฒ์ ์ฌ๋ฌ ํ์ผ์ ๋ํ ์์ฒญ์ ๋ณด๋์ผ๋ก์จ ์ฝ๋๋ฅผ ๋ ํจ์จ์ ์ด๊ณ ๋น ๋ฅด๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
์๋ก์ด Promise๋ฅผ ๋ฐ๋ค๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋์ค์ ๋ฐ์ผ๋ฉด ๋ฉ๋๋ค. ์๋ ์ฝ๋ ์์ ์์ ์ธ ํ์ผ์ ๋์์ fetchํ๊ณ ๋ฐ์ promise๋ ๋์ค์ ์ธ์ ๊ฐ(await
)์์ resolve ๋์ด์ ธ์ผ ํฉ๋๋ค.
// fake fetch function returning a new Promise object
const fetchFile = (file) => new Promise(resolve => fakeFetch(file, resolve))
// ํ๋์ฉ ๋ณ๋ ฌ์ ์ผ๋ก ๋ชจ๋ ํ์ผ์ ๋ํด ์์ฒญ์ ๋ณด๋
const promise1 = fetchFile('file1')
const promise2 = fetchFile('file2')
const promise3 = fetchFile('file3')
// ๋์ค์ ๊ธฐ๋ค๋ฆฌ๊ธฐ
const file1 = await promise1
Promise ๊ฐ์ฒด์๋ ์ฌ๋ฌ promise๋ฅผ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ ๋ฐฉ๋ฒ๋ค์ด ํฌํจ๋์ด ์์ผ๋ฏ๋ก ์ฌ๋ฌ ํ์ผ์ ๋์์ fetchํ ์ ์๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Promise.all()
์ ๋ณ๋ ฌ์ ์ผ๋ก ํ์ผ์ ์์ฒญํ๊ณ ๊ฐ์ ๋ผ์ธ์์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค
. ๋ฐ๋ก ๊ฐ์ ์ป์ ์ ์์ด์!
// ๊ฐ์ ๊ธฐ๋ค๋ฆฌ์ง๋ง ๊ฐ ์์ฒญ์ ๋ณ๋ ฌ์ ์ผ๋ก ๋ณด๋ด์ง๋ ์ค
const fileArray = await Promise.all([fetchFile('file1'), fetchFile('file2'), fetchFile('file3')])
๋๋ฌด ๋ง์ ๋ณ๋ ฌ ์์ฒญ์ (ํนํ ํฐ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๋ ์ํฉ์์) ๋์ ์ฑ๋ฅ์ ์ผ๊ธฐ์ํฌ ์ ์์์ ๊ธฐ์ตํด์ผ ํฉ๋๋ค.
์ฝ๋์์ ๋ฐ์ดํฐ๋ผ๋ฆฌ ์์กด์ฑ์ด ์์ ๋ ์ด์ promise์ resolve๋ ๊ฒฐ๊ณผ๊ฐ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ํ์ผ๋ค์ ์์ฐจ์ ์ผ๋ก ๋ฐ์์ผ ํ๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค. ์๋ ์ฝ๋ ์์ ์์ file2
์ ๋ํ fetch ์์ฒญ์ ์ฒ์์ ๋ณด๋ธ fetchFile()
ํธ์ถ์ด file1
์ ํจ๊ป resolve๋์ด์ก์ ๋ ๋ณด๋ผ ์ ์์ต๋๋ค. ๋์์ ์์ฒญ์ ๋ณด๋ด๋ ์ด์ ์์ ์ ๋นํ๋ฉด ๊ฝค ๋๋ฆฝ๋๋ค. ๊ฐ ๋ณ์๋ค์ promise๋ฅผ ์ฐธ์กฐํ์ง ์๊ณ ํ์ผ์ ์ฐธ์กฐํฉ๋๋ค.
// ์์ฐจ์ ์ผ๋ก ์์ฒญ์ ๋ณด๋
const file1 = await fetchFile('file1') // resolve ๋ ๋๊น์ง ์ ์ง
const file2 = await fetchFile('file2')
const file3 = await fetchFile('file3')
์๋ ์์ ๋ ์์ฐจ์ ์ผ๋ก ์์ฒญ์ ๋ณด๋ด์ผ ํ๋ ๊ฒฝ์ฐ์
๋๋ค. order๋ฅผ fetchํ๋ ค๋ฉด fetchUser()
Promise๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค.
const user = await fetchUser()
const userOrders = await fetchOrders(user)
ํต์ฌ ํ : ๋ ๋ฆฝ์ ์ธ ๋น๋๊ธฐ ์์ ๋ค์ ๋ณ๋ ฌ ์์ฒญ์ ์ฌ์ฉํ์ฌ ์๊ฐ ๋ฐ ์ฑ๋ฅ์ ๋ญ๋นํ์ง ๋ง์.
์ ์์ ์์๋ ๊ฐ์ ธ์ฌ ํ์ผ์ ์๋ฅผ ์ ํํ ์๋ ์ํฉ์์ ํด๋น ์๋งํผ์ promise๋ฅผ ์คํํ์ต๋๋ค. ์์์ ๊ธธ์ด์ ํ์ผ์ fetchํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
์ ์๋์ง ์์ ๊ธธ์ด์ ์งํฉ์ผ๋ก ์์
ํ ๋ Javascript๋ array์ array method๋ฅผ ์ฌ์ฉํฉ๋๋ค. promise๋ฅผ ๋ฆฌํดํ๊ณ promise์ fileNames
๋ฐฐ์ด์ ๊ฐ์ ๋งคํํ๋ map()
๊ณผ fetchFile()
์ ์ฌ์ฉํ์ฌ promise์ ๋ฐฐ์ด์ ๋ง๋ค ์ ์์ต๋๋ค.
// fake fetch function returning a new Promise object
const fetchFile = (file) => new Promise(resolve => fakeFetch(file, resolve))
// ์์์ ๊ธธ์ด๋ฅผ ๊ฐ์ง๋ ๋ฐฐ์ด
const fileNames = ['file1', 'file2', 'file3'/* ... */]
// Promise ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ ์ฝ๋ฐฑ์ ๊ฐ์ง promise ๋ฐฐ์ด ์์ฑ
const promises = fileNames.map(fetchFile)
์ผ๋จ promise๋ค์ ๋ฐฐ์ด๋ก ์์๋ ๋ค์ ๋ฃจํ๋ฅผ ๋๋ฉด์ promise๋ฅผ ์คํํ ์๋ ์๊ณ , Promise.all()
๊ณผ ๊ฐ์ ์ดํฐ๋ฌ๋ธ์ ๋ฐ๋ Promise ๊ฐ์ฒด ๋ฉ์๋์ ์ ๋ฌํ ์๋ ์์ต๋๋ค.
ํต์ฌ ํ : ๋ง์ promise๋ฅผ ๋ค๋ฃฐ ๋, promise๋ฅผ ๋ฐฐ์ด์ ์ ์ฅํ๋ผ.
์๋ฌธ : How Netflix Scales its API with GraphQL Federation (Part 1)
๋ทํ๋ฆญ์ค๋ ๋ฃจ์ฆํ ๊ฒฐํฉ๊ณผ ํ์ฅ์ฑ์ด ๋ฐ์ด๋ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ผ๋ก ์๋ ค์ ธ ์์ต๋๋ค. ๋ ๋ฆฝ์ ์ธ ์๋น์ค๋ฅผ ํตํด ์๋ก ๋ค๋ฅธ ์๋๋ก ๋ฐ์ ํ๋ฉฐ ๋ ๋ฆฝ์ ์ผ๋ก ํ์ฅ์ํฌ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋ฌ ์๋น์ค์ ๊ฑธ์ณ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ๋ณต์ก์ฑ์ ๊ฐ์ค์ํค๊ธฐ๋ ํฉ๋๋ค. UI ๊ฐ๋ฐ์์๊ฒ 100๊ฐ์ง์ ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ๋ ธ์ถ์ํค๋ ๋์ ๋ทํ๋ฆญ์ค๋ ์ฃ์ง์์ ํตํฉ๋ API ๊ณ์ธต์ ์ ๊ณตํฉ๋๋ค.
UI ๊ฐ๋ฐ์๋ ํฐ ๋๋ฉ์ธ์ ๋ํ ํ๋์ ๊ฐ๋ ์ ์ธ API๋ก ์์ ํ๋ ๋จ์ํจ์ ๊ต์ฅํ ์ข์ํฉ๋๋ค. ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ API ๊ณ์ธต์ด ์ ๊ณตํ๋ ๋์ปคํ๋ง๊ณผ ํ์ฑ์ ์ข์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์ ๋น์ฆ๋์ค๊ฐ ํ์ฅ๋จ์ ๋ฐ๋ผ, ๋น ๋ฅด๊ฒ ํ์ ํ๋ ์ฐ๋ฆฌ์ ๋ฅ๋ ฅ์ด ๋ณด์ด์ง ์๋ ์ ๊ทผ์ ์ ๊ฐ๊น์์ก์ต๋๋ค. ๊ฐ๋ฐ์ ์๊ฐ ์ฆ๊ฐํ๊ณ ๋๋ฉ์ธ ๋ณต์ก์ฑ์ด ์ปค์ง์ ๋ฐ๋ผ API ์งํฉ์ฒด ๊ณ์ธต์ ๊ฐ๋ฐํ๋ ๊ฒ์ ๋์ฑ ์ด๋ ค์์ก์ต๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด API ๊ณ์ธต์ ๊ฐํํ๋ ์ฐํฉ๋(federated) GraphQL ํ๋ซํผ์ ๊ฐ๋ฐํ์ต๋๋ค. ์ด๋ ํ์ฅ์ฑ ๋ฐ ์ด์์ฑ๊ณผ ๊ฐ์ ์ฐจ์๋ค์ ์ต์ํํ๋ฉฐ ๋ง์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ฐ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ทํ๋ฆญ์ค ์คํ๋์ค ์ํ๊ณ์์ ์ด ์ ๊ทผ๋ฒ์ ์ฑ๊ณต์ ์ผ๋ก ๊ตฌ์ถํ์ผ๋ฉฐ ๋ค๋ฅธ ๋๋ฉ์ธ์์ ๋์ํ ์ ์๋ ์ฌ๋ฌ ํจํด๊ณผ ์ ์ฉ๋ค์ ํ์ฌํ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ์๊ฐ์ ์ฃผ๊ณ ๋ค๋ฅธ ๊ณณ ๋ํ ์ ์ฉ ๊ฐ๋ฅ์ฑ์ ๋ํ ๋ํ๋ฅผ ์ฅ๋ คํ๊ณ ์ ์ด์ผ๊ธฐ๋ฅผ ๋๋๊ณ ์ ํฉ๋๋ค.
Netflix๋ ๊ต์ฅํ ๋น ๋ฅด๊ฒ ์ค๋ฆฌ์ง๋ ์ปจํ ์ธ ๋ฅผ ์ ์ํ๊ณ ์์ต๋๋ค. TV ์ผ๋ ์ํ๊ฐ ๋ทํ๋ฆญ์ค์์ ๋ฐฉ์๋ ๋๊น์ง ์์ฃผ ๋ง์ ์ผ๋ค์ด ์ผ์ด๋๊ณ ์์ต๋๋ค. ์ด๋ ์ค์นด์ฐํธ, ์บ์คํ ๋ฟ๋ง ์๋๋ผ ๊ฑฐ๋์ ๊ณ์ฝ ํ์, ์ ์, ์๊ฐ ํจ๊ณผ์ ์ ๋๋ฉ์ด์ , ์๋ง๊ณผ ๋๋น ๋ฑ์ ํฌํจํ์ฌ ์์ฃผ ๋ง์ ๊ฒ๋ค์ด ์กด์ฌํฉ๋๋ค. ์คํ๋์ค ์์ง๋์ด๋ง์ ์ด ์ํฌํ๋ก์ฐ๋ค์ ๊ฐํํ๋ ์๋ฐฑ๊ฐ์ง์ ์ดํ๋ฆฌ์ผ์ด์ ๊ณผ ํด์ ์ ์ํฉ๋๋ค.
๋ช ๋ ์ ์ผ๋ก ๋์๊ฐ๋ณด๋ฉด, ์คํ๋์ค ๊ณต๊ฐ์์์ ํ ๊ฐ์ง ๋ฌธ์ ์ ์ ๋ฐ์ดํฐ์ ๋ฐ์ดํฐ ๊ด๊ณ๋ค์ ์ฆ๊ฐํ๋ ๋ณต์ก์ฑ์ด์์ต๋๋ค. ์์์ ์ค๋ช ํ ์ํฌํ๋ก์ฐ๋ ์ฐ๊ฒฐ๋์ด ์์ผ๋ ๋ฐ์ดํฐ์ ๋ฐ์ดํฐ ๊ด๊ณ๋ ์ฌ๋ฌ ๋ง์ดํฌ๋ก์๋น์ค๋ก ๋ถ์ฐ๋์ด ์กด์ฌํ์ต๋๋ค. ํ๋ก๋ํธ ํ์ ๋ ๊ฐ์ง ๊ตฌ์กฐ์ ํจํด์ผ๋ก ์ด๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
๋จ ํ๋์ ๊ฒฐํฉ๋ ๋ ์ด์ด : ๋ฃจ์ฆํ๊ฒ ๊ฒฐํฉ๋์๊ธฐ ๋๋ฌธ์ ๋ง์ ํ๋ค์ด ์ค๋ณต๋๋ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๊ฐ์์ ํ๋ก๋ํธ ๋์ฆ์ ๋ฐ๋ผ ์ฌ๋ฌ ๊ฒฐํฉ ๋ ์ด์ด๋ฅผ ์์ฑํ๋ ๋ฐ ๋ง์ ์๊ฐ์ ์๋ชจํ์ต๋๋ค. ์ด๋ BFF๋ฅผ ํตํด UI ํ์ด๋ ๋ฏธ๋ํฐ์ด ์๋น์ค์ ๋ฐฑ์๋ ํ์ ์ํด ์ํ๋์์ต๋๋ค.
๋ค๋ฅธ ํ์ ๋ฐ์ดํฐ์ ๋ํ ๊ตฌ์ฒดํ๋ ๋ทฐ(materialized views) : ์ด๋ค ํ๋ค์ ์์คํ ์ ์๊ตฌ์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ ๋ฐ์ดํฐ์ ๊ตฌ์ฒดํ๋ ๋ทฐ๋ฅผ ๊ตฌ์ถํ๋ ํจํด์ ์ฌ์ฉํ์ต๋๋ค. ๊ตฌ์ฒดํ๋ ๋ทฐ๋ ์ฑ๋ฅ์์ ์ด์ ์ ๊ฐ์ง์ง๋ง ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์์ด์๋ ๋ถ์กฑํ์ต๋๋ค. ์ฌ๋ฌ ์คํ๋์ค ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฅด๋ ์ผ๊ด๋์ง ์์ ๋ฐ์ดํฐ๋ 2018๋ ์คํ๋์ค ์์ง๋์ด๋ง์์ ๊ฐ์ฅ ๋จผ์ ๋ค๋ฃจ์ด์ผ ํ๋ ๋ฌธ์ ์ ์ด์์ต๋๋ค.
Graph API : ๊ทผ๋ณธ์ ์ธ ํ์์ฑ์ ๋ ์ ๋ค๋ฃจ๊ธฐ ์ํด, ์ฐ๋ฆฌ ํ์ "Studio API"๋ผ๊ณ ๋ถ๋ฆฌ๋ ํ๋ ์ด์ graph API๋ฅผ ์ ์ํ๊ธฐ ์์ํ์ต๋๋ค. ๋ชฉํ๋ ๋ฐ์ดํฐ์ ๊ด๊ณ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋๋ก ํต์ผ๋ ์ถ์ํ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด์์ต๋๋ค. Studio API๋ ํต์ฌ์ ์ธ ๊ณต์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๊ธฐ ์ํด ์ ์ฉ์ฑ์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ์ ์ธ API ๊ธฐ์ ์ธ GraphQL์ ์ฌ์ฉํ์ต๋๋ค. Studio API์ ์ปจ์๋จธ๋ ๊ทธ๋ํ๋ฅผ ํ์ํ๊ณ ๋ ๋น ๋ฅด๊ฒ ์๋ก์ด ๊ธฐ๋ฅ์ ์ ์ํ ์ ์์์ต๋๋ค. ๋ํ GraphQL์ ๋ชจ๋ ํ๋๋ค์ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ํ๋์ ์ฝ๋๋ก ํด๊ฒฐ๋์์ผ๋ฏ๋ก ๋ค๋ฅธ UI ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ ์ ์ ๋ฐ์ดํฐ ๋ถ์ผ์น๋ฅผ ๊ด์ฐฐํ ์ ์์์ต๋๋ค.
Studio API์์ ๋ ธ์ถ๋๋ ํ๋์ ๊ทธ๋ํ๋ ์์ฒญ๋ ์ฑ๊ณต์ ๊ฑฐ๋์์ต๋๋ค. ํ๋ก๋ํธ ํ๋ค์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ฝ๊ณ ์ผ๊ด๋๋ ๋ฐ์ดํฐ ์ ๊ทผ์ ์์ฃผ ์ข์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ฌด์ํ ๋ง์ ์ปจ์๋จธ์ ๊ทธ๋ํ๊ฐ ์์ฑํ๋ ๋๋์ ๋ฐ์ดํฐ ๋๋ถ์ ๋ณ๋ชฉํ์์ ๋ถ๋ชํ๊ฒ ๋์์ต๋๋ค.
๋จผ์ Studio API ํ์ ๋๋ฉ์ธ ์ ๋ฌธ๊ฐ์ ํ๋ก๋ํธ ๋์ฆ๋ก๋ถํฐ ์ฐ๊ฒฐ์ด ๋๊น์ผ๋ก์จ ์คํค๋ง์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์ณค์ต๋๋ค. ๋ ๋ฒ์งธ๋ก ๋ฐฑ์๋์ ์๋ก์ด ์์๋ค๊ณผ Graph API๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ์ ์๋์ด์๊ณ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ๊ฐ ๋ณด์ฅํ๋ ๋น ๋ฅธ ์งํ๋ฅผ ๋ฐฉํดํ์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก ํ๋์ ์์ ํ์ด ํ๋๋๋ ๊ทธ๋ํ์ ๋ํ ์ด์๊ณผ ์ง์์ ๋ด๋นํ๋ ๊ฒ์ ๋งค์ฐ ๊ฐ๋นํ๊ธฐ ์ด๋ ค์ด ์ผ์ด์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค๊ณ ์๊ฐํ์ต๋๋ค. ํ๋๋ก ํต์ผ๋๋ฉด์ ๋์ปคํ๋ง๋๊ณ ํ๋ ์ดํธ๋๋ฉฐ ๋น ๋ฅด๊ฒ ์์ง์ด๋ ๊ฒ์ด์ฃ .
์ด ๋ณ๋ชฉํ์์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง์ดํฌ๋ก์๋น์ค์ ๋ชจ๋ ธ๋ฆฌ์ค๋ฅผ ๋ถํดํ ์ฌ๋ฌ ์ด์ผ๊ธฐ๋ค์ ๊ธฐ๋์ต๋๋ค. Studio API์ ํ๋๋ก ํต์ผ๋ GraphQL ์คํค๋ง๋ฅผ ์ ์งํจ๊ณผ ๋์์ ๋ฆฌ์กธ๋ฒ์ ๊ตฌํ์ ๊ฐ ๋๋ฉ์ธ ํ์ผ๋ก ๋น์ค์ํํ๊ณ ์ ํ์ต๋๋ค.
2019๋ ์ด ์๋ก์ด ์ํคํ ์ฒ์ ๋ํด ๋ธ๋ ์ธ์คํ ๋ฐํ๊ณ ์์ ๋ Apollo๋ GraphQL Federation ๋ช ์ธ๋ฅผ ๋ฐํํ์ต๋๋ค. ์ด๋ ๋ถ์ฐ๋ ์ค๋์ญ๊ณผ ๊ตฌํ๊ณผ ํจ๊ป ํ๋์ ์คํค๋ง์ ์ด์ ์ ์ฝ์ํ์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ํ๋ฉฐ ์คํ์ ํ ์คํธ ๊ตฌํ์ ์๋ํ๊ณ GraphQL Federation ๋ฏธ๋์ ๋ํด ์ํด๋ก์ ํ์ ํ๋ ๊ฒ์ ๋๋ฌํ์ต๋๋ค. ์ฐ๋ฆฌ์ ๋ค์ ์ธ๋ ๊ตฌ์กฐ์ธ "Studio Edge"๋ federation์ ์ค์ํ ์์๋ก ํ์ฌ ๋ฑ์ฅํ์ต๋๋ค.
GraphQL Federation์ ๋ชฉํ๋ ๋ ๊ฐ์ง์ ๋๋ค. ์ปจ์๋จธ์๊ฒ ํ๋์ API๋ฅผ ์ ๊ณตํ๋ฉฐ ๋ฐฑ์๋ ๊ฐ๋ฐ์์๊ฒ๋ ์ ์ฐํจ๊ณผ ์๋น์ค์ ๋ ๋ฆฝ์ฑ์ ์ฃผ๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ๋ฌ์ฑํ๊ณ ์ ์คํค๋ง๋ ์์ฑ๋๊ณ ์ด๋ป๊ฒ ์์ ๊ถ์ด ๋ถ์ฐ๋์๋์ง ์๋ ค์ฃผ๋๋ก ์ค๋ช ์ด ํ์ํฉ๋๋ค. ์ธ ๊ฐ์ง ์ํฐํฐ์ ํจ๊ป ์์๋ฅผ ์ดํด๋ด ์๋ค.
์ธ ๋๋ฉ์ธ์ ์ธ ๊ฐ์ ๋ถ๋ฆฌ๋ ์์ง๋์ด๋ง ํ์ด ์์ ํ๋ฉฐ ๊ฐ ํ์ ๊ฐ์์ ๋ฐ์ดํฐ ์์ค๋ ๋น์ฆ๋์ค ๋ก์ง, ์์ํ๋ ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ๋ด๋นํฉ๋๋ค. ์ฐํฉ๋์ง ์์ ๊ตฌํ์์๋ Studio API ํ์ด ์์ ํ๋ฉฐ ๊ตฌํํ๋ ์คํค๋ง์ ๋ฆฌ์กธ๋ฒ๋ฅผ ๊ฐ์ง ๊ฒ์ ๋๋ค. GraphQL ํ๋ ์์ํฌ๋ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์ ๊ด๋ฒ์ํ ์ํ๋ฅผ ํตํด ํด๋นํ๋ ๋ฆฌ์กธ๋ฒ๋ฅผ ํธ์ถํ๋๋ก ์กฐ์ ํฉ๋๋ค.
์ฐํฉ๋๋ ๊ตฌ์กฐ๋ก ์ ํํ๊ธฐ ์ํด ํตํฉ๋ ์คํค๋ง๋ฅผ ํฌ์์ํค์ง ์๊ณ ๊ฐ ๋ฆฌ์กธ๋ฒ๋ค์ ์์ ๊ถ์ ๊ฐ ๋ด๋นํ๋ ๋๋ฉ์ธ์ผ๋ก ์ฎ๊ฒจ์ผ ํ์ต๋๋ค. ๊ทธ๋ฌ๊ธฐ ์ํด Movie ํ์ ์ GraphQL ์๋น์ค ๋ฐ์ด๋๋ฆฌ๋ก ํ์ฅํด์ผ ํ์ฃ .
Movie ํ์ ์ GraphQL ์๋น์ค ๋ฐ์ด๋๋ฆฌ๋ก ํ์ฅํ๋ ๊ฒ์ด ๊ธฐ๋ฅ์ Movie ํ์ ์ Federated Type์ผ๋ก ๋ง๋ญ๋๋ค. ์ฃผ์ด์ง ํ๋๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ ๊ฒ์ดํธ์จ์ด ๊ณ์ธต์ผ๋ก๋ถํฐ ์์ ๋๋ฉ์ธ ์๋น์ค๋ก ์์ํ๋ ๊ฒ์ด ํ์ํฉ๋๋ค.
ํ์ ์ ์ฐํฉํ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ํ์ต๋๋ค.
**Domain Graph Service (DGS)**๋ ๋ ๋ฆฝ์ ์ด๋ฉฐ ๊ท๊ฒฉ์ ์ค์ํ๋ GraphQL ์๋น์ค์ ๋๋ค. ๊ฐ๋ฐ์๋ ๊ฐ์์ ์ฐํฉ๋ GrpahQL ์คํค๋ง๋ฅผ DGS์์ ์ ์ํฉ๋๋ค. API์ ์ธ๋ถํญ๋ชฉ์ ๋ด๋นํ๋ ๋๋ฉ์ธ ํ์ DGS๋ฅผ ์์ ํ๊ณ ์ด์ํฉ๋๋ค. DGS ๊ฐ๋ฐ์๋ ๊ธฐ์กด ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ DGS๋ก ์ ํํ ๊ฒ์ธ์ง ์์ ์๋ก์ด ์๋น์ค๋ฅผ ์คํ์ ํ ๊ฒ์ธ์ง ์์ ๋กญ๊ฒ ๊ฒฐ์ ํฉ๋๋ค.
Schema Registry๋ ๋ชจ๋ DGS์ ๋ํด ๋ชจ๋ ์คํค๋ง์ ์คํค๋ง ๋ณ๊ฒฝ์ฌํญ์ ์ ์ฅํ๋ ์ํ๊ฐ ์๋ ์ปดํฌ๋ํธ์ ๋๋ค. ๊ฐ๋ฐ์ ํด๊ณผ CI/CD ํ์ดํ๋ผ์ธ์์ ์ฌ์ฉ๋๋ ์คํค๋ง์ ๋ํ CRUD API๋ฅผ ๋ ธ์ถํฉ๋๋ค. ๊ฐ๋ณ์ ์ธ DGS ์คํค๋ง์ ๊ฒฐํฉ๋ ์คํค๋ง ๋ชจ๋์ ๋ํด ์ ํจ์ฑ์ ํ์ธํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ๋ ์ง์คํธ๋ฆฌ๋ ํ๋์ ํตํฉ๋ ์คํค๋ง๋ฅผ ๊ตฌ์ฑํ๋ฉฐ ์ด๋ฅผ ๊ฒ์ดํธ์จ์ด์ ์ ๊ณตํฉ๋๋ค.
GraphQL ๊ฒ์ดํธ์จ์ด๋ ๊ธฐ๋ณธ์ ์ผ๋ก GraphQL ์ฟผ๋ฆฌ๋ฅผ ์ปจ์๋จธ์๊ฒ ์ ๊ณตํ๋ ์ญํ ์ ํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ฟผ๋ฆฌ๋ฅผ ๋ฐ์ ์์ ์๋ธ ์ฟผ๋ฆฌ๋ค(์ฟผ๋ฆฌํ๋)๋ก ์ชผ๊ฐ๊ณ ์ ์ ํ DGS๋ค์๊ฒ ํธ์ถ์ ํ๋ก์ฑํ์ฌ ์ฟผ๋ฆฌ ํ๋์ ์คํํฉ๋๋ค.
GrpahQL Federation์ ๊ฐํํ๋ ์ธ ๊ฐ์ง ์ฃผ์ํ ๋น์ฆ๋์ค ๋ก์ง ๊ตฌ์ฑ ์์๊ฐ ์์ต๋๋ค.
Schema Composition
Composition์ ๋ชจ๋ federated DGS ์คํค๋ง๋ค์ ๋ฐ์ ํ๋๋ก ํตํฉ๋ ์คํค๋ง๋ก ํฉํ๋ ๊ณผ์ ์ ๋๋ค. ๊ตฌ์ฑ๋ ์คํค๋ง๋ ๊ฒ์ดํธ์จ์ด์ ์ํด ๊ทธ๋ํ์ ์ปจ์๋จธ๋ค์๊ฒ ๋ ธ์ถ๋ฉ๋๋ค.
์๋ก์ด ์คํค๋ง๊ฐ DGS์ ์ถ๊ฐ๋ ๋๋ง๋ค ์คํค๋ง ๋ ์ง์คํธ๋ฆฌ๋ ๋ค์ ์ฌํญ๋ค์ ๊ฒ์ฆํฉ๋๋ค.
๋ง์ฝ ๋ชจ๋ ์กฐ๊ฑด์ด ๋ง์กฑ๋๋ฉด, ๊ทธ ์คํค๋ง๋ ์คํค๋ง ๋ ์ง์คํธ๋ฆฌ๋ก ์ฒดํฌ์ธ๋ฉ๋๋ค.
Query Planning and Execution
federation config๋ ๋ชจ๋ ๊ฐ๋ณ์ ์ธ DGS ์คํค๋ง์ ๊ตฌ์ฑ๋ ์คํค๋ง๋ก ์ด๋ฃจ์ด์ง๋๋ค. ๊ฒ์ดํธ์จ์ด๋ ์ฟผ๋ฆฌ ํ๋์ ์์ฑํ๊ธฐ ์ํด federation config์ ํด๋ผ์ด์ธํธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฟผ๋ฆฌ ํ๋์ ํด๋ผ์ด์ธํธ ์ฟผ๋ฆฌ๋ฅผ ๋ ์์ ์๋ธ ์ฟผ๋ฆฌ๋ก ์ชผ๊ฐ ๊ฒ์ธ๋ฐ ์คํ์ ์ํด DGS๋ก ๋ณด๋ด์ง๊ณ ์์ฐจ์ ์ธ ์คํ ์์์ ๋ณ๋ ฌ ์คํ ์์๋ฅผ ํฌํจํฉ๋๋ค.
์์์ ์ฐธ์กฐํ ์คํค๋ง๋ก๋ถํฐ ๊ฐ๋จํ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ ์ด๋ป๊ฒ ์ฟผ๋ฆฌํ๋์ด ์์ฑ๋๋์ง ๋ด ์๋ค.
์ด ์ฟผ๋ฆฌ์์ ๊ฒ์ดํธ์จ์ด๋ federation config๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ฌ ์ด๋ค ํ๋๊ฐ ์ด๋ค DGS์ ์๋์ง ์๊ณ ์์ต๋๋ค. ์ด ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด๋ ํด๋ผ์ด์ธํธ ์ฟผ๋ฆฌ๋ฅผ ์ธ ๊ฐ์ง ๊ฐ๋ณ์ ์ธ ์ฟผ๋ฆฌ๋ก ๋ถํดํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์ฟผ๋ฆฌ๋ Movie DGS๋ก ๋ณด๋ด์ง๋๋ฐ ๋ฃจํธ ํ๋ movies๋ ํด๋น DGS์์ ์์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด์ ๋ํ ๊ฒฐ๊ณผ๋ก ๋ฐ์ดํฐ์ ์์์ ์ฒซ 10๊ฐ์ง ์ํ๋ค์ ๋ํ movieId์ title์ ๊ฐ์ ธ์ต๋๋ค. ๊ทธ๋ฌ๊ณ ๋์ ์ด์ ์์ฒญ์์ ์ป์ movieId๋ค์ ์ฌ์ฉํ์ฌ ๊ฒ์ดํธ์จ์ด๋ 10๊ฐ์ง ์ํ์ ๋ํ production๊ณผ actors ํ๋๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด Prodction DGS์ Talent DGS์ ๋ ๋ณ๋ ฌ ์์ฒญ์ ์ํํฉ๋๋ค. ์๋ฃ๋๋ฉด ์๋ธ์ฟผ๋ฆฌ์ ์๋ต์ ํ๋๋ก ํฉ์ณ์ ธ ํธ์ถ์์๊ฒ ๊ฒฐํฉ๋ ๋ฐ์ดํฐ ์๋ต์ ๋ณด๋ ๋๋ค.
์ฑ๋ฅ์์ ์ฐธ๊ณ ํ ์ฌํญ : ์ฟผ๋ฆฌ ํ๋๋๊ณผ ์คํ์ ์ต์ ์ ๊ฒฝ์ฐ 1~10ms ์ค๋ฒํค๋๋ฅผ ๋ํฉ๋๋ค. ์ด๋ ์ฟผ๋ฆฌ ํ๋์ ์์ฑํ๊ณ DGS ์๋ต์ deserialization๊ณผ ํฉ์ณ์ง ๊ฒ์ดํธ์จ์ด ๊ฒฐ๊ณผ์ serialization์ ํฌํจํฉ๋๋ค.
Entity Resolver
์ด์ ์ฌ๋ฌ๋ถ๋ค์ ์ด๋ป๊ฒ Prodction๊ณผ Talent DGS์์ ๋ณ๋ ฌ์ ์ธ ์๋ธ ์ฟผ๋ฆฌ๊ฐ ๋์ํ๋์ง ๊ถ๊ธํ์ค ๊ฒ๋๋ค. DGS๊ฐ ์ง์ํ๋ ๊ฒ์ ์์ต๋๋ค. ์ด๊ฒ์ด ํผ์ฆ์ ๋ง์ง๋ง ์กฐ๊ฐ์ ๋๋ค.
federated ํ์ ์ธ Movie๋ก ๋์๊ฐ ๋ด ์๋ค. ๊ฒ์ดํธ์จ์ด๊ฐ DGS๋ค์ ๋๋๋ค๋ฉฐ Movie๋ฅผ ํฉ์น๋ ค๋ฉด Movie๋ฅผ ์ ์ํ๊ณ ํ์ฅํ๋ ๋ชจ๋ DGS๋ ํ๋ ์ด์์ ํ๋์ ๋ํด ํ๋ผ์ด๋จธ๋ฆฌ ํค(e.g. movieId)๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ๋์์ํค๊ณ ์ ์ํด๋ก๋ @key directive๋ฅผ ๋ช ์ธ์์ ์๊ฐํ์ต๋๋ค. ๋ํ DGS๋ค์ ์ผ๋ฐ์ ์ธ Query ํ๋์ธ _entities์ ๋ํด ๋ฆฌ์กธ๋ฒ๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. _entities ์ฟผ๋ฆฌ๋ ๋ชจ๋ federated ํ์ ๋ค์ ๋ํ ํ๋์ ํ์ ์ ๋ฐํํฉ๋๋ค. ๊ฒ์ดํธ์จ์ด๋ _entities ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ movieId๋ก Movie๋ฅผ ์ฐพ์ต๋๋ค.
์ค์ ๋ก ์ด๋ป๊ฒ ์ฟผ๋ฆฌํ๋์ด ์๊ฒจ๋์ง ์ดํด๋ด ์๋ค.
ํํ ๊ฐ์ฒด๋ movieId๋ก ์ด๋ฃจ์ด์ ธ ์๊ณ Movie DGS์ ์ฒซ ๋ฒ์งธ ์์ฒญ์ ๋ํ ์๋ต์ผ๋ก๋ถํฐ ์์ฑ๋ฉ๋๋ค. ์ฒซ 10๊ฐ์ ์ํ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ธฐ ๋๋ฌธ์ Prodction๊ณผ Talent DGS์ ๋ณด๋ผ 10๊ฐ์ ํํ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋๋ค.
์ด๋ Realy์ ๊ฐ์ฒด ์๋ณ๊ณผ ๋น์ทํ์ง๋ง ์ฝ๊ฐ์ ์ฐจ์ด์ ์ด ์์ต๋๋ค. _Entity๋ ํ๋์ union ํ์ ์ด์ง๋ง Relay์ Node๋ ์ธํฐํ์ด์ค์ ๋๋ค. ๋ํ @key๋ฅผ ์ฌ์ฉํ์ฌ ๋ณตํฉ ํค ๋ฟ๋ง ์๋๋ผ ๋ณ์ ํค ์ด๋ฆ๊ณผ ํ์ ์ ์ง์ํ ์ ์๋๋ฐ Relay์์๋ ๋จ์ผํ IDํ๋์ ๋๋ค.
ํจ๊ป ๊ฒฐํฉ๋๋ฉด, ์ด๊ฒ๋ค์ federated API ๊ตฌ์กฐ์ ํต์ฌ์ ํ์ ์ค์ด์ฃผ๋ ์์๋ค์ ๋๋ค.
์ฐ๋ฆฌ์ ์คํ๋์ค ์ํ๊ณ ๊ตฌ์กฐ๋ ๊ฐ๊ธฐ ๋ค๋ฅธ ์๋ฉด์ผ๋ก ์งํํด์๊ณ , ์์ด๋์ด์ ๊ตฌํ ์ฌ์ด์ ์๊ฐ์ ์ค์ด๋ฉฐ ๊ฐ๋ฐ์์ ๊ฒฝํ์ ํฅ์์ํค๊ณ , ์ด์์ ๊ตญ์ํ์ํค๋ ๋ฐฉํฅ์ผ๋ก ๋๊ธฐ๋ถ์ฌ๋์ต๋๋ค. ๊ตฌ์กฐ์ ์ธ ๋จ๊ณ๋ ์๋์ ๊ฐ์ต๋๋ค.
์ง๋ ๋ช๋ ๋์ ์ฐ๋ฆฌ๋ Studio Edge์์ federated API ๊ตฌ์กฐ ๊ตฌ์ฑ์์๋ค์ ๊ตฌํํ์ต๋๋ค. ์ฌ๊ธฐ๊น์ง ๋๋ฌํ๋ ค๋ฉด ๋น ๋ฅธ ๋ฐ๋ณต, ๋ง์ ๋ถ์๊ฐ์ ํ์ , ๋ช ๊ฐ์ง์ ํผ๋ฒ๊ณผ ์ง์์ ์ธ ํฌ์๊ฐ ํ์ํฉ๋๋ค. ํ์ฌ 70๊ฐ์ง์ DGS๋ฅผ ๊ฐ์ง๋ฉฐ ์๋ฐฑ๋ช ์ ๊ฐ๋ฐ์๊ฐ ์๋๋ฐ Studio Edge ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ค์ ๋ทํ๋ฆญ์ค ํ ํฌ ๋ธ๋ก๊ทธ ํฌ์คํ ์์๋ ์ ์ฒด์ ์ธ ํด๊ฒฐ์ฑ ์ ๊ตฌ์ถํ๋๋ฐ ํ์ํ ๊ต์ฐจ์ ์ธ ๊ด์ฌ์ฌ๋ฅผ ํฌํจํ์ฌ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๊ฒ๋ค์ ๋ํด ๊ณต์ ํ ๊ฒ์ ๋๋ค.
์๋ฌธ : Welcome to the World of 'NFTs'
๋ถ์ : What are Non Fungible Tokens & Why are they becoming so popular?
์ต๊ทผ, NFT๋ก ์ธํด ๋์งํธ ์์งํ์ ์ธ๊ธฐ๊ฐ ํญ๋ฐ์ ์ผ๋ก ์ฆ๊ฐํ๊ณ ์์ต๋๋ค. ์๋ง NFT์ ๋ํด ์ด์ผ๊ธฐํ๋ ์ฌ๋๋ค์ SNS ํผ๋์์ ๋ณด์
จ์ ๊ฒ๋๋ค.
NFT ์์ฅ์ด ์ปค์ง์ ๋ฐ๋ผ ์์ , ์์
, ๊ฒ์, ๊ธ์ต์ฐ์
์ด ๋ค์งํ๊ณ ์์ต๋๋ค. NFT๋ฅผ ์ฒ์ ๋ฃ๋ ์ฌ๋๋ค์ ์ดํดํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ NFT๊ฐ ๋ฌด์์ธ์ง ์ดํด๋ณด๊ณ ์ ๊ฐ์๊ธฐ ์ธํฐ๋ท์์ ์ฐจ์ธ๋ ์ํ์ด ๋๊ณ ์๋์ง ์์๋ด
์๋ค.
NFT์ ๋ํด ์์์ผ ํ ๊ฒ๋ค์ ๋ชจ๋ ๋ณด๊ฒ ์ต๋๋ค. ๐
์๋ง ์ฌ๋ฌ๋ถ๋ค์ ํธ์ํฐ์ ๊ณต๋ ์ค๋ฆฝ์์ด์ CEO์ธ Jack Dorsey์ ์ ๋ช
ํ ํธ์์ ์๊ณ ์์ ๊ฒ๋๋ค.
๊ทธ๋ ์์ ์ ์ฒซ ๋ฒ์งธ ํธ์์ NFT๋ก ํ๋งคํ๊ณ ์์ต๋๋ค.
์ด ํธ์์ด ๋ณด๊ณ ์ ํ๋ค๋ฉด ๋๊ตฌ๋ ๋ฌด๋ฃ๋ก ๋ณผ ์ ์๋ ์ด ๋์งํธ ์์ดํ ์ด ๊ณต๊ฐ์ ์ผ๋ก ์ด์ฉ์ด ๊ฐ๋ฅํจ์๋ ๋ถ๊ตฌํ๊ณ , 3์ 6์ผ ๊ธฐ์ค์ผ๋ก ์ด ํธ์์ ๋ํด ๊ฐ์ฅ ๋๊ฒ ์ ์ํ ๊ธ์ก์ด 250๋ง ๋ฌ๋ฌ๊ฐ ๋์์ต๋๋ค. ๐คฏ
์ฌ๋ฌ๋ถ์ด ๊ตฌ๋งคํ๋ ๊ฒ์ ์ด ํธ์์ ๋์งํธ ์ฆ๋ช ์ ์ธ๋ฐ, ์์ฑ์์ ์ํด ๊ฒ์ฆ๋์๊ณ "์ ์ผํ๊ฒ" ์ด ์ฐ์ฃผ์ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ๋ถ์ด ๊ตฌ๋งคํ๋ ๊ฒ์ ๊ณ ์ ํ ์์ดํ ์ด ๋ฉ๋๋ค.
NFT(Non-Fungible Tokens)๋ ๋์ฒด ๋ถ๊ฐ๋ฅํ ํ ํฐ์ผ๋ก ๋ธ๋ก์ฒด์ธ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ ๊ณ ์ ํ๊ฒ ํน์ ๋ฏธ๋์ด ์กฐ๊ฐ์ ๋ํ๋ด๋ ๊ธฐ๋ก์
๋๋ค.
๋ฏธ๋์ด๋ ๋์งํธ๋ก ๋ ์ด๋ค ๊ฒ์ด๋ ๋ ์ ์์ต๋๋ค. "๋์ฒด ๋ถ๊ฐ๋ฅํ๋ค๋" ๊ฒ์ ๊ทธ ์กฐ๊ฐ์ด ๊ณ ์ ํ๋ฉฐ ์ด๋ ํ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋์ฒด ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ฐ๋ฆฌ์ ๋ฒ์ ์ธ ํ๊ธ์ ๋์ฒด๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ๋ค๋ฅธ ๊ฒ์ผ๋ก ๊ตํํ ์ ์์ผ๋ฉฐ ๋์ผํ ๊ฐ์น๋ฅผ ๊ฐ์ง ์ด๋ค ๊ฒ์ผ๋ก ๊ฐ์ง ์ ์์ต๋๋ค.
์ด๋ฌํ ์์ดํ
๋ค์ ์์ ๊ถ์ ๋ธ๋ก์ฒด์ธ์ ํตํด ๊ธฐ๋ก๋ฉ๋๋ค. NFT๋ ์ด๋๋ฆฌ์์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ํธํํ์ ๋์ผํ ๋ธ๋ก์ฒด์ธ ๋ก๊ทธ์ ๋ณด๊ด๋์ด ์์ต๋๋ค.
๋๊ตฌ๋ ๋ณผ ์ ์๊ณ ๊ฐํํ ์ ์๋ ์คํ ๋ง์ผ์ ์ ๋ํฌํ ์์งํ๋ค๊ณผ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ค์ง ํ ์ฌ๋๋ง์ด(๋๋ ์ํธํํ ์ง๊ฐ)๋ง์ด ์ฃผ์ด์ง ์๊ฐ์ ์์ ํ ์ ์์ต๋๋ค.
NFT๋ ์ง๋ ํ ๋ฌ๋์ 3์ต ๋ฌ๋ฌ ์ด์์ ๋งค์ถ์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ์ต๊ทผ ๋ง์ ๊ด์ฌ์ ๋ฐ๊ณ ์์ต๋๋ค. ๐ฐ ๊ฐ NFT๋ ๊ณ ์ ํ๊ณ ๋ณต์ ๋ ์ ์์ผ๋ฉฐ ํฌ์์ฑ ์๋๋ก ์ค๊ณ๋์์ต๋๋ค.
๋ฐ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ NFT๋ ๋ณต์ ๋ ์ ์๋ ๋ฌด์ธ๊ฐ๋ฅผ ์ฌ๋ฌ๋ถ์๊ฒ ์ฃผ๋๋ก ์ค๊ณ๋ฉ๋๋ค. ๊ทธ๊ฑด ๋ฐ๋ก ์์ ๋ฌผ์ ์์ ๊ถ์ ๋๋ค. (๋ฌผ๋ฆฌ์ ์ธ ์์ ์ํ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ํฐ์คํธ๊ฐ ์ฌ์ ํ ์ ์๊ถ๊ณผ ์ฌ์์ฐ๊ถ์ ๊ฐ์ง๊ณ ์๋คํด๋ ๋ง์ ๋๋ค.) ๋ฌผ๋ฆฌ์ ์ธ ์์ ํ ์์ง์ ๊ด์ ์์ ๋ณด์๋ฉด, ๋๊ตฌ๋ ๋ชจ๋ค ํํ๋ฅผ ๊ตฌ๋งคํ ์ ์์ง๋ง ์๋ณธ์ ํ ์ฌ๋๋ง ์์ ํ ์ ์๋ ๊ฒ์ด์ฃ .
๋จ์ํ ์ด๋ฏธ์ง๋ ๋๋ก์์ด ์๋๋ผ๋ ๊ฒ์ ์ดํดํ๋ ๊ฒ ์ค์ํฉ๋๋ค. ๋ธ๋ก์ฒด์ธ์ ๋ ํนํ๊ฒ ๋ง๋๋ ๊ฒ์ ๋ธ๋ก์ฒด์ธ์ ๋์งํธ ๊ฐ์ฒด๋ก์์ ์กด์ฌ์ ๋๋ค.
์ผ๋ฐ์ ์ธ ์ํธํํ์ ๋ค๋ฅด๊ฒ, NFT๋ ์ง์ ์ ์ผ๋ก ๋ค๋ฅธ ๊ฒ๊ณผ ๊ตํ๋ ์ ์์ต๋๋ค. ๋ ๊ฐ์ NFT๋ ๋์ผํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๋ค๋ฅธ ์์ฐ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ์์์ ๊ณต๊ธ์ ๊ฐ๊ฒฉ์ ๊ฒฐ์ ํ๋ ๋ฐ ์ค์ํ ์ด์ ์
๋๋ค. NFT์ ํฌ์์ฑ์ผ๋ก ์ธํด ์ฌ๋๋ค์ NFT์ ๋ง์ ๋์ ์ง๋ถํ ์ค๋น๊ฐ ๋์ด ์๋ ๊ฒ๋๋ค.
NFT๊ฐ ์ธ๊ธฐ ์๋ ๋ ๋ค๋ฅธ ์ด์ ๋ ์ค์ํ๋ ์์ ํ๋ซํผ(ex. ์ ํ๋ธ)์ด ์ฐฝ์์์ ํฌ๋ค์ ์ฐ๊ฒฐํ๋ ์ฐ์ธํ ๋ฐฉ๋ฒ์ด ๋์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ์์ ์ฐฝ์์์ ๋๋ถ๋ถ ์์ ์ ์์ฒ์ ๊ด๊ณ ์ธ ๊ฒ์ด์ฃ . ํ๋ซํผ์ ์ฐฝ์์์ ์๋น์ ์ฌ์ด์ ํ๋ซํผ ์์ฒด์ ์ถ์ฒ ์๊ณ ๋ฆฌ์ฆ์ ์ฝ์ ํจ์ผ๋ก์จ ์์ ๋ค์ ์์ ์ ์งํค๋ฉด์ ์ค๊ฐ์๊ฐ ๋ ์ ์๋๋ก ํ์ต๋๋ค. NFT๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ๋ถ์ ์ด๋ฌํ ์ค๊ฐ์๋ฅผ ์์ ํ ์ ๊ฑฐํ ์ ์๊ณ , ์ฐฝ์์์๊ฒ ๊ทผ๋ณธ์ ์ผ๋ก ๋ ๋์ ๊ฒฝ์ ์ฑ์ ์ ๊ณตํ์ฌ ๊ณ ๊ฐ ๊ตฌ์ ๋น์ฉ์ 0์ ๊ฐ๊น๊ฒ ์ค์ผ ์ ์์ต๋๋ค.
์ฌ๋๋ค์ด ๋์งํธ ์ํ์ ์ฌ๊ณ ํ ์ ์๊ฒ ํ๋ NFT ์ค์ฌ์ผ๋ก ๋ง๋ค์ด์ง ์์ฅ๋ค์ด ์ฌ๋ฟ ์์ต๋๋ค. MakersPlace.com, SuperRare.co, ๊ทธ๋ฆฌ๊ณ Rarible.com์ ๋์งํธ NFT ์์ ์ํ์ ํนํ๋ ์ฌ์ดํธ๋ค์ ๋๋ค. Grimes, partner of Elon Musk, mother to X ร A-12๋ "Nfty Gateway"๋ฅผ ํตํด NFT๋ฅผ ํ๋งคํ์ง๋ง ๋ค๋ฅธ ๊ฒ๋ค๋ ๋ง์ด ์์ต๋๋ค.
Dragon the CryptoKitty๋ ์ด ์ฐ์ฃผ์์ ๊ฐ์ฅ ๋น์ผ ๊ฐ์น๋ฅผ ์ง๋ NFT ์ค ํ๋์ธ๋ฐ, ๋๋ต 600์ด๋๋ฆฌ์์ ๊ฐ์น๋ฅผ ๊ฐ์ง๋๋ค.
๋๊ตฌ ์คํ LeBron James์ NBA ํ์ท ๋์งํธ ์์ง ์นด๋๋ 10๋ง ๋ฌ๋ฌ์ ํ๋งค๋์์ต๋๋ค.
NFT ๊ธฐ๋ฐ ๊ฒ์์ธ Axie Infinity์ Angel์ธ Axie๋ 300 ์ด๋๋ฆฌ์์ ํ๋งค๋์ต๋๋ค.
NFT๋ ์ฌ์ ํ ์์ฃผ ์๋กญ์ต๋๋ค. ํ๋์ ์ฐ์ ์ผ๋ก์ ๊ธฐ์ ๊ฐ์ ์ ์ํด ํด์ผ ํ ์ผ์ด ๋ง์ต๋๋ค. ์ฌ์ ํ ์ฐ๋ฆฌ๊ฐ ์ง๋ฉดํ๊ณ ์๋ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ๊ต์ฅํ ๋ง์ ํธ๋์ญ์ ์ ์ง์ํ ์ ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ง๋๋ ๊ฒ์ ๋๋ค. NFT๋ ์์ง ์๋์ ์ผ๋ก ๋ฉ์ธ์คํธ๋ฆผ ์ฌ์ฉ์๋ค์ด ์ ๊ทผํ ์ ์๋๋ฐ์. ํ์ฌ๋ ์ผ๋ฆฌ์ด๋ตํฐ๋ ํฌ์์๋ง์ด ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํ๋ซํผ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ NFT์ ์ง์ ์ฅ๋ฒฝ์ ๋ฎ์ถ์ด์ผ ํฉ๋๋ค.
๋ํ ๋น์ค์ํ ์ดํ๋ฆฌ์ผ์ด์ ๋ณด๋ค ์ค์ํ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ ์ฝ๊ฒ ํ์ฅํ ์ ์๋ ์ ๋ํ ๊ทน๋ณตํด์ผ ํ ์ฅ์ ๋ฌผ์ด ๋ฉ๋๋ค. ์ด ๋ํ ์ฐ๋ฆฌ๊ฐ ์ ๊ทน์ ์ผ๋ก ํด๊ฒฐํ๊ณ ์๋ ๋ฌธ์ ์ ๋๋ค.
๋ฐํ
์ ์ก
ํ๋งค
์ ์
๋ค์์ ์ถ๊ธ๊ถ์๋ ์ด๋ป๊ฒ ํ ๊ฒ์ธ์ง์ ๋ํ ๊ณ ๋ ค ๋ถ์กฑ
RoyaltyRouter
: ๋ชจ๋ ์ถ๊ธ๊ถ์ ์กฐํํ ์ ์๋ ์ปจํธ๋ํธ, ์ถ๊ธ๊ถ ์กฐํ๋ฅผ ์ํด ์ด ์ปจํธ๋ํธ๋ง ์๋ฉด ๋จFixedPriceExchange
> ํ๋ถ ์ฒ๋ฆฌ๋ฅผ ์ํ Escrow
์ปจํธ๋ํธ ํ์2021๋ 7์ 28์ผ์ ์์ฑ๋ Using BLoC Pattern with React์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์ฒ์์ BLoC(Business Logic Component) ํจํด์ ๊ตฌ๊ธ์ด ํ๋ฌํฐ ์ฑ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก ์๊ฐํ์ต๋๋ค.
์ด ํจํด์ ์ปดํฌ๋ํธ์์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌํจ์ผ๋ก์จ UI ์ปดํฌ๋ํธ์ ์ํฌ๋ก๋๋ฅผ ์ค์ฌ์ค๋๋ค.
์๊ฐ์ด ์ง๋๋ฉฐ ๋ค๋ฅธ ํ๋ ์์ํฌ ๋ํ BLoC ํจํด์ ์ง์ํ๊ธฐ ์์ํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๊ธ์์๋ ๋ฆฌ์กํธ์์ BLoC ํจํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ด์ผ๊ธฐ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
BLoC ํจํด ๋ค์ ์๋ ๊ฐ๋
์ ๊ฐ๋จํฉ๋๋ค. ์์์ ๋ณผ ์ ์๋ฏ์ด UI ์ปดํฌ๋ํธ์์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌํฉ๋๋ค.
๋จผ์ ์ต์ ๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ BLoC์ ์ด๋ฒคํธ๋ฅผ ๋ณด๋
๋๋ค. ๊ทธ ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ฉด UI ์ปดํฌ๋ํธ๋ค์ BLoC์ ์ต์ ๋ฒ๋ธ์ ํตํด ์๊ฒ ๋ฉ๋๋ค.
์, ์ด ์ ๊ทผ๋ฒ์ ์ฌ์ฉํ ๋์ ์ฅ์ ์ ์์ธํ๊ฒ ์ดํด๋ด ์๋ค.
๋น์ฆ๋์ค ๋ก์ง์ด UI ์ปดํฌ๋ํธ๋ก๋ถํฐ ๋
๋ฆฝ์ ์ผ ๋ ์ดํ๋ฆฌ์ผ์ด์
์ ๊ฐํด์ง๋ ์ํฅ๋ ์์์ง ๊ฒ์
๋๋ค.
UI ์ปดํฌ๋ํธ์ ์ด๋ ํ ์ํฅ์ ์ฃผ์ง ์๊ณ ๋น์ฆ๋์ค ๋ก์ง์ ๋ณ๊ฒฝํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.
๋น์ฆ๋์ค ๋ก์ง์ด ํ ๊ตฐ๋ฐ์ ์๋ค๋ฉด, UI ์ปดํฌ๋ํธ๋ ์ค๋ณต๋๋ ์ฝ๋ ์์ด ๋ก์ง์ ์ฌ์ฌ์ฉํ์ฌ ์ฑ์ ๋จ์ํจ์ ์ฆ๊ฐ์ํต๋๋ค.
ํ ์คํธ์ผ์ด์ค๋ฅผ ์์ฑํ ๋ ๊ฐ๋ฐ์๋ค์ BLoC ์์ฒด์๋ง ์ง์คํ๋ฉด ๋ฉ๋๋ค. ์ฝ๋๋ฒ ์ด์ค๊ฐ ์ง์ ๋ถํด์ง์ง ์์ต๋๋ค.
์๊ฐ์ด ์ง๋๋ฉฐ ์ดํ๋ฆฌ์ผ์ด์
์๊ตฌ์ฌํญ์ ๋ณ๊ฒฝ๋ ์ ์๊ณ ๋น์ฆ๋์ค ๋ก์ง๋ ์ปค์ง๊ฒ ๋ฉ๋๋ค.
์ด๋ฐ ์ํฉ์์ ์ฝ๋๋ฒ ์ด์ค์ ๋ช
๋ฃํจ์ ์ ์งํ๊ณ ์ ๊ฐ๋ฐ์๋ค์ ์ฌ๋ฌ BLoC๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
๊ฒ๋ค๊ฐ BLoC ํจํด์ ํ๋ซํผ์ด๋ ํ๊ฒฝ์ ์ข ์๋์ง ์์ ๊ฐ๋ฐ์๋ค์ ๋ค์ํ ํ๋ก์ ํธ์์ ๋์ผํ BLoC ํจํด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
BLoC ํจํด์ ์ฌ์ฉ์ฑ์ ์ ์ฆํ๊ณ ์ ์์ ์นด์ดํฐ ์ฑ์ ๋ง๋ค์ด๋ด ์๋ค.
๋จผ์ ๋ฆฌ์กํธ ์ฑ์ ์์ฑํด์ผ ํฉ๋๋ค. ์ ๋ ์ด ์ฑ์ bloc-counter-app์ด๋ผ ์ด๋ฆ ์ง๊ฒ ์ต๋๋ค. ๋ํ rxjs
๋ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
// Create React app
npx create-react-app bloc-counter-app
// Install rxjs
yarn add rxjs
๊ทธ ํ ํ์์๋ ์ฝ๋๋ฅผ ๋ชจ๋ ์ง์ฐ๊ณ ์๋ ๋ชฉ๋ก์ ๋ฐ๋ผ ๊ตฌ์กฐ๋ฅผ ๋ง๋ญ๋๋ค.
์ด์ BLoC ํด๋์ค๋ฅผ ๊ตฌํํด๋ด
์๋ค. BLoC ํด๋์ค๋ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ด๋ จ๋ ๋ชจ๋ subject๋ฅผ ๊ตฌํํ๋ ์ญํ ์ ํฉ๋๋ค.
์ด ์์์์๋ ์นด์ดํฐ ๋ก์ง์ ๋ํ ์ญํ ์ ์ํํ์ฃ .
bloc ๋๋ ํ ๋ฆฌ ๋ด์ CounterBloc.js
๋ผ๋ ํ์ผ์ ์์ฑํ๊ณ pipe๋ฅผ ์ฌ์ฉํ์ฌ UI ์ปดํฌ๋ํธ์ ์นด์ดํฐ๋ฅผ ์ ๋ฌํ์ต๋๋ค.
import { Subject } from 'rxjs';
import { scan } from 'rxjs/operators';
export default class CounterBloc {
constructor() {
this._subject = new Subject();
}
get counter() {
return this._subject.pipe(scan((count, v) => count + v, 0));
}
increase() {
this._subject.next(1);
}
decrease() {
this._subject.next(-1);
}
dispose() {
this._subject.complete();
}
}
ํด๋์ค์๋ ๊ฐ๋จํ ๋ก์ง๋ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฑ์ ์ฌ์ด์ฆ๊ฐ ์ปค์ก๋๋ฐ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌํ์ง ์์์ ๋ ์ผ๋ง๋ ๋ณต์กํ ์ง ์์ํด๋ณด์ธ์.
์ด ๋จ๊ณ์์ UI๋ก๋ถํฐ ์ค๋ ์นด์ดํฐ ์์ฒญ์ ๋ค๋ฃจ๊ธฐ ์ํด utils ๋๋ ํ ๋ฆฌ ๋ด์ StreamBuilder.js
ํ์ผ์ ์์ฑํฉ๋๋ค.
๊ฒ๋ค๊ฐ ๊ฐ๋ฐ์๋ค์ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๊ณ customer ํธ๋ค๋ฌ๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค.
class AsyncSnapshot {
constructor(data, error) {
this._data = data;
this._error = error;
this._hasData = data ? true : false;
this._hasError = error ? true : false;
}
get data() {
return this._data;
}
get error() {
return this._error;
}
get hasData() {
return this._hasData;
}
get hasError() {
return this._hasError;
}
}
AsyncSnapshot
ํด๋์ค ๋ด์์ ์์ฑ์๋ฅผ ์ด๊ธฐํํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ณ , ์๋ฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด ์์ ์์๋ ์ค๋ช
์ ์ฝ๊ฒ ํ๊ธฐ ์ํด ๋จ์ํ ๋ฐ์ดํฐ๋ง ๋ฆฌํดํฉ๋๋ค.
class StreamBuilder extends Component {
constructor(props) {
super(props);
const { initialData, stream } = props;
this.state = {
snapshot: new AsyncSnapshot(initialData),
};
stream.subscribe(
data => {
this.setState({
snapshot: new AsyncSnapshot(data, null),
});
}
);
}
render() {
return this.props.builder(this.state.snapshot);
}
}
์ด๊ธฐ ๋ฐ์ดํฐ๋ AysncSnapshot
์ ์ ๋ฌ๋์ด ๊ฐ ๊ตฌ๋
๋ง๋ค ์ค๋
์ท ์ํ ๋ด์ ์ ์ฅ๋ฉ๋๋ค.
๊ทธ ํ UI ์ปดํฌ๋ํธ ๋ด์์ ๋ ๋๋ ๊ฒ์
๋๋ค.
import { Component } from 'react';
class AsyncSnapshot {
constructor(data) {
this._data = data;
}
get data() {
return this._data;
}
}
class StreamBuilder extends Component {
constructor(props) {
super(props);
const { initialData, stream } = props;
this.state = {
snapshot: new AsyncSnapshot(initialData),
};
stream.subscribe(
data => {
this.setState({
snapshot: new AsyncSnapshot(data, null),
});
}
);
}
render() {
return this.props.builder(this.state.snapshot);
}
}
export default StreamBuilder;
์ฃผ์ : UI ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ ๋ ๋ ๋ชจ๋ ์ต์ ๋ฒ๋ธ๋ก๋ถํฐ ๊ตฌ๋ ์ ํด์ ํ๊ณ BLoC๋ฅผ ํ๊ธฐํด์ผ ํฉ๋๋ค.
increase()
์ decrease()
๋ฉ์๋๋ค์ UI ์ปดํฌ๋ํธ ๋ด์์ ๋ฐ๋ก ํธ์ถ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ถ๋ ฅ ๋ฐ์ดํฐ๋ stream builder์ ์ํด ๋ค๋ค์ง๋๋ค.
์๋ฌ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ปค์คํ ํธ๋ค๋ฌ๋ฅผ ๊ตฌํํ๋ ์ค๊ฐ ์ธต์ ๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
import { Fragment } from 'react';
import StreamBuilder from '../utils/StreamBuilder';
const Counter = ({ bloc }) => (
<Fragment>
<button onClick={() => bloc.increase()}>+</button>
<button onClick={() => bloc.decrease()}>-</button>
<lable size="large" color="olive">
Count:
<StreamBuilder
initialData={0}
stream={bloc.counter}
builder={snapshot => <p>{snapshot.data}</p>}
/>
</lable>
</Fragment>
);
export default Counter;
app.js
ํ์ผ์์ BLoC๋ CounterBloc
ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ด๊ธฐํ๋ฉ๋๋ค.
๊ทธ๋์ Counter
์ปดํฌ๋ํธ๋ BLoC๋ฅผ prop์ผ๋ก ์ ๋ฌํ์ฌ ์ฌ์ฉ๋ฉ๋๋ค.
// App.js
import React, { Component } from 'react';
import Counter from './components/Counter';
import CounterBloc from './blocs/CounterBloc';
const bloc = new CounterBloc();
class App extends Component {
componentWillUnmount() {
bloc.dispose();
}
render() {
return (
<div>
<Counter bloc={bloc} />
</div>
);
}
}
export default App;
์ด๊ฒ์ด ์ ๋ถ์
๋๋ค. ์ด์ ์ฌ๋ฌ๋ถ์ UI ์ปดํฌ๋ํธ ๋ฐ์์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌ๋ ์ํฐํฐ๋ก์ ์ฒ๋ฆฌํ ์ ์๊ณ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
์ด ์์ ์ฑ์ ์ฌ์ฉํ๊ณ ๊ฐ์ ์ํค๊ณ ์ถ๋ค๋ฉด ํ๋ก์ ํธ ์ ์ฅ์๋ฅผ ์ฐธ์กฐํ์๊ณ PR์ ๋ ๋ ค์ฃผ์ธ์. ๐
์ ๊ฒฝํ์ ๋น์ถ์ด ๋ณด๋ฉด, BLoC ํจํด์ ์์ ๊ท๋ชจ์ ํ๋ก์ ํธ์์๋ ์คํ๋ ค ์ค๋ฒํค๋๊ฐ ๋ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ํ๋ก์ ํธ๊ฐ ์ปค์ง์๋ก BLoC ํจํด์ ๋ชจ๋ํ๋ ์ฑ์ ๋ง๋๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ํ rxjs์ ๋ํ ๊ธฐ๋ณธ์ ์ธ ์ดํด์ ์ด๋ป๊ฒ ์ต์ ๋ฒ๋ธ์ด BLoC ํจํด์ ๊ตฌํํ๋์ง๋ฅผ ์๋ ๊ฒ์ด ํ์ํฉ๋๋ค.
์ ๋ ์ฌ๋ฌ๋ถ์๊ฒ BLoC ํจํด์ ์ฌ์ฉํ๋๋ก ์ด๋ํ์ผ๋ ๋๊ธ์์ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๊ณต์ ํด์ฃผ์ธ์.
์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค !!!
**Bit**์ ๋
๋ฆฝ์ ์ผ๋ก ์์ฑ๋๊ณ ๋ฒ์ ๊ด๋ฆฌ๋๋ฉฐ ์ ์ง๋๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ์์ ํ ๋ชจ๋ํ๋ ์ฑ์ ์์ฑํ๋๋ก ํ๋ ํ์ฅ ๊ฐ๋ฅํ ํด์
๋๋ค.
๋ชจ๋๋ฌ ์ฑ๊ณผ ๋์์ธ ์์คํ
์ ์ค๊ณํ๊ฑฐ๋ ๋ง์ดํฌ๋ก ํ๋ก ํธ์๋๋ฅผ ์์ฑํ๊ณ ์ ๊ณตํ๊ฑฐ๋ ์ฑ ์ฌ์ด์์ ์ปดํฌ๋ํธ๋ฅผ ๊ณต์ ํ ๋ ์ฌ์ฉํด๋ณด์ธ์.
2021๋ 7์ 23์ผ์ ์์ฑ๋ 5 useEffect Infinite Loop Patterns์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก, ๋ฌดํ๋ฃจํ๋ ๋์ ์ํฉ์
๋๋ค. ์ผ๋ถ ์ฃ์ง์ผ์ด์ค์์๋ ๋ฌดํ๋ฃจํ ๋ง๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ ํํ ์ ์์ ๋๊ฐ ์์ต๋๋ค.
React์ ๋ฌดํ๋ฃจํ ํจํด์ ์๊ณ ์๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ฌดํ๋ฃจํ๊ฐ ์ค๋จ ์์ด ์๋๋ ๋, ํนํ ๋ธ๋ผ์ฐ์ ๋ ์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ ๋์๊ฐ๋ ํญ์ ์ฃฝ์ผ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ์ค๋จ์ ์์ด Infinite Loop
๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์.
useEffect๋ ์ปดํฌ๋ํธ์์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ์ํํ๊ฒ ํฉ๋๋ค. React 16๋ฒ์ ์์ ์๊ฐ๋์์ ๋ ๋ค๋ฅธ ๊ฒ๋ณด๋ค ๋ ๋ง์ด ์ธ๊ธฐ๋ฅผ ๋์๋๋ฐ์. ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋์ธ componentDidMount
, componentDidUpdate
, componentWillUnmount
๋ฅผ ๊ฒฐํฉํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ด์ฃ .
useEffect๋ ์์กด์ฑ์ ์ํ ๊ฐ๋ค์ด ๋ณ๊ฒฝ๋์์ ๋๋ง ์ฝ๋ฐฑํจ์๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณ๊ฒฝ์ ์ฒดํฌํ ๋๋ ์์
๋น๊ต๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฌ๋ฌ๋ถ์ ์๋ง useEffect๋ฅผ ์์ฃผ ๊ฐ๋ ฅํ ๋๊ตฌ๋ก ์๊ฐํ ์ ์๊ณ ์ค์ ๋ก๋ ๊ทธ๋ ๊ธฐ๋ ํฉ๋๋ค.
ํ์ง๋ง ์ฌ๋ฌ๋ถ์ด ์ ๋๋ก ๋ค๋ฃจ์ง ๋ชปํ๋ฉด ์ฌ๋ฌ๋ถ์ ํ๊ดดํ ์๋ ์์ต๋๋ค.
์์กด์ฑ ์๋ useEffect๋ ๋์ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ ๋ ค๋๋ ์ด๋ ๊ฒ ์์ฑํ๋ ๊ฒ์ ์ง์ํ์ธ์.
๋ค์ ์ฝ๋์์ useEffect๋ API๋ฅผ ํ์ ํธ์ถํฉ๋๋ค.
useEffect(() => {
fetch("/api/user")
.then((res) => res.json)
.then((res) => {
setData(res);
});
});
๋ํ๋์๊ฐ ๋ณ๊ฒฝ๋์์ ๋ useEffect๊ฐ ์ฝ๋ฐฑ ํจ์๋ฅผ ํธ์ถํ ๋ ์ฌ๊ธฐ์์ ๋ฌดํ๋ฃจํ๋ฅผ ๋ง๋๊ฒ ๋ฉ๋๋ค.
๋ค๋ฅธ ๋ฌด์๋ ์๋React์ ์ข์ฐ๋ช
"state๋ props๊ฐ ๋ณ๊ฒฝ๋์์ ๋ ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง๋๋ค"๋ฅผ ํญ์ ๊ธฐ์ตํด์ผ ํฉ๋๋ค.
์ด ์ฝ๋์์ ๋คํธ์ํฌ ํธ์ถ์ด ์ฑ๊ณตํ์ ๋ setData
๋ฅผ ์ฌ์ฉํ์ฌ ์ํ ๊ฐ์ ์ค์ ํ๋๋ฐ ์ด๋ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง์ ์ผ๊ธฐ์ํต๋๋ค.
useEffect๋ ๋น๊ตํ ๊ฐ์ด ์์ผ๋ฏ๋ก ๋ ๋ค์ ์ฝ๋ฐฑ์ ํธ์ถํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ค์ fetch๋ setData
๋ฅผ ํธ์ถํ๊ณ setData
๊ฐ ํธ์ถ๋๋ฉด ์ปดํฌ๋ํธ๋ ๋ฆฌ๋ ๋๋ง๋๋๋ฐ ์ด๊ฒ์ด ๋ฐ๋ณต๋ฉ๋๋ค.
๋น ๋ฐฐ์ด๋ก ์์กด์ฑ์ ๊ตฌ์ฒดํํด์ผ ํฉ๋๋ค.
useEffect(() => {
fetch("/api/user")
.then((res) => res.json)
.then((res) => {
setData(res);
});
}, []); // <- dependencies
๊ณต์ ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด ๋ํ๋์๋ฅผ ์๋ตํ๋ ๊ฒ์ ์์ ํ์ง ์์ต๋๋ค.
useEffect๋ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ ๋ ์์ ๋น๊ต๋ฅผ ์ํํฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ์กฐ๊ฑด๋ถ ์์คํ ๋๋ฌธ์ด์ฃ . ๐
var mark1 = function(){ return ('100')}; // has a unique object reference
var mark2 = function(){ return('100')}; // has a unique object reference
mark1 == mark2; // false
mark1 === mark2; // false
๋ค์ ์ฝ๋๋ฅผ ๋ณด์์ฃ .
import React, { useCallback, useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const getData = () => {
return window.localStorage.getItem("token");
};
const [dep, setDep] = useState(getData());
useEffect(() => {
setCount(count + 1);
}, [getData]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setCount(count + 1)}>{count}</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
ํจ์ getData
๊ฐ ์์กด์ฑ ๊ฐ์ผ๋ก ์ ๋ฌ๋์์ต๋๋ค.
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ฌดํ๋ฃจํ๋ฅผ ํฌํจํ๊ณ ์๋ค๋ Maximum update depth exceeded
์๋ฌ๋ฅผ ๋ฑ์ ๊ฒ๋๋ค.
useEffect๋ ์์ ๋น๊ต๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ํจ์์ ๋ํ ์์ ๋น๊ต๋ ์ธ์ ๋ false๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ useCallback
์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
useCallback
์ ์ฝ๋ฐฑ์ ๋ฉ๋ชจ์ด์ ์ด์
๋ฒ์ ์ ๋ฐํํ์ฌ ๋ํ๋์๊ฐ ๋ณ๊ฒฝ๋์์ ๋๋ง ๋ณ๊ฒฝ๋๋ ํจ์์
๋๋ค.
const getData = useCallback(() => {
return window.localStorage.getItem("token");
}, []); // <- dependencies
๋ ๋ฐฐ์ด์ ์์ ๋น๊ต๋ ์ธ์ ๋ false๋ฅผ ๋ฆฌํดํ๋ฏ๋ก ๋ฐฐ์ด์ ์์กด๊ฐ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๋ฌดํ๋ฃจํ
๋ฅผ ๋ง๋ค์ด ๋
๋๋ค.
๋ค์ ์ฝ๋๋ฅผ ๋ณด์์ฃ .
import React, { useCallback, useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const dep = ['a'];
const [value, setValue] = useState(['b']);
useEffect(() => {
setValue(['c']);
}, [dep]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setCount(count + 1)}>{count}</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
์ฌ๊ธฐ useEffect์ ๋ํ๋์๋ก dep
์ด ์ ๋ฌ๋์์ต๋๋ค. ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ธ๋ผ์ฐ์ ์ฝ์์ ์๋ฌ๋ฅผ ๋์ง๋๋ค.
๋ ๋ฐฐ์ด์ ๋ํ ์์ ๋น๊ต๋ ์ธ์ ๋ false์ด๋ฏ๋ก useEffect
๋ ์ธ์ ๋ ์ฝ๋ฐฑ์ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
useCallback
์ ํจ์๋ฅผ ๋ฐํํ๋ฏ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด? ์ฐ๋ฆฌ๋ useRef
๋ผ๋ ๋ค๋ฅธ ํ
์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
useRef
์ ์ด๊ธฐ๊ฐ์ ๊ฐ์ง๋ .current
๊ณผ ํจ๊ป ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
import React, { useEffect, useState, useRef } from 'react';
export default function Home() {
const [value, setValue] = useState(['b']);
const {current:a} = useRef(['a'])
useEffect(() => {
setValue(['c']);
}, [a])
}
๋ ๊ฐ์ฒด์ ์์ ๋น๊ต๋ ์ธ์ ๋ false์ด๋ฏ๋ก ๋น์ฐํ๊ฒ useEffect
๋ ์ฝ๋ฐฑ์ ๊ณ์ ํธ์ถํฉ๋๋ค.
import React, { useCallback, useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const data = {
is_fetched:false
};
useEffect(() => {
setCount(count + 1);
}, [data]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setCount(count + 1)}>{count}</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
data
๋ useEffect์ ๋ํ๋์๋ก ์ ๋ฌ๋์์ต๋๋ค. ์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด ๋ธ๋ผ์ฐ์ ์ฝ์์์ ๋ฌดํ๋ฃจํ ์๋ฌ๋ฅผ ๋ฑ์ต๋๋ค.
๋ ๊ฐ์ฒด์ ์์ ๋น๊ต๋ ์ธ์ ๋ false์ด๋ฏ๋ก useEffect์ ์ฝ๋ฐฑ์ ํธ์ถํ๊ฒ ๋์ฃ .
๋ํ๋์๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์
ํ๊ฒ ๋๋ฉด ๋ฌดํ๋ฃจํ๋ฅผ ์ค๋จ์ํฌ ์ ์์ต๋๋ค. ๊ทธ๋ผ ์ด๋ป๊ฒ ํด์ผ ํ ๊น์?
๋ค, ๋ ๋ค๋ฅธ ํ
์ธ useMemo
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
useMemo
๋ ๋ํ๋์๊ฐ ๋ณ๊ฒฝ๋์์ ๋๋ง ๊ธฐ์ต๋ ๊ฐ์ ์ฌ์ฐ์ฐํฉ๋๋ค.
import React, { useMemo, useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const data = useMemo(()=>({
is_fetched:false
}), []); // <- dependencies
useEffect(() => {
setCount(count + 1);
}, [data]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={() => setCount(count + 1)}>{count}</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
์๋ชป๋ ์์กด์ฑ์ React
, ์ฌ์ง์ด javascript
์ ๊ด๊ณ๊ฐ ์์ต๋๋ค. ์๋ชป๋ ์์กด์ฑ์ด ์ฌ์ฉ๋๋ ๊ฒ์ ์ฐ๋ฆฌ์ ์ฑ
์์
๋๋ค.
import React, { useEffect, useState } from "react";
const App = () => {
const [text, setText] = useState("");
useEffect(() => {
setText(text);
}, [text]);
return null;
};
export default App;
์ด ์ฝ๋๋ฅผ ์์ ํ ์ด์ ๊ฐ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์์ ํด์ผ ํ๋ค๋ฉด ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์.
์ฃผ๋ชฉ : ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ๋ด์์ ๋ฌดํ๋ฃจํ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํ ๋ง์ ๋ฐฉ๋ฒ๋ค์ด ์์ง๋ง ์ ๋ ์ผ๋ถ๋ง ์๊ฐํ์ต๋๋ค.
์ธ์ ๋ eslint-plugin-react-hooks๋ CRA๋ฅผ ์ฌ์ฉํ์ธ์. ์ด๋ ํ๋ก๋์
์๋ฒ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ธฐ ์ ์ ์ฌ๋ฌ๋ถ๋ค์๊ฒ ์๋ ค์ค๋๋ค.
์ด๋ค ํ์ฌ๋ ๋ฌดํ๋ฃจํ ๋๋ฌธ์ ์ผ์ฃผ์ผ ๋ง์ 72k๋ฅผ ์์๋ค๊ณ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์ ๊ฐ๋ ฅํ useEffect
์๊ฒ ํน๋ณํ ์ ๊ฒฝ์ ์จ์ฃผ์ธ์.
๋ํ ๋ฆฌ์กํธ์ ๊ดํด ์ ๊ฐ ์์ฑํ ์ต๊ทผ ๊ธ๋ ๊ฐ์ด ๋ณด์๊ธธ ๋ฐ๋๋๋ค.
1. API๋ฅผ ํธ์ถํ๋ ๋์ Fetch ๋์ useQuery๋ฅผ ์ฌ์ฉํ๊ธฐ
2. API๋ฅผ ํธ์ถํ ๋ useState ๋์ useSWR๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ์ด์
3. React ์ฑ์์ Axios๋ฅผ ์ฌ์ฉํ๋ ์์ธํ ๊ฐ์ด๋
LINE Akinori Inoue๋ ๊ฐ์ฐ
ํ๋ฉด ์ ์ฒด๋ฅผ ํ๋์ skeleton์ผ๋ก ๋ฎ์ด์ฃผ๊ฒ
ํด๊ฒฐ
์ฐ๋ฆฌ๋ ๊ฐ๋น์ง(garbage)๊ฐ ๋ฌด์์ธ์ง ์๋๋ค. ๊ฐ๋น์ง๋ ๋ณธ์ง์ ์ผ๋ก ๋ ์ด์ ํ์์๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ํ๋ก๊ทธ๋๋ฐ์์ ๊ฐ๋น์ง ์ฝ๋ ์
์ด๋ ์ฌ์ฉํ๊ณ ์์ง ์๋ ๋ฐ์ดํฐ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ ๋ฆฌํ๊ณ ํด๋น ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ํ ๋ฐ์ดํฐ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ผ๋ก ์ฌํ ๋นํฉ๋๋ค. ์ด๋ ๊ฑฐ์ ๋ชจ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ๊ฐ๋น์ง ์ปฌ๋ ์
์ ๊ธฐ๋ณธ์ ์ธ ๊ณผ์ ์
๋๋ค. ์ผ๋ถ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ฐ์
ํด์ผ ํ์ง๋ง ์ด๋ค ์ธ์ด๋ค์ ์๋์ผ๋ก ์คํ๋ฉ๋๋ค. C์ธ์ด ๊ฐ์ด ์ ์์ค ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๊ฐ๋ฐ์๊ฐ ๋ ์ด์ ํ์์๋ ๋ณ์๋ ๊ฐ์ฒด๋ค์ ๋ํด malloc()
์ free()
์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ด์ฃผ์ด์ผ ํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ๋ ๊ฒ์ ๊ฐ๋ฐ์์ ํน๊ถ์ด๋ฉฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํ ๊ฒ์ธ์ง๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ ๊ฐ๋ฐ์ ์ ์์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํญ์ ๊ทธ๋ฐ ๊ฒ๋ง์ ์๋๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฐ์ด ๊ณ ์์ค ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ํ๋ก์ธ์ค๊ฐ ์๋์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์์์ ํด์ค๋๋ค.
์ด ์น์ ์์๋ ์๋ ๋ด์ฉ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ด๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ๋ ์ ์ดํดํ๊ธฐ ์ํด ๋จผ์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ์ผ๋ฐ์ ์ธ ๋ผ์ดํ์ฌ์ดํด์ ๋ณด๊ฒ ์ต๋๋ค.
๋ง์ง๋ง ๋จ๊ณ๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋ฉ์ปค๋์ฆ์ด๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ์๋์ผ๋ก ์งํ๋๋ฉฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ฐ์ฒด๊ฐ ์ํํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ์์ง์์ ์ง์ ์ฐพ์ ์๋ ์์ง๋ง ๋ง์ ๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ๋ชฉ์ ์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ๊ฐ์ํ๊ณ ํน์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ ์ด์ ํ์์๋์ง ๊ฒฐ์ ํ๋ ๊ฒ์ ๋๋ค. ๋ ์ด์ ํ์ ์๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋์ฐพ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋ฉ์ปค๋์ฆ์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ์ ํน์ ๋ธ๋ก์ด ์ ์ฉํ์ง๋ ๊ฒฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ํญ์ ๊ทผ์ฌ์น์ ๊ฐ์ ๊ฐ์ง๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋ฉ์ปค๋์ฆ์ ์๋ ๋ ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ์ ์ํด ์ ์ด๋ฉ๋๋ค.
ํ๋์ฉ ์ดํด๋ด ์๋ค.
๋จผ์ ์ฐธ์กฐ๊ฐ ๋ฌด์์ธ์ง ์ดํดํด๋ด ์๋ค. ๋ ๊ฐ์ ๊ฐ์ฒด๊ฐ ์ฃผ์ด์ก์ ๋ ํ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฉ์๋๋ ์์ฑ์ ์ ๊ทผํ ์ ์๋ ๊ฒฝ์ฐ ์ด ๊ฐ์ฒด๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๊ฐ์ ๋๋ค. ๊ทธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ฎ๊ฒจ๊ฐ์๋ค. ์ฐธ์กฐ ์นด์ดํธ ์๊ณ ๋ฆฌ์ฆ์ ๋งค์ฐ ๊ฐ๋จํ๊ณ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ํด ์ฐธ์กฐ๋๋์ง ์๋์ง์ ๋ฐ๋ผ ์ด๋ค ๊ฐ์ฒด์ ์ ์ฉ์ฑ์ ๊ฒฐ์ ํฉ๋๋ค. ์ด๋ค ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ฐธ์กฐ๋์ง ์๋๋ค๋ฉด ๊ฐ๋น์ง ๊ฐ์ผ๋ก ๊ฐ์ฃผํ๊ณ ์์งํฉ๋๋ค. ๊ฐ๋จํ ์์๋ ์๋๋ฅผ ๋ณด์ธ์.
var obj = { // first object created
property1: { // second object created
property2 : 10
}
}
๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋์๊ณ ํ ๊ฐ์ฒด๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ๋ค๋ฅธ ๊ฐ์ฒด๋ obj
๊ฐ์ฒด์ ํ ๋น๋์ด ์ฐธ์กฐ๋ฉ๋๋ค. ์ฐธ์กฐ๋ฅผ ํ๊ณ ์์ผ๋ฏ๋ก ๊ฐ๋น์ง ์ปฌ๋ ์
์ ๋ฒ์๊ฐ ์๋๋๋ค.
var newObj = obj; // ์กด์ฌํ๋ ๊ฐ์ฒด์ ๋ํ ์๋ก์ด ๊ฐ์ฒด๊ฐ ์์ต๋๋ค.
obj = 10; // `obj`๋ `newObj` ๊ฐ์ ์ํด ์ฌ์ ํ ์ฐธ์กฐ๋๋ฏ๋ก GC์ ๋์์ด ์๋๋๋ค.
๋ค๋ฅธ ๊ตฌํ์ ๋ด ์๋ค.
var anotherObj = newObj.property1;
property1
์ ๋ ๊ฐ์ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ํ๋๋ newObj
๋ณ์์ ํ๋กํผํฐ์ด๊ณ ๋ค๋ฅธ ํ๋๋ anotherObj
๋ณ์๋ก๋ถํฐ ์ฐธ์กฐ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๊ฐ๋น์ง ์ฝ๋ ์
์ ๋์์ด ์๋๋๋ค.
newObj = โSome stringโ;
obj
๋ณ์์ ์ํด ์์ฑ๋ ๊ฐ์ฒด๋ ๋ ์ด์ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ property1
์ด anotherObj
๋ณ์์ ์ํด ์ฐธ์กฐ๋๋ฏ๋ก ๊ฐ๋น์ง ์ปฌ๋ ์
์ ๋์์ด ๋์ง ์์ต๋๋ค.
anotherObj = null;
์ด์ ์ด๋์์๋ property1
๊ฐ์ฒด์ ๋ํด ์ฐธ์กฐํ์ง ์์ต๋๋ค. ์ด ์ํ์์ ๊ฐ์ฒด๋ ๊ฐ๋น์ง ์ปฌ๋ ์
์ ๋์์ด ๋ฉ๋๋ค.
์ฐธ์กฐ ์นด์ดํ ์๊ณ ๋ฆฌ์ฆ์ ๋ณธ์ง์ ์ผ๋ก ๋๋ฌด ๋์ด๋ธํด์ ์์ ํ ์์กดํ ์๋ ์์ต๋๋ค. ์๋์ ์์์ ์ฐธ์กฐ ์๊ณ ๋ฆฌ์ฆ์ ํ์ด ํฌ์ง ์์ต๋๋ค.
function foo() {
var obj1 = {};
var obj2 = {};
obj1.a = obj2;
obj2.a = obj1;
console.log(obj1);
console.log(obj2);
}
foo();
์ถ๋ ฅ๋๋ ๊ฐ์ฒด๋ฅผ ํต๊ณผํด๋ณด์ธ์. ์ค์ฒฉ๋ ์์ฑ๋ค์ด ๋ณด์ด์๋์? ์ด๋ ์ํ ์ฐธ์กฐ๋ผ๊ณ ๋ถ๋ฆฌ๋ ๊ฒ์ ๋๋ค. ์ด ๊ฒฝ์ฐ์์ ์ฐธ์กฐ ์นด์ดํ ์๊ณ ๋ฆฌ์ฆ์ ์๋ก๋ฅผ ์ฐธ์กฐํ๋ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ค์๊ฒ ์ฒ์ฐธํ๋ ์คํจํฉ๋๋ค. ๋ฐ๋ผ์ ์ด ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ์ ๋ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์ด๋ ๋ค์์ ์ดํด๋ณผ Mark and Sweep ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ด์ด์ง๋๋ค.
Mark and Sweep ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ฒด๋ค์ ๋๋ฌํ๋ ๋ฐฉ๋ฒ์ผ๋ก GC ๋ฉ์ปค๋์ฆ์ ๊ตฌํํฉ๋๋ค. ์ด๋ค ๊ฐ์ฒด๊ฐ ๋๋ฌํ ์ ์๋ ๊ฑฐ๋ผ๋ฉด ๊ฐ๋น์ง๋ก ์ธ์ํ์ฌ ์์ง๋ฉ๋๋ค. ์๊ณ ๋ฆฌ์ฆ์ ์ด๋ค ๊ฐ์ฒด๊ฐ ์ ํ ์ฐธ์กฐ๋์ง ์๋๋ค๋ฉด ๋๋ฌํ ์ ์๋ค๋ ์๋ฆฌ๋ฅผ ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์ ํด๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋น์ง๋ก ์ทจ๊ธํฉ๋๋ค.
์ด ๊ณผ์ ์ window
์ ๊ฐ์ด ๋ฃจํธ ๊ฐ์ฒด๋ฅผ ์๋ณํ๊ณ ๊ฑฐ๊ธฐ์๋ถํฐ ๋ชจ๋ ์์ ๊ฐ์ฒด๋ค, ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฒด๋ค์ ์์๋ค์ ์ํํฉ๋๋ค. ์ด ๊ณผ์ ์์ ๋๋ฌํ ์ ์๋ ์ผ๋ถ ๊ฐ์ฒด๋ค์ด ์๋ค๋ฉด ๊ทธ ๊ฐ์ฒด๋ค์ ๊ฐ๋น์ง๋ก ์์ง๋๊ณ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํด์ ํฉ๋๋ค. ์ด ์๊ณ ๋ฆฌ์ฆ์ ํจ๊ณผ์ ์ผ๋ก ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๊ฐ๋ฐ์๋ค์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ง์ ๊ฒ๋ค์ ํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํค๋ ์์ฃผ ์ผ๋ฐ์ ์ธ ์์ธ๋ค์ ์๋์ ๊ฐ์ต๋๋ค.
setInterval()
๊ณผ ๊ฐ์ ํ์ด๋จธ๋ฅผ ํด๋ฆฌ์ดํ์ง ์๋ ๊ฒฝ์ฐ๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ ์์ ๊ฐ์ ์ค์๋ค์ ํผํด์ผ๋ง ํฉ๋๋ค.
์ด ๊ธ์ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ต์ฅํ ๊ฐ๋จํ๊ฒ ๊ฐ๋น์ง ์ปฌ๋ ์ ๊ณผ์ ์ ์ดํด๋ดค์ต๋๋ค. ์ด ํ ํฝ์ ๊ต์ฅํ ๋ฐฉ๋ํ์ง๋ง ๋ ํฐ ์ง์์ ์ํ ์ถ๋ฐ์ ์ ๋๋ค.
์๋ฌธ : Making Sense of React Hooks์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์ด๋ฒ์ฃผ์ Sopie Alpert์ ์ ๋ ๋ฆฌ์กํธ ์ปจํผ๋ฐ์ค์์ "Hooks" ์ธ์ ์์ ๋ฐํํ๊ณ , Ryan Florence์ ์ฌ์ธต์ ์ธ ์ค๋ช ์ ๋ค์์ต๋๋ค.
์ ๋ Hooks proposal๋ก ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ค์ ๋ณด๊ธฐ ์ํด ์ด ์คํ๋ ํค๋ ธํธ๋ฅผ ๋ณด์๋ ๊ฒ์ ๊ฐ๋ ฅํ๊ฒ ์ถ์ฒํฉ๋๋ค. ๊ทธ๋ฌ๋ 1์๊ฐ์ ๊ฝค ํฐ ํฌ์์ด๊ธฐ ๋๋ฌธ์ ์๋์์ ๋ช ๊ฐ์ง Hooks์ ๋ํ ์๊ฐ๋ค์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค.
์ฃผ๋ชฉ : Hooks๋ ๋ฆฌ์กํธ์์ ์คํ์ ์ธ ์ ์์ ๋๋ค. ์ง๊ธ ๋น์ฅ ๋ฐฐ์ธ ํ์๋ ์์ต๋๋ค. ๋ํ ์ด ํฌ์คํ ์ ์ ์ ๊ฐ์ธ์ ๊ฒฌํด๋ฅผ ๋ด๊ณ ์์ผ๋ฉฐ ๋ฆฌ์กํธ ํ์ ์ ์ฅ์ ๋ชจ๋ ๋ฐ์ํ๋ ๊ฒ์ ์๋๋๋ค.
์ปดํฌ๋ํธ์ top-down ๋ฐฉ์์ ๋ฐ์ดํฐ ํ๋ฆ์ด ํฐ UI๋ฅผ ์๊ณ ๋ ๋ฆฝ์ ์ด๋ฉฐ ์ฌ์ฌ์ฉ๊ฐ๋ฅํ ๋จ์๋ก ๋๋ ์ ์๊ฒ ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋, ์ฐ๋ฆฌ๋ ๋ก์ง์ด ์ํ์ ์ฐ๊ด๋์ด ์๊ฑฐ๋ ํจ์๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณต์กํ ์ปดํฌ๋ํธ๋ฅผ ์ชผ๊ฐค ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๋๋๋ก ์ฌ๋๋ค์ React์์ "๊ด์ฌ์ฌ ๋ถ๋ฆฌ"๋ฅผ ํ์ง ๋ชปํ๋ค๊ณ ํ์ฃ .
์ด๋ฐ ๊ฒฝ์ฐ๋ค์ ์์ฃผ ํํ๊ณ ์ ๋๋ฉ์ด์ ์ด๋ ํผ ํธ๋ค๋ง, ์ธ๋ถ ๋ฐ์ดํฐ ์์ค์ ์ฐ๊ฒฐ๋๋ ๊ฒฝ์ฐ ๋ฑ ์ฐ๋ฆฌ๊ฐ ์ปดํฌ๋ํธ๋ก ํ๊ณ ์ถ์ ๋ง์ ๊ฒ๋ค์ ํฌํจํฉ๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ๋ฅผ ์ปดํฌ๋ํธ๋ก๋ง ํด๊ฒฐํ๋ ค๊ณ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์๊ฒจ๋ฉ๋๋ค.
์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ Hooks๋ผ๊ณ ์๊ฐํ์ต๋๋ค. Hooks๋ ์ปดํฌ๋ํธ ๋ด๋ถ์ ๋ก์ง์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ ๋ถ๋ฆฌ๋ ๋จ์๋ก ์กฐ์งํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. Hooks์ ๋ฆฌ์กํธ ์ฒ ํ(๋ช ์์ ์ธ ๋ฐ์ดํฐ ํ๋ฆ๊ณผ ๊ตฌ์ฑ)์ ์ปดํฌ๋ํธ _์ฌ์ด_๊ฐ ์๋ ์ปดํฌ๋ํธ ๋ด๋ถ์ ๋ฐ์ํฉ๋๋ค. ์ ๊ฐ Hooks๊ฐ React ์ปดํฌ๋ํธ ๋ชจ๋ธ๊ณผ ์์ฐ์ค๋ฝ๊ฒ ์ ๋ถํฉํ๋ค๊ณ ๋๋ ์ด์ ์ ๋๋ค.
props์ ๋ ๋๋ ๊ณ ์ฐจ ์ปดํฌ๋ํธ์ ๊ฐ์ ํจํด๊ณผ ๋ค๋ฅด๊ฒ Hooks๋ ์ฌ๋ฌ๋ถ์ ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ ๋ถํ์ํ ์ค์ฒฉ์ ๋ง๋ค์ง ์์ต๋๋ค. mixin์ ๋จ์ ์ผ๋ก๋ถํฐ ๊ณ ํต๋ฐ์ง ์์๋ ๋์ฃ .
(์ ๊ฐ ๊ทธ๋ฌ๋ ๊ฒ์ฒ๋ผ) ์ฌ๋ฌ๋ถ์ด ์ฒ์์๋ ๋ณธ๋ฅ์ ์ผ๋ก ๊ฑฐ๋ถํ๊ณ ์ ํ๋ค ํด๋, ์ผ๋จ์ ์๋ํด๋ณด๊ณ ๋ค๋ค๋ณด๊ธฐ๋ฅผ ๊ถํฉ๋๋ค. ์๋ง ์ข์ํ์ค ๊ฒ๋๋ค.
Hooks์ ๋ํด ์์ธํ ์์๋ณด๊ธฐ ์ ์๋ Hooks์ ์ฌ์ฉํ๋ฉด ๋ ๋ง์ ์ปจ์ ์ ๋ํด์ผ ํ๋ค๊ณ ์ฐ๋ คํ์ค ์๋ ์์ต๋๋ค. ํฉ๋ฆฌ์ ์ธ ๋นํ์ ๋๋ค. Hooks์ ๋ฐฐ์ฐ๋๋ฐ ๋จ๊ธฐ์ ์ผ๋ก๋ ์ธ์ง์ ๋น์ฉ์ด ๋ค๊ธฐ๋ ํ๊ฒ ์ง๋ง, ์ต์ข ๊ฒฐ๊ณผ๋ก๋ ๊ทธ ๋ฐ๋๊ฐ ๋ ๊ฒ์ ๋๋ค.
๋ฆฌ์กํธ ์ปค๋ฎค๋ํฐ๊ฐ Hooks๋ฅผ ์ ์์ฉํ๋ค๋ฉด, Hooks์ ๋ฆฌ์กํธ ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ๋ฉด์ ํ์ํ ๊ฐ๋ ์ ์๋ฅผ ์ค์ผ ๊ฒ์ ๋๋ค. Hooks์ ํจ์, ํด๋์ค, ๊ณ ์ฐจ ์ปดํฌ๋ํธ, props ๋ ๋ ์ฌ์ด์ ๋์์์ด ์ค์์นญํ ํ์ ์์ด ํจ์๋ง ์ฌ์ฉํ๋ฉด ๋๊ฒ๋ ํฉ๋๋ค.
๊ตฌํ ์ฌ์ด์ฆ์ ๊ด์ ์์ Hooks์ ~1.5kB๋ง ์ฆ๊ฐ์ํฌ ๋ฟ์ ๋๋ค. ํด๋์ค๋ฅผ ์์ฑํ์ฌ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ๋ณด๋ค Hooks๋ฅผ ์ฑํํ์ฌ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์ฝ๋์ ์์ ์ค์ผ ์ ์์ผ๋ฏ๋ก Hooks๋ ๊ฒฐ๊ตญ ์ฌ๋ฌ๋ถ์ ๋ฒ๋ค ์ฌ์ด์ฆ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค. ์๋ ์์๋ ๋ค์ ๊ทน๋จ์ ์ด์ง๋ง Hooks๋ฅผ ์ฑํํด์ผ ํ๋ ์ด์ ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ณด์ฌ์ค๋๋ค.
์๋ฌธ์์ ์์๊ฐ ์ฌ๋ผ์ง
Hooks๋ฅผ ์ฑํํ์ฌ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ Hooks ๊ธฐ๋ฐ์ผ๋ก ์์ฑํด๋ ํ์ฌ ์ฝ๋์ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค. ์ฌ์ค์ ์ฐ๋ฆฌ๊ฐ Hooks๋ฅผ ๊ถ์ฅํ๋ ์ด์ ๋ ์ฝ๋์ ์ฌ์์ฑ์ด ํ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ค์ํ ์ฝ๋์์ Hooks๋ก ์์ฑํ๊ณ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ด ์ข์ต๋๋ค. React 16.7 ์ํ๋ฒ์ ์ผ๋ก ์คํํด๋ณด์๊ณ ํผ๋๋ฐฑ์ด ์๊ฑฐ๋ ๋ฒ๊ทธ๊ฐ ์์ผ๋ฉด ์ ๋ณดํด์ฃผ์ ๋ค๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค.
Hooks๋ฅผ ์ดํดํ๊ธฐ ์ํด์ ํ ๊ฑธ์ ๋์๊ฐ ์ฝ๋์ ์ฌ์ฌ์ฉ์ ๋ํด ์๊ฐํด๋ณด์์ผ ํฉ๋๋ค.
์ค๋๋ ๋ฆฌ์กํธ ์ฑ์์ ๋ก์ง์ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ๊ฐ๋จํ ํจ์๋ค์ ์์ฑํด์ ๋ฌด์ธ๊ฐ๋ฅผ ์ฐ์ฐํ ๋ ํจ์๋ค์ ํธ์ถํ ์ ์์ต๋๋ค. ๋ํ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ์๋ ์์ฃ . ์ปดํฌ๋ํธ๋ ๋ ๊ฐ๋ ฅํ์ง๋ง UI๋ฅผ ๋ ๋๋งํด์ผ ํฉ๋๋ค. ์ด๋ ์๊ฐ์ ์ด์ง ์์ ๋ก์ง์ ๊ณต์ ํ ๋ ๋ถํธํฉ๋๋ค. ๊ทธ๋์ render props๋ ๊ณ ์ฐจ ์ปดํฌ๋ํธ์ ๊ฐ์ ๋ณต์กํ ํจํด์ด ๋ง๋ค์ด์ง ๊ฒ์ ๋๋ค. ๋ง์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋์ ํ๋์ ๊ณตํต์ ์ธ ์ฌ์ฌ์ฉ ๋ฐฉ๋ฒ์ด ์๋ค๋ฉด ๋ ๊ฐ๋จํ์ง ์์๊น์?
ํจ์๋ ์ฝ๋ ์ฌ์ฌ์ฉ์ ์์ด ์๋ฒฝํ ๋ฉ์ปค๋์ฆ์ผ๋ก ๋ณด์ ๋๋ค. ํจ์ ์ฌ์ด์ ๋ก์ง์ ์ด๋์ํค๋ ๊ฒ์ ์ ์ ๋ ธ๋ ฅ์ด ๋ญ๋๋ค. ๊ทธ๋ฌ๋ ํจ์ ๋ด๋ถ์์ React์ ๋ก์ปฌ state๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฝ๋๋ฅผ ์ฌ๊ตฌ์ฑํ๊ฑฐ๋ ์ต์ ๋ฒ๋ธ๊ณผ ๊ฐ์ ์ถ์ํ๋ฅผ ๋์ ํ์ง ์๋๋ค๋ฉด ํด๋์ค ์ปดํฌ๋ํธ๋ก๋ถํฐ "์๋์ฐ ์ฌ์ด์ฆ๋ฅผ ๋ณด๊ณ ์ํ๋ฅผ ์ ๋ฐ์ดํธ"ํ๊ฑฐ๋ "์๊ฐ์ด ์ง๋๋ฉด์ ๊ฐ ๋ณ๊ฒฝํ๊ธฐ"์ ๊ฐ์ ๋์์ ๊บผ๋ด์ฌ ์ ์์ต๋๋ค. ๋ ์ ๊ทผ๋ฒ์ ๋ฆฌ์กํธ์ ๋จ์ํ ์ฑ์ง์ ํด์น๊ฒ ๋์ฃ .
Hooks๋ ๊ทธ ๋ฌธ์ ๋ฅผ ์ ํํ๊ฒ ํด๊ฒฐํฉ๋๋ค. Hooks๋ ํจ์๋ก๋ถํฐ ๋ฆฌ์กํธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ฒ ํฉ๋๋ค. ๋ฆฌ์กํธ๋ ์ํ, ๋ผ์ดํ์ฌ์ดํด, ์ปจํ ์คํธ์ ๊ฐ์ "๊ตฌ์ฑ์์"๋ฅผ ๋ ธ์ถํ๋ ๋ช ๊ฐ์ง ๋นํธ์ธ Hooks๋ฅผ ์ ๊ณตํฉ๋๋ค.
Hooks๋ ์ผ๋ฐ์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ํจ์์ด๋ฏ๋ก ์ฌ๋ฌ๋ถ์ ๋ฆฌ์กํธ์์ ์ ๊ณตํ๋ ๋นํธ์ธ Hooks์ ์ฌ๋ฌ๋ถ์ "์ปค์คํ ํ "์ ๊ฒฐํฉํ ์ ์์ต๋๋ค. ์ด๋ ๋ณต์กํ ๋ฌธ์ ๋ฅผ ํ ์ค๋ก ํด๊ฒฐํ๊ณ ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ์ด๋ ๋ฆฌ์กํธ ์ปค๋ฎค๋ํฐ์ ๊ณต์ ํ ์ ์์ต๋๋ค.
์ปค์คํ ํ ์ ๊ธฐ์ ์ ์ผ๋ก๋ ๋ฆฌ์กํธ์ ๋ฏธ๋๊ฐ ์๋๋๋ค. ์ฌ๋ฌ๋ถ์ ํ ์ ์์ฑํ ์ ์๋ ๊ฒ์ Hooks์ด ์ค๊ณ๋ ๊ฒ์ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ๋ผ๊ฐ ๊ฒฐ๊ณผ๋ฌผ์ ๋๋ค.
์ปดํฌ๋ํธ๋ฅผ ํ์ฌ ์๋์ฐ width์ ๊ตฌ๋ ํ๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. (์ข์ ๋ทฐํฌํธ์ ๋ค๋ฅธ ์ปจํ ์ธ ๋ฅผ ๋ณด์ฌ์ค๋ค๊ณ ๊ฐ์ )
์ด๋ฐ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ํด๋์ค๋ฅผ ์์ฑํ๊ฑฐ๋ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ๋๋ ์ปดํฌ๋ํธ ์ฌ์ด์ ์ฌ์ฌ์ฉ์ ํ๊ณ ์ถ๋ค๋ฉด render prop, ๊ณ ์ฐจ ์ปดํฌ๋ํธ๋ ๋ฐฉ๋ฒ์ ํฌํจ๋์ฃ . ํ์ง๋ง ์ด ๋ฐฉ๋ฒ๋ณด๋ค ๋ ์ข์ ๋ฐฉ๋ฒ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
function MyResoponsiveComponent() {
const width = useWindowWidth(); // custom hook
return (
<p>window width is {width}</p>
)
}
์ด ์ฝ๋๋ฅผ ์ฝ์ผ์ ๋ค๋ฉด ๋ฌด์์ ํ๊ณ ์ ํ๋์ง ๋ฐ๋ก ์ ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ ๋ด์์ _window width_๋ฅผ ์ฌ์ฉํ๊ณ , ๋ฆฌ์กํธ๋ ํด๋น ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํฉ๋๋ค. ์ปดํฌ๋ํธ์ ์ํ๋ ์ฌ์ด๋ ์ดํํธ๊ฐ ์๋๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ์ง์ ํ ์ ์ธ์ ์ผ๋ก ๋ง๋๋ ๊ฒ์ด Hooks์ ๋ชฉํ์ ๋๋ค.
์ด ์ปค์คํ ํ ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ด ์๋ค. ํ์ฌ window width๋ฅผ ์ ์งํ๋๋ก React ๋ก์ปฌ ์ํ ๋ฅผ ์ฌ์ฉํ๊ณ , window ์ฌ์ด์ฆ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ํ ๊ฐ์ ์ค์ ํ๋๋ก ์ฌ์ด๋ ์ดํํธ ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
}
});
return wudth;
}
์์์ ๋ดค๋ฏ์ด useState ์ useEffect ์ ๊ฐ์ ๋นํธ์ธ ๋ฆฌ์กํธ Hooks๊ฐ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์๋ก ์ ๊ณต๋ฉ๋๋ค. ์ปดํฌ๋ํธ๋ก๋ถํฐ ์ง์ ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ณ useWindowWidth ๊ฐ์ ์ปค์คํ ํ ๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ปค์คํ ํ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ด์ฉ์ ์ผ๋ก ๋๊ปด์ง๋๋ค.
๋นํธ์ธ Hooks์ ๋ํด ๋ ์๊ณ ์ถ๋ค๋ฉด ์ด ๊ฐ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
Hooks์ ์์ ํ ์บก์ํ ๋์ด ์์ด, ์ฌ๋ฌ๋ถ์ด Hook์ ํธ์ถํ ๋๋ง๋ค Hook์ ์คํํ๋ ์ปดํฌ๋ํธ ๋ด์ ๋ ๋ฆฝ์ ์ธ ๋ก์ปฌ ์ํ๋ฅผ ๊ฐ์ง๋๋ค. ์ฐ๋ฆฌ ์์์์๋ ์ค์ํ์ง๋ ์์ง๋ง ์ด ํน์ง์ด Hooks๋ฅผ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ค์ด ์ค๋๋ค. ์ํ ๋ฅผ ๊ณต์ ํ๋ ๋ฐฉ์์ด ์๋๋ผ ์ํ ์ ์ฅ ๋ ผ๋ฆฌ ๋ฅผ ๊ณต์ ํ๋ ๋ฐฉ์์ ๋๋ค. top-down ๋ฐ์ดํฐ ํ๋ฆ์ ๋ง์น์ง ์์ต๋๋ค.
๊ฐ Hook์ ๋ก์ปฌ ์ํ์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ๊ฐ์ง๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํจ์๋ค ์ฌ์ด์์ ํ๋ฏ์ด ์ฌ๋ฌ Hooks ์ฌ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค. Hooks๋ ์๋ฐ์คํฌ๋ฆฝํธ ํจ์์ด๊ธฐ ๋๋ฌธ์ ์ธ์๋ฅผ ๋ฐ์ ๊ฐ์ ๋ฐํํฉ๋๋ค.
Hooks ์ฌ์ด์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ ์๋ ๊ฒ์ ์ ๋๋ฉ์ด์ , ๋ฐ์ดํฐ ๊ตฌ๋ , ํผ ๊ด๋ฆฌ, ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ์ํ ์ถ์ํ๋ฅผ ํํํ๋ ๋ฐ ์ ๋ค์ด ๋ง์ต๋๋ค. render props๋ ๊ณ ์ฐจ ์ปดํฌ๋ํธ์ ๋ค๋ฅด๊ฒ Hooks๋ ๋ ๋ ํธ๋ฆฌ์ "false hierarchy"๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค. ์ปดํฌ๋ํธ์ ๋ถ์ฐฉ๋ ํํํ "๋ฉ๋ชจ๋ฆฌ ์ " ๋ฆฌ์คํธ์ ๋ ๊ฐ๊น์ต๋๋ค. ์ถ๊ฐ์ ์ธ ๋ ์ด์ด๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค.
์ฐ๋ฆฌ์ ์๊ฒฌ์ผ๋ก๋ ์ปค์คํ ํ ์ด Hooks ์ ์์์ ๊ฐ์ฅ ๋งค๋ ฅ์ ์ธ ์์์ ๋๋ค. ๊ทธ๋ฌ๋ Hooks๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ React๋ ์ํ์ ์ฌ์ด๋ ์ดํํธ๋ฅผ ์ ์ธํ ๋ฐฉ๋ฒ์ผ๋ก ํจ์๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ useState ์ useEffect ๊ฐ ์ค์ ๋ก ํ๋ ๋ฐฉ์์ด์ฃ . ์ด ๋ฌธ์์์ ์ด Hooks์ ๋ํด ๋ ๋ฐฐ์ธ ์ ์์ต๋๋ค.
๋นํธ์ธ Hooks๊ฐ ์ปค์คํ ํ ์ ์์ฑํ ๋๋ง ์ ์ฉํ ๊ฒ์ ์๋๋๋ค. Hooks๋ ๋ํ ์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ๋ ๋ฐ ์์ด ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ์ํ์ ๊ฐ์ด ํ์ํ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํฉ๋๋ค. ๋ฏธ๋์ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ๋ ๋ฐ ์์ด Hooks๊ฐ 1์ฐจ์ ์ธ ๋ฐฉ๋ฒ์ด ๋๊ธฐ๋ฅผ ์ํ๋ ์ด์ ์ ๋๋ค.
ํด๋์ค๋ฅผ ์์จ ๊ณํ์ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ด์ค๋ถ์์๋ ๋ฌด์ํ ๋ง์ ํด๋์ค ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์๊ณ ์ด๋ฅผ ์ฌ์์ฑํ๊ณ ์ถ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ฆฌ์กํธ ์ปค๋ฎค๋ํฐ์์ Hooks๋ฅผ ๋ฐ์๋ค์ธ๋ค๋ฉด, ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋ ๋ฐ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ ํ์๊ฐ ์์ต๋๋ค. Hooks๋ ํด๋์ค์ ๋ชจ๋ ์ํฉ์ ๋ค ์ปค๋ฒํ ์ ์์ต๋๋ค. ์คํ๋ ค ์ถ์ถ, ํ ์คํ , ์ฝ๋ ์ฌ์ฌ์ฉ ๋ฉด์ ์์ด ๋ ์ ์ฐํจ์ ๋ณด์ฌ์ค๋๋ค. ๋ฆฌ์กํธ์ ๋ฏธ๋์์ Hooks๋ฅผ ์ฐ๋ฆฌ์ ๋น์ ์ผ๋ก ์ ์ํ๋ ์ด์ ์ ๋๋ค.
Hooks์ ๊ท์น์ ๋๋ผ์ จ์ ์๋ ์์ต๋๋ค.
Hooks๋ ํ ๋ ๋ฒจ์์ ํธ์ถํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ด์ง ์์ง๋ง, ๊ฐ๋ฅํ ๊ฒฝ์ฐ์๋ ์ํ๋ฅผ ์ ์ํ๊ณ ์ถ์ง ์์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํด๋์ค์์ ์ํ๋ฅผ ์กฐ๊ฑด๋ถ๋ก ์ ์ํ ์ ์๊ณ ๋ฆฌ์กํธ ์ฌ์ฉ์์๊ฒ๋ ์ด๋ฐ ๋ถ๋ง์ ๋ค์ ์ ์ ์์ต๋๋ค.
์ด๋ฌํ ์ค๊ณ๋ ์ถ๊ฐ์ ์ธ ๊ตฌ๋ฌธ์ด๋ ์ฌ๋ฌ ํจ์ ์ ๋ง๋ค์ง ์๊ณ ์ปค์คํ ํ ์ ํ์ฑํํ๋ ๋ฐ ์์ฃผ ์ค์ํฉ๋๋ค. ์ฒ์์๋ ์์ํ ์ ์์ง๋ง ๊ฒฐ๊ตญ์ Hooks๋ง์ ๊ธฐ๋ฅ์ด ๊ฐ์ง๋ ๊ฐ์น๋ก ํธ๋ ์ด๋ ์คํ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋์ํ์ง ์์ผ์ ๋ค๋ฉด ์ผ๋จ ์ฐ์ต์ผ๋ก ๊ฐ๊ณ ๋์๋ณด๋ฉด์ ๋ง์์ด ๋ฐ๋์๋์ง ํ์ธํด๋ณด์๊ธธ ๋ฐ๋๋๋ค.
์ ํฌ๋ ์์ง๋์ด๋ค์ด Hooks์ ๊ท์น์ ํผ๋์ค๋ฌ์ ํ์ง ์๋์ง ํ์ธํด๋ณด๊ณ ์ ํ๋ฌ๋์ ์ค์ ๊ฐ๋ฐํ ๋ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ค์ ๋ก ๊ฐ๋ฐ์๋ค์ด ๋ช ์๊ฐ ์์ ์ต์ํด์ง๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ์ ๋ ์ฒ์์ ๊ท์น๋ค์ด ์๋ชป๋์๋ค๊ณ ๋๊ผ๊ธฐ๋ ํ์ง๋ง ๊ธ๋ฐฉ ๊ทน๋ณตํ์ต๋๋ค. ์ด ๊ฒฝํ์ ๋ฆฌ์กํธ๋ฅผ ์ฒ์ ๊ฒฝํํ์ ๋์ ๋น์ทํ์ต๋๋ค. (๋ฐ๋ก ๋ฆฌ์กํธ๋ฅผ ์ข์ํ์ จ๋์? ์ ๋ ๋ ๋ฒ ํด๋ณด๊ณ ์ข์ํ์ต๋๋ค.)
Hooks์ ๊ตฌํ์ ์์ด "๋ง๋ฒ"์ ์์ต๋๋ค. Jamie๊ฐ ์ง์ ํ ๋ฐ์ ๊ฐ์ด ์ด๊ฒ์ ์๋์ ๋น์ทํด ๋ณด์ ๋๋ค.
์๋ฌธ : https://javascript.plainenglish.io/proto-vs-prototype-in-js-140b9b9c8cd5
๋ถ์ : An explanation of the relationship between the two concepts.
์ ํ์ ์ต๊ทผ์ ์๋ก์ด ์์ดํฐ ๋ชจ๋ธ์ธ iPhone 11์ ์ถ์ํ์ต๋๋ค. ๊ทธ ๋ชจ๋ธ์ ํน์ ํ ๊ธฐ๋ฅ์ ๊ฐ์ง๋๋ฐ ์๋ฅผ ๋ค์ด Face ID์ 4K ๋น๋์ค๊ฐ์ ๊ฒ๋ค์ด์ฃ . ๋ชจ๋ ์์ดํฐ 11์ ๋์ผํ ๊ธฐ๋ฅ๋ค์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด, ์๋ก์ด ์์ดํฐ 11์ด ํธ์ถ๋ ๋๋ง๋ค ์์ดํฐ11์ ๋ง๋๋ ์์ฑ์ ํจ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. ์ ์ ํ๊ฒ ์์ดํฐ 11์ ๋ง๋ค๊ธฐ ์ํด ๋ชจ๋ธ์ ์ฐธ๊ณ ํ๋ _prototype_์ด ํ์ํฉ๋๋ค. ์ด ํ๋กํ ํ์ ๋๋ ๋ชจ๋ธ์ ๋ชจ๋ ์์ดํฐ์ด Face ID๋ฅผ ๊ฐ์ง๋ฉฐ 4K ๋น๋์ค๋ฅผ ์ฐ์ ์ ์๋๋ก ๋ณด์ฅํฉ๋๋ค. ๋ฐ๋ผ์ ์์ดํฐ ์์ฑ์๋ ๋ฐ๋์ ์ ์ํด์ผ ํ๋ ํ๋กํ ํ์ ์ ์๊ณ ์ ๊ทผํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ์์ฑ์์ prototype ํ๋กํผํฐ์ ๋๋ค.
function iPhone() {}; // ์์ฑ์
// a method for recognizing faces
iPhone.prototype.faceID = function() { ... };
// a method for taking 4k video
iPhone.prototype.video = function() { ... };
let newPhone = new iPhone(); // ์์ดํฐ11
์ฌ๊ธฐ๊น์ง ์ดํด๊ฐ ๋์ จ๋์? ๊ทธ๋ผ __proto__์ ๋ํด ์์๋ด ์๋ค.
์๋ก์ด iPhone 11์ ๋ง๋ค๊ณ newPhone์ด๋ผ๋ ๋ณ์์ ์ ์ฅํ์ต๋๋ค. newPhone์ ๋ด์ฉ๋ฌผ์ ์๋์ ๊ฐ์ ๊ฒ๋๋ค.
์ด ์์ดํฐ11์ FaceID์ video ๊ธฐ๋ฅ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค! ์ฌ์ค ์ฌ๋ฌ๋ถ์ newPhone.faceID()๋ newPhone.video()๋ฅผ ์คํํ ์ ์๊ณ ์ด ๋ฉ์๋๋ค์ด ์ ๋์ํ๋ ๊ฑธ ๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฐ ํจ์๋ค์ด __proto__๋ผ๋ ๊ฐ์ฒด์ ์ ์ฅ๋๊ณ ์ง์ ์ ์ผ๋ก newPhone์ ํ๋กํผํฐ๋ก ์ ์ฅ๋์ง ์๋ ๊ฒ์ผ๊น์?
__proto__๋ ์์ฑ๋ ํ๋กํ ํ์ ์ ๊ฐ๋ฆฌํค๋ ๋ชจ๋ ํด๋์ค _์ธ์คํด์ค_์ ๊ฐ์ฒด์ ๋๋ค. newPhone.__proto__๋ iPhone.prototype์ ๋ํ ์ฐธ์กฐ์ด๊ณ ๋ฐ๋ผ์ ์ ํํ ๋์ผํ ๊ฒ๋ค์ ์ง๋๊ณ ์์ต๋๋ค. iPhone.prototype๊ณผ ๋์ผํ proto ํ๋กํผํฐ๋ฅผ ๊ฐ์ง์ผ๋ก์จ, newPhone์ ๋ณธ์ง์ ์ผ๋ก "๋ณด์ธ์, ์ ๋ ์์ดํฐ11์ด๋ผ์ ๋ค๋ฅธ ์์ดํฐ11๊ณผ ๋์ผํ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ด์! ํ์ด์ค ์์ด๋, 4K ํ์ง ๋ฑ ๋ญ๋ ์." ๋ผ๊ณ ๋งํ๋ ๊ฒ๊ณผ ๊ฐ์ฃ .
ํ์ค์ธ๊ณ์์ prototype๊ณผ __proto__์ ์ ์ผํ ์ง์ง ์ฐจ์ด์ ์ ์ ์๋ ํด๋์ค ์์ฑ์์ ํ๋กํผํฐ๋ผ๋ ์ ์ด๊ณ ํ์๋ ํด๋์ค ์ธ์คํด์ค์ ํ๋กํผํฐ๋ผ๋ ์ ์ ๋๋ค. ๋ค๋ฅธ ๋ง๋ก ๋งํ๋ฉด iPhone.prototype์ iPhone์ ๋ง๋๋ ์ฒญ์ฌ์ง์ ์ ๊ณตํ๋ฉฐ, newPhone.__proto__๋ ๊ทธ ์ฒญ์ฌ์ง์ ๋ฐ๋ผ ์ธ์คํด์ค๊ฐ ๋ง๋ค์ด์ก๋ค๋ ๊ฒ์ ๋งํด์ค๋๋ค. ๋ ๊ฐ์ฒด์ ์กด์ฌํ๋ ํ๋กํผํฐ๋ค๊ณผ ๋ฉ์๋์ ๋ํด์๋... ์ ์ ํํ ๊ฐ์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก, ์ฌ๋ฌ๋ถ์ ์ ์ด๋ฏธ์ง์ ๋ง์ง๋ง ๋ผ์ธ์ ์๋ proto: Object์ ๋ป์ ๋ํด ๊ถ๊ธํ์
จ์ ๊ฒ๋๋ค. newPhone.__proto__๋ ์ฌ์ค ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ค ๋ํ ํน์ ํ "์ฒญ์ฌ์ง"์ผ๋ก๋ถํฐ ๋ง๋ค์ด์ง ๊ฒ์
๋๋ค. ์ด ์์์์ newPhone.__proto__.__proto__
๋ Object.prototype์ ๋ํ๋
๋๋ค. ์ด๋ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๊ฐ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ํ๋กํ ํ์
์ด์ฃ . ๊ทธ๊ฒ ๋ค์
๋๋ค!
๋ฆฌํดํ๊ธฐ ์ ์ ํ๋ก๋ฏธ์ค๋ฅผ awaitํ๋ ๊ฒ์ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ๋๋ฆฌ๊ฒ ๋ง๋ญ๋๋ค.
์์ฝ: ESLint no-return-await
rule์ ์ฌ์ฉํ์ธ์
ํฐ ์ค์ผ์ผ์ ์ดํ๋ฆฌ์ผ์ด์
๊ฐ๋ฐ์ ์ฃผ์ ํจ๋ฌํ์์ ๊ณ ์์ค์ ์ธ์ด๋ก ํ๋ก๊ทธ๋๋ฐ์ ํ๋ ๊ฒ์
๋๋ค. ๊ณ ์์ค์ ์ธ์ด๋ ๊ฐ๋ฐ์ ๋น ๋ฅด๊ฒ ํ๋ ๋์ ๋ฐํ์์์ ์๋๊ฐ ๋๋ฆฌ๋ค๋ ํธ๋ ์ด๋์คํ๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ์์๋ ๊ทธ ์ธ์ด๋ก ์๋ฐ์คํฌ๋ฆฝํธ
๋ฅผ ์ ํํ ๊ฒ์ด์ฃ .
์ฌ๋ฌ๋ถ์ ์๋ง "์ง์ง ์ฑ๋ฅ์ด ์ค์ํ๋ค๋ฉด, Rust๋ก ์ฝ๋๋ฅผ ์งฐ๊ฒ ์ง" ๋ผ๊ณ ์๊ฐํ์ค ์๋ ์์ง๋ง ๊ทธ๋ ๊ฒ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋๋ฆฐ ๊ฑด ์๋๋๋ค. NodeJs ๋ ๋๋ถ๋ถ์ ์ํฉ์์ ๊ฐ๋ฐ๊ณผ ๋ฐํ์ ์๋ ์ถฉ๋ถํ ๋น ๋ฆ ๋๋ค. Techempower ๋ฒค์น๋งํฌ ๊ฒฐ๊ณผ ๋ํ NodeJs๊ฐ ์ถฉ๋ถํ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ์๋ ค์ค๋๋ค.
Web API๊ฐ์ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ 1ํผ์ผํธ๋ผ๋ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค๋ฉด, ์ด๋น 9์ฒ๊ฐ์ ์์ฒญ์ ์ฒ๋ฆฌํ ๊ฒฝ์ฐ 800๊ฐ๋ฅผ ์ถ๊ฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ค๋ ๋ป์ด์ฃ . ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฑด ์ค๋์ ์ฑ๋ฅ ์ผ๋ก ์ฐ๊ฒฐ๋ฉ๋๋ค.
๋ค๋ฅธ ๋น๋๊ธฐ ํจ์ ํธ์ถ์ ๊ฐ์ธ๊ณ ๊ธฐ๋ค๋ฆฌ๋๋ก ํจ์๋ฅผ ์ง๋ ๊ฒ์ ๋น๋๊ธฐ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋๋ฐ์์ ์์ฃผ ํํ ํจํด์ ๋๋ค.
async function example() {
const server = await createServer();
const endpoints = await createEndpoints(server);
return await startServer(server, endpoints);
}
๋ณด์๋ค์ํผ ์์ ํจ์๋ return
๋ฌธ ์ ์ await
๋ฅผ ์คํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ถ๋ถ์ด ๊น๋ค๋กญ๊ฒ ๋ง๋๋ ๋ถ๋ถ์
๋๋ค.
๋ฌธ์ ๋ฅผ ๊น๊ฒ ์ค๋ช
ํ๊ธฐ ์ ์ ์ด๊ฒ์ด ์ผ๋ง๋ ๋๋ฆฌ๊ฒ ๋ง๋๋์ง ๋ณด์ฌ์ฃผ๋ ๊ฐ๋จํ ๋ฒค์น๋งํฌ๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
์ฌ๊ธฐ์ ์ฌ์ฉํ๋ ๋ชจ๋ ์ฝ๋๋ [arthur-place/the-cost-of-return-await](https://github.com/arthur-place/the-cost-of-return-await) ๊นํ๋ธ ์ ์ฅ์์ ์์ต๋๋ค.
๋ฉ์ธ ํจ์์ธ work()
๋ setImmediate
ํจ์๊ฐ ํธ์ถ๋์๋ง์ resolve๋๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ 3๊ฐ์ ํจ์๊ฐ ์๋๋ฐ ์ด ํจ์๋ค์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ง๋ง ํ๋๋ ๋น๋๊ธฐ์ด๋ฉฐ await
์ ์ฌ์ฉํฉ๋๋ค. ๋ค๋ฅธ ํ๋๋ ๊ทธ๋ฅ ๋น๋๊ธฐ์ด๊ณ ๋ง์ง๋ง ํ๋ ๋จ์ํ return
๋ฌธ๋ง ์ฌ์ฉํฉ๋๋ค.
// function work(): Promise<any>;
async function doWait() {
return await work();
}
async function dontWait() {
return work();
}
function justReturn() {
return work();
}
์ค์ ๋ก๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ ์ด์ ์ EcamScript ๋ฒ์ ์ผ๋ก ํธ๋์คํ์ผ๋๋๋ฐ ๊ทธ ์ ์ด ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ ํ๋ ๊ฒ์ ๋๋ค.
๊ฐ๋จํ ํ ์คํธ๋ฅผ ๋ง๋ค์ด ๋์ผํ ์์ค ํ์ผ์ ES3์์ ES2022๊น์ง ํธ๋์คํ์ผํ์ต๋๋ค. ์๋์ ๊ฐ ๊ฒฐ๊ณผ๋ฌผ๋ค์ ์ฐจ์ด์ ์ด ์์ต๋๋ค.
function doWait() {
return _doWait.apply(this, arguments);
}
function _doWait() {
_doWait = (0, _asyncToGenerator2['default'])(
/*#__PURE__*/ _regenerator['default'].mark(function _callee() {
return _regenerator['default'].wrap(function _callee$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
_context.next = 2;
return work();
case 2:
return _context.abrupt('return', _context.sent);
case 3:
case 'end':
return _context.stop();
}
}
}, _callee);
})
);
return _doWait.apply(this, arguments);
}
function dontWait() {
return _dontWait.apply(this, arguments);
}
function _dontWait() {
_dontWait = (0, _asyncToGenerator2['default'])(
/*#__PURE__*/ _regenerator['default'].mark(function _callee2() {
return _regenerator['default'].wrap(function _callee2$(_context2) {
while (1) {
switch ((_context2.prev = _context2.next)) {
case 0:
return _context2.abrupt('return', work());
case 1:
case 'end':
return _context2.stop();
}
}
}, _callee2);
})
);
return _dontWait.apply(this, arguments);
}
function doWait() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
return [4 /*yield*/, work()];
case 1:
return [2 /*return*/, _a.sent()];
}
});
});
}
function dontWait() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, work()];
});
});
}
function doWait() {
return __awaiter(this, void 0, void 0, function* () {
return yield work();
});
}
function dontWait() {
return __awaiter(this, void 0, void 0, function* () {
return work();
});
}
async function doWait() {
return await work();
}
async function dontWait() {
return work();
}
์ ์ปดํจํฐ๋ ์๋์ ์คํ์ฌํญ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์๋ง ์ฌ๋ฌ๋ถ๋ค์ Es6๊ฐ ์ ์ด๋ ๊ฒ ๋๋ฆฐ์ง ๊ถ๊ธํดํ์ค ์๋ ์๊ฒ ์ต๋๋ค. ์ ์ ๊ฐ๋จํ ์คํ๊ฒฐ๊ณผ๋ tslib generator ํด๋ฆฌํ(__generator)์ Node 17 native function*
๊ณผ yield
๋ณด๋ค ๋น ๋ฅด๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋๋ค. ๊ทธ๋ ์ง๋ง ์ด๊ฑด ๋ ๋ค๋ฅธ ์๊ธฐ์ฃ .
return await
์ด ์๋ชป๋๊ฑธ๊น?Babel, ES5, ES6์ผ๋ก ํธ๋์คํ์ผ๋ ๊ฒ๋ค์ ๊ฐ๊ธฐ ๋ค๋ฅธ ์ฑ๋ฅ์ ๋ณด์ฌ์ค ๊ฒ์ด๋ผ๊ณ ์์๋ฉ๋๋ค. ๊ฐ๊ฐ ๋ค๋ฅธ ํด๋ฆฌํ๊ณผ ECMAScript ๋ฒ์ ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ช
๋ฐฑํ ์ผ์
๋๋ค.
๊ฐ๋จํ ๋งํด์, await
์ ๋ง ๊ทธ๋๋ก ๊ธฐ๋ค๋ฆฌ๊ณ ์์ต๋๋ค. ํ๊ฐ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํดํ๊ธฐ ์ ์ ํ๋ก๋ฏธ์ค๊ฐ ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ด์ฃ .
๋ํ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ๊ฒฐ๊ณผ ์์ฒด๋ ํ๋ก๋ฏธ์ค์ ๊ฐ์ ๋์์ผ ๊ฒ์ด๋ผ๊ณ ์์ํ๋ฏ๋ก await(promise)
์ await(non-promise)
๋ ๋์ผํ ๋์์ ํ๊ฒ ๋๋ ๊ฒ๋๋ค.
NodeJS Event Loop๋ ์ด๋ฏธ ์ง์ ๋ ์ฝ๋ ๋ผ์ธ์ด ํ์ฌ์ iteration์ด ๋๋ ๋ ์คํ๋๋๋ก ์ค์ผ์ฅด๋ง์ ํ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์์์ผ ๋๋จธ์ง๋ฅผ ์คํํ๊ณ ๋ด๋ถ ํ๋ก๋ฏธ์ค๋ ์ผ๋ค์ ๋ํด ๊ธฐ๋ค๋ฆฌ๊ฒ ๋ฉ๋๋ค.
์์ ์ ์ฃผ์ฅ์ ๋ท๋ฐ์นจํ ์ ์๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
async function withAwait() {
console.log(1);
// This will make nodejs wait for the
// end of the current loop. Because it
// "expects" that a promise was given
// in place of 0
await 0;
console.log(2);
}
async function withoutAwait() {
console.log(3);
}
withAwait();
withoutAwait();
$ node example.js
#> 1
#> 3
#> 2
๋ค์ ๋ฒค์น๋งํฌ ์๊ธฐ๋ก ๋์๊ฐ์, ์์ ์๊ธฐํ 1%๊ฐ ์์ต๋๋ค. ๊ทธ 1%๋ 10,000ops/s์์ 100์ด ๋ ์๋ ์๊ณ ์ฌ์ง์ด๋ 1,000,000 ops/s์ธ ์๋ฒ์์ 10,000์ด ๋ ์๋ ์์ต๋๋ค. ๋จ์ํ await
ํค์๋๋ฅผ ์๋ชป ์ฌ์ฉํจ์ผ๋ก์จ ์ฌ๋ฌ๋ถ์ ํจ์๊ฐ ๋ฐ๋ณต๋๋ ํ๋ก์ฐ๋ฅผ ์ฌ๋ฌ๋ฒ ์ค๋จ๋๋ค๋ ๊ฒ์ ์ ์ ์์ฃ . return
๋ฌธ์ด ์ ์ ํ๊ฒ ์ฌ์ฉ๋ ๋๋ง๋ค ์ธ์ด๋ธ๋๋ ๊ฐ ๋ฐ๋ฆฌ์ด๋ค์ด ๋ํด์ ธ ์ด๋น ๋ ๋ง์ ์์
๋ค์ ํ ์ ์๊ฒ ๋ง๋ญ๋๋ค. return await
์ ํผํ๋ ๊ฒ์ ์ฑ๋ฅ์ ํฅ์์ํค๋ ์ข์ ๋ฐฉ๋ฒ์
๋๋ค.
์ด์ ์ ๋ฐํ๋ฏ์ด, ํ๋ก๋ฏธ์ค๋ฅผ ๋ฆฌํดํ๊ธฐ ์ ์ ๊ธฐ๋ค๋ฆด ํ์๊ฐ ์๋ค๋ฉด, ์ฆ์ ๋ฐํ๋ฉ๋๋ค.Chain of Responsibility๊ณผ ๋น์ทํ๊ฒ ๋ง์ ๋๋ค. ์ฆ ๋ฆฌํดํ๋ ๊ฒ์ ์ฑ ์์ ์ง๋ ๋์ ํจ์์ ํธ์ถ์์๊ฒ ์ฑ ์์ ๋๊ธฐ๊ฒ ๋๋๋ฐ์. ์ด๋ฐ ๊ฒฝ์ฐ Try-Catch Blocks์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
// Correct usage of `return await`
async function fn() {
try {
return await work();
} catch (err) {
return handleWorkError(error);
}
}
์์ ์์์์ await
ํค์๋๋ฅผ ์ ๊ฑฐํด๋ณธ๋ค๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
// return await work();
return work();
ํจ์ ๋ด์์ ์ด๋ค ์์ธ๋ฅผ ์ง์ throwํ๋ค ํ๋๋ผ๊ณ catch ๋ธ๋ก์ ํธ์ถ๋์ง ์์ต๋๋ค. work()
ํจ์๊ฐ ๋ฆฌํดํ๋ ํ๋ก๋ฏธ์ค๋ fn()
ํธ์ถ์์๊ฒ ์์ ์ ์ฒ๋ฆฌํ๋ ์ฑ
์์ ์ง์ ์ ๋ฌํด์ฃผ๊ธฐ ๋๋ฌธ์
๋๋ค. fn()
ํจ์๋ฅผ ํธ์ถํ๋ ์ธ๋ถ์ try-catch ๋ธ๋ก์ ๋๋ฉด, ๋ด๋ถ fn()
catch ๋ธ๋ก์ ์คํ๋์ง ์๊ณ ์ธ๋ถ์ ์๋ ๋ธ๋ก๋ง ์คํ๋ฉ๋๋ค.
์์ ์์ธ์ฌํญ์ ๋ฌด์ํ๊ณ , ์ฌ๋ฌ๋ถ๋ค์ ๊ฐ๋จํ await
์ ์ ๊ฑฐํ์๋ฉด ๋ฉ๋๋ค. ๋ง์ฝ ESLint๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด(์ฌ์ฉํ์ง ์๋๋ค๋ฉด ์ฌ์ฉํ์ธ์) no-return-awaitrule์ ์ผ๋์๋ฉด ๋ฉ๋๋ค.
์ฌ๋ฌ๋ถ๋ค์ด ์ข์ ๋ ์๋ผ๋ฉด ์๋ง no-return-await์ ๋ํด ์ฝ์์ ๊ฒ์ด๊ณ ์คํ ์ถ์ ์ ๋ณด์กดํ๋ ๊ฒ์ ๋ํด์๋ ๋ณด์ จ์ ๊ฒ๋๋ค. ๊ทธ๋ ์ง ์์๋๋ผ๋ ์ ๊ฐ ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์์ฝํ์๋ฉด, ํ๋ก๋ฏธ์ค๋ฅผ ๋ฆฌํดํ๊ณ ํธ์ถ์๊ฐ ์์ธ๋ฅผ ์ฒ๋ฆฌํ๊ฒ ๋๋ฉด ์คํ ์ถ์ ์ ๋ํ ์์ค(loss)๊ฐ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋ง์ดํ๊ฒ ๋ฉ๋๋ค. ๊ฐ๋จํ ์์๋ฅผ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
async function foo() {
await bar();
return 42;
}
async function bar() {
await Promise.resolve();
throw new Error('BEEP BEEP');
}
foo().catch((error) => console.log(error.stack));
$ node index.js
Error: BEEP BEEP
at bar (index.js:8:9) --> (ONLY SHOWS BAR) <--
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:745:11)
at startup (internal/bootstrap/node.js:266:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:595:3)
But as written on the official [v8.dev](https://v8.dev/blog) blog, they solved this problem with something called [zero-cost async stack traces](https://bit.ly/v8-zero-cost-async-stack-traces) and now you can see the exact stack trace in the console:
๊ทธ๋ฌ๋ v8.dev ๊ณต์ ๋ธ๋ก๊ทธ์ ์ฐ์ธ ๊ฒ์ฒ๋ผ zero-cost async stack traces๋ฅผ ํตํด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ผ๋ฉฐ ์ฌ๋ฌ๋ถ๋ค์ ์ด์ ์ฝ์์์ ์ ํํ ์๋ฌ ์คํ์ ํ์ธํ ์ ์์ต๋๋ค.
$ node index.js
Error: BEEP BEEP
at bar (index.js:8:9)
at process._tickCallback (internal/process/next_tick.js:68:7)
at Function.Module.runMain (internal/modules/cjs/loader.js:745:11)
at startup (internal/bootstrap/node.js:266:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:595:3)
at async foo (index.js:2:3)
์ ๊ฐ ๋ชจ๋ ๊ฒ์ ์ค๋ช ํ์ง ์์์ผ๋ ์์ธํ ๊ฑด official blog post๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์.
์ฌ๋ฌ๋ถ๋ค์ด ์ ๊ธ์ ํตํด ์๋ก์ด ๊ฒ์ ๋ฐฐ์ ์ฝ๋๋ฅผ ๋ ์ข๊ฒ ๋ง๋ค ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
Typescript docs ์ฐธ๊ณ
utility types
์ ๊ณตPartial<Type>
Type
์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ optional๋ก ๊ตฌ์ฑRequire<Type>
Readonly<Type>
Type
์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ readonly
๋ก ์์ฑํ์ฌ ์ฌํ ๋น์ ํ ์ ์๊ฒ ํจObject.freeze
์ ๊ฐ์ด ๋ฐํ์์ ํ ๋น์์ ๋ํ ์๋ฌ๋ฅผ ๋ํ๋ผ ๋ ์ฌ์ฉํ๋ฉด ์ข์ ํ์
interface Todo {
title: string;
}
const todo: Readonly<Todo> = {
title: "Delete inactive users",
};
todo.title = "Hello";
// Cannot assign to 'title' because it is a read-only property.
Record<Keys, Type>
interface CatInfo {
age: number;
breed: string;
}
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
miffy: { age: 10, breed: "Persian" },
boris: { age: 5, breed: "Maine Coon" },
mordred: { age: 16, breed: "British Shorthair" },
};
Pick<Type, Keys>
Type
์์ Keys
์ ๋ํ ํ๋กํผํฐ๋ฅผ picking ํด์์ ํ์
๊ตฌ์ฑKeys
๋ string ๋ฆฌํฐ๋ด์ด๋ string ์ฌ๋ฌ ๊ฐinterface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
title: "Clean room",
completed: false,
};
Omit<Type, Keys>
Type
์ ๋ชจ๋ ํ๋กํผํฐ์์ Keys
๋ฅผ ์ ์ธExclude<Type, ExcludeUnion>
Type
์์ ExcludeUnion
์ ์ํ ํฉ์งํฉ ๊ฐ๋ค์ ์ ๊ฑฐtype T0 = Exclude<"a" | "b" | "c", "a">;
// type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">;
// type T1 = "c"
Extract<Type, Union>
Type
์์ Union
์ ์ํ๋ ๊ฐ๋ค๋ง ํ์
์ผ๋ก ๊ตฌ์ฑtype T1 = Extract<string | number | (() => void), Function>;
// type T1 = () => void
// Function์ ์ํ๋ ๊ฒ๋ง ๊ฐ๋ฅํ๋ฏ๋ก
NonNullable<Type>
Type
์์ null
๊ณผ undefined
์ ๊ฑฐParameters<Type>
Type
์ ํ๋ผ๋ฏธํฐ๋ฅผ ํํ์ ํ์
์ผ๋ก ์ฌ์ฉConstructorParameters<Type>
Type
์ด ํจ์๊ฐ ์๋ ๊ฒฝ์ฐ never
ReturnType<Type>
Type
์ ๋ฆฌํด ํ์
์ ์ฌ์ฉInstanceType<Type>
Type
์ ์์ฑ์ ํจ์์ ์ธ์คํด์ค ํ์
์ผ๋ก ๊ตฌ์ฑThisParameterType<Type>
unknown
์ this ํ๋ผ๋ฏธํฐ๋ฅผ ์ถ์ถํ์ฌ ์ฌ์ฉunknown
OmitThisParameter<Type>
Type
์์ this ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ฑฐType
๋ง์์ ์ฌ์ด๋ ํ๋ก์ ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ ์ ํ ๋ missing value๋ฅผ ํํํด์ผ ํ์ต๋๋ค. ๊ณผ๊ฑฐ์๋ ๊ฐ๋จํ ์ธํ ์ ํ๊ฑฐ๋ ๋ ๋ง์ด ์ ์ดํ๊ธฐ ์ํด Option์ ํตํด nullableํ ์ ๊ทผ๋ฒ์ ์ฌ์ฉํ์ต๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ๋ ๋ค ๋ง์ง ์์์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์๊ฐํ์ต๋๋ค.
Nullable
์ ๊ฐ์ด ์กด์ฌํ ๋ ๊ทธ ๊ฐ์ ๋ฌธ์์ด, ์ซ์, ๋๋ ๊ฐ์ฒด์์ ์๋ฏธํฉ๋๋ค. ๊ฐ์ด ์์ ๋ ์ฐ๋ฆฌ๋ null
์ด๋ undefined
๋ฅผ ์ฌ์ฉํ์ฃ .
ํ: ํ์
์คํฌ๋ฆฝํธ์์ nullable types๋ก ์์
ํ ๋ strictNullChecks
์ต์
์ ์ผ๋์ธ์.
์ด ๋ฐฉ์์ ์ข ์ข ๊ด์ฐฎ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ด์ฐฎ์ง ์์ ๋ ๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
null
์ด๋ undefined
๊ฐ ๋ ์ ์์ ๋. ๊ฒฐ๊ตญ ์ด ๊ฐ๋ค์ ์ ํจํ ์๋ฐ์คํฌ๋ฆฝํธ ์์๊ฐ์ด๊ณ ์ฌ๋๋ค์ ๋ค์ํ๊ฒ ์ด ๊ฐ๋ค์ ์ฌ์ฉํฉ๋๋ค.x == null
์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ท์ฐฎ์ ์ผ์
๋๋ค.๋ง์ ๊ฒฝ์ฐ์์ Promise์ ์ถ๋ ฅ๊ฐ์ ์ ์ดํ๊ณ ์ด๋ค ๊ฐ์ ๋ฆฌํดํ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ missing๋ ๋ ๊ฐ์ด ๊ฒฐ๊ตญ ๋ฆฌํด๋๋ค๋ ๊ฒ์ ์๊ฒฌํ ์ ์์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฌธ์ 1๊ณผ 2๋ ๋์ผํ ํด๊ฒฐ๋ฒ์ ๊ฐ์ง๋๋ค. Option type์ ๊ตฌํํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
(๋๋๋ก Maybe๋ผ๊ณ ๋ถ๋ฆฌ๋) Option ํ์
์ ๋ ๊ฐ์ง ๊ฐ๋ฅ์ฑ์ ๊ฐ์ง๋๋ค. ๊ฐ์ด ์๊ฑฐ๋(None
, Nothing
) ๊ฐ์ด ์๋ ๊ฒฝ์ฐ(Some
, Just
)์ด์ฃ .
์๋ฐ์คํฌ๋ฆฝํธ์ ํ์
์คํฌ๋ฆฝํธ์์ ์ด๋ ๊ฐ์ ๊ฐ์ธ๋ ์๋ก์ด ๊ตฌ์กฐ๋ฅผ ๋์
ํจ์ ์๋ฏธํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ฐ๋ฅํ ์์ฑ์ ์ ์ํ๋ tag
ํ๋กํผํฐ๊ฐ ์๋ ๊ฐ์ฒด์
๋๋ค.
์ด๋ ํ์ ์คํฌ๋ฆฝํธ์์ ์ผ๋ง๋ ์ฌ๋ฌ๋ถ์ด ๋น ๋ฅด๊ฒ Option์ ๊ตฌํํ ์ ์๋์ง๋ฅผ ๋ณด์ฌ์ค๋๋ค.
type Option<T> = { tag: 'none' } | { tag: 'some', value: T }
๋ณดํต ์ฌ๋ฌ๋ถ๋ค์ ํ์ ์ ์ ์ํ๊ณ ์ ์ฉํ ์ ํธ์ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
navigator
์ธํฐํ์ด์ค์ ์์ฑ์ด๊ธฐ๋ ํ๋ค.NCSA Mosaic
๋ผ๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ๊ฐ๋ฐ. ์ด๋๋ถํฐ UA๊ฐ ๋ค์ด๊ฐ๋๋ฐ ๋น์ ๊ตฌ์กฐ๋ ์ ํ๋ช
/๋ฒ์
์ด์๋ค.
Mosaic/0.9
Netscape Navigator
๋ผ๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ค์ ๊ฐ๋ฐํ๋ค. ์ด ๋ท์ค์ผ์ดํ์๋ Mozilla
๋ผ๋ ์ฝ๋๋ค์์ด ์กด์ฌํ๊ณ ์ด๊ฒ์ด UA์ ๊ทธ๋๋ก ๋ฐ์๋์๋ค. ์ฌ๊ธฐ์ ์ธ์ด์ค์ , ์ด์์ฒด์ ๋ฑ์ ๋ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ๋ง๋ถ์๊ณ ๋ฒ์ ์ ๋ฐ๋ผ UA ํ์์ ๋ณ๊ฒฝํ์๋ค.
Trident
๋ผ๋ ์์ง์ ๋ง๋ค๊ณ IE
๋ฅผ ๊ฐ๋ฐํ๋ค.<frame>
์ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ง์ดํฌ๋ก์ํํธ ์ฌ๋ ์์ ๋ค์ UA๋ฅผ Mozilla
๋ก ์์ํ๊ฒ ๋ง๋ค์ด ์น ์๋ฒ๋ฅผ ์์ด๊ฒ๋ ํ์ฌ ํ๋ ์ ํ๊ทธ๊ฐ ์ ์ฉ๋ HTML ํ์ผ์ ๋ฐ์ ์ ์์๋ค.
Mozilla/2.0 (compatible; MSIE 3.02; Windows 95)
(IE)Gecko
์์ง์ ๊ณต๊ฐํ์์ผ๋ฉฐ, 2002๋
๋ธ๋ผ์ฐ์ Firefox
๋ฅผ ๊ณต๊ฐํ๋ค.
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.4) Gecko/20011128 Netscape6/6.2.1
Mozilla/5.0
์ ๋ฌด์๋ฏธํ ์กด์ฌ๊ฐ ๋์์ผ๋ ์ด์ ์ฝ๋์์ ํธํ์ฑ์ ์ํด ๊ทธ๋๋ก ์ ์งํ๋ค. ์ด ๋๋ถํฐ ๋ชจ๋ UA ๋ฌธ์์ด์ Mozilla/5.0
๋ก ์์ํ๊ฒ ๋๋ค.Gecko
๋ผ๋ ๋ฌธ์์ด์ด ํฌํจ๋ ๋ธ๋ผ์ฐ์ ์ ๋ํ ์ง์์ ๊ฐํํ๋ค.Webkit
๊ธฐ๋ฐ์ ์น ๋ธ๋ผ์ฐ์ Safari
๋ฅผ ๋ฐํํ๋ค. ์ ํ๋ ์ด์ ๋ง์ดํฌ๋ก์ํํธ์ ๋์ผํ ํด๊ฒฐ์ฑ
์ผ๋ก Gecko ๊ธฐ๋ฐ์ ๋ธ๋ผ์ฐ์ ์ํ๊ณ์์ Safari๋ฅผ ์์ฐฉ์ํค๊ณ ์ ํ๋ค.
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/522.15.5 (KHTML, like Gecko) Version/3.0.3 Safari/522.15.5
Chrome
์ webkit ๊ธฐ๋ฐ์ ๋ธ๋ผ์ฐ์ ์๊ธฐ ๋๋ฌธ์ Safari์ฒ๋ผ ์ธ์๋๊ธฐ๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์ Safari์ UA๋ฅผ ๋ฐ๋ผํ๋ฉด์ Chrome
์ด๋ผ๋ ๋ฌธ์์ด์ ์ถ๊ฐํ๋ค.
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
์ถ์ฒ : https://wormwlrm.github.io/2021/10/11/Why-User-Agent-string-is-so-complex.html
๋ถ์ : ํ์ด์ค๋ถ์ด ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ ํํ ์ด์
์๋ฌธ <Is offset pagination dead? Why cursor pagination is taking over>
ํ์ด์ค๋ถ ๊ฐ๋ฐ์ ํ์ด์ง๋ ์ด๋ ๊ฒ ๋งํฉ๋๋ค.
"์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๊ฐ์ฅ ํจ์จ์ ์ธ ํ์ด์ง ๊ธฐ๋ฒ์ด๊ณ ๊ฐ๋ฅํ ์ปค์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํด์ผ ํ๋ค."
๊ทธ๋ ๋ค๋ฉด ํ์ด์ง๋ค์ด์ ์ด๋ ๋ฌด์์ผ๊น์?
ํ์ด์ง๋ค์ด์ ์ ๋ฐ์ดํฐ ์งํฉ์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ๋ ๊ณผ์ ์ ๋๋ค. ์ฑ ์ ํ์ด์ง๋ค๊ณผ ๊ฐ์ฃ .
์น์ฌ์ดํธ์์ ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ๋ ๋ ๊ฐ์ง ์ฃผ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๋ฐฉ๋ฒ์ด ๋ ์ข์ ๊ฑธ๊น์? ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ดํด๋ด ์๋ค.
์ด ๋ฐฉ๋ฒ์ ์์ญ ๋
๋์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉ๋์์ต๋๋ค. ๋ค์๊ณผ ๊ฐ์ด OFFSET
๊ฐ์ ๊ฐ์ง๋ SQL ์ฟผ๋ฆฌ๋ฅผ ํ์ฉํฉ๋๋ค.
SELECT * FROM table
ORDER BY timestamp
OFFSET 10
LIMIT 5
๋ช ์์ ์ผ๋ก ํ์ด์ง ์๋ฅผ ๋ณด์ฌ์ฃผ์ด ์ฌ์ฉ์๊ฐ ์ ํํ ์ ์๋ ํ๋ก ํธ์๋์ ํจ๊ป ์์ ์ด๋ฃจ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๋ง์น ์ฑ ์ ํ์ด์ง๋ฅผ ๋๊ธฐ๋ ๊ฒ๊ณผ ๋น์ทํ์ฃ .
์ด ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ด (๋ณดํต ํ์์คํฌํ๋ฅผ ๋น๊ตํ๋) <
, >
์ ๊ฐ์ ๋น๊ต ์ฐ์ฐ์๋ฅผ ํฌํจํ๋ SQL ์ฟผ๋ฆฌ๋ฅผ ํ์ฉํฉ๋๋ค.
SELECT * FROM table
WHERE cursor > timestamp
ORDER BY timestamp
LIMIT 5
์ฌ๋ฌ๋ถ์ด ๋ง์ ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ์น์ฌ์ดํธ(ํ์ด์ค๋ถ, ์ฌ๋, ํธ์ํฐ ๋ฑ๊ณผ ๊ฐ์)๋ฅผ ๋ณด๊ณ ์๋ค๋ฉด ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ด ๋์ํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ํ๋ก ํธ์๋์ ๋ฌดํ ์คํฌ๋กค ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์ ํธ๋๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋ฌดํ ์คํฌ๋กค์ ์ฌ๋ฌ๋ถ์ด ํ์ด์ค๋ถ ํผ๋๋ฅผ ๋ด๋ฆฌ๋ค๊ฐ ๋ฐ๋ฅ์ ๋ค๋ค๋์ ๋, ๋ ๋ง์ ํผ๋๋ค์ด ์ด๋ป๊ฒ ๋ ๋ํ๋ฌ๋์ง ์๊ฐํด๋ณด์๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ์ด๋ ๊ฒ ๋ง์ ๊ธฐ์ ๋ค์ด ์คํ์ ๊ธฐ๋ฐ์์ ์ปค์ ๊ธฐ๋ฐ์ผ๋ก ์ ํํ ๊ฒ์ผ๊น์?
์๋ง๋ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ํจ์จ์ ์ผ๋ก ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์๋ํ๋ฉด ์ปค์๋ค์ ๋ฐ์ดํฐ๋ฅผ ์ ์ ์ผ๋ก ์ ์งํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ด์ฃ . ์ฆ, ์์ดํ ๋ค์ด๋ ํ๋ค์ด ์ถ๊ฐ๋๊ณ ์ญ์ ๋๋ค ํด๋ ๊ฐ ์๋ก์ด ํ์ด์ง๋ค์ด ์ฌ์ ํ ์ฌ๋ฐ๋ฅด๊ฒ ๋ก๋๋๋ค๋ ๊ฒ๋๋ค.
์ง๋ 10๋ ๊ฐ real-time ์ดํ๋ฆฌ์ผ์ด์ ์ ํด์ผ ์์์, ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ๋ฐฉ๋ฒ์ ํฐ ํ๋ ฅ์ ์ป๊ฒ ๋์์ต๋๋ค.
๊ธฐ์กด ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉํ์ ๋ ๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ๊ณ ์ ๋ ์ํ๊ฐ ์๋๋ผ๋ฉด ๋ ๊ฐ์ง ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด ๋ ๊ฐ์ง ์ํฉ์ ๋ํด์ ์ข ๋ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ฐ์ดํฐ๊ฐ ์คํต๋๋ ์ค์๊ฐ ์์ ๋ฅผ ์ดํด๋ด ์๋ค. ์ฌ๋ฌ๋ถ์ด ํ์ด์ค๋ถ ๋ด์คํผ๋์ ์ฒ์ ๋๋ฌํ์ ๋ ์ฌ๋ฌ๋ถ์ ์น๊ตฌ๋ค์ด ์์ฑํ ์ต๊ทผ 5๊ฐ์ ๊ฒ์๋ฌผ์ ๋ฐ๋ก ๋ณผ ์ ์์ต๋๋ค.
... ๋ฑ๋ฑ. ๋ค์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ ๋ ๋ค์๊ณผ ๊ฐ์ ์๋ก์ด ๊ฒ์๋ฌผ์ด ๋ก๋๋ฉ๋๋ค.
์ฌ๋ฌ๋ถ์ ์์ ๋ ํ์ด์ง๋ฅผ ๊ธฐ๋ํ๊ฒ ์ง๋ง ์ฌ๋ฌ๋ถ์ด ํ์ด์ง 1์ ๋ณด๊ณ ์๋ ๋์ ์์ด ์ ๊ณผ ์ ์์ ๊นจ์ด ์ด์ ฏ๋ฐค์ ์ฌ๋ฆฐ ์์ ์ ์ฌ์ง์ ์ง์ฐ๊ธฐ๋ก ํ๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค.
์ฌ๋ฌ๋ถ์ด ๋ ๋ง์ ๊ฒ์๋ฌผ์ ๋ก๋ํ๊ธฐ ์ํด ์คํฌ๋กค ํ์ ๋, ๊ฐ์๊ธฐ ์ฌ๋ฌ๋ถ์ด ๋ณด๋ ํ์ด์ง 2๋ ์ด์ ๊ฐ์ ๊ฒ์ ๋๋ค.
์ ์๋ง! ๊ณ ์์ด ์ฌ์ง๋ค์ ์ด๋ ๊ฐ๊ฑธ๊น์?
๋ถํํ๊ฒ๋ ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๊ฒ์ ๋ํด ์ ๊ฒฝ์ฐ์ง ์์ต๋๋ค. ๋จ์ง ๋ค์ 5๊ฐ์ ๊ฒ์๋ฌผ์ ๋ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆด ๋ฟ์ด์ฃ . ์ด 5๊ฐ์ ๊ฒ์๋ฌผ์ ์ฌ์ ํ 5์ ์คํ์ ์ ์์นํ ๊ฒ์ ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋งค๋ฒ ๋ค์๊ณผ ๊ฐ์ด ์ฟผ๋ฆฌ๋ ๊ฒ๋๋ค.
SELECT * FROM table ORDER BY timestamp OFFSET 0 LIMIT 5
SELECT * FROM table ORDER BY timestamp OFFSET 5 LIMIT 5
SELECT * FROM table ORDER BY timestamp OFFSET 10 LIMIT 5
SELECT * FROM table ORDER BY timestamp OFFSET 15 LIMIT 5
...
๊ฐ ๋ผ์ธ์ ํ์ด์ง 1, ํ์ด์ง 2, ํ์ด์ง 3 ๋ฑ์ ์๋ฏธํฉ๋๋ค.
์ด๋ ์ฌ๋ฌ๋ถ์ด ๊ท์ฌ์ด ๊ณ ์์ด ์ฌ์ง๋ค์ ๋ณผ ์ ์๋ค๋ ๊ฒ์ ๋๋ค! ๊ทธ๋ฆฌ๊ณ ๋์ฑ ์ํ๊น๊ฒ๋ ์ฌ๋ฌ๋ถ์ ๊ณ ์์ด ์ฌ์ง์ ์์ด๋ฒ๋ ธ๋ค๋ ๊ฒ์ ์ ์๋ ์๋ค๋ ๊ฑฐ์ฃ . ์ด๊ฒ ๋ค ์ ๋๋ฌธ์ด์์!
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ธ๋ฑ์ค๋ก ์ฌ์ฉ๋๋ ์คํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ๋ ๋์ ๋ฐ์ดํฐ์ ์ ํน์ ๋ ์ฝ๋์ ํฌ์ธํฐ ์ญํ ์ ํ๋ ์ปค์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ง์ง๋ง ํ์ด์ง๊ฐ ์ค๋จ๋ ์์น๋ฅผ ๋ํ๋ ๋๋ค. ์๋ฅผ ๋ค์ด ์ด ์ปค์๋ September 12, 4:02 PM ํ์์คํฌํ๋ฅผ ๊ฐ์ง๋ ๋ฐ์ดํฐ๋ฅผ ๋ง์ง๋ง์ผ๋ก ๋ฐ์๋ค๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์๊ฒ ์๋ ค์ฃผ์ด ํด๋น ํ์์คํฌํ ์ด์ ์ 5๊ฐ์ ๊ฒ์๋ฌผ์ ๋ฐํ๋ฐ์ต๋๋ค.
SELECT * FROM table WHERE cursor > timestamp ORDER BY timestamp LIMIT 5
์ด ๋ฐฉ๋ฒ์ ์์ด ๋ ์ฅ์ ์ฌ์ง์ ์ง์ด ๊ฒ๊ณผ ์๊ด์์ด ๊ณ ์์ด ์ฌ์ง์ด ํฌํจ๋ ์ด์ ๋ฐ์ดํฐ๋ค์ ๊ฐ์ ธ์ฌ ์ ์๋ ๊ฒ๋๋ค. ์ ๋ง ๋คํ์ด์ฃ .
๋ ๋ฒ์งธ ์๋๋ฆฌ์ค๋ฅผ ์๊ฐํด๋ด ์๋ค. ์ฌ๋ฌ๋ถ์ด ํ์ด์ง 1์ ๋ณด๊ณ ์๊ณ ์์ ์ฌ์ ํ ์ ์ ์ทจํด ์ฌ์ง์ ๋ ์ฌ๋ฆฐ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ํ์ด์ง 2๋ฅผ ๋ณด๋ ค๊ณ ํ ๋ ์คํ์ ์ด ์ค๋ณต๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ ๋ ์ทจํ ๊ฑธ๊น์? ์๋๋ฉด ์ด๋ชจ๊ฐ ์ทจํ ๊ฑธ๊น์?
์๋์. ์คํ์ ์ด 5๊ฐ ์๋ 6์์ ์์๋์ด์ผ ํ๋๋ฐ ์ฌ๋ฌ๋ถ์ ๊ฒ์๋ฌผ 1๊ฐ๊ฐ ์ถ๊ฐ๋จ์ ๋ฐ๋ผ ๋ณด์ฌ์ง๋ ๋ฐ์ดํฐ๊ฐ ์ค๋ณต๋๋ฒ๋ฆฐ ๊ฒ์ ๋๋ค.
์ด ์ํฉ์ ์ฌ์ฉ์์๊ฒ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ์๋ ค์ฃผ๊ณ ์ค์ ๋ก๋ ์ ์๋ํ๊ณ ์์ง๋ง ๋ถ์์ ํ๊ฒ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์์ฃผ ์ต์ ์ ์๋๋ฆฌ์ค์ ๋๋ค.
์ฌ๋ฌ๋ถ์ SQL์ OFFSET
์ ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๊ถ๊ธํ์ ์ ์ด ์๋์? ์ ์ญ์ ๊ทธ๋ ์ง ์์์ต๋๋ค. ์ปค์ ๊ธฐ๋ฐ์ด ๊ฐ์ฅ ํจ์จ์ ์ธ ํ์ด์ง๋ค์ด์
์ด๋ผ๊ณ ํ์ด์ค๋ถ์์ ์ฃผ์ฅํ๊ธฐ ์ ๊น์ง๋ ๋ง์ด์ฃ .
์ ๊ฐ ์ฐพ์๋ณธ ๊ฒ์ ์ ๋ฅผ ๋๋ผ๊ฒ ํ์ต๋๋ค.
์คํ์ ์ ๋จ์ํ ๋ ์ฝ๋๋ฅผ ์ ํํ๊ธฐ ์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๊ฑด๋๋ธ ๋ ์ฝ๋ ์์ ๋๋ค.
์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ฒญํ ๋ค์ ๋ฐ์ดํฐ์ ์ ๋ฐํํด์ฃผ๋ ๊ฒ์ด ์๋๋ผ ์ด์ ์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ค์ ๋ชจ๋ ์ค์บํ๋ค๋ ๊ฒ์ธ๋ฐ์. ์คํ์ ์๊ฐ ์ฆ๊ฐํ ์๋ก ์ด๋ ํฐ ๋ฌธ์ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
์ฝ 730๋ง ๊ฐ์ ๋ ์ฝ๋๋ก ๊ตฌ์ฑ๋ ๋ฐ์ดํฐ์ ์์ ์ปค์ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ์ ์คํ์ ๊ธฐ๋ฐ ์ฟผ๋ฆฌ๋ฅผ ๋ชจ๋ ํ ์คํธํ๊ธฐ ์ ๊น์ง๋ ๋ฌธ์ ๊ฐ ์์ ํ ๊ณ์ฐ๋์ง ์์์ต๋๋ค.
์ฌ๊ธฐ์ ์ค์ ์ฌ์ฉ์ ๊ฒฝํ์ผ๋ก ํ๋ํด ๋ณด๊ฒ ์ต๋๋ค. ์ฌ์ฉ์๊ฐ 700๋ง ๋ฒ์งธ ํ์ ํ์ํ๋ ํ์ด์ง๋ก ์ด๋ํด๋ณธ๋ค๊ณ ๊ฐ์ ํ์ฃ .
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉ์๊ฐ ๋ค์ ๋๋ ์ด์ ๋ฒํผ์ ๋๋ ์ ๋ ์๋ก์ด ํ์ด์ง๊ฐ ๋ก๋๋๊ธฐ๊น์ง ์ฝ 0.18์ด๊ฐ ์์๋ฉ๋๋ค.
์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋์ผํ ๋์์์๋ 13์ด๊ฐ ๊ฑธ๋ฆฌ๋ ๊ฒ๋๋ค! ์ด๋ ๊ฐ ํ์ด์ง๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ๋ฐ 13์ด๊ฐ ๊ฑธ๋ฆฐ๋ค๋ ๊ฑฐ๊ณ ์ปดํจํ ์ธ๊ณ์์๋ ์์ํ ๋ก๋ํ๋ค๋ ๊ฒ๊ณผ ๊ฐ์ฃ !
์ค์ ๋ก๋ ์ฌ๋ฌ๋ถ๋ค์ ์ฌ์ฉ์๊ฐ 13์ด๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ธฐ๋ณด๋ค๋ ์ฌ์ดํธ์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค๊ณ ์๊ฐํ๊ณ ๋ค๋ฅธ ๊ณณ์ผ๋ก ์ด๋ํ ๊ฐ๋ฅ์ฑ์ด ๋ ๋์ต๋๋ค.
์ฌ์ฉ์๊ฐ ์ค์ ๋ก 13์ด๋ฅผ ๊ธฐ๋ค๋ ค์ ํด๋น ํ์ด์ง๋ก ์ด๋ํ ํ๋ฅ ์ ์ผ๋ง๋ ๋ ๊น์? ๊ฐ๋ฅ์ ํ๊ฒ ์ง๋ง, ์๋ง ๊ฑฐ์ ๊ทธ๋ด ํ๋ฅ ์ ํฌ๋ฐํ๋ค๊ณ ๋ง์๋๋ฆด ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ 700๋ง ๋ฒ์งธ ๋ ์ฝ๋ ์ด์ ์๋ ์๊ฐ๋ณต์ก๋๊ฐ linearํ O(N), ๋ ๊ตฌ์ฒด์ ์ผ๋ก๋ O(offset+limit)์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์์ UX๋ ๊ฐ์ํ๊ธฐ ์์ํฉ๋๋ค. ๋ฐ๋ฉด์ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ O(1), ๊ตฌ์ฒด์ ์ผ๋ก๋ O(limit)์ ์๊ฐ ๋ณต์ก๋๋ฅผ ๊ฐ์ง๋๋ค.
์ ๊ทธ๋ํ์์๋ ํ์ธํ ์ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด ํผ๋๋ฅผ ๊ณ์ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ์๋ก ํ์ด์ง ๋ก๋ฉ์ด ๋๋ ค์ง๋ ์ด์ ์ ๋ํด ๊ถ๊ธํ ์ ์ด ์์๋ค๋ฉด, ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋นํจ์จ์ฑ์ ๊ฒฝํํด๋ดค๊ธฐ ๋๋ฌธ์ผ ๊ฒ์ ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ ๋ง ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฅ๋ ๊ฒ์ผ๊น์?
์, ๊ผญ ๊ทธ๋ ์ง๋ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ์น๊ตฌ๋ค์ ์ฒ ์ผ์ ์ด๋ํ๊ธฐ ์ ์ ์คํ์ ๊ธฐ๋ฐ์ด ๋ ์ ํฉํ ๊ฒฝ์ฐ๋ฅผ ๋ช ๊ฐ์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
ํ์ด์ค๋ถ์ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๊ฐ๋ฅํ ์ฌ์ฉ๋์ด์ผ ํ๋ค๊ณ ํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ค ์ํฉ์์๋ ๋ถ๊ฐ๋ฅํ๊ฑฐ๋, ์ปค์ ๊ธฐ๋ฐ์ด ํ์ค์ ์ด์ง ์์ ๋๋ ๋ถ๋ช ํ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด ์ฑ๊ณผ ์ด๋ฆ์ผ๋ก ์ ๋ ฌํ ์ ์๋ ์ ์ ํ ์ด๋ธ์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. ๊ตฌํํ๋ ๋ฐ ํ์ํ ์๊ตฌ์ฌํญ์ด ์ ๋ ฌ ๊ธฐ์ค์ผ๋ก ์ฌ์ฉํ ๊ณ ์ ํ ์์ฐจ ์ด์ด๊ธฐ ๋๋ฌธ์ ์ปค์ ๊ธฐ๋ฐ์ ์ฌ์ฉํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ปค์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ ์งํฉ์ ํน์ ์์น๋ฅผ ๊ฐ๋ฆฌํค๊ณ , ํด๋น ๋ ์ฝ๋ ๋ค์์ ๋ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์.
์ฆ ๋๋ถ๋ถ์ ์ปค์ ๊ตฌํ์ ํ์์คํฌํ ์ด์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค. ํ์คํ๊ฒ ์์ฐจ์ ์ด๊ณ ์๊ฐ์ ์ธ๋ถํ๋ ์์ค์ผ๋ก ์ถ์ ํ๋ฉด ํด๋น ์ด์ด ๊ณ ์ ํ๋ค๊ณ ํฉ๋ฆฌ์ ์ผ๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
์ด๋ฆ
์ ์์ฐจ์ ์ผ ์ ์์ง๋ง, ๊ณ ์ ํ์ง๋ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฃผ์์ ๋๋ช
์ด์ธ๋ค์ ๋ง์ด ๋ดค์ผ๋๊น์. ๊ทธ๋์ ์ปค์ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌํํ๊ฒ ๋๋ฉด ๋ฐ์ดํฐ์ ์คํต์ด๋ ์ค๋ณต๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ๋ ๋ฌธ์ ์ ๋ด์ฐฉํ๊ฒ ๋ ๊ฒ์
๋๋ค.
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ๊ณผ ํจ๊ป ์ฌ์ฉ์ ์ ๋ ฌ์ ๊ตฌํํ๋ ค๋ฉด ์ฌ์ฉ์ ์์ด๋๋ ์ด๋ฉ์ผ๊ณผ ๊ฐ์ด ์์ฐจ์ ์ด๋ฉฐ ๊ณ ์ ํ ์ด์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด๋ฆ์ด๋ ์ฑ์ผ๋ก ์ ๋ ฌํด์ผ ํ ๋๋ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ด ์ต์ ์ ๋ฐฉ๋ฒ์ด ์๋ ์ ์์ต๋๋ค. ์ด๋ฆ๊ณผ ์ฑ์ ์ด์ด์ ๊ณ ์ ํ ์ปฌ๋ผ์ผ๋ก ์์ฑํ ์๋ ์๊ณ , ์ฌ๋ฌ ํํ์ ์ฌ์ฉํ์ฌ ๊ณ ์ ํ ์ปฌ๋ผ์ ์ฌ์ฉํ ์๋ ์์ง๋ง ์ด๋ ๊ฒ ํ๋ฉด ์คํ์ ์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋๋ ค์ง ์ ๋๋ก ์๋๊ฐ ๊ฐ์ํฉ๋๋ค. SQL ๋ฌธ์ ์ฐ๊ฒฐ์ด๋ ํํ์ ๋น๊ตํ๋ ๊ฒ์ด O(N), ๊ตฌ์ฒด์ ์ผ๋ก๋ O(์ ์ฒด ๋ฐ์ดํฐ์ )์ ์๊ฐ๋ณต์ก๋๋ฅผ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌ์ค ์ฒซ ๋ฒ์งธ ํ์ด์ง๊ฐ ๊ฐ์ฅ ๋๋ฆฌ๊ฒ ๋ก๋๋ ๊ฒ๋๋ค. ์ด์ํ๊ณ ์ง๊ด์ ์ด์ง๋ ์์ง๋ง SELECT ๋ฌธ์ ๋์๊ฐ์๋ก ๋ ๋ง์ ๋ ์ฝ๋๋ฅผ ์ ์ธํ๊ฒ ๋ฉ๋๋ค.
์ฌ๊ธฐ์์ ์ด ์ด์๋ฅผ ํด๊ฒฐํ ๋ช ๊ฐ์ง ํธ๋ฆญ์ด ์์ต๋๋ค. ์ฐธ๊ณ : ์ด ํ์์ ๋ํด์
์ปค์๊ฐ ๋ฐ๋์ ๊ตฌํํ๊ธฐ ์ด๋ ค์ด ๊ฒ์ ์๋์ง๋ง, ์คํ์ ์ ๊ตฌํํ๋ ๊ฒ์ด ๋งค์ฐ ์ฝ์ต๋๋ค. ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ๋ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ ์ฐพ๊ณ ์๋ค๋ฉด ์คํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํนํ ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฒ์ด ์๋๋ผ๋ฉด์. ํ์ํ์ง ์์๋ฐ ์ผ์ ๋ณต์กํ๊ฒ ๋ง๋ค ํ์๋ ์์ต๋๋ค.
์ง์ ์ปค์๋ฅผ ๊ตฌํํด๋ณธ ๊ฒฐ๊ณผ, 90% ์ฌ๋ก์์ ์ปค์๋ฅผ ๊ตฌํํ๋ ๊ฒ์ด ๊ทธ๋ฆฌ ์ด๋ ต์ง๋ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์คํ์ ๋ณด๋ค๋ ๊ณ ๋ คํด์ผ ํ ์ฃ์ง ์ผ์ด์ค๊ฐ ํจ์ฌ ๋ ๋ง์์ต๋๋ค. ๋ค์ ๋งํ์๋ฉด, ์์ ํ๋ ๊ฒ์ด ์ด๋ ต์ง๋ ์์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ์คํ์ ๋ณด๋ค๋ ์ด๋ ต์ต๋๋ค.
๋ฐ๋ผ์ ์ปค์๋ฅผ ๊ตฌํํ๋ ๋ฐ ์๊ฐ์ด ๋ ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ, ์ฌ๋ฌ๋ถ์ ํ์ฌ ๋๋ PM๋ค์ด ํด์ผ ํ๋ trade-off์ผ ๋ฟ์ ๋๋ค.
์ด๊ฒ์ ์ ํํ ๋งํ์๋ฉด ์คํ์ ๊ธฐ๋ฐ์์๋ ๋ฌดํ ์คํฌ๋กค์ด ๊ตฌํ์ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ด์๋ ์๋๋๋ค. ๊ทธ๋ฌ๋ ์ปค์์ ์ฌ์ฉ์ด ์ฆ๊ฐํ๋ฉด์ ์์ ์ธ๊ธํ ๋ฐ์ดํฐ ์ค๋ณต ๋ฌธ์ ์์ด ํจ์จ์ ์ผ๋ก ๋ฌดํ ์คํฌ๋กค์ ๊ตฌํ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ค์๊ฐ ์ดํ๋ฆฌ์ผ์ด์ ์์ ๋ฌดํ ์คํฌ๋กค์ ๋น๋๊ฐ ์ฆ๊ฐํ์ต๋๋ค.
๋ฌดํ ์คํฌ๋กค์ ์ฌ์ฉ์๊ฐ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ๋ณผ ์ ์๋ ํธ๋ฆฌํ UI์ด๊ธฐ๋ ํ์ง๋ง, ์ฌ์ฉ์๊ฐ ๋ค์ ํ์ด์ง๋ฅผ ๋ณด๊ธฐ ์ํด ๋ฒํผ์ ๋๋ฅด๋ ์์์ ์ธ ๊ฒฐ์ ๊ณผ์ ์ด ์ฌ๋ผ์ง๊ฒ ํฉ๋๋ค. ์ด๋ ์ฌ์ฉ์๊ฐ ๋ ๋ง์ ๊ฒ์๋ฌผ์ ๋ก๋ํ๊ณ ์์์ ์์์ฑ์ง ๋ชปํ ์ ์์ด ๋์ฑ ์ค๋ ์ฑ์ด ๋์ ๊ฒฝํ์ ํ๊ฒ ๋ฉ๋๋ค.
๋ชจ๋ ์ด์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌํ ๋ ์ฝ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋๋ผ๋ ์ค๊ธฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋๋ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ๋งํผ ์ข์ ๊ฒ์ด ์์ต๋๋ค.
์ ํ์ด์ค๋ถ ๊ฐ์ ๊ธฐ์ ๋ค์ด ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋ํด ๊ณผ๊ฐํ ๋ฐ์ธ์ ํ๋ ์ง ์ดํด๊ฐ ๋๊ธฐ ์์ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ ์น์ฌ์ดํธ๊ฐ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉํ์ ๋ ์ป์ ์ ์๋ ํจ๊ณผ๋ค์ด ์๋์ง ์๋ฌธํด๋ณผ ๋ ์ ๋๋ค.
์ปค์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๋ ํ์ ์ด ๋ ๋ค๋ฉด, ์น์ฌ์ดํธ์์ ์ปค์๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์คํํธ์ ๊ธฐ์ฌ๋ฅผ ์ฝ์ด๋ณด์ธ์!
์ถํํฉ๋๋ค!! ๐ ๋๋์ด ๋๊น์ง ๋ค ์ฝ์ผ์ จ์ด์. ์ด ์ํฐํด์ด ๋ง์์ ๋์ จ๋ค๋ฉด ๐, ์๋ clap ๋ฒํผ์ ๋๋ฌ์ฃผ์ธ์ ๐. ์ ์๊ฒ ํฐ ํ์ด ๋ ๊ฒ๋๋ค. ๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ด ์ํฐํด์ ๋ณผ ์ ์๊ฒ ํ๋ต๋๋ค.
์๋ฌธ : Top 5 JavaScript ES12 Features You Should Start Using Now
ECMAScript 2021(12๋ฒ์งธ ๋ฒ์ )์ด ์ด์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ฉฐ, ์๋ก์ด ๊ธฐ๋ฅ๊ณผ ๋ฌธ๋ฒ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. 2021๋ 6์ 22์ผ ECMA ๊ตญ์ ๊ธฐ๊ตฌ์ ์ํด ๋ช ์ธ๊ฐ ํ์ ๋์์ต๋๋ค. ์ด๋ฒ ํฅ์์ ๊ฐ๋ฐ์์ ์์ ์ ์ฝ๊ฒ ์ํํ ์ ์๋๋ก ํ์ฌ JavaScript๋ฅผ ๋์ฑ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ญ๋๋ค.
ECMAScript 2021์์ ์ ๊ณต๋๋ Top 5 ๊ธฐ๋ฅ์ ์์ธํ๊ฒ ์ค๋ช ๋๋ฆดํ ๋, ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์์ ํ์ฉํ์ฌ ์ฌ๋ฌ๋ถ์ด ๋ ์ JavaScript๋ฅผ ์ฌ์ฉํ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋น๊ธฐ๋์ ์๋ จ๋ ๊ฐ๋ฐ์ ๋ชจ๋ ์ด ๊ธ์์ ๋ง์ ๊ฒ์ ์ป์ด๊ฐ์ค ์ ์์ ๊ฒ๋๋ค.
์ซ์ ๊ตฌ๋ถ์๋ ๋ฆฌํฐ๋ด ์ซ์๋ค ์ฌ์ด์ ์ธ๋์ค์ฝ์ด(_)๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ๋์ฑ ๊ฐ๋ ์ฑ์ ๋์ฌ์ค๋๋ค. ์ธ๋์ค์ฝ์ด ๊ธฐํธ๋ ๊ฐ ํ์ผ๋ค์ด ํ์ฑ๋ ๋ ์๋์ผ๋ก ์ ๊ฑฐ๋ฉ๋๋ค.์ซ์ ๊ตฌ๋ถ์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์ถ๋ค๋ฉด ์๋ ์ฝ๋ ์ค๋ํซ์ ์ฐธ๊ณ ํ์ธ์.
// ์ฒ ๋จ์๋ก ๊ตฌ๋ถ๋ ์ญ์ง์ ์ ์ ๋ฆฌํฐ๋ด
let n1 = 1_000_000_000;
console.log(n1); // ์ถ๋ ฅ : 1000000000
// ์ฒ ๋จ์๋ก ๊ตฌ๋ถ๋ ์ญ์ง์ ๋ฆฌํฐ๋ด
let n2 = 1_000_000_000.150_200
console.log(n2); // ์ถ๋ ฅ : 1000000000.1502
// ๋ฐ์ดํธ ๋จ์๋ก ๊ตฌ๋ถ๋ 16์ง์ ์ ์ ๋ฆฌํฐ๋ด
let n3 = 0x95_65_98_FA_A9
console.log(n3); // ์ถ๋ ฅ : 641654651561
// ์ฒ ๋จ์๋ก ๊ตฌ๋ถ๋ BigInt ๋ฆฌํฐ๋ด
let n4 = 155_326_458_156_248_168_514n
console.log(n4); // ์ถ๋ ฅ : 155326458156248168514n
String ํ๋กํ ํ์
์ replaceAll()
ํจ์๋ ์ ๊ท์ ์์ด ๋ชจ๋ ์๋ธ์คํธ๋ง์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋์ฒดํ ์ ์์ต๋๋ค. ๋ง์ฝ ๋ฌธ์์ด์์ replace()
๊ฐ ์ฌ์ฉ๋๋ค๋ฉด, ์ผ์นํ๋ ์ฒซ ๋ฒ์งธ ์ธ์คํด์ค๋ง์ ๋์ฒดํฉ๋๋ค. ๊ทธ๋ฌ๋ replaceAll()
์ ์ผ์นํ๋ ๋ชจ๋ ์ธ์คํด์ค๋ฅผ ๋์ฒดํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// ๋ณ์ ์ ์ธ ๋ฐ ๊ฐ ์ ์ฅ
const orgStr = 'JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification. JavaScript is high-level, often just-in-time compiled and multi-paradigm.';
// replace()๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค ํ๋ ๋์ฒด
let newStr = orgStr.replace('JavaScript', 'TypeScript');
console.log(newStr);
// replaceAll()์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์ธ์คํด์ค ๋์ฒด
let newStr2 = orgStr.replaceAll('JavaScript', 'TypeScript');
console.log(newStr2);
Promise.any
๋ Promise.all()
๊ณผ ๋ฐ๋๋๋ ํจ์๋ก ์ฌ๋ฌ promise ์ค ํ๋๊ฐ resolve๋๋ฉด ํธ๋ฆฌ๊ฑฐ๋ฉ๋๋ค. ๋ฐ๋ฉด์ Promise.all()
์ ๋ชจ๋ promise๊ฐ resolve ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. any()
, all()
, allSettled()
์ ์ฐจ์ด์ ์ ์๋์ ๊ฐ์ต๋๋ค.
any()
: ํ๋์ promise๊ฐ resolve๋๋ฉด ์คํ๋๊ณ , ๋ชจ๋ promise๊ฐ reject๋๋ฉด reject๋ฉ๋๋ค.all()
: ๋ชจ๋ promise๊ฐ resolve๋๋ฉด ์คํ๋๊ณ , ํ๋์ promise๋ผ๋ reject๋๋ฉด reject๋ฉ๋๋ค.allSettled()
: ๋ชจ๋ promise๊ฐ resolve๋๊ฑฐ๋ reject๋๋ฉด ์คํ๋ฉ๋๋ค.Promise.any
๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// Promise ์์ฑ
const promise1 = new Promise((resolve, reject) => {
// 2์ด ํ์ ์ฒซ ๋ฒ์งธ Promise๊ฐ resolve ๋จ
setTimeout(() => resolve("The first promise has been resolved."), 2000);
});
// Promise ์์ฑ
const promise2 = new Promise((resolve, reject) => {
// 1์ด ํ์ ๋ ๋ฒ์งธ Promise๊ฐ resolve
setTimeout(() => resolve("The second promise has been resolved."), 1000);
});
// Promise ์์ฑ
const promise3 = new Promise((resolve, reject) => {
// 3์ด ํ์ ์ธ ๋ฒ์งธ Promise๊ฐ resolve
setTimeout(() => resolve("The third promise has been resolved."), 3000);
});
(async function () {
const data = await Promise.any([promise1, promise2, promise3]);
// Print the data returned from the first resolved Promise.
// ์ฒซ resolved๋ Promise๋ก๋ถํฐ ๋ฆฌํด๋ฐ์ ๋ฐ์ดํฐ ์ถ๋ ฅ
console.log(data);
// ์ถ๋ ฅ : The second promise has been resolved.
})();
๋ง์ฝ ๋ชจ๋ promise๊ฐ reject๋๋ฉด, AggregateError Exception๊ฐ ๋์ ธ์ง๋๋ค. exception์ ์ด๋ป๊ฒ ๋ค๋ค์ผ ํ๋์ง ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// Promise ์์ฑ
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => reject("The first promise has been rejected."), 1000);
});
// Promise ์์ฑ
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => reject("The second promise has been rejected."), 500);
});
// Promise ์คํ
(async function () {
try {
const data = await Promise.any([promise1, promise2]);
console.log(data);
} catch (error) {
// ๋ชจ๋ Promise๊ฐ reject๋๋ฉด try-catch block์ด aggregate error์ ์ฒ๋ฆฌ
console.log("Error: ", error);
}
})();
์ธ ๊ฐ์ง ๋ ผ๋ฆฌ ํ ๋น ์ฐ์ฐ์๋ ECMAScript 2021์์ ๋์ ๋์์ต๋๋ค. ์ด ์ฐ์ฐ์๋ค์ ๋ ผ๋ฆฌ ์ฐ์ฐ์์ ํ ๋น ํํ์์ ์กฐํฉ์ ์ ๊ณตํฉ๋๋ค.
||=
&&=
??=
๋
ผ๋ฆฌ OR ํ ๋น ์ฐ์ฐ์ ||=
๋ ๋ ๊ฐ์ ํผ์ฐ์ฐ์๋ฅผ ๋ฐ์ ์ผ์ชฝ ํผ์ฐ์ฐ์๊ฐ false์ธ ๊ฒฝ์ฐ ์ค๋ฅธ์ชฝ ํผ์ฐ์ฐ์๋ฅผ ์ผ์ชฝ ํผ์ฐ์ฐ์์ ํ ๋นํฉ๋๋ค. ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// ||= ๋ songsCount๊ฐ false (0)์ธ์ง ํ์ธ
// false์ธ ๊ฒฝ์ฐ ์ค๋ฅธ์ชฝ ๊ฐ์ด ์ผ์ชฝ ๋ณ์์ ํ ๋น๋จ
let myPlaylist = {songsCount: 0, songs:[]};
myPlaylist.songsCount ||= 100;
console.log(myPlaylist); // ์ถ๋ ฅ: {songsCount: 100, songs: Array(0)}
๋ ผ๋ฆฌ OR ํ ๋น ์ฐ์ฐ์๋ ์งง์ ํํ์ ์ ๊ณตํ๋๋ฐ ์๋ ํํ๊ณผ ๋์ผํ ํจ๊ณผ์ ๋๋ค.
a || (a = b)
๋
ผ๋ฆฌ AND ํ ๋น ์ฐ์ฐ์ &&=
๋ ์ผ์ชฝ ํผ์ฐ์ฐ์๊ฐ true์ธ ๊ฒฝ์ฐ์๋ง ์ค๋ฅธ์ชฝ ํผ์ฐ์ฐ์๋ฅผ ์ผ์ชฝ ํผ์ฐ์ฐ์์ ํ ๋นํฉ๋๋ค. ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// &&= ๋ filesCount๊ฐ true์ธ์ง ํ์ธ
// true์ธ ๊ฒฝ์ฐ ์ค๋ฅธ์ชฝ ๊ฐ์ด ์ผ์ชฝ ๋ณ์์ ํ ๋น๋จ
let myFiles = {filesCount: 100, files:[]};
myFiles.filesCount &&= 5;
console.log(myFiles); // ์ถ๋ ฅ: {filesCount: 5, files: Array(0)}
๋ ผ๋ฆฌ AND ํ ๋น ์ฐ์ฐ์ ๋ํ ํ๋์ short-circuit์ผ๋ก ์๋ ํํ๊ณผ ๋์ผํ ํจ๊ณผ์ ๋๋ค.
a && (a = b)
Nullish ๋ณํฉ ํ ๋น ์ฐ์ฐ์ ??=
๋ ์ผ์ชฝ ํผ์ฐ์ฐ์๊ฐ null์ด๊ฑฐ๋ undefined์ธ ๊ฒฝ์ฐ์๋ง ์ค๋ฅธ์ชฝ ํผ์ฐ์ฐ์๋ฅผ ์ผ์ชฝ ํผ์ฐ์ฐ์์ ํ ๋นํฉ๋๋ค. ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
// ??=๋ lastname์ด null ๋๋ undefined์ธ์ง ํ์ธ
// null ๋๋ undefined๋ผ๋ฉด ์ค๋ฅธ์ชฝ ๊ฐ์ด ์ผ์ชฝ ๋ณ์์ ํ ๋น๋จ
let userDetails = {firstname: 'Katina', age: 24}
userDetails.lastname ??= 'Dawson';
console.log(userDetails); // ์ถ๋ ฅ: {firstname: 'Katina', age: 24, lastname: 'Dawson'}
Nullish ๋ณํฉ ํ ๋น ์ฐ์ฐ์ ๋ํ ํ๋์ short-circuit์ผ๋ก ์๋ ํํ๊ณผ ๋์ผํ ํํ์ ๋๋ค.
a ?? (a = b)
ํด๋์ค ๋ฉ์๋์ ํ๋กํผํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก publicํ์ง๋ง ํด์ ์ ๋์ฌ(#
)๋ฅผ ์ฌ์ฉํ๋ฉด private ๋ฉ์๋์ ํ๋กํผํฐ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. privacy ์บก์ํ๋ ECMAScript 2021 ์
๋ฐ์ดํธ๋ถํฐ ์ ์ฉ๋ ๊ธฐ๋ฅ์
๋๋ค. privateํ ๋ฉ์๋์ ํ๋กํผํฐ๋ ํด๋์ค ๋ด์์๋ง ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค. ๊ด๋ จํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
class User {
constructor() {}
// ๋ฉ์๋ ์ด๋ฆ ์์ '#'์ ๋ถ์ด๋ฉด private ๋ฉ์๋๊ฐ ๋จ!
#generateAPIKey() {
return "d8cf946093107898cb64963ab34be6b7e22662179a8ea48ca5603f8216748767";
}
getAPIKey() {
return this.#generateAPIKey();
}
}
const user = new User();
const userAPIKey = user.getAPIKey();
console.log(userAPIKey); // ์ถ๋ ฅ: d8cf946093107898cb64963ab34be6b7e22662179a8ea48ca5603f8216748767
private ์ ๊ทผ์๋ privateํ Getter์ Setter์
๋๋ค. Getter๋ ํด๋์ค ํ๋กํผํฐ์ ๊ฐ์ ๊ฐ์ ธ์ค๊ฒ ํ๊ณ , Setter๋ ํด๋์ค ํ๋กํผํฐ์ ๊ฐ์ ํ ๋นํฉ๋๋ค. ํด์ ์ ๋์ฌ(#
)๋ฅผ ์ฌ์ฉํ์ฌ private getter๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.
get #newAccountPassword() {}
๋น์ทํ๊ฒ private setter๋ฅผ ์ ์ํ ์๋ ์์ฃ .
set #generateAccountPassword(newPassword) {}
์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
class Str {
// ์์ฑ ์ด๋ฆ ์์ ํด์ ์ ๋์ฌ๋ฅผ ๋ถ์ด๋ฉด private์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
#uniqueStr;
constructor() {}
// private setter๋ ์ด๋ฆ ์์ '#'๋ฅผ ๋ถ์
๋๋ค.
set #generateUniqueStringByCustomLength(length = 24) {
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let randomStr = "";
for (let i = 0; i < length; i++) {
const randomNum = Math.floor(Math.random() * characters.length);
randomStr += characters[randomNum];
}
this.#uniqueStr = randomStr;
}
// Public Setter
set setRandomString(length) {
this.#generateUniqueStringByCustomLength = length;
}
// private getter๋ ์ด๋ฆ ์์ '#'๋ฅผ ๋ถ์
๋๋ค.
get #fetchUniqueString() {
return this.#uniqueStr;
}
// Public Getter
get getRandomString() {
return this.#fetchUniqueString;
}
}
const str = new Str();
// ํด๋์ค ๋ด์์ private setter์ ์ ๊ทผ ๊ฐ๋ฅํ public setter๋ฅผ ํธ์ถํฉ๋๋ค.
str.setRandomString = 20;
// ํด๋์ค ๋ด์์ private getter์ ์ ๊ทผ ๊ฐ๋ฅํ public getter๋ฅผ ํธ์ถํฉ๋๋ค.
const uniqueStr = str.getRandomString;
console.log(uniqueStr);
๋๋์ด ๋์ ๋๋ค! JavaScript ES12์์ ์ ๊ณต๋๋ ๊ธฐ๋ฅ๋ค์ ๋ฐฐ์๋ณด์ จ์ต๋๋ค. ์ด์ ์์์ ๋ฐฐ์ด ๊ธฐ๋ฅ๋ค์ ์ฌ๋ฌ๋ถ๋ค์ด ํ๊ณ ์๋ ํ๋ก์ ํธ๋ ์์ผ๋ก ํ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด์ธ์.
์๋ฌธ : Understanding Javascript Function Executions โ Call Stack, Event Loop , Tasks & more
์์ฆ ์น ๊ฐ๋ฐ์๋ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ ๋ธ๋ผ์ฐ์ ๋ด์์ ์ธํฐ๋ํฐ๋ธํ ์์๋ฅผ ๋์์ํค๊ฑฐ๋ ์ปดํจํฐ ๊ฒ์, ๋ฐ์คํฌํ ์์ ฏ, ํฌ๋ก์คํ๋ซํผ ๋ชจ๋ฐ์ผ ์ฑ ์ ์ ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ๊ธฐ ์ํด ์๋ฒ์ฌ์ด๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ(node.js๋ฅผ ๋ง์ด ์ฌ์ฉ)์ ์ด๋ฅด๊ธฐ๊น์ง ์คํฌ๋ฆฝํธ ์ธ์ด๋ก ๋ค์ํ ๊ฒ์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ ๊ธฐ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด๋ถ ๋์์ ์ดํดํ๋ ๊ฒ๊ณผ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์์ฃผ ์ค์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ์ํฐํด์์ ์ด๋ฐ ์ฃผ์ ๋ค์ ๋ํด ๋ค๋ฃฐ ๊ฒ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์ํ๊ณ๋ ๊ทธ ์ด๋ ๋๋ณด๋ค ๋ณต์กํด์ก๊ณ ์์ผ๋ก๋ ๊ณ์ ๋ณต์กํด์ง ๊ฒ๋๋ค. Webpack, Babel, ESLint,Mocha, Karma, Grunt ๋ฑ ๋ชจ๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ์ํ๊ธฐ ์ํด ํ์ํ ๋๊ตฌ๋ค์ ์์ฒญ๋ฉ๋๋ค. ์ด๋ค ๋๊ตฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๊ณ ๊ทธ ๋๊ตฌ๋ ์ด๋ค ์ผ์ ํ ๊น์? ์ค๋๋ ์น ๊ฐ๋ฐ์๋ค์ ๊ณ ๊ตฐ๋ถํฌ๋ฅผ ์์ฃผ ์ ์ค๋ช ํด์ฃผ๋ ๋งํ๋ฅผ ์ฐพ์์ต๋๋ค.
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์๋ค์ ์ด๋ค ํ๋ ์์ํฌ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ๊น์ด ์์๋ณด๊ธฐ ์ ์ ๋ฃจํธ ๋ ๋ฒจ์์ ๋ด๋ถ์ ์ผ๋ก ์ด๋ป๊ฒ ๋์ํ๋์ง์ ๋ํ ๊ธฐ์ด ์ง์๋ค์ ์์์ผ ํฉ๋๋ค. ๋๋ถ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์๋ค์ ์๋ง ํฌ๋กฌ์ ๋ฐํ์์ธ V8์ด๋ผ๋ ๋จ์ด์ ๋ํด ๋ค์ด๋ณด์ จ์ ๊ฒ๋๋ค. ๊ทธ๋ ์ง๋ง ์ ํํ V8์ด ๋ฌด์์ ํ๋์ง ์์ง ๋ชปํ๋ ๋ถ๋ค๋ ์๊ฒ ์ฃ . ์ ๋ ๊ฐ๋ฐ์๋ก์์ ์ปค๋ฆฌ์ด ์ฒซ 1๋ ๋์ ์ฃผ์ด์ง ์ผ์ ๋ง๋ฌด๋ฆฌํ๋ ๊ฒ์ ์ฃผ๋ก ํ๊ธฐ์ ์ด๋ฐ ํ๋ คํ ์ฉ์ด๋ค์ ๋ํด์๋ ์ ๋ชฐ๋์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์ด๋ป๊ฒ ์ด๋ฐ ์ผ๋ค์ ํด๋ด๋์ง์ ๋ํ ์ ์ ํธ๊ธฐ์ฌ์ ๋ง์กฑ์ํค์ง ๋ชปํ์ฃ . ์ ๋ ๊ตฌ๊ธ์ ๋ํด ๋ ๊น์ด ํ๋ณด๊ธฐ๋ก ๊ฒฐ์ ํ๊ณ Phili Roberts๊ฐ JS ์ปจํผ๋ฐ์ค์์ ์งํํ ์ด๋ฒคํธ ๋ฃจํ์ ๋ํ ๋ฉ์ง ๊ฐ์ฐ๊ณผ ๊ฐ์ ๋ช๋ช ์ข์ ๋ธ๋ก๊ทธ ํฌ์คํ ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ทธ๋์ ๋ฐฐ์ด ๊ฒ๋ค์ ์์ฝํด์ ๊ณต์ ํ๊ณ ์ ํ์ต๋๋ค. ์์์ผ ํ๋ ๋ด์ฉ๋ค์ด ๋๋ฌด ๋ง์ ์ํฐํด์ ๋ ํํธ๋ก ๋๋์์ต๋๋ค. ์ด๋ฒ ํํธ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์ฉ์ด๋ฅผ ์๊ฐํ ๊ฒ์ด๊ณ ๋ ๋ฒ์งธ ํํธ์์๋ ๊ฐ ์ฉ์ด๋ค์ ์ฐ๊ฒฐํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋์ ์ฑ๊ธ ๋์์ฑ ์ธ์ด์ ๋๋ค. ์ฆ ํ ๋ฒ์ ํ๋์ ํ์คํฌ, ์ฝ๋ ํ ์กฐ๊ฐ์ ๋ค๋ฃฐ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ํ ์๋ฐ์คํฌ๋ฆฝํธ๋ (V8 ๋ด๋ถ์ ๊ตฌํ๋) ์๋ฐ์คํฌ๋ฆฝํธ ๋์์ฑ ๋ชจ๋ธ์ ๊ตฌ์ฑํ๋ ํ๊ณผ ํ ๊ทธ๋ฆฌ๊ณ ํ๋์ ์ฝ์คํ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด ์ฉ์ด๋ค์๊ฒ ๋ํด ์์๋ด ์๋ค.
ํจ์ ํธ์ถ๊ณผ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฌ ํ๋ก๊ทธ๋จ ์์น๋ฅผ ์ ์ฅํด๋๋ ์๋ฃ๊ตฌ์กฐ์
๋๋ค. ์ฐ๋ฆฌ๊ฐ ํจ์๋ฅผ ์คํํ๊ธฐ ์ํด ํธ์ถํ ๋ ์คํ์ ๋ฌด์ธ๊ฐ๋ฅผ push
ํด๋๊ณ ํจ์๋ก๋ถํฐ ๋ฆฌํด๋ฐ์ ๋ ์คํ์ top
์์ ํด๋น ํจ์๋ฅผ pop
ํฉ๋๋ค.
์์ ํ์ผ์ ์คํํ ๋ ์คํ์ด ์์๋๋ ๋ฉ์ธ ํจ์๊ฐ ๋จผ์ ๋ณด์
๋๋ค. console.log(bar(6))
๋ก๋ถํฐ ๊ฐ์ ์คํ์ push
ํ ํ ์ธ์์ ํจ๊ป bar
ํจ์๋ก ๋์ด๊ฐ๋๋ค. ๋ค์ foo
ํจ์๋ฅผ ํธ์ถํ์ฌ ํด๋น ํจ์๋ฅผ ์คํ์ push
ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ foo
ํจ์๊ฐ ๋ฆฌํดํ๋ฉด ์คํ์์ pop
๋๊ณ ๋น์ทํ๊ฒ bar
๊ฐ ์ฐจ๋ก๋๋ก pop
๋ฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก console
์ด ๊ฐ์ ์ถ๋ ฅํ๋ฉด์ pop
๋ฉ๋๋ค. ์ด ๋ชจ๋ ๊ฒ๋ค์ ํ๋ฒ์ ํ๋์ฉ ์คํ๋ฉ๋๋ค.
์ฌ๋ฌ๋ถ๋ค์ ๋ธ๋ผ์ฐ์ ์ฝ์์ฐฝ์์ ๊ธธ๊ณ ๋นจ๊ฐ ์ค๋ค๋ก ์ฑ์์ง ์๋ฌ ์คํ์ด ์ถ์ ๋ ๊ฒ์ ์ ์ด๋ ํ๋ฒ์ฏค์ ๋ณธ ์ ์ด ์์ผ์ค ๊ฒ๋๋ค. ์๋ฌ ์คํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฌ ์ํ์ ์์์ ์๋์ ์์๋ก ์คํจํ ์์น๋ฅผ ๋ณด์ฌ์ค๋๋ค. (์๋ ์ด๋ฏธ์ง ์ฐธ๊ณ )
๋๋๋ก ์ฌ์ฐ๋ฆฌ๋ ํจ์๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํธ์ถํ๋ค๊ฐ ๋ฌดํ ๋ฃจํ์ ๋น ์ง๊ธฐ๋ ํฉ๋๋ค. ๋ํ ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ฌ์ฉํ๋ฉด 16,000 ํ๋ ์์ ์คํ ํฌ๊ธฐ์ ์ ํ์ ๋๊ฒ ๋์ด ํ๋ก๊ทธ๋จ์ด ์ฃฝ๊ณ Max Stack Error Reached ์๋ฌ๋ฅผ throwํฉ๋๋ค.
๊ฐ์ฒด๋ค์ (๋๋ถ๋ถ ๋น๊ตฌ์กฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ธ) Heap์ ํ ๋น๋ฉ๋๋ค. ๋ณ์๋ ๊ฐ์ฒด๋ค์ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ํ์์ ์ด๋ฃจ์ด์ง๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์์ ์ฒ๋ฆฌ๋๋ ๋ฉ์ธ์ง๋ค์ ๋ชฉ๋ก๊ณผ ๊ด๋ จ๋์ด ์คํํ ์ฝ๋ฐฑ ํจ์๋ค์์ ๋ด๋ ๋ฉ์ธ์ง ํ๋ฅผ ๊ฐ๊ณ ์์ต๋๋ค. ์คํ์ ์ฉ๋์ด ์ถฉ๋ถํ๋ฉด ํ์์ ๋ฉ์ธ์ง๋ฅผ ๊ฐ์ ธ์ ๊ด๋ จ๋ ํจ์๋ฅผ ํธ์ถํฉ๋๋ค. ์คํ์ด ๋ค์ ๋น์์ง ๋๊น์ง ๋ฉ์ธ์ง๊ฐ ์ฒ๋ฆฌ๋ฉ๋๋ค. ์ด๋ฌํ ๋ฉ์ธ์ง๋ค์ ์ฝ๋ฐฑ ํจ์๊ฐ ์ฃผ์ด์ง (๋ง์ฐ์ค ํด๋ฆญ ์ด๋ฒคํธ๋ HTTP ์์ฒญ์ ๋ํ ์๋ต์ ๋ฐ์ ๊ฒฝ์ฐ์ ๊ฐ์) ์ธ๋ถ ๋น๋๊ธฐ ์ด๋ฒคํธ์ ๋ํ ์๋ต์ผ๋ก ํ์ ๋ค์ด๊ฐ๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ ๋ฒํผ์ ํด๋ฆญํ์ผ๋ ์ฝ๋ฐฑํจ์๊ฐ ๋ฐ๋ก ์๋ค๋ฉด ํ์ ๋ค์ด๊ฐ๋ ๋ฉ์ธ์ง๋ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์ ์ฑ๋ฅ์ ํ๊ฐํ ๋ ์คํ์ ํจ์๋ฅผ ๋๋ฆฌ๊ฒ ๋๋ ๋น ๋ฅด๊ฒ ์กฐ์ํฉ๋๋ค. console.log()
์ ๊ฐ์ ํจ์๋ ๋น ๋ฅด๊ธด ํ์ง๋ง for
๋ while
๋ฌธ ์์์ ์์ฒ ๋ฒ, ์๋ฐฑ๋ง ๋ฒ ๋ฐ๋ณตํ๊ฒ ๋๋ฉด ๋๋ ค์ง๊ณ , ์คํ์ ๊ทธ๋งํผ ๋ง์ด ์ฐจ์งํ๊ณ ๋๋ก๋ ์คํ์ ๋ธ๋ฝํด๋ฒ๋ฆด ๊ฒ๋๋ค. ์ด๋ฐ ๊ฒ์ blocking script๋ผ ๋ถ๋ฅด๋ฉฐ, Webpage Speed Insights์์ ์๋ง ๋ณด๊ฑฐ๋ ๋ค์ผ์
จ์ ๊ฒ์
๋๋ค.
๋คํธ์ํฌ ์์ฒญ์ด๋ ์ด๋ฏธ์ง ์์ฒญ์ ๋๋ฆด ์ ์์ง๋ง ๋คํํ๋ ์๋ฒ์ ๋ณด๋ด๋ ์์ฒญ๋ค์ ๋น๋๊ธฐ ํจ์์ธ AJAX๋ฅผ ํตํด ์ด๋ฃจ์ด์ง๋๋ค. ๋ง์ฝ ๋คํธ์ํฌ ์์ฒญ๋ค์ด ๋๊ธฐ ํจ์๋ฅผ ํตํด ๋ง๋ค์ด์ก๋ค๋ฉด ์ด๋ค ์ผ์ด ์๊ธธ๊น์? ๋คํธ์ํฌ ์์ฒญ์ ๋ณดํต ๋ค๋ฅธ ์ปดํจํฐ๋ ์ด๋๊ฐ์ ์๋ ๊ธฐ๊ณ์ ์๋ ์ด๋ค ์๋ฒ์๊ฒ ๋ณด๋ด์ง๋๋ค. ๊ทธ๋ ๊ธฐ์ ๋ค์ ์๋ต์ ๋ฐ์ ๋๊น์ง ์๊ฐ์ด ๊ฝค ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ๊ทธ ์ฌ์ด์ CTA ๋ฒํผ์ ํด๋ฆญํ๊ฑฐ๋ ๋ค๋ฅธ ๊ฒ๋ค์ ๋ ๋๋งํ ๊ฒ ์๋๋ผ๋ ์คํ์ด ๋ธ๋ฝ๋์ด ์๋ฌด๋ฐ ์ผ๋ ์ผ์ด๋์ง ์์ต๋๋ค. Ruby์ ๊ฐ์ ๋ฉํฐ ์ค๋ ๋ ์ธ์ด์์๋ ์ด๋ฐ ์ผ๋ค์ด ์ฒ๋ฆฌ ๊ฐ๋ฅํ์ง๋ง ์๋ฐ์คํฌ๋ฆฝํธ์ ๊ฐ์ ์ฑ๊ธ ์ค๋ ๋ ์ธ์ด์์๋ ์คํ์ ํจ์๊ฐ ๊ฐ์ ๋ฐํํ ๋๊น์ง ๊ฐ๋ฅํ์ง ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ฌด ๊ฒ๋ ํ ์ ์์ด ์นํ์ด์ง๋ ๋ง๊ฐ์ ธ ๋ฒ๋ฆฝ๋๋ค. ์ฌ์ฉ์๋ค์ด ์ ๋์ ์ธ UI๋ฅผ ์ํ๋ค๋ฉด ์ด๋ฐ ์ํฉ์ ์ข์ง ์์ต๋๋ค. ์ด ์ผ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ ๊น์?
"JS์์ ๋์์ฑ์ ๋น๋๊ธฐ ์ฝ๋ฐฑ์ ์ ์ธํ๊ณ ํ๋ฒ์ ํ๋์ฉ์ ์๋ฏธํ๋ค."
๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ ๋น๋๊ธฐ ์ฝ๋ฐฑ์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ์ฆ ์ฝ๋์ ์ผ๋ถ๋ฅผ ์คํํ๊ณ ๋์ค์ ์คํํ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฃผ๋ ๊ฒ์ด์ฃ . ์ฐ๋ฆฌ๋ ๋ชจ๋ $.get(),setTimeout(),setInterval(), Promises
๋ฑ๊ณผ ํจ๊ป AJAX ์์ฒญ๊ณผ ๊ฐ์ ๋น๋๊ธฐ ์ฝ๋ฐฑ์ ๊ฒฝํํ์ ๊ฒ๋๋ค. Node๋ ๋น๋๊ธฐ ํจ์ ์คํ์ ์ ๋ถ์
๋๋ค. ์ด๋ฐ ๋น๋๊ธฐ ์ฝ๋ฐฑ๋ค์ ์ฆ์ ์คํ๋์ง ์๊ณ ๋์ค์ ์คํ๋ฉ๋๋ค. ๊ทธ๋์ console.log(), ์ํ์ ์ฐ์ฐ
๊ณผ ๊ฐ์ ๋๊ธฐ ํจ์๋ค์ฒ๋ผ ์คํ์ ๋ฐ๋ก push
๋์ง ์์ต๋๋ค. ๊ทธ๋ผ ๋๋์ฒด ๋น๋๊ธฐ ํจ์๋ค์ ์ด๋์ ๊ฐ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌ๋๋ ๊ฑธ๊น์?
์ ์ฝ๋์์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์์ ๋คํธ์ํฌ ์์ฒญ์ด ์คํ๋๋ ๊ฒฝ์ฐ
onreadystatechange
์ด๋ฒคํธ์ ๋ฏธ๋์ ์ธ์ ๊ฐ ์๋ต์ด ๋์ฐฉํ์ ๋ ์คํํ ์ฝ๋ฐฑํจ์๋ก ์ต๋ช
ํจ์๋ฅผ ์ ๋ฌํฉ๋๋ค.caller
๋ฅผ ์๋ต์์ ๋ถ๋ฆฌ๋๋ฉด ๋น๋๊ธฐ ์์
์ด ์๋ฃ๋๊ณ ํธ์ถ์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์์ด ๋ค๋ฅธ ์์
์ ์ํํ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก DOM ์ด๋ฒคํธ๋ HTTP ์์ฒญ, setTimeout๊ณผ ๊ฐ์ด ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด C++๋ก ๊ตฌํ๋ ๋ธ๋ผ์ฐ์ ์ ์ํด ์์ฑ๋ ์ค๋ ๋์ธ ๋ธ๋ผ์ฐ์ API๊ฐ ์์ํ๊ณ API๋ฅผ ํธ์ถ๋ฉ๋๋ค.
๋ธ๋ผ์ฐ์ ์น API ์ค๋ ๋๋ DOM ์ด๋ฒคํธ, HTTP ์์ฒญ, setTimeout๊ณผ ๊ฐ์ ๋น๋๊ธฐ ์ด๋ฒคํธ๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด C++๋ก ๊ตฌํ๋ ๋ธ๋ผ์ฐ์ ์ ์ํด ์์ฑ๋ฉ๋๋ค.
WebAPI๋ ์ค์ค๋ก ์คํ์ ์คํ ์ฝ๋๋ก ๋ค์ด๊ฐ ์ ์์ต๋๋ค. ๋ง์ฝ ๊ฐ๋ฅํ๋ค๋ฉด ์ฝ๋ ์ค๊ฐ์ API๊ฐ ๋ฌด์์๋ก ๋ํ๋ฌ์ ๊ฒ๋๋ค. ์์์ ๋ค๋ฃฌ ๋ฉ์ธ์ง ์ฝ๋ฐฑ ํ๋ ๊ทธ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. WebAPI๋ ์คํ์ด ์๋ฃ๋๋ฉด ์ฝ๋ฐฑํจ์๋ฅผ ํ๋ก push
ํฉ๋๋ค. ์ด๋ฒคํธ ๋ฃจํ๋ ํ์ ์๋ ์ด ์ฝ๋ฐฑํจ์๋ค์ ์คํ์ ์ฑ
์์ง๊ณ , ์คํ์ด ๋น ๊ฒฝ์ฐ์ push
ํ๋ ์ญํ ์ ํฉ๋๋ค. ์ด๋ฒคํธ ๋ฃจํ์ ๊ธฐ๋ณธ์ ์ธ ์ผ์ ์คํ๊ณผ ํ์คํฌ ํ๋ฅผ ๋ณด๋ค๊ฐ ์คํ์ด ๋น์์ ๋ ํ์ ์ฒซ ๋ฒ์งธ ํ์คํฌ๋ฅผ ์คํ์ push
ํ๋ ๊ฒ์
๋๋ค. ๊ฐ ๋ฉ์ธ์ง๋ ์ฝ๋ฐฑ์ ๋ค๋ฅธ ๋ฉ์ธ์ง๊ฐ ์ฒ๋ฆฌ๋๊ธฐ ์ ์ ์์ ํ ์ฒ๋ฆฌ๋ฉ๋๋ค.
while (queue.waitForMessage()) {
queue.processNextMessage();
}
์น ๋ธ๋ผ์ฐ์ ์์ ๋ฉ์ธ์ง๋ค์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์๊ฐ์ ์ถ๊ฐ๋๊ณ , ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ด๋ฒคํธ์ ์ฅ์ฐฉ๋ฉ๋๋ค. ๋ฆฌ์ค๋๊ฐ ์์ผ๋ฉด ์ด๋ฒคํธ๋ ์ฌ๋ผ์ง๋๋ค. ๊ทธ๋์ ํด๋ฆญ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์๋ ์๋ฆฌ๋จผํธ๋ฅผ ํด๋ฆญํ์ ๋ ๋ฉ์ธ์ง๊ฐ ๋ํด์ง๋๋ค. ์ด ์ฝ๋ฐฑ ํจ์์ ํธ์ถ์ ์ฝ์คํ์ ์ด๊ธฐ ํ๋ ์ ์ญํ ์ ํ๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋จ์ผ์ค๋ ๋์ด๋ฏ๋ก ๋ชจ๋ ํธ์ถ์ด ๋ฐํ๋ ๋๊น์ง ์๋ก์ด ๋ฉ์ธ์ง๋ฅผ ํด๋งํ๊ฑฐ๋ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ค๋จ๋ฉ๋๋ค. ๊ทธ ๋ค์์ (๋๊ธฐ) ํจ์๊ฐ ์คํ์ ์๋ก์ด ์ฝํ๋ ์์ ์ถ๊ฐ๋ฉ๋๋ค.
๋ค์ ํํธ์์ ์ ์ ์ฐจ๋๋ก ์ฝ๋๊ฐ ์คํ๋๋ ์๊ฐ์ ์ธ ์ ๋๋ฉ์ด์ ๊ณผ ๋๋ถ์ด ํ์์ ์ฐ์ ์์๊ณผ ๋์ ๋น๋๊ธฐ ํจ์์ ์ ํ ๋ฑ ๋น๋๊ธฐ ํจ์์ ์ฌ๋ฌ ์ ํ์ ์ค๋ช ํ๊ฒ ์ต๋๋ค. ๋ํ ์ผ๋ถ ํจ์๋ฅผ ์ํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ ๋ก ๋๋ ์ด์ ๊ฐ์ hacks์ ๋ํด ๋ง์๋๋ฆฌ๊ฒ ์ต๋๋ค.
์๋ฌธ : Using the new JavaScript .at() method์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ .at()
๋ฉ์๋๋ ์ธ๋ฑ์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ฆฌ๋จผํธ๋ฅผ ์ ํํ ์ ์๋๋ก ํ๊ธฐ ์ํด ECMA ์ธํฐ๋ด์
๋ TC39์ 8์ ๋ฆด๋ฆฌ์ฆ์์ ์๊ฐ๋์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ์๋ฆฌ๋จผํธ๋ฅผ ์ ํํ๋ ๊ฒ์ ๊ฐ๋ฐํ๋ ๋ฐ ์์ด ํํ๊ฒ ๋ฐ์ํ๋ ์ผ์ด์ง๋ง, .at()
๋ฉ์๋๊ฐ ๋ํ๋๊ธฐ ์ ๊น์ง ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ฐฐ์ด์ ์ฒ์์ด๋ ๋ ๋๋ ๋ฌธ์์ด ๋ด์์ ์๋ฆฌ๋จผํธ๋ ๋ฌธ์๋ฅผ ์ ํํ๋ ๋ฉ์๋์ ๊ธฐ์ ๋ง ์กด์ฌํ์ต๋๋ค.
๋๊ดํธ ํ๊ธฐ์ธ []
๋ ๋ณดํต ํน์ ์ธ๋ฑ์ค์ ์๋ฆฌ๋จผํธ๋ฅผ ๊ฐ์ ธ์ฌ ๋ ์ฌ์ฉ๋๋๋ฐ, ์ด๋ ๋จ์ ์ด ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ฐฐ์ด์ ๋ง์ง๋ง ์์ดํ
์ ์ ๊ทผํ๊ธฐ ์ํด ํ์ด์ฌ๊ณผ ๊ฐ์ ์ธ์ด์์ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ arr[-1]
๊ณผ ๊ฐ์ด ์์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ ๊ฒฐ๊ณผ ๊ฐ๋ฐ์๋ค์ slice()
๋ฉ์๋์ length
ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐ์ด์ ๋์ ์๋ ์์ดํ
์ ์ ํํฉ๋๋ค. ๊ทธ๋ผ์๋ ์ด ๋ฐฉ๋ฒ ๋ํ ๋จ์ ์ด ์์ต๋๋ค.
์ด ํํ ๋ฆฌ์ผ์์๋ .at()
๋ฉ์๋์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ดํด๋ณด๊ณ ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐฉ๋ฒ๊ณผ ๋น๊ตํ์ฌ ์ผ๋ง๋ ๋ ๋์์ก๋์ง ๋ํ ์์๋ณด๊ฒ ์ต๋๋ค.
.at()
๋ฉ์๋๋ ์ธ๋ฑ์ฑ ๊ฐ๋ฅํ ๊ฐ์ฒด์ prototype
์ ์์นํฉ๋๋ค.
์ธ๋ฑ์ค ํญ๋ชฉ์ ํํํ ์ ์๋ ์ด ๊ฐ์ฒด๋ค์ Array
, String
, TypedArray
์ ๊ฐ์ ํด๋์ค๋ฅผ ํฌํจํ๋๋ฐ, ๋ํ ๊ฐ ํด๋์ค๋ Array.prototype.at()
, String.prototype.at()
, TypedArray.prototype.at()
๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก
์ธ๋ฑ์ฑ ๊ฐ๋ฅํ ๊ฐ์ฒด์์ ๋ฐ๋ก .at()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
.at()
๋ฉ์๋์ ์ฅ์ ์ ๋ณด๊ธฐ ์ํด ๋น๊ต์ ๋ชฉ์ ์ผ๋ก ๊ธฐ์กด์ ๋ฐฉ๋ฒ๋ค์ ๋ํด ๋น ๋ฅด๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ ์
๋ฌธ์๋ค์๊ฒ๋ ๋ค์๊ธ ํ๊ธฐํ๋ ์ญํ ๋ ํด์ค ๊ฒ์
๋๋ค.
arr
์ด๋ผ๋ ๋ฐฐ์ด์ด ์๋ค๊ณ ํด๋ด
์๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
๋๊ดํธ []
์ ์ฌ์ฉํ์ฌ arr
๋ฐฐ์ด์์ ํน์ ์ธ๋ฑ์ค์ ์์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด arr[0]
์ ์ฒซ ๋ฒ์งธ ์์์ธ 1
์ ๊ฐ์ ธ์ค๊ฒ ์ฃ . ๊ทธ๋ฌ๋ ๋ฐฐ์ด์ ๊ธธ์ด๋ฅผ ์ ์ ์๋ ์ํฉ์ด๋ผ๋ฉด length
ํ๋กํผํฐ๋ slice()
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ ๊ฒ์
๋๋ค.
length
ํ๋กํผํฐ ์ฌ์ฉํ๊ธฐlength
ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ต๋๋ค.
arr[arr.length - N];
์ฌ๊ธฐ์ N
์ ๋ฐฐ์ด์ ๋์์๋ถํฐ n๋ฒ์งธ ์์๋ฅผ ๊ฐ์ ธ์จ๋ค๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ๋ํ ์ด ๋ฐฉ๋ฒ์ ํตํด ๋ฐฐ์ด์ ๋์์๋ถํฐ ๋ฐฐ์ด์ ์์๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
์๋ ์ฝ๋์์ ์ด ๋ฐฉ๋ฒ์ผ๋ก arr
๋ฐฐ์ด์ ๋ง์ง๋ง ์์๋ฅผ ๊ฐ์ ธ์๋ณด๊ฒ ์ต๋๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
const lastItem = arr[arr.length - 1];
console.log(lastItem); // Expected Output: false
์ด ๋ฐฉ๋ฒ์ ์ ์๋ํ์ง๋ง ๊ฐ๋จํ ์์ ์ ๋นํด ๋ฌธ๋ฒ์ด ๋ถํธํ๊ณ ์ฉ ์ข์ง๋ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ ํจ์์ ๋ฆฌํด๊ฐ์ ์ฌ์ฉํ ๋ ๋ฆฌํด๊ฐ์ ๋ณ์์ ์ ์ฅํด์ผ ํ๋ค๋ ๋จ์ ์ด ์์ต๋๋ค.
function appendNumber(arr, N) {
arr.push(N);
return arr;
}
const tempArr = appendNumber([1, 2, "three", 4, 5, true, false], 6);
console.log(tempArr[tempArr.length - 1]); // Expected Output: 6
์ ์ฝ๋์์ appendNumber()
ํจ์์ ๋ฐํ๊ฐ์ length
ํ๋กํผํฐ๋ฅผ ์ ์ฉํ๊ธฐ ์ ์ ๋จผ์ tempArr
์ ์ ์ฅ๋์ด์ผ ํฉ๋๋ค.
slice()
๋ฉ์๋ ์ฌ์ฉํ๊ธฐ๊ฐ๋ฐ์๋ ๋ฐฐ์ด์ ๋ง์ง๋ง ์์๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์๋์ ๊ฐ์ด slice()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
arr.slice(-1)[0]
์ด ๋ฌธ๋ฒ์ ์์ ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ๋๋ฐ ์ถํ์ ๋์ค๋ .at()
๋ฉ์๋์์๋ ๋ณผ ์ ์์ต๋๋ค.
์์ ์ธ๋ฑ์ค๋ ๋ฐฐ์ด์ ๋์์ ๋ถํฐ์ ์คํ์
์ ๋ํ๋
๋๋ค. ์๋ฅผ ๋ค์ด slice(-1)
์ ๋ค์์๋ถํฐ ๋ง์ง๋ง ์์ดํ
์ ์ ๊ฑฐํ์ฌ ์๋ก์ด ๋ฐฐ์ด๋ก ๋ฐํํฉ๋๋ค. slice(-2)
๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ง๋ง 2๊ฐ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฌ๊ธฐ์ ์ด์ ์ ๋ง์ง๋ง ์์์ด๊ธฐ ๋๋ฌธ์ [0]
์ ๋ง์ง๋ง ์์๋ฅผ ์ ํํ๊ฒ ๋ฉ๋๋ค.
์ด ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ arr
๋ฐฐ์ด์ ๋ง์ง๋ง ์์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr.slice(-1)[0]); // Expected Output: false
์์์ ๋ดค๋ length
ํ๋กํผํฐ์ ๋ค๋ฅด๊ฒ ์ด ๋ฐฉ๋ฒ์ ํด๋น ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ธฐ ์ํด ํจ์์ ๋ฐํ๊ฐ์ ์ ์ฅํด์ผ ํ ํ์๋ ์์ต๋๋ค.
๊ทธ๋์ ์ข ๋ ์ ์ฐํ ๋ฐฉ๋ฒ์
๋๋ค.
function appendNumber(arr, N) {
arr.push(N);
return arr;
}
console.log(appendNumber([1, 2, "three", 4, 5, true, false], 6).slice(-1)[0]); // 6
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ด ๋ฌธ๋ฒ์ ์ด์ํ๊ฒ ๋ณด์ด๊ณ ๊ฐ๋ฐ์์ ์๋๋ฅผ ๋ช ํํ๊ฒ ๋ณด์ฌ์ฃผ์ง ์์ต๋๋ค. ๋ํ ๋ถํธํ ์๋ ์๊ณ ์.
arr[-1]
๋ก ๋ง์ง๋ง ์์์ ์ ๊ทผํ ์ ์๋๊ฐ?์ด ์ง๋ฌธ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฒ์ ์ฌ์ฉํ๋ ์ฌ๋๋ค์ด ํํ๊ฒ ์ ๊ธฐํ๋ ์ง๋ฌธ์
๋๋ค. ํนํ Python๊ณผ ๊ฐ์ ์ธ์ด๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋๋ค์ด์ฃ .
์๋ฐ์คํฌ๋ฆฝํธ์์ arr[-1]
๊ณผ ๊ฐ์ ํ๊ธฐ๋ ์ ํจํ ๊ฐ์ฒด ํ๋กํผํฐ์
๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ฐฐ์ด์ ํฌํจํ ๋ชจ๋ ๊ฒ์ ๊ฐ์ฒด์
๋๋ค.
๊ทธ๋์ ์ธ์ ๋ ์ง ์ฐ๋ฆฌ๋ arr[0]
๊ณผ ๊ฐ์ ๋๊ดํธ ํ๊ธฐ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ๊ฐ์ฒด์ ํ๋กํผํฐ ์ค 0
์ด๋ผ๋ ํค๋ฅผ ๊ฐ์ง๋ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์
๋๋ค.
๊ฐ์ฒด ํ๊ธฐ ๋ฐฉ๋ฒ์ผ๋ก arr
๋ฅผ ๋ค์ ์์ฑํด๋ณธ๋ค๋ฉด ์๋์ ๊ฐ์ ๊ฒ๋๋ค.
const arr = {
0: 1,
1: 2,
3: "three",
// ...
};
console.log(arr[0]); // Expected Output: 1
์ ์ฝ๋์์ -1
์ key๋ก ๊ฐ์ง๋ ๊ฐ์ ์กด์ฌํ์ง ์์ต๋๋ค. ๊ทธ๋์ arr[-1]
์ undefined
๋ฅผ ๋ฐํํ ๊ฒ๋๋ค.
๋ง์ฝ ์๋์ ๊ฐ์ด ๊ฐ์ฒด ํ๋กํผํฐ ์ค์ -1
key๊ฐ ์กด์ฌํ๋ค๋ฉด ๊ทธ์ ํด๋นํ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
const arr = {
"-1": "valid"
};
console.log(arr[-1]); // Expected Output: valid
์ฆ, ์ด๋ฏธ ํด๋น ๋ฌธ๋ฒ์ ์ ํจํ ๋ฌธ๋ฒ์ด๊ธฐ ๋๋ฌธ์ ๋ง์ง๋ง ์์๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ผ๋ก arr[-1]
ํ๊ธฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๋ป์
๋๋ค.
๋ฐฐ์ด์ ๋์์๋ถํฐ ์์๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์์์ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด .at()
๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
.at()
๋ฌธ๋ฒ.at()
๋ฉ์๋๋ ๋ฆฌํด๋ฐ์ ์์์ ์ธ๋ฑ์ค๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ต๋๋ค. ์์ ์ธ๋ฑ์ค๋ฅผ ๋ฐ์ผ๋ฉด ๋ฐฐ์ด์ด๋ ๋ฌธ์์ด์ ๋ค์์๋ถํฐ ์ธ๋ฑ์ค๋ฅผ ์ธ์ด ํด๋น ์์๋ ๋ฌธ์๋ฅผ ๋ฐํํ๊ฑฐ๋ undefined
๋ฅผ ๋ฐํํฉ๋๋ค.
at(index)
.at()
๋ฉ์๋ ์ฌ์ฉํ๊ธฐ์์์ ์ธ๊ธํ๋ ๊ฒ์ฒ๋ผ .at()
๋ ๋ฐํ๋ฐ์ ์์์ ์ธ๋ฑ์ค๋ฅผ ๋ฐ์ต๋๋ค. ์ด ์น์
์์๋ ์ ์ฆ์ผ์ด์ค๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
arr
๋ฐฐ์ด๋ก ๋ค์ ์ฌ๋ผ๊ฐ ์ด๋ป๊ฒ .at()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ ์์๋ฅผ ๋ฐํ๋ฐ๋์ง ๋ด
์๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr.at(0)); // Expected Output: 1
console.log(arr.at(2)); // Expected Output: "three"
console.log(arr.at(-1)); // Expected Output: false
console.log(arr.at(-3)); // Expected Output: 5
.at()
๋ฉ์๋์ ์์ ์ธ๋ฑ์ค๋ฅผ ์ ๋ฌํ๋ฉด, ๋ฉ์๋๋ ํด๋น ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง๋ ์์๋ฅผ ๋ฐํํฉ๋๋ค. ์์์ ์ธ๋ฑ์ค์ธ ๊ฒฝ์ฐ์๋ ๋ฐฐ์ด์ ๋์์๋ถํฐ์ ์ธ๋ฑ์ค์ ํด๋นํ๋ ์์๋ฅผ ๋ฐํํฉ๋๋ค. ์ ์ฝ๋์์ at(-1)
๋ ๋ฐฐ์ด์ ๋์์๋ถํฐ 1๊ฐ๋ฅผ ์ธ์ด false
๋ฅผ ๋ฐํํฉ๋๋ค. ๊ฐ์ ๋ฐฉ์์ผ๋ก at(-3)
์ ๋์์๋ถํฐ ์ธ๋ฒ์งธ์ ์๋ 5
๋ฅผ ๋ฐํํฉ๋๋ค.
๋ฌธ์์ด์์๋ ๋ฐฐ์ด๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋์ํฉ๋๋ค.
const str = "The last alphabet is z";
console.log(str.at(0)); // Expected Output: T
console.log(str.at(-1)); // Expected Output: z
์ด ๋ฉ์๋๋ ์ฌ์ฉํ๊ธฐ์ ์์ฃผ ์ข์ต๋๋ค. at(-1)
์ ์ฌ์ฉํ์ฌ ๋ฌธ์์ด์์ ๊ฐ์ฅ ๋์ ์๋ ๋ฌธ์๋ฅผ ์ป์ ์ ์์ต๋๋ค.
๋์ผํ ๋์์ length
ํ๋กํผํฐ๋ฅผ ์ด์ฉํ๋ค๋ฉด ๋ฌธ๋ฒ์ ๋์ฑ ๋ณต์กํด์ง๋๋ค.
console.log(str[str.length - 1]); // Expected Output: z
length
ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํ ๋์ ๋ค๋ฅด๊ฒ at()
๋ฉ์๋๋ ํจ์์ ๋ฐํ๊ฐ์ ์ฌ์ฉํ๊ธฐ ์ ์ ์ ์ฅํด์ผ ํ ํ์๋ ์์ต๋๋ค.
๋ค์์ ๋ฐฐ์ด์ ๋ง์ง๋ง์ผ๋ก ์ฝ์
๋ ์์๋ฅผ ์ถ๋ ฅํ๋ ์ฝ๋์
๋๋ค.
function appendNumber(arr, N) {
arr.push(N);
return arr;
}
console.log(appendNumber([1, 2, "three", 4, 5, true, false], 6).at(-1));
// Expected Output: 6
์ฝ๋์์ .at()
๋ฉ์๋๋ ๋ฐํ๋ ๊ฐ์ ๋ฐ๋ก ์ ์ฉ๋์ด ๋ณ์์ ๊ฐ์ ์ ์ฅํ์ง ์์๋ ๋ฉ๋๋ค.
์๋ ์ฝ๋๋ฅผ ์ดํด๋ด
์๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr.at(0.6)); // Expected Output: 1
console.log(arr.at(-3.6)); // Expected Output: 5
์ ์ฝ๋์์ ์ฒซ ๋ฒ์งธ ์ถ๋ ฅ์ 0
์ธ๋ฑ์ค์ ํด๋นํ๋ ์์์ด์ง๋ง ๋ ๋ฒ์งธ ์ถ๋ ฅ์ ๋์์๋ถํฐ ์ธ ๋ฒ์งธ ์์์
๋๋ค.
์ด๊ฒ์ ๋ฌด์์๋ก ๋ฐฐ์ด์ ์์๋ฅผ ์ ํํ๊ณ ์ถ์ ๋ ๊ฝค ์ ์ฉํฉ๋๋ค. ์ด๋ฅผ ๊ฐ์๋ฐ์๋ณด ๊ฒ์ ํ๋ก์ ํธ๋ก ์ค๋ช
ํด๋ณด๊ฒ ์ต๋๋ค.
์ปดํจํฐ์์ ๋๋ค์ผ๋ก ์ ํํ๊ธฐ ์ํด .at()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ ์ฝ๋๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ป๊ฒ ์ปดํจํฐ๊ฐ ๋ฌด์์๋ก ์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
const computerOptions = ["rock", "paper", "scissors"];
const randomIndex = Math.random() * computerOptions.length;
console.log(computerOptions.at(randomIndex));
Math.random()
์ ์ฌ์ฉํ๋ฉด 0 ์ด์ ๋ฐฐ์ด ๊ธธ์ด ๋ฏธ๋ง ์ฌ์ด์ ์๋ฅผ ์ป์ต๋๋ค.
.at()
๋ฉ์๋๊ฐ ์ธ๋ฑ์ค๋ก ๋ถ๋์์์ ์๋ฅผ ๋ฐ๊ฒ๋๋ฉด ์์์ ์์ ์๋ฅผ ๊ณ ๋ คํ์ฌ ํด๋น ์ธ๋ฑ์ค์ ์์๋ฅผ ๋ฐํํฉ๋๋ค.
๊ฐ์ ๋์์ ํ๊ธฐ ์ํด ๋๊ดํธ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด floor ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๊น์ด ์ ์๋ก ๋ณํํ์ง ์๋ ํ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
const computerOptions = ["rock", "paper", "scissors"];
const randomIndex = Math.random() * computerOptions.length;
console.log(computerOptions.at(randomIndex));
๋๊ดํธ ํ๊ธฐ๋ฐฉ์์ ํด๋น ์๋ฅผ ๊ฐ์ง๋ ๊ฐ์ด ์์ผ๋ฏ๋ก undefined
๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์
๋๋ค.
const arr = [1, 2, "three", 4, 5, true, false];
console.log(arr[0.6]); // Expected Output: undefined
.at()
๋ฉ์๋๋ Math.floor
๋ฅผ ์ฌ์ฉํ์ฌ ๋๋ค ์๋ฅผ ๋ด๋ฆผํ๋ ๋จ๊ณ๋ฅผ ๊ฑฐ์น์ง ์๊ฒ ํด์ค๋๋ค.
์ด ํํ ๋ฆฌ์ผ์ ์์ฑํ ์์ ์ ๊ธฐ์ค์ผ๋ก .at()
๋ฉ์๋๋ ๊ทนํ ์ผ๋ถ๋ฅผ ์ ์ธํ ๋๋ถ๋ถ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ๊ฝค ์ ์๋ํฉ๋๋ค.
๋ธ๋ผ์ฐ์ ์ง์์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
.at()
๋ฉ์๋๋ ์ด ํํ ๋ฆฌ์ผ์์ ๋ดค๋ฏ์ด ์ธ๋ฑ์ค๋ก๋ถํฐ ์์๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ ํธํ๊ฒ ํด์ค๋๋ค.
๋ํ ์ด๋ฏธ ์กด์ฌํ๋ ๋ฐฉ๋ฒ๋ค๊ณผ ๋น๊ตํ์ ๋ ๋์ฑ ๊ฐ๊ฒฐํ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
์๋ฌธ : https://recoiljs.org/blog/2022/01/28/0.6.0-release/
Recoil 0.6์ด ๋์์ฑ ๋ ๋๋ง๊ณผ ์ ํ๋ฟ๋ง ์๋๋ผ ์๋ก์ด API์ ์์ ์ฌํญ, ์ต์ ํ ๋ฑ๊ณผ ํจ๊ป React 18์ ๋ํด ๋ ํฅ์๋ ์ง์๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
Recoil 0.6์ ํฅ์๋ ์์ ์ฑ๊ณผ ์ฑ๋ฅ์ ์ํด React 18์ ์ต์ API๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฒ ๋ฆด๋ฆฌ์ฆ๋ concurrent rendering๊ณผ <React.StrictMode>
๋ชจ๋ ์๋ฆฝ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋์์ฑ ๋ ๋๋ง์ ๋ํด ์ ์ฌ์ ์ธ ์ด์๋ค์ ํ
์คํธํ๊ณ ์๋ณํ๊ธฐ์ ์ ์ฉํฉ๋๋ค. ๋์ผํ ํธ๋ค๋ฌ์ ์ฝ๋ฐฑ์์ Recoil๊ณผ React ์ํ๋ฅผ ๋ณ๊ฒฝํ์ฌ ์ผ๊ด๋๋ ์ํ์ ๋ทฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ๊ฐ์ ์ฌํญ๋ค ์ค ์ผ๋ถ๋ React ์ด์ ๋ฒ์ ์ ์ฌ์ฉํ๋๋ผ๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. React 18๋ก ์คํํ์ ๋ค๋ฉด ์ต์ RC ๋น๋๋ฅผ ์ฌ์ฉํ์ธ์. ์ค๋ฆฌ์ง๋ React 18.0.0-rc.0 ํจํค์ง์๋ ๊ทธ ์ดํ ์์ ๋ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค.
React 18์ ์ํ๊ฐ ์ค๋น๋๊ธฐ ์ ์ ๋ ๋๋งํ ํญ๋ชฉ์ ์ ์ดํ๋ ๋์์ ์๋ก์ด ์ํ๋ก ์ ํํ๋ ๊ธฐ๋ฅ์ ๋ํ ์๋ก์ด hook, useTransition()
์ ์ ๊ณตํฉ๋๋ค. Recoil์ ์ด๋ฌํ ์ ๊ทผ๋ฐฉ์๊ณผ ํธํ๊ฐ๋ฅํ๋ฉฐ React ์ํ์ ๋ํ ์ผ๊ด์ ์ธ ๋ทฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋, React 18์ ๋์์ ์ธ ์
๋ฐ์ดํธ์์ ๋ฌผ๋ฌ๋ ์ ์์ผ๋ฉฐ, ์์ง ๊ณต์์ ์ผ๋ก ์ธ๋ถ ์ ์ฅ์์ ๋ํ ์ํ ๋ณ๊ฒฝ๊ฐ๋ค์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์ ํ์ ์ง์ํ์ง ์์ต๋๋ค. ์ด๋ ๋ฆฌ์กํธ ํ์์ ์ง์ํ๊ณ ์ ํ๋ ๊ธฐ๋ฅ์ด์ง๋ง ๋ค์์ hook์ ํตํด ์คํ์ ์ธ ์ง์์ ์ถ๊ฐํ์ต๋๋ค. ์ด API๋ ์์ง ์ฒ๋ฆฌ๋์ง ์์ ์ ์ฆ์ผ์ด์ค๋ค์ด ์์ผ๋ฏ๋ก ์คํ์ ์
๋๋ค.
useRecoilState_TRANSITION_SUPPORT_UNSTABLE()
useRecoilValue_TRANSITION_SUPPORT_UNSTABLE()
useRecoilValueLoadable_TRANSITION_SUPPORT_UNSTABLE()
์๋ก์ด ๊ฒฐ๊ณผ๊ฐ์ด ๋ก๋ฉ๋๋ ๋์ ํ์ฌ์ ๊ฒฐ๊ณผ๊ฐ์ ๋ณด์ฌ์ฃผ๋ ์๋ ์์ ๊ฐ ์์ต๋๋ค.
function QueryResults() {
const queryParams = useRecoilValue_TRANSITION_SUPPORT_UNSTABLE(queryParamsAtom);
const results = useRecoilValue_TRANSITION_SUPPORT_UNSTABLE(myQuerySelector(queryParams));
return results;
}
function MyApp() {
const [queryParams, setQueryParams] = useRecoilState_TRANSITION_SUPPORT_UNSTABLE(queryParamsAtom);
const [inTransition, startTransition] = useTransition();
return (
<div>
{inTransition ? <div>[Loading new results...]</div> : ''}
Results: <React.Suspense><QueryResults /></React.Suspense>
<button
onClick={() => {
startTransition(() => {
setQueryParams(...new params...);
});
}
>
Start New Query
</button>
</div>
);
}
useRecoilCallback()
์ ์
๋ ํฐ ์บ์๋ฅผ ์๋ก๊ณ ์นจํ ์ ์์ผ๋ฉฐ useRecoilRefresher_UNSTABLE()
์ ๋น์ทํฉ๋๋ค.getCallback()
์ ์ฌ์ฉํ๋ ์
๋ ํฐ์ ์ฝ๋ฐฑ์ useRecoilCallback()
์ ๋น์ทํ๊ฒ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ณ , ์๋ก๊ณ ์นจํ๊ณ ํธ๋์ญ์
์ ์ํํ๋ฉฐ ์ด๋ฅผ ์ฝ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.StoreID
๋ useRecoilStoreID()
๋ atom effects์ storeID
ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ป์ ์ ์์ต๋๋ค..isRetained()
๋ฉ์๋๋ฅผ ์ถ๊ฐํ์ฌ .retain()
์ ํตํด ์ค๋
์ท์ด ๋ฆด๋ฆฌ์ฆ๋์๋์ง ํ์ธํ ์ ์์ต๋๋ค.์๋ฌธ : 6 TypeScript Typing System Tricks You Should Know์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
ํ์ ์คํฌ๋ฆฝํธ๋ ํ์ ์ ๋ํ ์ธ์ด์ ๋๋ค. ์ปดํ์ผ ํ์์ ํ์ ์ฒดํฌ๊ฐ ๊ฐ๋ฅํ ๊ฐ๋ ฅํ ํ์ ์ธ์ด์ ๋๋ค. ๋์์ ์ ์ ํ์ ์ ์ ํ ์ฌํญ์ด๋ฏ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ํธํ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ ๋ 3๋ ์ด์ ํ์ ์คํฌ๋ฆฝํธ๋ก ์ผ์ ํด์์ต๋๋ค. ์ด ๊ธฐ๊ฐ ๋์ ๋ง์ ๊ฒ๋ค์ ๋ฐฐ์ ์ง๋ง ๋งค์ผ ์ผ์ ํ๋ฉด์ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ํธ๋ฆญ์ ๋ํด ๊ณต๋ถํ๋ฉด์ ์ฌ์ ํ ๋๋ผ๊ณ ์์ต๋๋ค.
ํ์ ์์คํ ์ ์ฌ์ฉํ๋ฉด์ ๋ฐฐ์ด ์ฌ๋ฌ ๋ชจ๋ฒ ์ฌ๋ก๋ค์ ์๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
ํ์ ์คํฌ๋ฆฝํธ์์, ํ์ ์ ๋ฐ์ดํฐ์ ํํ๋ ๊ตฌ์กฐ์ ๋๋ค. ํ์ ์ ๋ํ ์ ๋ณด๋ก ํ์ ์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ๋ ์ฌ๋ฌ๋ถ์๊ฒ ์ปดํ์ผ ์์ ์ ๊ฐ์งํ ์๋ฌ์ ๋ํด ๋น ๋ฅด๊ฒ ์ฃผ์๋ฅผ ์ค ๊ฒ์ ๋๋ค. ๋ฐํ์์ ์๋ฌ๋ฅผ ์๋ ค์ฃผ๋ ๋์ ์์.
ํ์ ์ ์ ์ํ ๋, ๊ฐ๋ฅํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ํ๊ณ ์ถ์ ๊ฒ๋๋ค. ๊ฐ๊ฒฐํ ํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ปดํ์ผ๋ฌ๊ฐ ๋ ์ผ์ ์ ํ ์ ์๊ฒ ํด์ค๋๋ค. ์ ์ ์๋ ํ์ ์ ์ค์ค๋ก ์ค๋ช ํ๋ ๋ฌธ์๋ก์์ ์ญํ ์ ํ๊ณ ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ฌ์ค๋๋ค.
์ผ๋ฐ์ ์ธ ๊ท์น์ ๋ ๊ฐ๊ฒฐํ ์๋ก ๋ ์ข๋ค๋ ๊ฒ์ ๋๋ค. ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ํ์ ์คํฌ๋ฆฝํธ๊ฐ ๊ตฌ์กฐ์ ํ์ , ๋งคํ๋ ํ์ , ์ปจํธ๋กค ํ๋ก์ฐ ๊ธฐ๋ฐ์ ๋ถ์์ด ์๋ ์กฐ๊ฑด ํ์ , ํ์ ์ถ๋ก (type inference), ํ์ ๋จ์ธ(type assertion)์ ์ ๊ณตํ๋ค๋ ์ฌ์ค๋ก๋ถํฐ ์ต๋๋ค.
์๋ฅผ ๋ค์ด PayGrade
๋ผ๋ ํ์
์ด ์๋ค๊ณ ํฉ์๋ค.
type PayGrade: number;
1๋ถํฐ 5๊น์ง์ ์ซ์์ ๋ํ ํ์ ์ด๋ผ๊ณ ์ข ๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋ํ๋ผ ์ ์์ต๋๋ค.
type PayGrade: 1 | 2 | 3| 4 | 5;
์ฌ๋ฌ๋ถ์ด ํ์ ์ ๋ ์๋ฏธ์๊ฒ ํํํ๊ธฐ ์ํด์๋ ๋ค์๊ณผ ๊ฐ์ด ํํํ ์ ์์ต๋๋ค.
const payGrade = {
low : 1,
average : 2,
good : 3,
better : 4,
best : 5} as const;
type PayGrade = typeof payGrade[keyof typeof payGrade]
์ฌ๋ฌ๋ถ์ ์ฝ๋์ ๊ฐ๋ ฅํ ํ์ ์ ๋ํด์ฃผ๋ฉด ์ฝ๋๋ ๋์ฑ ๊ฐํด์ง๋๋ค.
ํ์
์คํฌ๋ฆฝํธ์ strict ๋ชจ๋๋ ํ์
์ฒดํฌ์ ๊ท์น์ ๋์ฑ ์๊ฒฉํ๊ฒ ํฉ๋๋ค. ๊ฐ๋ฅํ๋ฉด strict ๋ชจ๋๋ ํ์ฑํ ๋์ด์ผ ํฉ๋๋ค. ์ด๋ tsconfig.json
์์ ์ค์ ์ด ๊ฐ๋ฅํฉ๋๋ค.
{ "compilerOptions":
{
"strict": true,
}
}
strict ๋ชจ๋๋ ์ฌ์ค ์ผ๊ณฑ๊ฐ์ง ์ต์ ์ ์ถ์ฝ ํํ์ด๊ณ , ์ธ๋ฐํ ์ปจํธ๋กค์ ํ๊ณ ์ถ๋ค๋ฉด ๊ฐ ์ต์ ์ ๋ถ๋ฆฌํด์ on/off๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
๋ง์ฝ ์ฌ๋ฌ๋ถ์ด ํ์ฌ ์กด์ฌํ๋ ํ๋ก์ ํธ๋ก ์์ ์ ํ๊ณ ์๊ณ ๋ชจ๋ ์ต์ ์ ํ์ฑํํ์ง ์์๋ค๋ฉด, ๋ค์ ๋ ๊ฐ์ง ๊ท์น์ด ๋ค๋ฅธ ๊ฒ๋ณด๋ค ๋์ฑ ์ค์ํฉ๋๋ค.
noImplicitAny
: any
ํ์
์ ์๋ฌ ๋ฐฉ์ถstrictNullChecks
: ๋ช
์์ ์ผ๋ก ํ์ฉ๋ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด ๋ณ์์ null
์ด๋ undefined
๋ฅผ ํ ๋นํ ์ ์์๋๋จธ์ง ๊ท์น์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
noImplicitThis
: any
ํ์
์ this
๋ฅผ ์ฐธ์กฐํ ์ ์์alwaysStrict
: ๋ชจ๋ ์ปดํ์ผ๋ JS ํ์ผ ์๋จ์ "use strict"๋ฅผ ์ค์ strictBindCallApply
: bind
, call
, apply
๋ฉ์๋์ strict ์ฒดํฌstrictFunctionTypes
: ํจ์ ํ์
์ฒดํฌ๋ฅผ ๊ธฐ๋ณธ๊ฐ์ธ _bivariant_๊ฐ ์๋ _contravariant_๋ก ์ค์ strictPropertyInitialization
: ์์ฑ์์์ ํด๋์ค ํ๋กํผํฐ์ ๊ธฐ๋ณธ๊ฐ์ด๋ ์ด๊ธฐํ๋๋๋ก ๊ฐ์ ์ ๋ค๋ฆญ์ ํ์ ์ด ํ๋ผ๋ฏธํฐ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค. ์ ๋ค๋ฆญ ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ๋ ์ฌ๋ฌ๋ถ์ ํ๋ผ๋ฏธํฐ์ ์ ์ฝ์กฐ๊ฑด์ ์ ์ธํด์ผ ํฉ๋๋ค. ์ด๋ ๋ค๋ฅธ ํ์ ์ด๋ ์ธํฐํ์ด์ค์ ์ํด ์ ์ฝ๋ ์ ์์ต๋๋ค.
๋ค์ ์์ ๋ extends
ํค์๋๊ฐ ์ด๋ป๊ฒ Animal
ํ์
์ ํ์
ํ๋ผ๋ฏธํฐ๋ฅผ ์ ์ฝํ๋์ง ๋ณด์ฌ์ค๋๋ค.
type Animal = {
owner: string;
}
function feedPets<T extends Animal>(pets: T[]): void { }
ํ๋ผ๋ฏธํฐ๊ฐ ๋ค๋ฅธ ํ์ ์ผ๋ก ๋ค์ด์๋ค๋ฉด ์ปดํ์ผ ์์ ์์ ์๋ฌ๊ฐ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ์ํ ๊ฒ๋๋ค.
![])(https://miro.medium.com/max/700/1*UJ2sg0TMILHr4a9BYDup4w.png)
์ฝ๋๋ฅผ ๋จ์ํ๊ฒ ํ๊ธฐ ์ํด ํ์ ์ถ๋ก ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ ์คํฌ๋ฆฝํธ์ ์ปดํ์ผ๋ฌ๋ ๋ณ์๋ ๋ฆฌํด ํ์ ์ ํฌํจํ ๊ฐ๋จํ ํ์ ํํ์ ํตํด ํ์ ์ ์ถ๋ก ํ ์ ์์ต๋๋ค. ๋ง์ ๊ฒฝ์ฐ์ ํ์ ์ ๋ช ์์ ์ผ๋ก ์ ์ธํ ์ด์ ๊ฐ ์์ต๋๋ค. ์ฝ๋๋ฅผ ๊ฐ๋จํ๋ ๊ฒ ๋ ์ข์ต๋๋ค.
const x: string = 'John'; // string is redundant here
๊ทธ๋ฌ๋ ์์ธ๋ ์์ต๋๋ค. ๋ณต์กํ ํํ์ ๊ฒฝ์ฐ ๋ช ์์ ์ธ ํ์ ์ ์ธ์ด ๊ฐ๋ ์ฑ์ ๋์์ด ๋ ์ ์์ต๋๋ค.
๋ ๋ค๋ฅธ ์์ธ๋ ์ปดํ์ผ๋ฌ๊ฐ ์ ๋ ์ถ๋ก ํ ์ ์๋ ํจ์ ํ๋ผ๋ฏธํฐ์ ๊ฒฝ์ฐ์
๋๋ค. ํ์
์ถ๋ก ์ด ์๋ค๋ฉด ํ๋ผ๋ฏธํฐ์๋ any
ํ์
์ด ์ฌ์ฉ๋ ๊ฒ๋๋ค.
ํจ์์ ๋ฆฌํด ํ์ ์ ํ์ ์คํฌ๋ฆฝํธ์ ์ํด ์ถ๋ก ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ํจ์๊ฐ ๋ณต์กํ ๋ฆฌํด ํ์ ์ ๊ฐ์ง๋ค๋ฉด, ์ฝ๋์ ๊ฐ๋ ์ฑ์ ์ํด ๋ช ์์ ์ผ๋ก ํ์ ์ ์ ์ธํ๋ ๊ฒ์ด ๋ ๋ซ์ต๋๋ค.
any
๋ฅผ ์ ๊ฒ ์ฌ์ฉํ๋ผ๋๋ถ๋ถ์ any
๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. any
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ฝ๋๋ฅผ ๊ณ์ ์ฐ๊ฒ ํ๋ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ด๊ธฐ๋ ํ์ง๋ง ์ด๋ ์ปดํ์ผ ์์ ์ ๋ฐ์ํ ์๋ฌ ๋๋ ์ ์ฌ์ ์ธ ์๋ฌ๋ฅผ ์จ๊ธฐ๊ณ ์์ ๋ฟ์
๋๋ค. ์ฆ, any
ํ์
์ ํ์
์คํฌ๋ฆฝํธ์ ๊ฐ์ฅ ํฐ ์ด์ ์ธ ๊ฐ๋ ฅํ ํ์ดํ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด์ฃ .
๋์ ์ unknown
์ ์ฌ์ฉํ์ธ์. unknown
ํ์
์ ์ฌ์ฉํ๋ฉด ํ์
์ ์ ํ๊ฑฐ๋ ์ขํ์ง๋ ์๊ณ ์๋ ๊ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
const data: unknown = value;
immutability๋ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ฝ๊ฒ ํ๊ณ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ก๋ถํฐ ์ค๋ ๋ณต์ก์ฑ์ ์ค์ฌ์ค๋๋ค. ํ์
์คํฌ๋ฆฝํธ๋ immutability๋ฅผ ์งํค๋๋ก readonly
๋ณ๊ฒฝ์์ ์ ํธ๋ฆฌํฐ ํ์
์ธ Readonly
๋ฅผ ์ ๊ณตํฉ๋๋ค.
readonly
๋ณ๊ฒฝ์๋ ์ธํฐํ์ด์ค๋ ํด๋์ค์ ํ๋กํผํฐ์ ์ ์ฉํ ์ ์๊ณ ์ฌํ ๋น์ ๋ง์ต๋๋ค.
class Fish {
constructor(public readonly name: string) {}
}
Readonly<T>
๋ ์ ๋ค๋ฆญ ํ์
T
์ ์ปดํ์ผ ์์ ์ ํ๋กํผํฐ์ readonly
๋ณ๊ฒฝ์๋ฅผ ์ ์ฉํ๊ฒ ํ๋ ํ์
์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ด๋ T
๋ก ๊ตฌ์ฑ๋ ํ๋กํผํฐ์๋ ์ฌํ ๋น์ ํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ํ์
์ด ๊ณต์ ๋ ๋ Readonly
์ ํธ๋ฆฌํฐ ํ์
์ผ๋ก immutable ํ์
์ ์ ์ธํ๋ ๊ฒ์ ์์ฃผ ์ข์ต๋๋ค.
readonly
๋ณ๊ฒฝ์์ Readonly
์ ํธ๋ฆฌํฐ ํ์
๋ ๋ค ๋ฐํ์์ด ์๋ ์ปดํ์ผ ์์ ์๋ง ํจ๊ณผ๊ฐ ์๋ค๋ ๊ฒ์ ์ฃผ๋ชฉํ์ธ์.
ํ์ ์คํฌ๋ฆฝํธ์ readonly๋ ์์์ ๋ํด ๋ ์ฝ๊ณ ์ถ์ผ์๋ฉด ๋ค๋ฅธ ์ํฐํด์ ์ฝ์ด์ฃผ์ธ์.
์ด ์ํฐํด์์๋ ํ์ ์คํฌ๋ฆฝํธ ํ์ ์ ๊ดํ ๋ชจ๋ฒ์ ์ธ ๋ฐฉ๋ฒ๋ค์ ๋ํด ์ด์ผ๊ธฐ ํ์ต๋๋ค.
ํ์ ์ ๊ตฌ์ฒด์ ์ผ๋ก ์ ์ธํ๊ณ ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ์์คํ ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ฐ๋ฆฌ์ ์ฝ๋๋ฅผ ๊ฐ๋ ์ฑ์๊ฒ, ์ ์ง๊ฐ ์ฉ์ดํ๊ฒ, ๊ฐ๋ ฅํ๊ฒ ๋ง๋ค์ด์ค๋๋ค.
์ด ์ํฐํด์ด ๋ง์์ ๋์ จ๋ค๋ฉด ์ ๊ฐ ์์ฑํ ๋ค๋ฅธ ํ์ ์คํฌ๋ฆฝํธ ์ํฐํด์ ์ฝ์ด๋ณด์ธ์.
ํ์ ์ธ์ด๋ฅผ ์ฌ์ฉํด์ ํ์ ์์ฑํ๋ ๋ฒ์ ๋ฐฐ์ฐ๊ณ ์ฌ๋ฌ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ค๋ ฅ์ ํ์ฉํ์ฌ ๋ ๋นจ๋ฆฌ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง์คํฐํ ์ ์์ต๋๋ค.
์ ๋ ํ์
์คํฌ๋ฆฝํธ๊ฐ ๋จ์ง ํ์
์ด๋
ธํ
์ด์
์ด ๋ฟ๋ ค์ ธ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์๊ฐํ๊ณค ํ์ต๋๋ค. ๊ทธ๋ฐ ๋ง์๊ฐ์ง์ผ๋ก๋ ์ข
์ข
์ ํํ ํ์
์ ์์ฑํ๋ ๊ฒ ๊ฝค ๊น๋ค๋กญ๊ณ ์ด๋ ต๋ค๋ ๊ฑธ ์๊ฒ ๋์๊ณ , ํ์
๋ค์ ์ ๊ฐ ๋ง๋ค๊ณ ์ ํ๋ ์ค์ ์ดํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ๋ ๋ฐ ๋ฐฉํด๊ฐ ๋์์ฃ . ๊ทธ๋์ ์ข
์ข
์ ๋ any
๋ผ๋ ์ตํ์ ํด๊ฒฐ์ฑ
์ ๋๋ฌํ๊ณค ํ๊ณ ๊ฒฐ๊ตญ ํ์
์ ์์ ์ฑ๊น์ง ์์ด๋ฒ๋ ธ์ต๋๋ค.
๊ฒ๋ค๊ฐ ์ฌ๋ฌ๋ถ์ด ํ๋ ๊ฒ์ ๋ฐ๋ผ ํ์ ์ ์์ฃผ ๋ณต์กํด์ง ์ ์์ต๋๋ค. ํ๋์ ํ์ ์คํฌ๋ฆฝํธ๋ก ์ฝ๋๋ฅผ ์ฐ๊ณ ๋์ ํ์ ์คํฌ๋ฆฝํธ๋ ์ค์ ๋ก ๋ ๊ฐ์ ์ธ์ด๋ก ์ด๋ฃจ์ด์ ธ ์๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค. ํ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ, ๋ค๋ฅธ ํ๋๋ ํ์ ์ธ์ด๋ผ๊ณ ๋ง์ ๋๋ค.
ํ์
์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์ฐ๋ฆฌ๋ ๋์์์ด ๋ ์ธ๊ณ ์ฌ์ด์์ ์๋ค๊ฐ๋ค ํด์ผ ํฉ๋๋ค. ํ์
์ธ๊ณ์์๋ ํ์
์ ๋ง๋ค๊ณ , ์๋ฐ์คํฌ๋ฆฝํธ ์ธ๊ณ๋ก ๊ฐ์ ํ์
์ด๋
ธํ
์ด์
์ผ๋ก ํ์
์ "์ํ"ํฉ๋๋ค. (์ปดํ์ผ๋ฌ์ ์ํด์ ์๋ฌต์ ์ผ๋ก ์ถ๋ก ๋๊ณค ํฉ๋๋ค.) ๋ค๋ฅธ ๋ฐฉํฅ์ผ๋ก๋ ๋ฌผ๋ก ๊ฐ ์ ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ๋ณ์/ํ๋กํผํฐ์ ๋ํด typeof
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ ๊ทธ์ ๋ํ ํ์
์ ๊ฐ์ ธ์ค๊ธฐ๋ ํฉ๋๋ค. (๋ฐํ์ ๊ฐ์ ํ์
์ ํ์ธํ๊ธฐ ์ํด ์ ๊ณต๋๋ typeof
์ฐ์ฐ์๋ฅผ ์๋ฏธํ๋ ๊ฒ์ด ์๋๋๋ค.)
์๋ฐ์คํฌ๋ฆฝํธ ์ธ์ด๋ ๋งค์ฐ ํํ์ ์ธ ํน์ฑ์ด ์๊ณ ์ด๋ ํ์ ์ธ์ด๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ์ค์ ๋ก ํ์ ์ธ์ด๊ฐ ํํ๋ ฅ์ด ๋ฐ์ด๋์ ํ๋ง ์์ ํจ์ด ์ฆ๋ช ๋์์ต๋๋ค.
์ฌ๊ธฐ์ ํ๋ง ์์ ์ฑ์ด ์ข์์ง ๋์์ง์ ๋ํ ๊ฐ์น ํ๋จ์ ํ์ง ์์ ๊ฒ์ด๋ฉฐ, ๊ทธ๊ฒ์ด ์ค๊ณ์ ์ํ ๊ฑด์ง ์ฐ์ฐ์ ์ํ ๊ฑด์ง ์์ง ๋ชปํฉ๋๋ค. (์ฌ์ค ์ข ์ข ํ๋ง ์์ ์ฑ์ ์ฐ์ฐํ ๋ฌ์ฑ๋์์ต๋๋ค.) ์ ๊ฐ ๋งํ๊ณ ์ ํ๋ ๋ฐ๋ ํ์ ์ธ์ด ์์ฒด๋ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ ์ํํ์ง ์์ผ๋ฉฐ, ์์ฃผ ๊ฐ๋ ฅํ๊ณ ์ ๋ฅํ๋ฉฐ ์ปดํ์ผ ์์ ์์ ์์์ ์ฐ์ฐ์ ์ํํ ์ ์๋ค๋ ์ ์ ๋๋ค.
์ ๊ฐ ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ์ธ์ด๋ฅผ ์์ ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ก์ ์๊ฐํ๊ธฐ ์์ํ์ ๋ ์ด ์ธ์ด๊ฐ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ช ๊ฐ์ง ํน์ฑ์ ๊ฐ๊ณ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
์ด ๊ธ์์๋ ๋ ๋นจ๋ฆฌ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง์คํฐํ๊ณ ์ ๊ฐ๊ณ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ง์์ ํ์ฉํ ์ ์๋๋ก ํ์ ์คํฌ๋ฆฝํธ์ ํ์ ์ธ์ด๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋น๊ตํ์ฌ ๋ฐฐ์ธ ๊ฒ์ ๋๋ค.
์ด ๊ธ์ ๋ ์๋ค์ด ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ ์คํฌ๋ฆฝํธ์ ์ด๋ ์ ๋ ์ต์ํ๋ค๊ณ ๊ฐ์ ํ๊ณ ์์ต๋๋ค. ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ฒ์๋ถํฐ ๋ฐฐ์ฐ๊ณ ์ ํ์ ๋ค๋ฉด The TypeScript Handbook์ ๋จผ์ ์ฝ์ด๋ณด์ธ์. ์ด ๊ธ๋ค๊ณผ ๊ฒฝ์ํ๋ ๋ชฉ์ ์ด ์๋๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ์ธ๊ณ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ค๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ var
, const
, let
๊ณผ ๊ฐ์ ํค์๋๋ก ๊ฐ๋ค์ ์ฐธ์กฐํ๊ธฐ ์ํด ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
const obj = {name: 'foo'}
ํ์
์ธ์ด์์๋, ์ธ๊ณ๋ ํ์
์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ฃ . ๊ทธ๋ฆฌ๊ณ type
๊ณผ interface
ํค์๋๋ก ํ์
๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
type Obj = {name: string}
"ํ์ ๋ณ์"์ ๋ํ ๋ ์ ํํ ์ด๋ฆ์ type synonyms ํน์ type alias(ํ์ ๋ณ์นญ)์ ๋๋ค. ๊ทธ๋ฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณ์๊ฐ ๊ฐ์ ์ฐธ์กฐํ๋ ๋ฐฉ์์ ๋ํ ๋น์ ๋ก์ "ํ์ ๋ณ์"๋ผ๋ ๋จ์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์๋ฒฝํ ๋น์ ๊ฐ ์๋์ง๋ผ๋ ํ์ ๋ณ์๋ ์๋ก์ด ํ์ ์ ๋ง๋ค์ง ์์ต๋๋ค. ํ์ ๋ณ์นญ์ ์ด๋ฏธ ์๋ ํ์ ์ ๋ํ ์๋ก์ด ์ด๋ฆ์ผ ๋ฟ์ ๋๋ค. ํ์ ์ธ์ด์ ๊ฐ๋ ์ ๋ ์ฝ๊ฒ ์ค๋ช ํ๊ณ ์ ํ๋ ๋ชฉ์ ์ผ๋ก ์ด ๋น์ ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ์
๊ณผ ๊ฐ์ ์๋ก ๊ด๋ จ์ด ์์ต๋๋ค. ํ์
์ ํต์ฌ์ ๊ฐ๋ฅํ ๊ฐ๋ค์ ์งํฉ๊ณผ ๊ฐ๋ค์ ๋ํด ์ํํ ์ ์๊ณ ์ ํจํ ์์
๋ค์ ๋ํ๋ธ๋ค๋ ๊ฒ์
๋๋ค. ๋๋๋ก ์งํฉ์ ์ ํํ๊ธฐ๋ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด type Name = 'foo' | 'bar'
์ ๊ฐ์ ๊ฒฝ์ฐ์์ ๋ง์ด์ฃ . ๊ทธ๋ฌ๋ ๋๋ถ๋ถ ์งํฉ์ ๋ฌดํํฉ๋๋ค. type Age = number
์ ๊ฐ์ด ๋ง์
๋๋ค. ํ์
์คํฌ๋ฆฝํธ๋ฅผ ์ธ ๋ ์ฐ๋ฆฌ๋ ํ์
๊ณผ ๊ฐ์ ๊ฒฐํฉํ๊ณ ๋ฐํ์ ์์ ์ ๊ฐ๊ณผ ์ปดํ์ผ ์์ ์ ํ์
์ด ๊ฐ๋ค๋ ๊ฒ์ ๋ณด์ฅํ๊ณ ์ ๋ ๊ฐ๊ฐ ํจ๊ป ์๋ํ๊ฒ๋ ํฉ๋๋ค.
ํ์
์ธ์ด์์ ํ์
๋ณ์๋ฅผ ์ ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ด์ผ๊ธฐํ์ต๋๋ค. ๊ทธ๋ฌ๋ ํ์
๋ณ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ญ ์ค์ฝํ๋ฅผ ๊ฐ์ง๋๋ค. ๋ก์ปฌ ํ์
๋ณ์๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ ํ์
์ธ์ด์์ infer
ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
type A = 'foo'; // global scope
type B = A extends infer C ? (
C extends 'foo' ? true : false// **์ด ํํ์์์๋ง** C๋ A๋ฅผ ๋ํ๋
๋๋ค.
) : never
์ด๋ฐ ๋ฐฉ์์ผ๋ก ์ค์ฝํ๋ฅผ ์ ํํ๋ ๋ณ์๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์์๊ฒ๋ ์ข ์์ํด๋ณด์ผ์ง๋ผ๋, ์ด๋ฐ ๋ฐฉ์์ ๋ฟ๋ฆฌ๋ ๋ช๋ช ์์ํ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ์ฐพ์ ์ ์๊ธฐ๋ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด Haskell ์ธ์ด์์๋ ํน์ ์ค์ฝํ๋ฅผ ํ ๋นํ๊ธฐ ์ํด in
๊ณผ ํจ๊ป let
ํค์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. let {assignments} in {expression}
์ ๊ฐ์ด ์์ฑํ๋ ๊ฒ์ด์ฃ .
let two = 2; three = 3 in two * three
// โ โ
// two and three are only in scope for the expression `two * three`
infer
๋ ์ค๊ฐ ํ์
๋ค์ ์บ์ฑํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
๊ด๋ จ๋ ์์๋ฅผ ๋ณด์ฌ๋๋ฆด๊ฒ์.
type ConvertFooToBar<G> = G extends 'foo' ? 'bar' : never
type ConvertBarToBaz<G> = G extends 'bar' ? 'baz' : never
type ConvertFooToBaz<T> = ConvertFooToBar<T> extends infer Bar ?
Bar extends 'bar' ? ConvertBarToBaz<Bar> : never
: never
type Baz = ConvertFooToBaz<'foo'>
infer
์์ด ๋ก์ปฌ ํ์
๋ณ์ Bar
๋ฅผ ์์ฑํ๋ ค๋ฉด ๋ ๋ฒ ๊ณ์ฐํด์ผ ํฉ๋๋ค.
type ConvertFooToBar<G> = G extends 'foo' ? 'bar' : never
type ConvertBarToBaz<G> = G extends 'bar' ? 'baz' : never
type ConvertFooToBaz<T> = ConvertFooToBar<T> extends 'bar' ?
ConvertBarToBaz<ConvertFooToBar<T> > : never // call `ConvertFooToBar` twice
type Baz = ConvertFooToBaz<'foo'>
์๋ฐ์คํฌ๋ฆฝํธ์์ if ๋ฌธ๊ณผ ํจ๊ป ===
์ ==
๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ผํญ ์ฐ์ฐ์ ?
๋ฅผ ์ฌ์ฉํด์ ๊ฐ์์ง๋ฅผ ๋น๊ตํ๊ณ ์กฐ๊ฑด ๋ถ๊ธฐ๋ฅผ ํ ์ ์์ต๋๋ค.
๋ฐ๋ฉด์, ํ์
์ธ์ด์์๋ "๋๋ฑ์ฑ ๋น๊ต"๋ฅผ ์ํด extends
ํค์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ํ, ๋น์ทํ๊ฒ ์กฐ๊ฑด ๋ถ๊ธฐ๋ฅผ ์ํด ์ผํญ ์ฐ์ฐ์ ?
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
TypeC = TypeA extends TypeB ? TrueExpression : FalseExpression
๋ง์ฝ TypeA
๊ฐ TypeB
์ ํ ๋น ๊ฐ๋ฅํ๊ฑฐ๋ ๋์ฒด๋ ์ ์๋ค๋ฉด, ์ฒซ ๋ฒ์งธ ๋ถ๊ธฐ์ ๋ค์ด๊ฐ๊ณ TrueExpression
์ ๋ํ ํ์
์ ์ป์ ์ ์๊ณ ๊ทธ ํ์
์ TypeC
์ ํ ๋นํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด FalseExpression
๋ฅผ ์ป์ด TypeC
์ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ ๋น์ํค๊ฒ ์ฃ .
ํ ๋น ๊ฐ๋ฅํ๋ค, ๋์ฒด ๊ฐ๋ฅํ๋ค(assignability, substitutability)์ ๊ฐ๋ ์ ํ์ ์คํฌ๋ฆฝํธ์์ ๊ต์ฅํ ํต์ฌ์ ์ธ ๊ฐ๋ ์ค ํ๋์ด๊ธฐ์ ์ด์ ๊ด๋ จํ ํฌ์คํ ์ ์์ฑํ๊ธฐ๋ ํ์ต๋๋ค. ์ด ๊ธ์์ ์์ธํ ๋ค๋ฃจ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ตฌ์ฒด์ ์ธ ์์๋ฅผ ๋ณผ๊น์?
const username = 'foo'
let matched
if(username === 'foo') {
matched = true
} else {
matched = false
}
์ด๋ฅผ ํ์ ์ธ์ด๋ก ๋ฐ๊พธ์ด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
type Username = 'foo'
type Matched = Username extends 'foo' ? true : false // true
extends
ํค์๋๋ ๋ค์ํ๊ฒ ํ์ฉํ ์ ์์ต๋๋ค. ์ ๋๋ฆญ ํ์์ ํ๋ผ๋ฏธํฐ์ ์ ์ฝ ์กฐ๊ฑด์ผ๋ก์ ์ ์ฉ์ํฌ ์๋ ์์ฃ .
function getUserName<T extends {name: string}>(user: T) {
return user.name
}
์ ๋๋ฆญ ์ ์ฝ์กฐ๊ฑด์ ์ถ๊ฐํจ์ผ๋ก์จ, <T extends {name: string}>
ํจ์๊ฐ ๋ฐ๋ ์ธ์๋ ํญ์ string
ํ์
์ name
ํ๋กํผํฐ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค๋ ๊ฒ์ ๋ณด์ฅํ ์ ์๊ฒ ๋๋ ๊ฒ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ์ฒด ํ๋กํผํฐ์ ์ ๊ทผํ๊ธฐ ์ํด obj['prop']
์ ๊ฐ์ด ๋๊ดํธ๋ฅผ ์ด์ฉํ๊ฑฐ๋ obj.prop
์ฒ๋ผ dot์ ์ฌ์ฉํฉ๋๋ค.
ํ์
์ธ์ด์์๋ ๋๊ดํธ๋ก ํ๋กํผํฐ ํ์
์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
type User = {name: string, age: number}
type Name = User['name']
์ด ๋ฐฉ์์ ๊ฐ์ฒด ํ์ ๋ฟ๋ง ์๋๋ผ ํํ์ด๋ ๋ฐฐ์ด๊ณผ ๊ฐ์ ํ์ ์์๋ ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
type Names = string[]
type Name = Names[number]
type Tuple = [string, number]
type Age = Tuple[1]
ํจ์๋ ์ด๋ ํ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋จ์์๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ "๊ตฌ์ฑ ์์"์
๋๋ค. ํจ์๋ ํน์ ํ input์ ๋ฐ์ output์ ๋ฆฌํดํด์ค๋๋ค.
ํ์
์ธ์ด์์๋ ์ ๋๋ฆญ์ด ์์ต๋๋ค. ์ ๋๋ฆญ์ ํจ์์ฒ๋ผ ๊ฐ์ ๋งค๊ฐ๋ณ์ํํ๋ ํ์
์
๋๋ค. ๊ทธ๋์ ์ ๋๋ฆญ์ ๊ฐ๋
์ ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ํจ์์ ๋น์ทํ๊ธฐ๋ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์๋ฐ์คํฌ๋ฆฝํธ๋ผ๋ฉด ์๋์ฒ๋ผ ์์ฑํฉ๋๋ค.
function fn(a, b = 'world') { return [a, b] }
const result = fn('hello') // ["hello", "world"]
ํ์ ์ธ์ด์์๋ ์ด๋ ๊ฒ ์์ฑํฉ๋๋ค.
type Fn <A extends string, B extends string = 'world'> = [A, B]
// โ โ โ โ โ
// name parameter parameter type default value function body/return statement
type Result = Fn<'hello'> // ["hello", "world"]
์๋ฒฝํ ๋น์ ๋ ์๋์ง๋ผ๋ ...
์ ๋๋ฆญ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ํจ์์ ์ ํํ ๋์ผํ์ง๋ ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ํจ์์ ๋ค๋ฅด๊ฒ ์ ๋๋ฆญ์ ํ์
์ธ์ด์ ์ผ๊ธ ๊ฐ์ฒด๊ฐ ์๋๋๋ค.
์ฆ, ํ์
์คํฌ๋ฆฝํธ๋ ํจ์๋ฅผ ๋ค๋ฅธ ํจ์๋ก ์ ๋ฌํ๋ ๊ฒ์ฒ๋ผ ์ ๋๋ฆญ์ ๋ค๋ฅธ ์ ๋๋ฆญ์ ์ ๋ฌํ ์ ์๋ค๋ ์๋ฏธ๊ฐ ๋๊ฒ ์ฃ .
ํ์
์ธ์ด์์ ํ์
์ ๋ถ๋ณํฉ๋๋ค. ํ์
์ ์ด๋ ๋ถ๋ถ์ ์์ ํ๊ณ ์ถ๋ค๋ฉด ๊ธฐ์กด์ ํ์
์ ์๋ก์ด ํ์
์ผ๋ก ๋ณํ์์ผ์ผ๋ง ํฉ๋๋ค.
ํ์
์ธ์ด์์ ๋ฐ์ดํฐ ๊ตฌ์กฐ(์๋ฅผ ๋ค์ด ๊ฐ์ฒด)์ ๊ฑธ์ณ ๋ฐ๋ณตํ๊ณ ๋ณํํ๋ ๊ฒ์ ๊ณ ๋ฅด๊ฒ ์ ์ฉํ๋ ์ธ๋ถ ์ฌํญ๋ค์ Mapped Types์ ์ํด ์ถ์ํ๋ฉ๋๋ค.
์ด๋ฅผ ์ฌ์ฉํด์ map๊ณผ filter์ ๊ฐ์ ๋ฐฐ์ด ๋ฉ์๋์ ๊ฐ๋
์ ์ผ๋ก ๋น์ทํ ๋์๋ค์ ๊ตฌํํ ์ ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๋๋ฒ ํ๋กํผํฐ๋ฅผ ๋ฌธ์์ด๋ก ๋ฐ๊พธ๋ ค๋จผ ์๋ ์ฝ๋์ฒ๋ผ ์์ฑํฉ๋๋ค.
const user = {
name: 'foo',
age: 28
}
function stringifyProp(object) {
return Object.fromEntries(Object.entries(object)
.map(([key, value]) => [key, String(value)]))
}
const userWithStringProps = stringifyProp(user) // {name:'foo', age: '28'}
ํ์
์ธ์ด์์ ๋งคํ์ [K in keyof T]
์ ๊ฐ์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฅํฉ๋๋ค. keyof
์ฐ์ฐ์๋ ํ๋กํผํฐ ์ด๋ฆ๋ค์ string ์ ๋์จ ํ์
์ผ๋ก ์ ๋ฌํฉ๋๋ค.
type User = {
name: string,
age: number
}
type StringifyProp<T> = {
[K in keyof T]: string
}
type UserWithStringProps = StringifyProp<User> // { name: string; age: string; }
์๋ฐ์คํฌ๋ฆฝํธ์์ ํน์ ๊ธฐ์ค์ ๋ฐ๋ผ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ํํฐ๋งํ ์ ์์ต๋๋ค. ๋ฌธ์์ด์ด ์๋ ํ๋กํผํฐ๋ฅผ ํํฐ๋งํ๋ ์์ ๋ฅผ ๋ณผ๊น์?
const user = {
name: 'foo',
age: 28
}
function filterNonStringProp(object) {
return Object.fromEntries(Object.entries(object)
.filter(([key, value]) => typeof value === 'string' && [key, value]))
}
const filteredUser = filterNonStringProp(user) // {name: 'foo'}
ํ์
์ธ์ด์์๋ as
์ฐ์ฐ์์ never
ํ์
์ผ๋ก ์ด๋ฅผ ์ํํ ์ ์์ต๋๋ค.
type User = {
name: string,
age: number
}
type FilterStringProp<T> = {
[K in keyof T as T[K] extends string ? K : never]: string
}
type FilteredUser = FilterStringProp<User> // { name: string }
ํ์ ์คํฌ๋ฆฝํธ์๋ ํ์ ์ ๋ณํ์์ผ์ฃผ๋ ๋ด์ฅ๋ ์ ํธ๋ฆฌํฐ "ํจ์"(์ ๋๋ฆญ)์ด ๋ค์ ์์ผ๋ฏ๋ก ์ฌ๋ฌ๋ถ๋ค์ ์ด๋ฅผ ์ง์ ๋ง๋ค ํ์๋ ์์ต๋๋ค.
ํ์
์ธ์ด์์ ํจํด ๋งค์นญ์ ํ๊ณ ์ infer
ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด JS ํ๋ก๊ทธ๋จ์์๋ ๋ฌธ์์ด์ ํน์ ๋ถ๋ถ์ ์ถ์ถํ๊ธฐ ์ํด ์ ๊ท์์ ์ฌ์ฉํฉ๋๋ค.
const str = 'foo-bar'.replace(/foo-*/, '')
console.log(str) // 'bar'
์ด ์ฝ๋๋ฅผ ํ์ ์ธ์ด๋ก ๋ฐ๊พธ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
type Str = 'foo-bar'
type Bar = Str extends `foo-${infer rest}` ? rest : never // 'bar'
๋ค๋ฅธ ๋ง์ ์์ํ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ฐ ๊ทธ๋ ๋ฏ์ด, ํ์ ์ธ์ด ๋ํ ๋ฐ์ดํฐ์ ๋ชฉ๋ก์ ๋ฃจํ๋ฅผ ๋๋ฉฐ ๋ฐ๋ณตํ๋ ๊ตฌ๋ฌธ ๊ตฌ์กฐ๊ฐ ์์ต๋๋ค. ์ฌ๊ท ๋ฐฉ์์ด ๋ฃจํ ๋ฐฉ์์ ๋์ฒดํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์๋ ๋์ผํ ์์ดํ ์ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณตํ๋ ๋ฐฐ์ด์ ๋ฐํํ๋ ํจ์๋ฅผ ์์ฑํ๋ค๋ฉด ์๋์ฒ๋ผ ์ธ ์ ์๊ฒ ์ต๋๋ค.
function fillArray(item, n) {
const res = [];
for (let i = 0; i < n; i++) {
res[i] = item;
}
return res;
}
์ด๋ฅผ ์ฌ๊ท๋ก ๋ฐ๊พธ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
function fillArray(item, n, array = []) {
return array.length === n ? array : fillArray(item, n, [item, ...array])
}
์ด ์ฝ๋๋ฅผ ํ์ ์ธ์ด์์ ๋์ผํ๊ฒ ๋์ํ๋ ค๋ฉด ์ด๋ป๊ฒ ์จ์ผ ํ ๊น์? ํด๊ฒฐ์ฑ ์ ์ฐพ๊ธฐ ์ํ ๋ ผ๋ฆฌ์ ์ธ ๋จ๊ณ๋ค์ด ์์ต๋๋ค.
FilArray
๋ผ๋ ์ ๋๋ฆญ ํ์
์ ์์ฑํ๋ค. (ํจ์์ฒ๋ผ ํ์
์ธ์ด์์๋ ์ ๋๋ฆญ์ด ์๋ค๊ณ ๋งํ์ฃ ?)FillArray<Item, N extends number, Array extends Item[] = []>
extends
ํค์๋๋ฅผ ์ฌ์ฉํด์ Array
์ length
ํ๋กํผํฐ๊ฐ N
์ด ๋์๋์ง ํ์ธํ๋ค.
N
์ ๋๋ฌํ๋ค๋ฉด, Array
๋ฅผ ๋ฆฌํดํ๋ค.N
์ ๋๋ฌํ์ง ์์๋ค๋ฉด, Array
์ Item
์ ๋ํ๊ณ ๋ค์ ๋ฐ๋ณตํ๋ค.์ด ๋จ๊ณ๋ค์ ํ์ ์ธ์ด๋ก ํํํ๋ค๋ฉด ์ด๋ ๊ฒ ์ธ ์ ์์ต๋๋ค.
type FillArray<Item, N extends number, Array extends Item[] = []>
= Array['length'] extends N
? Array : FillArray<Item, N, [...Array, Item]>;
type Foos = FillArray<'foo', 3> // ["foo", "foo", "foo"]
TS 4.5 ์ ์ ์ต๋ ์ฌ๊ท ๊น์ด๋ 45๊น์ง ์์ต๋๋ค. 4.5 ๋ฒ์ ์์ ๊ผฌ๋ฆฌ ํธ์ถ์ด ์ต์ ํ๋จ์ ๋ฐ๋ผ 999๊น์ง ์ฆ๊ฐํ์ต๋๋ค.
๋๋๋ก ํ์ ํ๋ก๊ทธ๋๋ฐ์ ์ฐ์ค๊ฐฏ์๋ฆฌ๋ก "type gymnastics"๋ผ๊ณ ๋ถ๋ฆฌ๊ธฐ๋ ํ๋๋ฐ ์ด๋ ์ผ๋ฐ์ ์ธ ์ดํ๋ฆฌ์ผ์ด์ ์์ ํ์ํ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ณต์กํ๊ณ ํ๋ คํ๋ฉฐ ์ ๊ตํ ๋๋ฅผ ์๋ฏธํฉ๋๋ค. ์๋ฅผ ๋ค์๋ฉด,
์ด๋ฐ ๊ฒฝ์ฐ๋ค์ ํจ์ฌ ๋ ํ์ ์ ์ธ ์์์ด๋ฏ๋ก ์ค์ ํ๋ก๋์ ์ดํ๋ฆฌ์ผ์ด์ ๊ณผ๋ ๋ง์ง ์์ต๋๋ค.
์ ๊ฐ์ ์ด์ ๋ค์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฝ์ด ํ๋ก๊ทธ๋๋ฐ ์คํฌ์ ํฅ์์ํค๊ธฐ ์ํด ๋ฆฌํธ์ฝ๋ ๋ฌธ์ ๋ฅผ ํธ๋ ๊ฒ์ฒ๋ผ ์ฌ๋ฌ๋ถ์ ํ์ ํ๋ก๊ทธ๋๋ฐ ์คํฌ์ ์ํด type-challenges์ ํ์ด๋ณผ ์ ์์ต๋๋ค.
์ ๋ง ๋ง์ ๊ฒ๋ค์ ์ด ๊ธ์์ ๋ค๋ฃจ์๋ค์. ์ด ๊ธ์ ํต์ฌ์ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ๋ฅด์น๋ ๊ฒ์ด ์๋๋ผ, ์ด์ฉ๋ฉด ์ฌ๋ฌ๋ถ๋ค์ด ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฐฐ์ฐ๊ณ ๋์ ๊ฐ๊ณผํ์ ์๋ ์๋ "์จ๊ฒจ์ง" ํ์ ์ธ์ด๋ฅผ ๋ค์ ์๊ฐํ๋ ๊ฒ์ ๋๋ค.
ํ์ ํ๋ก๊ทธ๋๋ฐ์ ํ์ ์คํฌ๋ฆฝํธ ์ปค๋ฎค๋ํฐ์์ ํ๋ฐํ๊ฒ ๋ ผ์๊ฐ ์ด๋ฃจ์ด์ง๊ณ ์์ง ์์๋ฐ, ๊ทธ๊ฒ์ด ์๋ชป๋๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๊ถ๊ทน์ ์ผ๋ก ํ์ ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋ชฉ์ ์ ์ํ ์๋จ์ผ๋ฟ, ๊ฒฐ๊ตญ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์ ๋ขฐ์ฑ ์๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ง๋๋ ๊ฒ ์ค์ํ๋๊น์. ๊ทธ๋์ ์ฌ๋๋ค์ด ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ค๋ฅธ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ค์ฒ๋ผ "์ ์ ํ๊ฒ" ํ์ ์ธ์ด๋ฅผ ๊ณต๋ถํ๋ ๋ฐ ์๊ฐ์ ๋ค์ด์ง ์๋ ๊ฒ์ด ์ถฉ๋ถํ ์ดํด๊ฐ ๋ฉ๋๋ค.
์ฑ๋ฅ์ต์ ํ๋ ์ธ์ ๋ ๋น์ฉ์ด ๋ค์ง๋ง ํญ์ ์ข์ ๊ฑด ์๋๋๋ค. useMemo์ useCallback์ ๋น์ฉ๊ณผ ์ฅ์ ์ ๋ํด ์ด์ผ๊ธฐํด๋ด ์๋ค.
์ฌ๊ธฐ์ ์ฌํ ๋์คํ์๊ฐ ์์ต๋๋ค.
์ด๋ป๊ฒ ๊ตฌํํ๋์ง ๋ด ์๋ค.
function CandyDispenser() {
const initialCandies = ['snickers', 'skittles', 'twix', 'milky way']
const [candies, setCandies] = React.useState(initialCandies)
const dispense = candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}
return (
<div>
<h1>Candy Dispenser</h1>
<div>
<div>Available Candy</div>
{candies.length === 0 ? (
<button onClick={() => setCandies(initialCandies)}>refill</button>
) : (
<ul>
{candies.map(candy => (
<li key={candy}>
<button onClick={() => dispense(candy)}>grab</button> {candy}
</li>
))}
</ul>
)}
</div>
</div>
)
}
๊ทธ๋ผ ์ด์ ์ฌ๋ฌ๋ถ๋ค์๊ฒ ์ง๋ฌธ์ ํ ๊ฒ๋๋ค. ์์ผ๋ก ๋์๊ฐ๊ธฐ ์ ์ ์ฌ๋ฌ๋ถ๋ค์ด ์ ์ง๋ฌธ์ ๋ํด ์ ์๊ฐํด๋ณด๊ธธ ๋ฐ๋๋๋ค. ์ด ์ฝ๋๋ฅผ ์์ ํ ๊ฑด๋ฐ ์ด๋ค ๊ฒ์ด ๋ ๋์ ์ฑ๋ฅ์ ๊ฐ์ง ์ ์๋์ง ์๋ ค์ฃผ์ธ์.
์ ๊ฐ ๋ฐ๊ฟ ๊ฒ์ dispense
ํจ์๋ React.useCallback
์ผ๋ก ๊ฐ์ธ๋ ๊ฒ์
๋๋ค.
const dispense = React.useCallback(candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}, [])
์๋ ์ฝ๋๋ ์ด๋ ์ต๋๋ค.
const dispense = candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}
์ด ์ํฉ์์ ์๋ ์ฝ๋์ ๋ณ๊ฒฝ๋ ์ฝ๋ ์ค ์ด๋ค ๊ฒ์ด ์ฑ๋ฅ์ ๋ ์ข์๊น์? ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ์๋ ค์ฃผ์ธ์.
์ญ : ์๋ฌธ์๋ ๋ ์๊ฐ ์ ํํ ์ ์๋ ๋ฒํผ์ด ์์ง๋ง ์๋ตํฉ๋๋ค.
์ ๋ต์ '์๋ณธ ์ฝ๋' ์ ๋๋ค.
useCallback
์ ์ฐ๋๊ฒ ๋ ์์ข์๊ฐ์?์ฑ๋ฅ์ ํฅ์์ํค๊ณ "์ธ๋ผ์ธ ํจ์๋ ์ฑ๋ฅ์ ๋ฌธ์ ๊ฐ ์๋ค"๊ณ ํ๊ธฐ ๋๋ฌธ์ React.useCallback
์ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๋ง์ด ๋ค์ผ์
จ์ ๊ฒ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ useCallback
์ ์ฌ์ฉํ์ง ์๋๊ฒ ์ ๋ ์ข์ ์ฝ๋์ผ๊น์?
์๊น ๋ดค๋ ์์์์ ํ ๋ฐ์ง ๋ฌผ๋ฌ๋ React ์ฝ๋๋ฅผ ์์ฑํ ๋๋ ์คํ๋๋ ์ฝ๋์ ๋ชจ๋ ๋ผ์ธ์ ๋น์ฉ์ด ๋ ๋ค๋ ์ ์ ๊ณ ๋ คํ์ธ์. ์ด์ useCallback
์์๋ฅผ ๋ช
ํํ๊ฒ ์ค๋ช
ํ๊ณ ์ ์ข ๋ ์ดํด๋ณด๊ฒ ์ต๋๋ค. (์ค์ ๋ณํ๋ ์์ง๋ง ์ฝ๊ฐ์ ์ด๋๋ง ํฉ๋๋ค)
const dispense = candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}
const dispenseCallback = React.useCallback(dispense, [])
์๋ณธ ์ฝ๋๋ฅผ ๋ค์ ๋ณด์ฌ๋๋ฆฌ์ฃ .
const dispense = candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}
๋ ์ฝ๋์ ๋ํด ๋ญ๊ฐ ์์์ฐจ๋ฆฌ์ จ๋์? ์ฐจ์ด์ ์ ์ดํด๋ด ์๋ค.
const dispense = candy => {
setCandies(allCandies => allCandies.filter(c => c !== candy))
}
+ const dispenseCallback = React.useCallback(dispense, [])
๋ง์ต๋๋ค. useCallback
๋ฒ์ ์ด ์ข ๋ ๋ง์ ์ผ์ ํ๋ค๋ ๊ฒ ๋นผ๊ณ ๋ ์ฝ๋๋ ์ ํํ ๊ฐ์ต๋๋ค. ํจ์๋ฅผ ์ ์ํด์ผ ํ๋ ๊ฒ ๋ฟ๋ง ์๋๋ผ ๋ฐฐ์ด์ ์ ์ํ๊ณ ํ๋กํผํฐ๋ฅผ ์ค์ ํ๊ณ ๋
ผ๋ฆฌ์ ์ธ ํํ์ ํตํด ์คํ๋๋ React.useCallback
์ ํธ์ถํด์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ ๋ ๊ฐ์ง ๊ฒฝ์ฐ ๋ชจ๋ JavaScript๋ ๋ ๋๋ง ๋๋ง๋ค ํจ์ ์ ์์ ๋ํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ผ ํ๊ณ ์ด๋ป๊ฒ useCallback
์ด ๊ตฌํ๋๋์ง์ ๋ฐ๋ผ ํจ์ ์ ์์ ๋ํด ๋ ๋ง์ ํ ๋น์ด ํ์ํ ์ ์์ต๋๋ค. (์ด ๊ฒฝ์ฐ์ ํด๋นํ์ง๋ ์์ง๋ง ์ ๋ง์ ์์ ์ ์ฌ์ ํฉ๋๋ค) ์ ๊ฐ ํธ์ํฐ ํฌํ๋ฅผ ํตํด ์ ๋ฌํ๊ณ ์ ํ๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ ๋ต์ ์๊ณ ์์ง๋ง ์ ๊ฐ ๋ง์ ์ํด๊ฒ ํด์ ํ๋ฆฐ ๋ต์ ์ ํํ์ จ๋ค๋ฉด ์ฃ์กํฉ๋๋ค.
์ปดํฌ๋ํธ์ ๋ ๋ฒ์งธ ๋ ๋๋ง ๋ ์๋ ์๋ dispense
ํจ์๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์์งํ๊ณ (๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ๋ ํ๋ฆฌ์ฃ ) ์๋ก์ด ํจ์๊ฐ ์์ฑ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ useCallback
๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์๋ ์๋ dispense
ํจ์๋ ์์ง๋์ง ์๊ณ ์๋ก์ด ํจ์๊ฐ ์์ฑ๋๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ธก๋ฉด์์๋ ์ข์ง ์๋ค๋ ๊ฒ์ ๋ง์๋๋ฆฌ๊ณ ์ถ์์ต๋๋ค.
๊ด๋ จํด์ useCallback
์ dependency๊ฐ ์๋ ๊ฒฝ์ฐ React๊ฐ ์ด์ ํจ์์ ๋ํ ์ฐธ์กฐ๋ก ๊ทธ ๊ฐ๋ค์ ๊ณ์ ๊ฐ์ง๊ณ ์์ ๊ฒ๋๋ค. ๋ฉ๋ชจ์ด์ ์ด์
์ ์ด์ ์ ์ฃผ์ด์ก๋ dependency ๊ฐ๋ค์ด ๋์ผํ ๊ฒฝ์ฐ ์ด์ ๊ฐ๋ค์ ๊ทธ๋๋ก ๋ฆฌํดํด์ฃผ๊ธฐ ๋๋ฌธ์
๋๋ค.ํนํ ๋์น๊ฐ ๋น ๋ฅธ ๋ถ๋ค์ด๋ผ๋ฉด React๊ฐ dependency ๊ฐ๋ค์ ๋์ผ์ฑ ์ฒดํฌ๋ฅผ ์ํด ํด๋น ๊ฐ๋ค์ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ด์ผ ํ๋ค๋ ๊ฒ์ ์์์ฐจ๋ฆฌ์
จ์ ๊ฒ๋๋ค.
useMemo
๋ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ์?useMemo
๋ ํจ์ ๋ฟ๋ง ์๋๋ผ ์ด๋ค ํ์
์ ๊ฐ์ด๋ ๋ฉ๋ชจ์ด์ ์ด์
์ ํ ์ ์๋ค๋ ๊ฒ ์ธ์ useCallback
๊ณผ ์ ์ฌํฉ๋๋ค. ๊ฐ์ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐ์ผ๋ฉด ํจ์๋ ๊ฐ์ด ๋ฐํ๋์ด์ผ ํ ๋๋ง ํธ์ถ๋ฉ๋๋ค. (๋ณดํต ๋ ๋ ์ dependency ๋ฐฐ์ด ๋ด ๊ฐ๋ค์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํ๋ฒ ๋ฐ์ํฉ๋๋ค.)
๊ทธ๋์ ๋ ๋๋ง ๋๋ง๋ค initialCandies
๋ฐฐ์ด์ ๋ค์ ๋ง๋ค๊ธฐ ์ซ๋ค๋ฉด ์ด๋ ๊ฒ ์ฝ๋๋ฅผ ๋ฐ๊พธ์ด์ผ ํฉ๋๋ค.
- const initialCandies = ['snickers', 'skittles', 'twix', 'milky way']
+ const initialCandies = React.useMemo(
+ () => ['snickers', 'skittles', 'twix', 'milky way'],
+ [],
+ )
๊ทธ๋ฌ๋ฉด ๊ทธ ๋ฌธ์ ๋ ํผํ ์ ์๊ฒ ์ง๋ง, ์ ์ฅ๋ ๊ฐ๋ค์ด ๋๋ฌด ์์์ ์ฝ๋๋ฅผ ๋ณต์กํ๊ฒ ํ๋ ๊ฒ๋งํผ์ ๊ฐ์น๊ฐ ์์ง ์์ต๋๋ค. ์ฌ์ค ์ด๋ ๊ฒ useMemo
๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์๋ฅผ ํธ์ถํ๋ฉด์ ํ๋กํผํฐ ํ ๋น ๋ฑ์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ข์ง ์์ต๋๋ค.
์ด ์์์์๋ ์ด๋ ๊ฒ ์ฝ๋๋ฅผ ๋ฐ๊พธ๋ ๊ฒ์ด ์ข์ต๋๋ค.
+ const initialCandies = ['snickers', 'skittles', 'twix', 'milky way']
function CandyDispenser() {
- const initialCandies = ['snickers', 'skittles', 'twix', 'milky way']
const [candies, setCandies] = React.useState(initialCandies)
๊ทธ๋ฌ๋ ๊ฐ๋ค์ด props๋ก ๋์ด์ค๊ฑฐ๋ ํจ์ ๋ฐ๋์์ ์ด๊ธฐํ๋๋ ๋ค๋ฅธ ๊ฐ๋ค์ด ํ์ํ๋ฉด ์ด๋ ๊ฒ ์์ฑํ ์ ์์ ๊ฒ๋๋ค.
์ ๊ฐ ๋งํ๊ณ ์ ํ๋ ๋ฐ๋ ๊ฒฐ๊ตญ ์ฝ๋๋ฅผ ์ต์ ํํ ๋ ์ป๋ ๋ฒ ๋คํ์ด ๋งค์ฐ ๋ฏธ๋ฏธํ๊ธฐ ๋๋ฌธ์ ์ด๋ป๊ฒ ํ๋ก์ ํธ๋ฅผ ๊ฐ์ ํ ์ ์์์ง๋ฅผ ์๊ฐํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๋ ๊ฒ์ ๋๋ค.
๊ฒฐ๊ตญ ์ด ๊ธ์ ์์ ์ ๋ง์๋๋ฆฌ์๋ฉด, ์ฑ๋ฅ ์ต์ ํ๋ ๊ณต์ง๊ฐ ์๋๋๋ค. ์ฑ๋ฅ ์ต์ ํ๋ ์ธ์ ๋ ๋น์ฉ์ ๋๋ฐํ์ง๋ง ํญ์ ๋น์ฉ๋งํผ์ ๋ฒ ๋คํ์ ๊ฐ์ ธ๋ค์ฃผ๋ ๊ฒ์ ์๋๋ผ๋ ๊ฒ๋๋ค.
๊ทธ๋ฌ๋ ์ฑ ์๊ฐ์ ๊ฐ๊ณ ์ต์ ํํ์ธ์.
useMemo
์ useCallback
์ ์ฌ์ฉํด์ผ ํ๋์?๋ hook์ด React์ ๋ด์ฅ๋์ด ์๋ ๋ถ๋ช ํ ์ด์ ๊ฐ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด JavaScript๋ ํ๋ก๊ทธ๋๋ฐ ์ด๋ณด๋ผ ํ ์ง๋ผ๋, ์ ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋์ง ๊ธ๋ฐฉ ์ ๊ฒ๋๋ค.
true === true // true
false === false // true
1 === 1 // true
'a' === 'a' // true
{} === {} // false
[] === [] // false
() => {} === () => {} // false
const z = {}
z === z // true
// NOTE: React actually uses Object.is, but it's very similar to ===
์ด ์ฝ๋์ ๋ํด ๊น๊ฒ ์๊ธฐํ์ง๋ ์๊ฒ์ง๋ง, ์ฌ๋ฌ๋ถ์ด React ํจ์ํ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ ์ธํ ๋ ๊ฐ์ ๊ฐ์ฒด๊ฐ ์ ์๋ ๋ง์ง๋ง ์๊ฐ๊ณผ ์ฐธ์กฐ๊ฐ ๋์ผํ์ง ์์ ๊ฒ๋๋ค. (๋์ผํ ํ๋กํผํฐ๊ณผ ๊ฐ์ ๊ฐ์ง๊ณ ์๋ค๊ณ ํด๋ ๋ง์ด์ฃ .)
React์์ ์ฐธ์กฐ ๋์ผ์ฑ์ด ์ค์ํ ๋ ๊ฐ์ง ์ํฉ์ด ์๋๋ฐ ํ๋์ฉ ์ดํด๋ด ์๋ค.
๋ค์ ์์๋ฅผ ๋ด ์๋ค.
๊ฒฝ๊ณ : ๋ถ์์ฐ์ค๋ฌ์ด ์ฝ๋๊ฐ ๋ณด์ด๋๋ผ๋ ์ปจ์ ์ ์ง์คํด์ฃผ์ธ์!
function Foo({bar, baz}) {
const options = {bar, baz}
React.useEffect(() => {
buzz(options)
}, [options]) // we want this to re-run if bar or baz change
return <div>foobar</div>
}
function Blub() {
return <Foo bar="bar value" baz={3} />
}
์ด ์ฝ๋๊ฐ ๋ฌธ์ ์ธ ์ด์ ๋ useEffect
๊ฐ ๋ ๋๋ง ์์ ๋ง๋ค options
์ ๋ํ ์ฐธ์กฐ ๋์ผ์ฑ ํ์ธ์ ํด์ผ ํ๊ณ JavaScript์ ๋์ ๋ฐฉ์์ ์ํด options
๋ ๋ชจ๋ ์์ ์์ ์๋ก์ด ์ฐธ์กฐ๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฒฐ๊ตญ React๋ ํญ์ options
๊ฐ ๋ณ๊ฒฝ๋์๋ค๊ณ ํ๊ฐํ ๊ฒ๋๋ค. ๊ทธ๋ ๋ค๋ฉด useEffect
์ ์ฝ๋ฐฑํจ์๋ bar
์ baz
๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ํธ์ถ๋๋ ๊ฒ์ด ์๋๋ผ ๋งค ๋ ๋๋ง ๋๋ง๋ค ํธ์ถ๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค.
// option 1
function Foo({bar, baz}) {
React.useEffect(() => {
const options = {bar, baz}
buzz(options)
}, [bar, baz]) // we want this to re-run if bar or baz change
return <div>foobar</div>
}
์ด ๋ฐฉ๋ฒ์ ์์ฃผ ์ข์ต๋๋ค. ์ค์ ๋ก ์ ๊ฐ ํด๊ฒฐํ ๋ฐฉ๋ฒ์ด์ฃ .
๊ทธ๋ฌ๋ ์ด ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ํ ๊ฐ์ง ์ํฉ์ด ์์ต๋๋ค. bar
๋ baz
๊ฐ ์์๊ฐ์ด ์๋ ๊ฐ์ฒด/๋ฐฐ์ด/ํจ์ ๋ฑ์ผ ๋์
๋๋ค.
function Blub() {
const bar = () => {}
const baz = [1, 2, 3]
return <Foo bar={bar} baz={baz} />
}
์ด๋ฐ ๊ฒฝ์ฐ๊ฐ useCallback
๊ณผ useMemo
์ ์กด์ฌ ์ด์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋์
๋๋ค. ์ด๋ป๊ฒ ์์ ํ ๊น์?
function Foo({bar, baz}) {
React.useEffect(() => {
const options = {bar, baz}
buzz(options)
}, [bar, baz])
return <div>foobar</div>
}
function Blub() {
const bar = React.useCallback(() => {}, [])
const baz = React.useMemo(() => [1, 2, 3], [])
return <Foo bar={bar} baz={baz} />
}
์ฐธ๊ณ ๋ก useEffect
, useLayoutEffect
, useCallback
, useMemo
์ ์ฌ์ฉ๋๋ dependencies ๋ฐฐ์ด์ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค.
React.memo
๊ฒฝ๊ณ : ๋ ๋ถ์์ฐ์ค๋ฌ์ด ์ฝ๋๊ฐ ๋ณด์ผ์ง๋ผ๋ ์ปจ์ ์ ์ํ ๊ฒ์ด๋ ์ดํด ๋ฐ๋๋๋ค.
์ด ์ฝ๋๋ฅผ ๋ณผ๊น์?
function CountButton({onClick, count}) {
return <button onClick={onClick}>{count}</button>
}
function DualCounter() {
const [count1, setCount1] = React.useState(0)
const increment1 = () => setCount1(c => c + 1)
const [count2, setCount2] = React.useState(0)
const increment2 = () => setCount2(c => c + 1)
return (
<>
<CountButton count={count1} onClick={increment1} />
<CountButton count={count2} onClick={increment2} />
</>
)
}
์ฌ๋ฌ๋ถ์ด ๋ฒํผ์ ํด๋ฆญํ ๋๋ง๋ค DualCounter
์ ์ํ๊ฐ์ ๋ณ๊ฒฝ๋์ด ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ์ฌ CountButton
์ปดํฌ๋ํธ๋ค๋ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋ก๋ ํด๋ฆญ๋ ๋ฒํผ๋ง ๋ค์ ๋ ๋๋ง์ด ๋์ด์ผ ํ์ง ์์๊น์? ์ฒซ ๋ฒ์งธ ๋ฒํผ์ ํด๋ฆญํ์ ๋, ๋ ๋ฒ์งธ ๋ฒํผ์ด ๋ค์ ๋ ๋๋ง๋๋๋ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฐ ์ํฉ์ "๋ถํ์ํ ๋ฆฌ๋ ๋"๋ผ๊ณ ํฉ๋๋ค.
๋ถํ์ํ ๋ ๋๋ง์ ์ต์ ํํ๋๋ฐ ๋๋ฌด ๋ง์ ์๊ฐ์ ์ฐ์ง ๋ง์ธ์. React๋ ๊ต์ฅํ ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ต์ ํํ๋ ๊ฒ๋ณด๋ค ๋ ์ค์ํ ์ผ๋ค์ด ๋ง์ต๋๋ค. ์ค์ ๋ก Paypal ์ ํ์ ์์ ํ๋ 3๋ ๋์ ๋ง ๊ทธ๋๋ก 3๋ ๋์, ๊ทธ๋ฆฌ๊ณ React๋ก ์์ ํ ๊ธฐ๊ฐ๋์ ํ ํ์๊ฐ ์์๋ต๋๋ค.
๊ทธ๋ฌ๋ ์ธํฐ๋ํฐ๋ธํ ๊ทธ๋ํ, ์ฐจํธ, ์ ๋๋ฉ์ด์ ๋ฑ ๋ ๋๋ง์ ๋ง์ ์๊ฐ์ด ์์๋๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ๋คํํ React์ ์ค์ฉ์ฃผ์์ ์ธ ํน์ฑ ๋๋ถ์ ๋น์๊ตฌ๊ฐ ์กด์ฌํฉ๋๋ค.
const CountButton = React.memo(function CountButton({onClick, count}) {
return <button onClick={onClick}>{count}</button>
})
์ด์ React๋ props๊ฐ ๋ณ๊ฒฝ๋ ๋ CountButton
๋ง์ ๋ฆฌ๋ ๋๋ง ํ ๊ฒ๋๋ค! ๊ทธ๋ฌ๋ ์์ง ํ ์ผ์ด ๋จ์์ต๋๋ค. ์๊น ์๊ธฐํ๋ ์ฐธ์กฐ ๋์ผ์ฑ์ ๊ธฐ์ตํ์๋์? DualCounter
์ปดํฌ๋ํธ์์ increment1
๊ณผ increment2
ํจ์๋ฅผ ์ ์ํ๋๋ฐ, DualCounter
๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋๋ง๋ค ์ด ํจ์๋ค์ ์๋ก ์์ฑ๋์ด CountButton
๋ค์ ๋ค์ ๋ ๋๋งํ๊ฒ ๋ ๊ฒ๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ๊ฐ useCallback
๊ณผ useMemo
๊ฐ ๋์์ด ๋๋ ๋ ๋ค๋ฅธ ์ํฉ์
๋๋ค.
const CountButton = React.memo(function CountButton({onClick, count}) {
return <button onClick={onClick}>{count}</button>
})
function DualCounter() {
const [count1, setCount1] = React.useState(0)
const increment1 = React.useCallback(() => setCount1(c => c + 1), [])
const [count2, setCount2] = React.useState(0)
const increment2 = React.useCallback(() => setCount2(c => c + 1), [])
return (
<>
<CountButton count={count1} onClick={increment1} />
<CountButton count={count2} onClick={increment2} />
</>
)
}
์ด์ ์ฐ๋ฆฌ๋ CountButton
์ปดํฌ๋ํธ์ "๋ถํ์ํ ๋ฆฌ๋ ๋๋ง"์ ํผํ ์ ์๊ฒ ๋์ต๋๋ค.
๋ค์ ๋งํ์ง๋ง ์ ๋ React.memo
(๋ ๋น์ทํ PureComponent
, ShouldComponentUpdate
)๋ฅผ ๊ธฐ์ค์์ด ์ฌ์ฉํ์ง ์๋ ๊ฒ์ ๊ถ๊ณ ํฉ๋๋ค. ์ต์ ํ๋ฅผ ํ์ ๋์ ๋น์ฉ๊ณผ ์ป์ ์ ์๋ ์ด์ ์ด ์๋์ง ํ์ธํ๋ ๊ฒ์ด ํ์ํฉ๋๋ค. ์์์ ์ดํด๋ณธ ๊ฒ์ฒ๋ผ ์ต์ ํ๋ฅผ ํ์ ๋ ์ป๋ ์ด์ ์ด ์์ ์๋ ์์ต๋๋ค.
React์์ useMemo
๊ฐ ๋ด์ฅ๋ ๋ ๋ค๋ฅธ ์ด์ ๊ฐ ์์ต๋๋ค.(useCallback
์ ํด๋น๋์ง ์์ต๋๋ค.) useMemo
์ ์ฅ์ ์ ์๋์ฒ๋ผ ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ๋๋ค.
const a = {b: props.b}
์ด ๊ฐ์ lazyํ๊ฒ ํด๋ณผ๊น์.
const a = React.useMemo(() => ({b: props.b}), [props.b])
์ด๊ฒ์ ์์ ์ผ์ด์ค์ฒ๋ผ ์ ์ฉํ ๊ฒ์ ์๋์ง๋ง ์ฌ๋ฌ๋ถ์ด ๋๊ธฐ์ ์ผ๋ก ๋ณต์กํ ๊ฐ์ ๊ณ์ฐํ๋ ํจ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํด๋ณด์ธ์.
function RenderPrimes({iterations, multiplier}) {
const primes = calculatePrimes(iterations, multiplier)
return <div>Primes! {primes}</div>
}
iterations
๋ multiplier
๋ฅผ ์๊ฐํด๋ณด๋ฉด ์ฐ์ฐ ์๋๊ฐ ๊ฝค ๋๋ฆด ๊ฑฐ๋ผ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ด ๋ฌธ์ ์ ๋ํด ํ ๊ฒ์ ๋ฑํ ์๊ณ , ํ๋์จ์ด๋ฅผ ์๋์ ์ผ๋ก ๋น ๋ฅด๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ์ ๊ฐ์ ๋ ๋ฒ ๊ณ์ฐํ์ง ์๋๋ก ํ ์๋ ์์ต๋๋ค.
function RenderPrimes({iterations, multiplier}) {
const primes = React.useMemo(() => calculatePrimes(iterations, multiplier), [
iterations,
multiplier,
])
return <div>Primes! {primes}</div>
}
์ด ๋ฐฉ๋ฒ์ด ํจ๊ณผ์ ์ธ ์ด์ ๋ ๋ชจ๋ ๋ ๋๋ง ๋๋ง๋ค ์์๋ฅผ ๊ณ์ฐํ๋ ํจ์๋ฅผ ์ ์ํ๋ค๊ณ ํ๋๋ผ๋ React๋ ํ์ํ ๊ฐ์ด ์์ ๋๋ง ํจ์๋ฅผ ํธ์ถํ๋ค๋ ๊ฒ๋๋ค. React๋ ์ด์ ์ ๊ฐ๋ค์ ์ ์ฅํ๊ณ ๊ฐ์ ์ ๋ ฅ๊ฐ์ด ๋ค์ด์ค๋ฉด ์ด์ ๊ฐ๋ค์ ๋ฐํํฉ๋๋ค. ๋ฉ๋ชจ์ด์ ์ด์ ์ด ๋์ํ๋ ๋ฐฉ์์ ๋๋ค.
๋ชจ๋ ์ถ์ํ(์ ์ฑ๋ฅ ์ต์ ํ)๋ ๋น์ฉ์ด ๋ ๋ค๋ ์ฌ์ค์ ๋ง์๋๋ฆฌ๋ฉด์ ๊ธ์ ๋ง๋ฌด๋ฆฌํ๊ณ ์ ํฉ๋๋ค. AHA ํ๋ก๊ทธ๋๋ฐ ์์น์ ์ ์ฉํ๊ณ ์ถ์ํ/์ต์ ํ๊ฐ ์ ๋ง ํ์ํ ๋๋ง ์ ์ฉ์ํจ๋ค๋ฉด ์ด์ ์ด ์์ด ๋น์ฉ๋ง ๋๋ ์ํฉ์์ ๋ฒ์ด๋ ์ ์์ ๊ฒ๋๋ค.
ํนํ useCallback
๊ณผ useMemo
๋ ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ๋ณต์กํ๊ฒ ๋ง๋๋ ๋น์ฉ์ ๊ฐ์ง๋๋ค. ๋ํ dependencies ๋ฐฐ์ด์ ์ค์๋ฅผ ํ๋ค๋ฉด ์ฌ๋ฌ๋ถ์ ๋ด์ฅ๋ hooks์ ํธ์ถํ๊ฑฐ๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ๊ฐ์ ์์งํ์ง ๋ชปํ๊ฒ ํ์ฌ ์ฑ๋ฅ์ ๋์๊ฒ ๋ง๋ค ์๋ ์์ต๋๋ค. ์ป๊ณ ์ ํ๋ ์ด์ต์ด ์์ ๋ ๋ฐ์ํ๋ ๋น์ฉ์ ๊ด์ฐฎ์ง๋ง, ๋จผ์ ํ์ธํด๋ณด๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
๊ด๋ จ๋์ด ์ฝ์ด๋ณผ๋งํ ๊ฒ๋ค์ ๋๋ค.
์ถ์ . ์ฌ๋ฌ๋ถ์ด hook์ผ๋ก ์ฎ๊ธฐ๋ ๊ฒ๊ณผ ํด๋์ค๋ก ์ ์ธํ๋ ๊ฒ๋ค์ ํจ์ํ ์ปดํฌ๋ํธ๋ก ์ ์ํด์ผ ํ๋ ๊ฑฐ์ ๊ฑฑ์ ํ๊ณ ์๋ ๋ถ ์ค์ ํ ๋ช ์ด๋ผ๋ฉด ๋ฉ์๋๋ฅผ render ๋จ๊ณ์์ ์ ์ํ๊ณ ์์๋ค๋ ์ฌ์ค์ ๊ณ ๋ คํด๋ณด์๊ธธ ๊ถํฉ๋๋ค.
class FavoriteNumbers extends React.Component {
render() {
return (
<ul>
{this.props.favoriteNumbers.map(number => (
// TADA! This is a function defined in the render method!
// Hooks did not introduce this concept.
// We've been doing this all along.
<li key={number}>{number}</li>
))}
</ul>
)
}
}
NestJS๋ ํจ์จ์ ์ด๊ณ ํ์ฅ ๊ฐ๋ฅํ Node.js ์๋ฒ ์ฌ์ด๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํ ํ๋ ์์ํฌ์ ๋๋ค. ์ต์ ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ฉฐ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ์๋ฒฝํ ์ง์ํฉ๋๋ค.
๋ณธ์ง์ ์ผ๋ก NestJS๋ ์๋ฒ ์ฌ์ด๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋น ๋ฅด๊ณ ์ฝ๊ฒ ์์ฑํ ์ ์๋๋ก ์ง์ํ๋ ๋ฉ์๋์ ๊ตฌํ ๊ธฐ๋ฅ์ ๊ฐ์ถ ๋ ธ๋ ์์ ๊ณ์ธต์ ๋๋ค. NestJS๋ ์ฌ๋ฌ๋ถ์ด ํ์ํ ๊ฒ์ ๋ชจ๋ ๋ง์กฑ์์ผ์ฃผ์ด ์์ฃผ ํธ๋ฆฌํฉ๋๋ค. ์ปค์คํฐ๋ง์ด์งํ๊ธฐ๊ฐ ์ข๊ณ ๊ธฐ๋ณธ์ ์ผ๋ก Express ๊ธฐ๋ฐ์์ ๋์ํ์ง๋ง ์ ํ์ ์ผ๋ก Fastify๋ฅผ ์ฌ์ฉํ๊ฒ ์ค์ ํ ์ ์์ต๋๋ค.
ํผํผํ ๊ตฌ์กฐ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ํด ์๊ธฐํ ๋, ์ฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ์ค์ํ๊ฒ ์๊ฐํ๋ ๊ฒ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๋ถ๋ถ์ ๋ถ๋ฆฌํ์ฌ ํจ๊ป ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ๊ตฌ์กฐ์ ์ธ ํจํด์ ๋ฐ๋ฅด๋ ๊ฒ์ ์์ฑํ๊ณ ์๋ ์คํ๊ฒํฐ ์ฝ๋๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด ์๋ ํ๋ก์ฐ ๋ค์ด์ด๊ทธ๋จ์ ๊ณ ๋ คํด๋ณผ ๋ ์ปจํธ๋กค๋ฌ์ ์๋น์ค ๋ ์ด์ด๊ฐ ํจ๊ป ์๋ํ์ฌ ๋ ผ๋ฆฌ๋ฅผ ์ํํ์ง๋ง ๋์ ์์ ํ ๋ค๋ฅธ ๊ฒ์ ๋๋ค. ์ปจํธ๋กค๋ฌ๋ค์ ๋ณธ์ง์ ์ผ๋ก ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ฃจํธ(route)๋ฅผ ๋ค๋ฃน๋๋ค. ํ๋์ ์ปจํธ๋กค๋ฌ๋ ๋ช ๊ฐ์ง ๋ค๋ฅธ ๋ฃจํธ๋ฅผ ๊ฐ์ง๊ณ ๋ผ์ฐํ ๋ฉ์ปค๋์ฆ์ ๋ฐ๋ผ ์ด๋ค ์ปจํธ๋กค๋ฌ๊ฐ ์ด๋ค ์์ฒญ์ ๋ํด ์๋ตํ ์ง ๋ฌ๋ผ์ง๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ปจํธ๋กค๋ฌ ๋ด๋ถ์ ๋ฃ๋๋ค๋ฉด ์ด๋จ๊น์? ์๋ง๋ ์์ง ์ ์ ๊ฐ ๋ฑ๋ก๋์ง ์์ ๊ฒฝ์ฐ ์ ์ ์ ๋ฅผ ๋ฑ๋กํ๊ฑฐ๋ ์ปจํธ๋กค๋ฌ ๋ด์์๋ง ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํํ ์ ์์ ๊ฒ์ ๋๋ค.
์ด๋ฌํ ์ํฉ์ ๋ง์ด ๋์ง ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ํฌํค๊ฐ ์๋ค๋ฉด ๋ฌธ์ ๊ฐ ๋์ง ์์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ด ์ปค์ง์ ๋ฐ๋ผ ๋ ๋ง์ ์ปจํธ๋กค๋ฌ์ ๋ฃจํธ๊ฐ ํ์ํด์ง๋ฉฐ ๋ ๋ง์ ๋น์ฆ๋์ค ๋ก์ง์ ์์ฑํด์ผ ํฉ๋๋ค. ์ด๋ ๊ฒ ๋๋ค๋ฉด ์ํฉ์ ํต์ ๋ถ๊ฐ๋ฅํด์ง๋ฉฐ ์ ์ง๋ณด์ํ ์ ์๊ฒ ๋ฉ๋๋ค.
CLI๋ฅผ ์ฌ์ฉํด์ NestJS ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๋ฉด, ๋ช ๊ฐ์ง ๋ณด์ผ๋ฌํ๋ ์ดํธ ํ์ผ์ ์ ๊ณตํฉ๋๋ค. ์ฌ๋ฌ๋ถ๋ค์ด ์์ ํ๋ ์ฝ์ด ํ์ผ๋ค์ ๋๋ค. ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ ์๋์ ๊ฐ์ต๋๋ค.
src
| โ app.controller.spec.ts
| โ app.controller.ts
| โ app.module.ts
| โ app.service.ts
| โ main.ts
์ฌ๋ฌ๋ถ์ด ๋ฐ๋ผ์ผ ํ๋ ํน์ ๊ตฌ์กฐ๊ฐ ์๋ค๋ ๊ฑธ ์๊ฒ ๋์์ต๋๋ค. ์ด๋ฌํ ๊ตฌ์กฐ๋ ๊นจ๋ํ๊ณ ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์๋น์ค ํ์ผ์ ์์ฑํ๊ณ ์ปจํธ๋กค๋ฌ ํ์ผ ๋ด์์ ์ํฌํธํ๊ณ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ํจ์๋ฅผ ๊ตฌํํ๋ CatsService๋ผ๋ ํด๋์ค๋ฅผ export ํด๋ด ์๋ค.
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatsService {
getAllCats(): string {
return 'Get all cats!';
}
getOneCat(): string {
return 'Get one cat!';
}
}
CatsService
ํด๋์ค๋ฅผ ์ต์คํฌํธํ๊ณ ์ธ ๊ฐ์ง์ ๋ฉ์๋๋ฅผ ์ ์ํ์ต๋๋ค. ๋ํ @Injectable()
๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๋ฐ์ฝ๋ ์ดํฐ๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ฒจ๋ถํ๊ณ ์ฃผ์
๊ฐ๋ฅํ ํด๋์ค๋ฅผ ์ข
์์ฑ์ผ๋ก ๋ํ๋
๋๋ค. ํด๋์ค๋ฅผ ๋ํ๋์๋ก ์ฃผ์
ํ๊ธฐ ๋๋ฌธ์ ๊ณ ์์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ์ปจํธ๋กค๋ฌ ๋ด๋ถ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import { Controller, Get } from '@nestjs/common';
import { CatsService } from '../services/cats.service';
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Get('allcats')
getCats(): string {
return this.catsService.getAllCats();
}
@Get('onecat')
getOneCat(): string {
return this.catsService.getOneCat();
}
}
์ปจํธ๋กค๋ฌ ํ์ผ์์ CatsService๋ฅผ ์ํฌํธํ๊ณ ์์ฑ์ ๋ด์์ ์๋น์ค ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. CatsService ๋ํ๋์๋ ํด๋์ค ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ๋ฉ๋๋ค. (dependency injection) CatsService ๋ด์์ ์ ์ํ ์ฌ๋ฌ ๋ฉ์๋๋ฅผ ๋ ธ์ถ์ํฌ ์ ์์ต๋๋ค. ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํด์ ๊ณ ์์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ต๋๋ค.
์์กด์ฑ์ ํด๋์ค๊ฐ ํจ์๋ฅผ ์ํํ๋ ๋ฐ ํ์ํ ์๋น์ค ๋๋ ๊ฐ์ฒด์ ๋๋ค. ์์กด์ฑ ์ฃผ์ (DI)์ ํด๋์ค๊ฐ ์ธ๋ถ ์์ค๋ก๋ถํฐ ์ข ์์ฑ์ ์์ฑํ๋ ๋์ ์์ฒญํ๋ ๋์์ธ ํจํด์ ๋๋ค.
@get() ๋ฐ์ฝ๋ ์ดํฐ๋ ์ธ์๋ฅผ ๋ฐ์ ์ถ๊ฐ๋ ๊ธฐ๋ฅ๊ณผ ๋์ผํ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค. ๋ํ @get() ๋ฐ์ฝ๋ ์ดํฐ๋ ํน์ route๋ฅผ ์์ฒญํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ pathname์ ํ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด /cats/allCats ์ ๋ํ ์์ฒญ์ getCats๋ฅผ ํธ์ถํ์ฌ ๋ชจ๋ ๊ณ ์์ด๋ฅผ ๋ฐํํฉ๋๋ค.
"Great User Experience"
Suspense
๋ client์์ React.lazy
๋ฅผ ์ด์ฉํ์ฌ ์ฝ๋๋ฅผ ๋์ ์ผ๋ก ๋ก๋ฉํ๋ ๊ฒฝ์ฐ์ ์ฅ์ ์ด ์์์
Reading the data
+ Specifying the loading state
if (isLoading) return <Spinner />;
return (...);
// declarative way !
<Suspense fallback={<Spinner />}>
<List pageId={pageId} />
</Suspese>
"design centric idea"
React.lazy
Concurrent Redering : "A behind-the-scenes capability in React that powers features like Suspense"
"what์ ์ง์คํ๋ผ, React๋ how์ ์ง์คํ๋ค . . "
Xuan Huang
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos);
const handleChange = todo => setTodos(todos => getUpdated(todos, todo));
const filtered = getFiltered(todos, visibility);
return (
<div>
<ul>
{filtered.map(todo => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
<AddTodo setTodos={setTodos} themeColor={themeColor} />
</div>
);
}
function TodoList({ visibility, themeColor }) {
const [todos, setTodos] = useState(initialTodos)
let hasVisibilityChanged, hasThemeColorChanged, hasTodosChanged, memoCache
if (hasVisibilityChanged || hasThemeColorChanged || hasTodosChanged) {
const handleChange = memoCache[0] || (memoCache[0] = (todo) => setTodos((todos) => getUpdated(todos, todo)))
let filtered, jsx_todos
if (hasVisibilityChanged || hasTodosChanged) {
filtered = memoCache[1] = getFiltered(todos, visibility)
jsx_todos = memoCache[2] = (
<ul>
{filtered.map((todo) => (
<Todo key={todo.id} todo={todo} onChange={handleChange} />
))}
</ul>
)
} else {
filtered = memoCache[1]
jsx_todos = memoCache[2]
}
}
const jsx_addTodo = hasThemeColorChanged ? (memoCache[3] = <AddTodo setTodos={setTodos} themeColor={themeColor} />) : memoCache[3]
return (
<div>
{jsx_todos}
{jsx_addTodo}
</div>
)
}
Daishi Kato
props
context
useState
useReducer
useSyncExternalStore
: React 18์์ ๋์
subscribe
: get callback, return unsubscribe funcgetSnapshot
: return immutable valueTafu Nakazaki (SmartHR)
์๋ฌธ GraphQL Pagination Primer: Offset vs. Cursor vs. Relay-Style Pagination
์ด ํฌ์คํ ์ ์ ๊ฐ ์ ์ ํ Advanced GraphQL with Apollo & React์ Relay ์คํ์ผ ํ์ด์ง๋ค์ด์ ์ ๋ํ ์ฑํฐ์์ ๋ฐ์ทํ์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด GraphQL API๋ฅผ ๊ฐ๋ฐํ ๋ ๋ฐ์ดํฐ ๋ชฉ๋ก์ ๋ฐํํด์ผ ํ๋ ๋ฐ ๋ชจ๋ ๊ฒฐ๊ณผ๋ฅผ ํ ๋ฒ์ ๊ฒ์ํ๊ธฐ์๋ ๋๋ฌด ๋ง์ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ๋ํ GraphQL ์ฟผ๋ฆฌ ๋ด์์ ์ค์ฒฉ๋ ๋ฆฌ์คํธ ํ๋๋ค์๋ ํด๋นํ๋ ์๊ธฐ์ ๋๋ค. ๊ทธ๋์ ํ์ด์ง๋ค์ด์ ์ด ํ์ํ ๊ฒ์ด์ฃ .
์ฐ๋ฆฌ๊ฐ ๋งค์ผ ์ฌ์ฉํ๋ ์ดํ๋ฆฌ์ผ์ด์ ์์ ํ์ด์ง๋ค์ด์ ์ ๋๋ฌด ํํ ๊ธฐ๋ฅ์ด์ง๋ง, ์ ๊ตฌํํ๊ธฐ์๋ ๊น๋ค๋ก์ด ๊ธฐ๋ฅ์ด ๋ ์ ์์ต๋๋ค. ํ ์ ๋ ๋ ์ GraphQL ์ฟผ๋ฆฌ๊ฐ ์ด๋ค ํ์ด์ง๋ค์ด์ ๋ฐฉ๋ฒ์ ์ ํํ ์ง์ ๋ํ ์ฌ๋ฌ ์ ํ์ง๋ค์ด ์กด์ฌํ๊ณ ์์ต๋๋ค.
์ด์ ์ ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ ์ ์ด ์๋ค๋ฉด ์๋ง offset ๊ธฐ๋ฐ์ด๋ cursor ๊ธฐ๋ฐ ๋ฐฉ์์ ๋ ์น์ํ์ค ๊ฒ๋๋ค. GraphQL API๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ฐ๋ฆฌ์๊ฒ๋ Relay-style ํ์ด์ง๋ค์ด์ ์ด๋ผ๋ ํ๋์ ์ต์ ์ด ๋ ์์ต๋๋ค.
Relay-style ํ์ด์ง๋ค์ด์ ์ ํ์ด์ง GraphQL ์ฟผ๋ฆฌ์์๋ ๊ฝค ์ธ๊ธฐ์๋ ์ ํ์ง์ ๋๋ค. ํ์ง๋ง GraphQL ์คํค๋ง๊ฐ Relay ๋ช ์ธ๋ฅผ ์ค์ํ๋์ง ํ์ธํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ๊ณ ๋ คํ ์ฌํญ์ด ์์ต๋๋ค.
์ด ํฌ์คํ ์์๋ ๊ฐ ํ์ด์ง๋ค์ด์ ๋ฐฉ์์ ๋ฐ๋ฅธ ์ฅ์ ๊ณผ ๋จ์ ์ ์ดํด๋ณผ ๊ฒ์ ๋๋ค. ๊ทธ ํ์ ์ฌ๋ฌ๋ถ์๊ฒ ๋ ์ ํฉํ ๋ฐฉ์์ ์ ํํ์๋ฉด ๋ฉ๋๋ค.
์ญ์ฌ์ ์ผ๋ก ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก๋ถํฐ ๊ฒฐ๊ณผ๊ฐ๋ค์ ํ์ด์งํ๋ ์ธ๊ธฐ์๋ ์ ํ์ง์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ผ๋ก ํ์ด์ง์ ํ๋ฉด, ํด๋ผ์ด์ธํธ๋ ํ์ด์ง ๋น ๋ฐ๊ณ ์ ํ๋ ํญ๋ชฉ์ ๊ฐ์ ๋ํ ์ ๋ณด(limit์ด๋ผ ๋ถ๋ฆผ)์ ๋ฐ์ด ๋์ ํญ๋ชฉ๋ค์ ๊ฐ์์ ๋ํ ์ ๋ณด(offset์ด๋ผ ๋ถ๋ฆผ)๋ฅผ ์๋ฒ์ ๋ณด๋ ๋๋ค. ์๋ฒ๋ ์ด ๊ธฐ์ค์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํน์ ๋ฐ์ดํฐ ์ ์ ์ฟผ๋ฆฌํด์ต๋๋ค. (ํ์ํ๋ค๋ฉด ๊ธฐ๋ณธ limit, offset์ ์ค์ ํด๋ก๋๋ค.)
์ด๋ป๊ฒ ๋์ํ๋์ง ์๊ฐ์ ์ผ๋ก ๋ณด๊ธฐ ์ํด, 5๊ฐ ํญ๋ชฉ์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฐ์ดํฐ ์ ์ด ์๋ค๊ณ ๊ฐ์ ํด๋ณด์ธ์. ๊ทธ๋ฆฌ๊ณ ๊ฐ ํ์ด์ง ๋น 2๊ฐ์ฉ, ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ๋์ด ์๋ ํญ๋ชฉ๋ค์ ๋ ๋ฒ์งธ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ฌ ๊ฒ๋๋ค.
์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์ฒด ํ์ด์ง ์๋ฅผ ์๊ณ ์์ ๋ ์ ์ฉํฉ๋๋ค. ๋ํ ์๋ฐฉํฅ ํ์ด์ง๋ค์ด์ ์ ์ ์ง์ํ์ฃ . ์๋ฐฉํฅ ํ์ด์ง๋ค์ด์ ์ ์ฌ๋ฌ๋ถ๋ค์ด ํ์ด์ง ์์ผ๋ก, ๋ค๋ก ์ด๋ํ๊ฑฐ๋ ํน์ ํ์ด์ง๋ก ์ด๋ํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. ๋ธ๋ก๊ทธ์ ๊ฐ์ ๊ณณ์์ ๋ง์ด ๋ณด์ด๋ ๋ฐฉ์์ด์ฃ .
๊ทธ๋ฌ๋ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๋ฌด ๋ง์ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ฒฝ์ฐ์ ์ด ๋ฐฉ์์ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ฑ๋ฅ ์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ๋น๋ฒํ๊ฒ ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ์๋ ์ค์๊ฐ์ผ๋ก ํ์ด์ง window๊ฐ ์๋ชป ๋งค์นญ๋์ด ๋ฐ์ดํฐ๊ฐ ์ค๋ณต๋์ด ๋ณด์ด๊ฑฐ๋ ์ ์ค๋ ์ ์์ต๋๋ค.
์ด ์ํ์ ์ค๋ช ํ๊ธฐ ์ํด ๋ฐ์ดํฐ์ ์์ ์ฒซ ๋ฒ์งธ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค๋ ์ํฉ์ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ํด๋น ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ ๋์ ๋ค์ ํ์ด์ง์ ๋์ด๊ฐ๊ธฐ ์ ์ 6๋ฒ์งธ ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋์์ต๋๋ค. ๊ฐ์๊ธฐ ํ์ด์ง ์๋์ฐ๊ฐ ํ ์๋ฆฌ์ฉ ๋ฐ๋ฆฌ๊ฒ ๋์ด 4๋ฒ์งธ ๋ฐ์ดํฐ๊ฐ ์ฒซ ๋ฒ์งธ ํ์ด์ง์ ๋ง์ง๋ง์ด์ ๋ ๋ฒ์งธ ํ์ด์ง์ ์ฒ์์ ๋ณด์ด๊ฒ ๋ฉ๋๋ค.
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ๋ฐ์ดํฐ์ ์์ ๊ฒฐ๊ณผ๋ฌผ๋ค์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์งํํ๊ธฐ ์ํ ์ปค์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ปค์๋ ๋ฐ์ดํฐ์ ์์ ํน์ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ์ ๋๋ค. ๊ณ ์ ํ๊ณ ์์ฐจ์ ์ธ ๊ฐ๋ค์ ํํด์ ๋ฐฑ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ํฉํ ์ด๋ค ๊ฐ์ด๋ ๋ ์ ์์ต๋๋ค. ํด๋ผ์ด์ธํธ๊ฐ ์ดํ ํ์ด์ง๋ฅผ ํ์ํ ๋ ์๋ฒ๋ ์ปค์ ๊ฐ์ผ๋ก ํ์๋ ํญ๋ชฉ ๋ค์ ์๋ ๊ฒฐ๊ณผ๊ฐ๋ค์ ๋ฐํํด์ค๋๋ค.
5๊ฐ์ ๋ฐ์ดํฐ์ ์์ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉํ๋ฉด ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ต๋๋ค.
์ปค์ ํน์ฑ ์์ฒด๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ค์ํ ๊ฒ์ด ์๋๋๋ค. ํด๋ผ์ด์ธํธ๋ ์ดํ ๋ค์ ๊ฐ๋ค์ ๋ํด ์์ฒญ์ ๋ณด๋ผ ๋ ์ปค์ ๊ฐ์ ์๋ฒ๋ก ๋ค์ ๋ณด๋ด๊ธฐ๋ง ํ๋ฉด ์๋ฒ๊ฐ ์ด๋ ์์ ๋ถํฐ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํด์ผ ํ๋์ง ์ ์ ์์ต๋๋ค.
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์คํ์ ๊ธฐ๋ฐ ๋ฐฉ์์์ ๋ฐ์ํ๋ ํ์ด์ง ์๋์ฐ์ ๋ถ์ ํ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ๋๋ฌธ์ ๋น ๋ฅด๊ฒ ๊ฐฑ์ ๋๋ ๋ฐ์ดํฐ์ ์ ์์ฃผ ์ ํฉํ ๋ฐฉ์์ ๋๋ค. ์ฒซ ๋ฒ์งธ ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค๊ณ 6๋ฒ์งธ ์์ดํ ์ด ์ถ๊ฐ๋์์ด๋ ์ปค์๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์ ํ์ด์ง๋ฅผ ์์ํ๋ ๊ฒ์ ํผ๋์ ์ฌ์ง๊ฐ ์์ต๋๋ค.
์ด ๋ฐฉ์์ ๋จ์ ๋ ์์ต๋๋ค. ์ปค์ ๊ธฐ๋ฐ์ ์ ๊ทผ์ ํน์ ํ์ด์ง ๋๋ฒ๋ก ์ ํํ๊ฑฐ๋ ์ ์ฒด ํ์ด์ง ์๋ฅผ ๊ณ์ฐํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋น ๋ฅด๊ฒ ์ ๋ฐ์ดํธ๋๊ณ ์ปจํ ์ธ ๋ฅผ ๋ธ๋ผ์ฐ์งํ๋ ๋ฌดํ ์คํฌ๋กค์ ๊ตฌํํด์ผ ํ ๋๋ ํ์ด์ง ๋๋ฒ๋ ์ ์ฒด ํ์ด์ง ์๊ฐ ์๋ ๊ฒ์ด ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
Relay-style ํ์ด์ง๋ค์ด์ ์ GraphQL API์์ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฝ๊ฐ์ ํฅ์ด ์ฒจ๊ฐ๋ ๋ฐฉ์์ ๋๋ค. Relay ์์ฒด๋ GraphQL API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๊ณ ์บ์ฑํ๋ ํด๋ผ์ด์ธํธ๋ก ์ฌ์ฉํ ์ ์๋ JavaScript ํ๋ ์์ํฌ์ ๋๋ค. ์ด ๋ฐฉ์์ ํ์ด์ค๋ถ์ ์ํด ๋ง๋ค์ด์ก๊ณ ํ์ด์ค๋ถ ์์ค์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ง์ ์ฑ์ ์ผ๋์ ๋๊ณ ์ค๊ณ๋์์ต๋๋ค.
Relay๋ Apollo Client์ ๊ฐ์ ๋ค๋ฅธ ์ต์ ๋ค๋ณด๋ค๋ ์ข ๋ ์ง์ ์ฅ๋ฒฝ์ด ๋์ต๋๋ค. ๊ทธ๋์ GraphQL์ ์์ํ ๋ Relay ์์ฒด๊ฐ ๊ฐ๋ฐ์๋ค์๊ฒ ์ฒซ ๋ฒ์งธ ํจํค์ง๋ ์๋์ฃ . ๊ทธ๋ฌ๋ Relay๋ GraphQL API์์ ์ด๋ป๊ฒ ํ์ด์ง๋ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ ๊ฒ์ธ์ง์ ๋ํ ์ ์ฉํ ๋ก๋๋งต์ ์ ๊ณตํ๋๋ฐ, ์ด๋ฅผ "์ปค์ ์ปค๋ฅ์ ๊ท๊ฒฉ(GraphQL Cursor Connections Specification)"์ด๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ด ๋งํฌ์์ Relay์ ์ ์ฒด ๊ท๊ฒฉ์ ์ฝ์ด๋ณด์ค ์ ์์ต๋๋ค.
๋น๋ก ์ฌ๋ฌ๋ถ์ ํด๋ผ์ด์ธํธ ์ฑ์์ Relay๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ์ง๋ ์์๋, ์ฌ๋ฌ๋ถ์ GraphQL API์์ ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ ๋ ์ฌ์ ํ ์ด ๊ท๊ฒฉ์ ๋ฐ๋ฅผ ์ ์์ต๋๋ค. ๋ํ Relay๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ๊ฐ ๋์ค์ ์ฌ๋ฌ๋ถ์ API์ ์์ฒญ์ ๋ณด๋ด๋ ค๋ ๊ฒฝ์ฐ ์ด ํ์ด์ง๋ค์ด์ ๋ฐฉ์์ ์ฌ์ฉํ ๋ ์ฌ๋ฌ๋ถ์ API๋ฅผ ์ข ๋ ๋ฏธ๋์งํฅ์ ์ผ๋ก ๋ง๋ค์ด์ค ์๋ ์์ต๋๋ค.
Relay-style ํ์ด์ง๋ค์ด์ ์์ ๊ธฐ์ตํด์ผ ํ ์ค์ํ ์ ์ ๋จ๋ฐฉํฅ์ฑ์ ๋๋ค. ์ฌ๋ฌ๋ถ์ด ์ฑ์์ "์ด์ ํ์ด์ง" ๋ฒํผ๊ณผ "๋ค์ ํ์ด์ง" ๋ฒํผ์ผ๋ก ์ปจํ ์ธ ์ด๋์ ๊ตฌํํ๊ณ ์ ํ๋ค๋ฉด Relay ๋ฐฉ์์ ์๋ง ์ฌ๋ฌ๋ถ์๊ฒ ์ ํฉํ ๋ฐฉ์์ด ์๋ ๊ฒ๋๋ค. (๊ตฌ๊ธ๋ง์ ํ๋ฉด ์๋ฐฉํฅ ํ์ด์ง์ ์ง์ํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๊ธฐ๋ ํฉ๋๋ค.) ๊ทธ๋ฌ๋ ์ถ๊ฐ์ ์ธ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ค ๋ ๋ฌดํ ์คํฌ๋กค์ UI๋ฅผ ๊ตฌํํ๋ค๋ฉด, ์ด ๋ฐฉ์์ ์์ฃผ ์ ๋ง์ ๊ฒ๋๋ค.
์ด์ ์ ์ธ๊ธํ๋ฏ์ด, Relay๋ ํ์ด์ง๋ ์ฟผ๋ฆฌ ๋ฐ์ดํฐ์ ์์ํ ๋ฟ๋ง ์๋๋ผ ์ธ์๋ฅผ ํตํด ์์ฒญ์ด ์ด๋ฃจ์ด์ง๋ ๋ฐฉ์์ ๋ํด ๋งค์ฐ ํ๊ณ ํฉ๋๋ค. Relay ๋ฐฉ์์ ํ์ด์ง๋ค์ด์
์ผ๋ก ๊ตฌํ๋ ๊ฐ์ ์ฟผ๋ฆฌ์ ์๋ฅผ ๋ด
์๋ค. following
ํ๋๋ User
๊ฐ์ฒด์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํฉ๋๋ค.
query {
user(username: "bob") {
fullName
following(first: 20, after: "someProfileId") {
edges {
cursor
node {
fullName
username
}
}
pageInfo {
hasPreviousPage
hasNextPage
}
}
}
}
์ฌ๋ฌ๋ถ๋ค์ ์ด ์ฟผ๋ฆฌ์ ๋ช ๊ฐ์ง ์ฌ๋ฐ๋ ํน์ง์ ๋ํด ์์์ฐจ๋ฆฌ์
จ์ ๊ฒ๋๋ค. ๋จผ์ , ์ฟผ๋ฆฌ์ edge
ํ์
์ ๋ฆฌ์คํธ๋ก ๊ฐ๊ณ ์๋edges
๊ฐ ์์ต๋๋ค. ์ด edge
ํ์
์ node
์ cursor
๋ก ๋ถ๋ฆฌ๋ ์ต์ 2๊ฐ์ ํ๋๋ก ์ด๋ฃจ์ด์ง ๊ฐ์ฒด ํ์
์
๋๋ค.
node
ํ๋๋ ๊ฐ์ฒด ์์ฒด์ด๊ณ ๋ฆฌ์คํธ๋ฅผ ์ ์ธํ GraphQL ์ด๋ค ํ์
์ด๋ ๋ ์ ์์ต๋๋ค. (์ฐ๋ฆฌ์ ๊ฒฝ์ฐ์๋ User
ํ์
์ด ๋๊ฒ ์ต๋๋ค.) cursor
ํ๋๋ ๊ฐ edge๋ฅผ ์๋ณํ๋ ๊ณ ์ ํ๊ณ ์์ฐจ์ ์ธ ๊ฐ์ ํด๋นํ๋ ๋ฌธ์์ด์
๋๋ค.
๋ง์ง๋ง์ผ๋ก pageInfo
๋ hasPreviousPage
์ hasNextPage
ํ๋๋ฅผ ๋ฌด์กฐ๊ฑด ๊ฐ์ง๋ ๊ฐ์ฒด์
๋๋ค. ๋ ํ๋ ๋ชจ๋ null์ด ๋ ์ ์๋ boolean ๊ฐ์
๋๋ค.
๋ํ ์ฟผ๋ฆฌ์ first
, after
์ธ์์ ๋ํด ์ฃผ๋ชฉํด์ผ ํ๋๋ฐ ์ด ๊ฐ๋ค์ ์ ๋ฐฉํฅ ํ์ด์ง๋ค์ด์
์ ์ํ ์ธ์ ๊ฐ๋ค์
๋๋ค. ์ ๋ฐฉํฅ์ด ์๋๋ผ ์ญ๋ฐฉํฅ์ผ๋ก ํ์ด์ง๋ค์ด์
์ ํ๊ณ ์ถ๋ค๋ฉด last
, before
์ธ์๋ฅผ ์ฌ์ฉํ ๊ฒ๋๋ค.
์ฐธ๊ณ ! ์ญ๋ฐฉํฅ ํ์ด์ง๋ค์ด์ ์ ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ๊ณผ๋ ๋ค๋ฆ ๋๋ค. ๋ฐ์ดํฐ์ ์ ๋์์๋ถํฐ ์์ํด์ ์ฒ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ์์ ์๋ฏธํฉ๋๋ค. ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ์ ๋์ ๊ฐ๋ถํฐ ๋ฎ์ ๊ฐ์ผ๋ก ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๊ฒ์ ์๋ฏธํ๋ ๊ฒ์ด๊ณ ์. ๋ฐ์ดํฐ์ ์ ๋ณดํต ๋จผ์ ์ ๋ ฌ์ด ๋๊ณ , ์ ๋ ฌ๋ ๊ฐ๋ค์ ํ์ด์ง๋ฅผ ๊ฒ์ํ ๋ ์ ๋ฐฉํฅ ๋๋ ์ญ๋ฐฉํฅ ํ์ด์ง๋ค์ด์ ์ ์ ์ฉํ๊ฒ ๋ฉ๋๋ค.
์ ์ฟผ๋ฆฌ ์์์์ ๋ช
ํํ์ง ์์ ์ ์ ์์ ์์ค์ "connection type"์ด ๊ฐ์ฒด ์ ํ์ผ๋ก ๊ตฌํ๋๊ณ (์ ๋์ฌ๋ก Connection
์ด ๋ถ๋) following
ํ๋๊ฐ User
๊ฐ์ฒด ํ์
์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฆฌ์คํธ ๋์ ํ๋์ ์ปค๋ฅ์
๊ฐ์ฒด๋ก ๋ฐํ๋๋ค๋ ๊ฒ์
๋๋ค.
์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ ๋ฌธ๋ฒ์ ๋ํ ์ด ๊ฐ๋ ์ ๋ชจ๋ธ์ด ์ฒ์์๋ ๋ถ๋ด์ค๋ฌ์ธ ์๋ ์์ง๋ง ์ดํ๋ฆฌ์ผ์ด์ ์์ ํ์ด์ง๋ค์ด์ ์ ๋ค๋ฃจ๋ ๋ฐ ๊น๋ํ๊ณ ํ์คํ๋ ๋ฐฉ์์ ์ ๊ณตํฉ๋๋ค.
์ด ํฌ์คํธ์์๋ ์คํ์ , ์ปค์, Relay ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ 3๊ฐ์ง ๋ฐฉ์์ ๋ํด ์์๋ณด์์ต๋๋ค.
์คํ์ ๊ธฐ๋ฐ์ ํ์ด์ง๋ค์ด์ ์ (๋ณดํต์) ๋น ๋ฅด๊ฒ ๊ตฌํ๋๊ณ ์๋ฐฉํฅ ํ์ด์ง๋ค์ด์ ์ ์ง์ํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค. ๋ํ ์ ์ฒด ํ์ด์ง ์๋ฅผ ๊ณ์ฐํ ๋๋ ์ข์ต๋๋ค. ๋ค๋ง ์ฑ๋ฅ ์ด์๊ฐ ์๊ณ ๋น ๋ฅด๊ฒ ๋ฐ์ดํฐ๊ฐ ์ ๋ฐ์ดํธ๋๋ ๊ฒฝ์ฐ์๋ ์ ๋ง์ง ์์ต๋๋ค.
์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์์ฃผ ๋น ๋ฅด๊ฒ ๋ฐ์ดํฐ๊ฐ ์ ๋ฐ์ดํธ๋๊ณ ์ผ๋ฐ์ ์ผ๋ก ๋จ๋ฐฉํฅ์ ์ง์ํ ๋ ์คํ์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฌ์ฉํ์ ๋์ ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํ ์ ์์ต๋๋ค. Relay ๋ฐฉ์์ ํ์ด์ง๋ค์ด์ ์ GraphQL API๋ก ํ์ด์ง๋ค์ด์ ์ ๊ตฌํํ ๋ ์ปค์ ๊ธฐ๋ฐ ํ์ด์ง๋ค์ด์ ์ ์ฝ๊ฐ์ ์กฐ๋ฏธ๋ฃ๋ฅผ ์ฒจ๊ฐํ ๋ ํ๋์ ์ ํ์ง์ ๋๋ค.
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ์ด ํฌ์คํธ๊ฐ ๋ง์์ ๋์ จ๋ค๋ฉด Advanced GraphQL with Apollo & React์ ์ ์ฒด ์ฑํฐ๋ฅผ ๋ฌด๋ฃ๋ก ๋ค์ด๋ก๋ ๋ฐ์ผ์ค ์ ์์ต๋๋ค.
์๋ฌธ : https://calvin.hashnode.dev/javascript-classes-are-harmful
๊ฝค ๋๋ดํ ํํ์ด์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ข ๋ค๋ค๋ณธ ๊ฐ๋ฐ์๋ผ๋ฉด ๋ค๋ค ๋๋ผ๋ ๊ฐ์ ์ผ ๊ฒ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ ๋๋ก ๋ฐฐ์ฐ์ง ์์ผ๋ฉด ๋์ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ ์ ๋ฐ๋๋ก ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์๋ฌํ์ง ์๊ณ ๋ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ ์ ์๋ค๋ ์ฅ์ ์ด ๋๊ธฐ๋ ํฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ์ด๋ฐ ์ ์ด ํ๋ก๊ทธ๋๋ฐ์ ๋ ๊ฐ์ง ์ค์ํ ํจ๋ฌ๋ค์์ผ๋ก ๋น ์ง๊ธฐ ์ ๊น์ง ์ค๋ซ๋์ ์ง์๋์ด์๋ ์๋ฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์ฐฝ์กฐ์๊ฐ ์ด๋ฌํ ๊ธฐ๋ฅ๋ค์ ๋ง๋ ๊ฒ์ ์๋์ง๋ง ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ ํจ๋ฌ๋ค์์ ๋ง์ ์ฌ๋๋ค์๊ฒ ๋ณด์ฌ์ฃผ์์ต๋๋ค.
// constructor function
function Person () {
this.name = 'John',
this.age = 23
}
// create an object
const person = new Person();
์ฌ๋ฌ๋ถ์ด ์์ฑ์ ํจ์๋ฅผ ๋ง๋ค๊ณ ๊ทธ ํจ์๋ฅผ ์์ํ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๊ฐ์ง๋ ๋ฅ๋ ฅ์ ๋ชจ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
this
๊ฐ ๋ฐ์ธ๋ฉ๋์ง ์๋๋ค๋ ๋ป์
๋๋ค.this
๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์ง์ง ํฉํ ๋ฆฌ ํจ์๋ณด๋ค ๋ ์ ์ฐํฉ๋๋ค.new
๋ก ํธ์ถํ๋ ๊ฒ์ ๊น๋จน๋๋ค๋ฉด, this
์ ํ ๋นํ ๋ชจ๋ ๊ฒ๋ค์ด ์ ์ญ ๋ค์์คํ์ด์ค๋ก ์ด๋ํฉ๋๋ค. ์ด ์ ์ด ์์ฃผ ์น๋ช
์ ์ด์ฃ .์๋ฐ์คํฌ๋ฆฝํธ๋ ์ด๋ ํ ํจ์๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ฐํํ ์ ์์ผ๋ฏ๋ก ์์ฑ์ ํจ์๊ฐ ํ์ํ์ง ์์ต๋๋ค.
๊ฐ์ฒด ๋ฆฌํฐ๋ด์ ์ฌ์ฉํ๊ฑฐ๋
const dog = {
name: 'Naya',
sex: 'female',
age: 2,
breed: 'Rottweiler mix'
};
**Object.create()**๋ฅผ ์ฌ์ฉํ๊ฑฐ๋
const person = {
isHuman: false,
printIntroduction: function() {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten
me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"
๋์ ๊ฐ์ฒด ํ์ฅ(dynamic object extension) ์ ์ฌ์ฉํ๋ฉด ์ฐ๋ฆฌ๊ฐ ํ์ํ ๋ชจ๋ ๊ฒ๋ค์ ๊ฐ์ง ์ ์์ต๋๋ค.
const dynamic1 = "Marks";
const dynamic2 = "Age";
const user = {
Name : "GeeksForGeeks",
[dynamic1] : "57",
[dynamic2] : "42"
};
function createJelly() {
return {
type: 'jelly',
colour: 'red'
scoops: 3
};
}
์๋ฐ์คํฌ๋ฆฝํธ์์ ํฉํ ๋ฆฌ ํจ์๋ new
๊ฐ ํ์ํ์ง ์๊ณ , ์ ์ญ ๊ณต๊ฐ์ ์ค์ผ์ํฌ ์ํ์ฑ์ด ์๋ ์์ฑ์ ํจ์์
๋๋ค.
ํด๋์ค ์์์ ์ผ๋ฐ์ ์ผ๋ก ํ๋์ ์กฐ์์ผ๋ก๋ถํฐ ์์๋ฐ์ ์ ์์ผ๋ฏ๋ก ๋์ค์ ๊ณค๋ํ ์ํฉ์ ๋์ฌ์ง ์ ์์ต๋๋ค.
๊ฐ๋ฐ์๋ค์ ๋ณดํต ๋ชจ๋ OO ๋์์ธ์ด ๊ฒฐ๊ตญ ์๋ชป๋๋ค๋ ๊ฑธ ์๊ฒ ๋ฉ๋๋ค.
Elliot์ ์ํ๋ฉด ์์๊ณผ ๋ถ๋ชจ ํด๋์ค์ ๊ธด๋ฐํจ์ ๋ชจ๋์ ์ฝ๋์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋์ ์ ๋ฐ๋์ ๋์ด๊ฒ ๋๋ค๊ณ ํฉ๋๋ค. ๋ฌด์์ผ๋ก๋ถํฐ ๋ฌด์์ ์์๋ฐ๋์ง๋ฅผ ๋ค์ ๊ตฌ์ฑํ๊ธฐ ์ํด ์ฝ๋๋ฒ ์ด์ค๋ก ๋ค์ ๋์๊ฐ์ผ ํ์ง๋ง ์์ ํ ๋ฆฌํฉํ ๋งํ๊ธฐ์๋ ๊ฒฐํฉ๋๊ฐ ๋๋ฌด ๋์ ์ ์์ต๋๋ค.
์ดํ๋ฆฌ์ผ์ด์ ์ด ์ปค์ง ์๋ก, ๋ฌธ์ ๋ ๋์ฑ ์ฌ๊ฐํด์ง๋ฉฐ ํด๋์ค์ ํผ์กํจ์ด ๊ฐ์ค๋์ด ๋ฒ๊ทธ๊ฐ ๋ํ๋๋ฉด ํ ๊ตฐ๋ฐ๊ฐ ์๋๋ผ ๋ฒ๊ทธ์ ๊ด๋ จ๋ ๋ชจ๋ ์ฝ๋๋ฅผ ๊ณ ์ณ์ผ ํ ์ ์์ต๋๋ค.
๊ฝค๋ ๋๋ดํ ๋ฌธ์ฅ์ด์ง๋ง Eliiot์ ์ํํธ์จ์ด ์ฌ์์ฑ๊ณผ ๋ณต์ ๋ฌธ์ ์ ์ํด ํฐ ๊ธฐ์
์์ ๋ญ๋น๋๋ ์๊ฐ์ ์์ด ๋ ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํฐ ๊ธฐ์
์ ๊ฒฝ์ฐ ์ด๋์ ๋ ์ฌ์ ๋ฅผ ๊ฐ์ง๊ณ ์์ ํ ์๋ ์์ง๋ง ์คํํธ์
์ ๊ทธ๋ด ์ฌ์ ๊ฐ ์์ต๋๋ค.
ES6์ ์๋ก์ด ๋ฌธ์์์ ํด๋์ค ํจํด์ ํ์ฅํจ์ผ๋ก์จ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๋ ๋์๊ฒ ๋ง๋ค์๊ณ , ์๋ง์ ํฌ์คํ
๊ณผ ์ฑ
์์ ํด๋์ค์ ์ฌ์ฉ์ ๊ฐ์กฐํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์์ ์์ฑ์ข ํด๋์ค ์์์ ์ ๊ฑฐํ๋ค๋ฉด
์ธ์ด์ ํน์ฑ์ ๋ํด ์ด๋ฆฐ ๋ง์์ ๊ฐ์ง๋ ๊ฒ์ด ๋์ค์ ์ด์ง๋ง, ๋ฌด์์ด ์ณ์ ๋ฐฉ๋ฒ์ด๊ณ ๊ทธ๋ฅธ ๋ฐฉ๋ฒ์ธ์ง๋ ๋ถ๋ช ํ ์์ต๋๋ค. ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ ์ ํํ์ธ์. ~ Eric Elliott
2021.12.21 ์๋ฌธ
tree-shaking
๊ณผ ๊ฐ์ ๊ธฐ๋ฅ๋ ์์ง๋ง, ๊ทธ๋ผ์๋ ์ถ๊ฐ์ ์ธ ์ฝ๋๋ฅผ ์ฌ์ฉ์์๊ฒ ์ ๋ฌํด์ผ๋ง ํ๋ค.// NoteWithMarkdown.server.js - Server Component === zero bundle size
import marked from 'marked'; // zero bundle size
import sanitizeHtml from 'sanitize-html'; // zero bundle size
function NoteWithMarkdown({text}) {
const html = sanitizeHtml(marked(text));
return (/* render */);
}
React.lazy
๋ก ์์ ํด์ผ ํจ2021๋ 8์ 26์ผ์ ์์ฑ๋ ์๋ฌธ <Announcing TypeScript 4.4>์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
TypeScript 4.4๋ฅผ ์ธ ์ ์๋ค๋ ๊ฒ์ ์๋ฆด ์ ์์ด ๊ธฐ์ฉ๋๋ค!
TypeScript์ ๋ํด ์์ง ๋ค์ด๋ณธ ์ ์ด ์์ผ์ ๋ถ๋ค์ ์ํด ์ค๋ช
ํ์๋ฉด, TypeScript๋ ์ ์ ํ์
์ ์ํด JavaScript์ ๋ฌธ๋ฒ์ ์ถ๊ฐํ ์ธ์ด์
๋๋ค.
ํ์
์คํฌ๋ฆฝํธ ์ปดํ์ผ๋ฌ์ ๊ฐ์ ๋๊ตฌ๋ค์ ํ์
์ ์ง์ฐ๊ณ ์ด๋์๋ ์คํ์ด ๊ฐ๋ฅํ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ง์ ๋จ๊น๋๋ค. ํ์ง๋ง ๊ทธ ํ์
๋ค์ ํ์
์ฒดํฌ ๊ฐ ๋์ด์ผ ํฉ๋๋ค! ํ์
์ ์ฌ๋ฌ๋ถ์ ์๋๋ฅผ ๋ช
ํํ๊ฒ ๋ง๋ค์ด์ฃผ๊ณ , ์ฌ๋ฌ๋ถ์ด ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ ์ ์ฝ๋๋ฅผ ์ฝ์ด ์๋ฌ๋ฅผ ์ก์๋ผ ์ ์์ฃ .
ํ์
์ ์ฒดํฌํจ์ผ๋ก์จ, ํ์
์คํฌ๋ฆฝํธ๋ ์คํ, ๋ก์ง ์๋ฌ ๋ฑ ๋ง์ ์ค๋ฅ๋ค์ ์ก์๋
๋๋ค! ์ค๋ฅ๋ฅผ ์ก์๋ด๋ ๊ฒ์ ๋์ด ์ ํํ ์ฝ๋ ์์ฑ, ์ ์ํ ๊ณณ์ผ๋ก ์ด๋, ๋ฆฌ๋ค์ด๋ฐ๊ณผ ๊ฐ์ ์๋ํฐ ๊ธฐ๋ฅ์ ๋์ฑ ํ์ฉํ ์ ์๊ฒ ๋ง๋ญ๋๋ค. ์์ธํ ๊ฑด ์ฌ๊ธฐ์ ์ฝ์ด๋ณด์ธ์!
TypeScript 4.4๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ Nuget์ด๋ npm์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
npm install typescript
์ด ๋ฒ์ ์ ์ง์ํ๋ ์๋ํฐ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์.
ํ์ ์คํฌ๋ฆฝํธ 4.4์ ์ฃผ์ ๋ณํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Control Flow Analysis of Aliased Conditions and Discriminants
์๋ฌธ, ๋์์ ๋งํฌ
#25 ๋ฅผ ์ ๋ฆฌํ๋ฉด์ ๋ด
Good UX
Cheap maintenance
Fast performance
๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์กด์ ์ด์ง ์์ผ๋ฉด์ ๋ฆฌ์กํธ ์ํ๊ณ์์ ๋ค์๊ฐ ๋ง์กฑํ ์ ์๋ ํด๊ฒฐ์ฑ ์ ๋ํ ๊ณ ๋ฏผ
.client.js
.server.js
๊ฐ์ ํ์ฅ์๊ฐ ์๊ณ ํด๋ผ์ด์ธํธ ๋ฒ๋ค์ ํฌํจ๋์ง ์๋๋ค. => ์ฆ RSC๋ ๋ฒ๋ค ์ฌ์ด์ฆ์ ์ํฅ์ ์ฃผ์ง ์๋๋ค. (zero)still in research and dev
์๋ฏ ๋ง๋ฏ,,
์๋ฌธ : Explaining Value vs. Reference in Javascript
๋ถ์ : ์ด๋ป๊ฒ ์ฐจ์ด๊ฐ ์๋์ง ์ปดํจํฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ดํด๋ณด์.
์ด ์ํฐํด์ ์ ์ ์จ๋ผ์ธ ์ฝ์ค Step Up Your JS: A Comprehensive Guide to Intermediate JavaScript์์ ์ฐ์ฌ์ง ๊ธ์ ๋๋ค. ์ธํฐ๋ํฐ๋ธํ ์ฝ๋ ํ๋ ์ด๊ทธ๋ผ์ด๋์ ์จ๋ผ์ธ ํด์ฆ๋ฅผ ์ด ๊ณณ์์ ์ฆ๊ฒจ๋ณด์ธ์.
์๋ฐ์คํฌ๋ฆฝํธ๋ _value_๋ก ์ ๋ฌ๋๋ 5๊ฐ์ง์ ๋ฐ์ดํฐ ํ์
์ ๊ฐ๊ณ ์์ต๋๋ค : Boolean
, null
, undefined
, String
, ๊ทธ๋ฆฌ๊ณ Number
๊ฐ ์์ต๋๋ค. ์ด ํ์
๋ค์ ์์ ํ์
์ด๋ผ๊ณ ๋ถ๋ฆ
๋๋ค.
๊ทธ๋ฆฌ๊ณ _reference_๋ก ์ ๋ฌ๋๋ 3๊ฐ์ง์ ๋ฐ์ดํฐ ํ์
์ด ์์ต๋๋ค : Array
, Function
, Object
์
๋๋ค. ์ด ํ์
๋ค์ ๊ธฐ์ ์ ์ผ๋ก๋ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ํตํ์ด **๊ฐ์ฒด(Objects)**๋ผ๊ณ ๋ถ๋ฅผ ๊ฒ์
๋๋ค.
์์ ํ์ ์ด ๋ณ์์ ํ ๋น๋๋ฉด ๋ณ์์ ์์ ๊ฐ์ ๊ฐ๊ฒ ๋๋ค๊ณ ์๊ฐํ ์ ์์ต๋๋ค.
var x = 10;
var y = 'abc';
var z = null;
x
๋ 10
์ ๊ฐ์ต๋๋ค. y
๋ 'abc'
๋ฅผ ๊ฐ์ต๋๋ค. ์ด ๊ฐ๋
์ ์ ์๊ธฐ ์ํด, ์ด ๋ณ์๋ค๊ณผ ๊ฐ๋ค์ด ๋ฉ๋ชจ๋ฆฌ์์ ์ด๋ป๊ฒ ๋ณด์ด๋์ง์ ๋ํ ์ด๋ฏธ์ง๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
=
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ณ์๋ค์ ๋ค๋ฅธ ๋ณ์๋ฅผ ํ ๋นํ ๋ ์๋ก์ด ๋ณ์์ ๊ฐ์ ๋ณต์ฌํฉ๋๋ค. ๊ฐ์ ์ํด ๋ณต์ฌ๋๋ ๊ฒ์ด์ฃ .
var x = 10;
var y = 'abc';
var a = x;
var b = y;
console.log(x, y, a, b); // -> 10, 'abc', 10, 'abc'
a
์ x
๋ชจ๋ 10
์ ๊ฐ๊ณ , b
์ y
๋ชจ๋ 'abc'
๋ฅผ ๊ฐ์ต๋๋ค. ๊ฐ๋ค์ ๋ณต์ฌ๋ ๊ฒ์ด๋ฏ๋ก ๊ฐ ๋ณ์๋ค์ ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค.
ํน์ ๋ณ์๋ฅผ ์์ ํ๋ค ํด๋ ๋ค๋ฅธ ๋ณ์์ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค. ๊ฐ ๋ณ์๋ค๋ผ๋ฆฌ๋ ์ด๋ ํ ๊ด๊ณ๋ ๊ฐ์ง ์๋๋ค๊ณ ์๊ฐํ์๋ฉด ๋ฉ๋๋ค.
var x = 10;
var y = 'abc';
var a = x;
var b = y;
a = 5;
b = 'def';
console.log(x, y, a, b); // -> 10, 'abc', 5, 'def'
ํผ๋์ค๋ฌ์ธ ์๋ ์์ง๋ง ์ผ๋จ ์ฐธ๊ณ ์ฝ์ด๋ณด์ธ์. ์ฝ๊ณ ๋๋ฉด ํจ์ฌ ์ฌ์๋ณด์ผ ๊ฒ์ ๋๋ค.
์์ ๊ฐ์ด ์๋ ๊ฐ์ ํ ๋น๋ฐ์ ๋ณ์๋ค์ ๊ฐ์ผ๋ก _์ฐธ์กฐ(reference)_๋ฅผ ๊ฐ์ง๋๋ค. ํด๋น ์ฐธ์กฐ๋ ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ฒด์ ์์น๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ๋ณ์๋ค์ ์ฌ์ค ์ค์ ๋ก ๊ฐ์ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ ์๋๋๋ค.
์ฌ๋ฌ๋ถ์ ์ปดํจํฐ ๋ฉ๋ชจ๋ฆฌ์ ํน์ ์์น์์ ๊ฐ์ฒด๊ฐ ์์ฑ๋ฉ๋๋ค. arr = []
๋ผ๋ ์ฝ๋๋ฅผ ์์ฑํ ๋ ๋ฉ๋ชจ๋ฆฌ์์ ๋ฐฐ์ด์ ํ๋ ์์ฑํ ๊ฒ์
๋๋ค. ๋ณ์ arr
์ ๋ฐฐ์ด์ ์์น, ์ฆ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ๋ฐ์ต๋๋ค.
address
๊ฐ number
๋ string
์ฒ๋ผ ๊ฐ์ผ๋ก ์ ๋ฌ๋๋ ์๋ก์ด ๋ฐ์ดํฐ ํ์
์ด๋ผ๊ณ ์๊ฐํด๋ด
์๋ค. address
๋ ์ฐธ์กฐ๋ก ์ ๋ฌ๋๋ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์์น๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ๋ฐ์ดํ๋ก ํ์๋๋ ๋ฌธ์์ด์ฒ๋ผ address
๋ <>
๊ธฐํธ๋ก ํ์๋ฉ๋๋ค.
์ฐธ์กฐ ํ์ ์ ๋ณ์๋ฅผ ํ ๋นํ๊ณ ์ฌ์ฉํ ๋ ์๋์ฒ๋ผ ์์ฑํฉ๋๋ค.
1) var arr = [];
2) arr.push(1);
์ฒซ ๋ฒ์งธ ์ค๊ณผ ๋ ๋ฒ์งธ ์ค์ ๋ฉ๋ชจ๋ฆฌ์์ ์๋์ ๊ฐ์ด ํํ๋ฉ๋๋ค.
๋ณ์ arr
์ ํฌํจ๋ ๊ฐ, ์ฆ ์ฃผ์๋ ๊ณ ์ ๋์ด ์์ต๋๋ค. ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ฐฐ์ด์ด ๋ณํ๋ ๊ฒ์
๋๋ค. arr
์ ๊ฐ์ ๋ฃ๋ ๊ฒ๊ณผ ๊ฐ์ด ๋ฐฐ์ด์ ์ฌ์ฉํ ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ฉ๋ชจ๋ฆฌ์ arr
์ ์์น๋ก ๊ฐ์ ๊ทธ ๊ณณ์ ์ ์ฅ๋ ์ ๋ณด๋ก ์์
ํ๋ ๊ฒ๋๋ค.
์ฐธ์กฐ ํ์
์ธ ๊ฐ์ฒด๊ฐ =
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ๋ณ์๋ก ๋ณต์ฌ๋ ๋ ํด๋น ๊ฐ์ ์ฃผ์๋ ์ค์ ๋ก ๋ณต์ฌ๋๋ ์ฃผ์ ๊ฐ์
๋๋ค. ๊ฐ์ฒด๋ ๊ฐ ๋์ ์ ์ฐธ์กฐ ๊ฐ์ด ๋ณต์ฌ๋ฉ๋๋ค.
var reference = [1];
var refCopy = reference;
์ ์ฝ๋๋ ๋ฉ๋ชจ๋ฆฌ์์ ์๋์ ๊ฐ์ต๋๋ค.
๊ฐ ๋ณ์๋ _๋์ผํ ๋ฐฐ์ด_์ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ง๋๋ค. ์ด ๋ง์ reference
๋ณ์๋ฅผ ์์ ํ๋ฉด refCopy
๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ค๋ ๊ฒ์
๋๋ค.
reference.push(2);
console.log(reference, refCopy); // -> [1, 2], [1, 2]
๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ฐฐ์ด์ 2
๋ฅผ ์ถ๊ฐํ์ต๋๋ค. reference
์ refCopy
๋ ๊ฐ์ ๋ฐฐ์ด์ ๊ฐ๋ฆฌํค๊ณ ์์ต๋๋ค.
์ฐธ์กฐ ๋ณ์๋ฅผ ์ฌํ ๋นํ๋ฉด ์ด์ ์ ์ฐธ์กฐ ๊ฐ์ ๋์ฒดํฉ๋๋ค.
var obj = { first: 'reference' };
๋ฉ๋ชจ๋ฆฌ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ ๋ฒ์งธ ๋ผ์ธ์ด ์๋ค๊ณ ํด๋ด ์๋ค.
var obj = { first: 'reference' };
obj = { second: 'ref2' }
obj
์ ์ ์ฅ๋ ์ฃผ์ ๊ฐ์ด ๋ณ๊ฒฝ๋ฉ๋๋ค. ์ฒซ ๋ฒ์งธ ๊ฐ์ฒด๋ ์ฌ์ ํ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๊ณ ๋ค์ ๊ฐ์ฒด๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค.
์ #234
๊ฐ์์ ๋ณผ ์ ์๋ฏ์ด ๋จ์์๋ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๊ฐ์ด ์์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๊ฐ๋น์ง ์ฝ๋ ์
์ ์ํํ ์ ์์ต๋๋ค. ๊ฐ์ฒด์ ๋ชจ๋ ์ฐธ์กฐ๋ฅผ ์๊ณ ๋ ์ด์ ๊ทธ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ทธ๋์ ์์ง์ ์์ ํ๊ฒ ๋ฉ๋ชจ๋ฆฌ๋ก๋ถํฐ ์ ๊ฑฐํฉ๋๋ค. ์ด ๊ฒฝ์ฐ์ ๊ฐ์ฒด `{ first: 'reference' }๋ ๋ ์ด์ ์ ๊ทผํ ์ ์๊ณ ๊ฐ๋น์ง์ฝ๋ ์
์ ๋์์ด ๋ฉ๋๋ค.
์ผ์น ์ฐ์ฐ์ ==
๊ณผ ===
๊ฐ ์ฐธ์กฐ ํ์
์ ๋ณ์์ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ์ฐธ์กฐ ๊ฐ์ ํ์ธํฉ๋๋ค. ๋์ผํ ํญ๋ชฉ์ ์ฐธ์กฐ๊ฐ์ ๊ฐ๋ ๊ฒฝ์ฐ ๋น๊ต ๊ฒฐ๊ณผ๋ true
๊ฐ ๋ฉ๋๋ค.
var arrRef = [โHi!โ];
var arrRef2 = arrRef;
console.log(arrRef === arrRef2); // -> true
๋ณ๊ฐ์ ๊ฐ์ฒด๋ผ๋ฉด ๋์ผํ ํ๋กํผํฐ๋ฅผ ๊ฐ๊ณ ์๋ค ํ๋๋ผ๋ ๋น๊ต ๊ฒฐ๊ณผ๋ false
๊ฐ ๋ฉ๋๋ค.
var arr1 = ['Hi!'];
var arr2 = ['Hi!'];
console.log(arr1 === arr2); // -> false
๋ ๊ฐ์ ๊ฐ์ฒด๊ฐ ์๊ณ ํ๋กํผํฐ๊ฐ ๊ฐ์์ง ํ์ธํ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ ๋ ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ์ฌ ๋ฌธ์์ด์ ๋น๊ตํ๋ ๊ฒ์ ๋๋ค. ์ผ์น ์ฐ์ฐ์๊ฐ ์์๊ฐ์ ๋น๊ตํ ๋ ๋จ์ํ ๊ฐ์ด ๊ฐ์ผ์ง๋ง ๋น๊ตํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
var arr1str = JSON.stringify(arr1);
var arr2str = JSON.stringify(arr2);
console.log(arr1str === arr2str); // true
๋ ๋ค๋ฅธ ์ ํ์ง๋ ๊ฐ์ฒด๋ค ๋ด ์ฌ๊ท์ ์ธ ๋ฃจํ์์ ๊ฐ ํ๋กํผํฐ๊ฐ ๊ฐ์์ง ๋น๊ตํ๋ ๊ฒ์ ๋๋ค.
ํจ์์ ์์ ๊ฐ์ ์ ๋ฌํ ๋ ํจ์๋ ํ๋ผ๋ฏธํฐ์ ๊ฐ์ ๋ณต์ฌํฉ๋๋ค. ์ด๋ =
์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ์ฌ์ค์ ๋์ผํฉ๋๋ค.
var hundred = 100;
var two = 2;
function multiply(x, y) {
// PAUSE
return x * y;
}
var twoHundred = multiply(hundred, two);
์์ ์์์ hundred
์ ๊ฐ 100
์ ์ฃผ์์ต๋๋ค. multiply
์ ์ด ๊ฐ์ ์ ๋ฌํ ๋ x
๋ ๊ฐ 100
์ ๊ฐ๊ฒ ๋ฉ๋๋ค. =
ํ ๋น์ ์ฌ์ฉํ ๋์ฒ๋ผ ๊ฐ์ด ๋ณต์ฌ๋ ๊ฒ์
๋๋ค. ์ญ์๋ hundred
์๋ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค. PAUSE ์ฃผ์์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ด๋ค ์ํ์ธ์ง์ ๋ํ ์ค๋
์ท์ ๋ณด์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ธ๋ถ ์ค์ฝํ์ ์ํฅ์ ๋ผ์น์ง ์๋ ํจ์๋ฅผ _์์ํจ์_๋ผ๊ณ ํฉ๋๋ค. ํ๋ผ๋ฏธํฐ๋ก ์์๊ฐ๋ง ๋ฐ๊ณ ํจ์๋ฅผ ๋๋ฌ์ผ ์ธ๋ถ ์ค์ฝํ์ ์๋ ์ด๋ ํ ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ํด๋น ํจ์๋ ์๋์ ์ผ๋ก ์ธ๋ถ ์ค์ฝํ์ ์ํฅ์ ๋ผ์น์ง ์๋ ์์ํจ์๊ฐ ๋ฉ๋๋ค. ๋ด๋ถ์์ ์์ฑ๋๋ ๋ชจ๋ ๋ณ์๋ค์ ํจ์๊ฐ ๋ฆฌํด๋ ๋ ๊ฐ๋น์ง ์ฝ๋ ํฐ์ ์ํด ์์ง๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ํจ์๊ฐ ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๋๋ค๋ฉด ํจ์๋ฅผ ๋๋ฌ์ผ ์ค์ฝํ๋ฅผ ๋ณ๊ฒฝ์ํฌ ์ ์์ต๋๋ค. ๋ฐฐ์ด์ ์ฐธ์กฐ๊ฐ์ ๋ฐ์ ํด๋น ๋ฐฐ์ด์ ๋ณ๊ฒฝ์ํจ๋ค๋ฉด ํจ์๋ฅผ ๋๋ฌ์ผ ์ค์ฝํ์ ์๋ ๋ณ์๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ๋๋ค. ํจ์๊ฐ ๋ฆฌํดํ๊ณ ๋์๋ ๊ทธ ๋ณ๊ฒฝ์ฌํญ์ด ์ธ๋ถ ์ค์ฝํ์ ์ ํจํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ์ถ์ ํ๊ธฐ ์ด๋ ต๊ณ ์์น ์์ ์ฌ์ด๋์ดํํธ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.
๊ทธ๋์ Array.map
๊ณผ Array.filter
๋ฅผ ํฌํจํ ๋ง์ ๋ค์ดํฐ๋ธ ๋ฐฐ์ด ํจ์๋ค์ ์์ ํจ์๋ก ์์ฑ๋์์ต๋๋ค. ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ๋ฐ์ ๊ฐ์ฒด์ ์๋ณธ์ ์ฌ์ฉํ๋ ๋์ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํฉ๋๋ค. ์๋ณธ์ ๊ทธ๋๋ก ๋์ด ์ธ๋ถ ์ค์ฝํ์๋ ์ํฅ์ ์ฃผ์ง ์๊ณ ์๋กญ๊ฒ ๋ง๋ค์ด์ง ๋ฐฐ์ด์ ์ฐธ์กฐ๋ฅผ ๋ฆฌํด๋ฐ์ต๋๋ค.
์์ํจ์์ ๋น์์ํจ์์ ์๋ฅผ ๋ด ์๋ค.
function changeAgeImpure(person) {
person.age = 25;
return person;
}
var alex = {
name: 'Alex',
age: 30
};
var changedAlex = changeAgeImpure(alex);
console.log(alex); // -> { name: 'Alex', age: 25 }
console.log(changedAlex); // -> { name: 'Alex', age: 25 }
์ด ๋น์์ ํจ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ age์ ๊ฐ์ 25๋ก ๋ณ๊ฒฝํฉ๋๋ค. ์ ๋ฌ๋ฐ์ ์ฐธ์กฐ๊ฐ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
alex๊ฐ์ฒด๋ฅผ ์ง์ ์ ์ผ๋ก ๋ณ๊ฒฝํ๊ฒ ๋ฉ๋๋ค.
person๊ฐ์ฒด๋ฅผ ๋ฐํํ ๋๋ ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด์ ์ ํํ ๋์ผํ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ ๊ฒ์
๋๋ค.
alex์
alexChanged๋ ๋์ผํ ์ฐธ์กฐ๊ฐ์ ๊ฐ๊ณ ์์ฃ .
person` ๋ณ์๋ฅผ ๋ฐํํ๊ณ ์๋ก์ด ๋ฐฐ์ด์ ์ฐธ์กฐ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ ์ค๋ณต๋๋ ์ผ์
๋๋ค.
์์ ํจ์์ ์๋ฅผ ๋ด ์๋ค.
function changeAgePure(person) {
var newPersonObj = JSON.parse(JSON.stringify(person));
newPersonObj.age = 25;
return newPersonObj;
}
var alex = {
name: 'Alex',
age: 30
};
var alexChanged = changeAgePure(alex);
console.log(alex); // -> { name: 'Alex', age: 30 }
console.log(alexChanged); // -> { name: 'Alex', age: 25 }
์ด ํจ์์์๋ ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ๊ธฐ ์ํด JSON.stringify
๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ๋ฌธ์์ด์ JSON.parse
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ก ํ์ฑํฉ๋๋ค. ์ด ๋ณํ ๊ณผ์ ์ ํตํด ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ต๋๋ค. ๋์ผํ ๋์์ ํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก๋ ์๋ณธ ๊ฐ์ฒด๋ฅผ ํตํ ๋ฐ๋ณต๋ฌธ ๋ด์์ ๊ฐ ํ๋กํผํฐ๋ฅผ ์๋ก์ด ๊ฐ์ฒด์ ๋์ผํ๊ฒ ํ ๋นํด์ฃผ๋ฉด ๋ฉ๋๋ค. ๋์ผํ ํ๋กํผํฐ๋ฅผ ๊ฐ๋ ์๋ก์ด ๊ฐ์ฒด๋ ๋ฉ๋ชจ๋ฆฌ ๋ด์์๋ ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด์๋ ์์ ํ ๋ณ๊ฐ์ ๊ฐ์ฒด์
๋๋ค.
์๋ก์ด ๊ฐ์ฒด์ age
ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝ์์ผ๋ ์๋ณธ ๊ฐ์ฒด๋ ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค. ์ด ํจ์๊ฐ ์์ํจ์์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ํจ์ ๋ด๋ถ ์ค์ฝํ ๋ฐ์ ์๋ ์ด๋ ํ ๊ฐ์ฒด์๋ ์ํฅ์ ์ฃผ์ง ์๊ณ ์ฌ์ง์ด ์ ๋ฌ๋ฐ์ ๊ฐ์ฒด์๋ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค. ์๋ก์ด ๊ฐ์ฒด๊ฐ ๋ฐํ๋๊ณ ์๋ก์ด ๋ณ์์ ์ ์ฅ๋ ์๋ ์๊ณ ํจ์๊ฐ ์ข
๋ฃ๋์ ๋ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด ๊ฐ๋น์ง ์ฝ๋ ํฐ๊ฐ ์์งํฉ๋๋ค.
Value vs. reference
๋น๊ต๋ ์ฝ๋ฉ ์ธํฐ๋ทฐ์์ ์ข
์ข
๋ฌผ์ด๋ณด๋ ๊ฐ๋
์
๋๋ค. ์ฌ๊ธฐ์ ์ด๋ป๊ฒ ์ถ๋ ฅ๋ ๊ฒ์ธ์ง ์ง์ ์์๋ด๋ณด์ธ์.
function changeAgeAndReference(person) {
person.age = 25;
person = {
name: 'John',
age: 50
};
return person;
}
var personObj1 = {
name: 'Alex',
age: 30
};
var personObj2 = changeAgeAndReference(personObj1);
console.log(personObj1); // -> ?
console.log(personObj2); // -> ?
์ฒ์์ ํจ์๋ ์ ๋ฌ๋ฐ์ ์๋ณธ ๊ฐ์ฒด์ age
ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝ์ํต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ณ์์ ์ฌํ ๋นํ๊ณ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ฃ . ์ฝ์ ์ฐฝ์๋ ์๋์ ๊ฐ์ด ์ถ๋ ฅ๋ฉ๋๋ค.
console.log(personObj1); // -> { name: 'Alex', age: 25 }
console.log(personObj2); // -> { name: 'John', age: 50 }
ํจ์ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ํ ๋นํ๋ ๊ฒ์ =
๋ก ํ ๋นํ๋ ๊ฒ๊ณผ ์์ ํ ๋๊ฐ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์. person
๋ณ์๋ personObj1
๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ง๊ธฐ ๋๋ฌธ์ ์ฒ์์๋ ๊ทธ ๊ฐ์ฒด๋ฅผ ์ง์ ์กฐ์ํฉ๋๋ค. ์๋ก์ด ๊ฐ์ฒด๋ก ์ฌํ ๋น๋๊ณ ๋์๋ ์๋ณธ ๊ฐ์ฒด์ ์ํฅ์ ์ฃผ์ง ์์ต๋๋ค.
์ฌํ ๋น์ ์ธ๋ถ ์ค์ฝํ์ personObj1
๊ฐ๋ฆฌํค๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝ์ํค์ง ์์ต๋๋ค. person
์ ์๋ก์ด ์ฐธ์กฐ ๊ฐ์ ๊ฐ์ง์ง๋ง ์ฌํ ๋น์ด personObj1
์ ๋ณ๊ฒฝ์ํค์ง ์์ต๋๋ค.
์์ ์ฝ๋๋ ์๋ ์ฝ๋์ ๊ฐ์ต๋๋ค.
var personObj1 = {
name: 'Alex',
age: 30
};
var person = personObj1;
person.age = 25;
person = {
name: 'john',
age: 50
};
var personObj2 = person;
console.log(personObj1); // -> { name: 'Alex', age: 25 }
console.log(personObj2); // -> { name: 'John', age: '50' }
๋ ์ฝ๋์ ์ฐจ์ด๋ ํจ์์ ์ฌ์ฉ ์ฌ๋ถ์
๋๋ค. ํจ์๊ฐ ์ข
๋ฃ๋๋ฉด person
์ ๋ ์ด์ ์ค์ฝํ์ ์กด์ฌํ์ง ์์ต๋๋ค.
์ด ๊ธ์ด ์ ์ฉํ์ จ๋ค๋ฉด ํํธ ๋ฒํผ์ ๋๋ฌ์ฃผ์๊ณ ์ ์ ๋ค๋ฅธ ๊ธ๋ค๋ ๋ด์ฃผ์ธ์.
Basically, first-class citizenship simply means โbeing able to do what everyone else can do.โ
์ผ๊ธ ๊ฐ์ฒด์ธ ํจ์๋ฅผ ์ผ๊ธ ํจ์๋ผ๊ณ ํ๋ค. (first class function)
Object
ํ๋กํ ํ์
์ ์์๋ฐ๋๋ค.ํจ์
๋ ์ผ๊ธ ๊ฐ์ฒด์ด๋ฉฐ ์ผ๊ธ ํจ์์ด๋ค.์๋ฐ์คํฌ๋ฆฝํธ์์๋ ํจ์๋ ๊ฐ์ฒด์ด๋ฏ๋ก ๋ณดํต ์ผ๊ธ ๊ฐ์ฒด๋ผ๊ณ ํ๋ ๋ฏ ํ๋ค.
var
const
let
ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ์์ ํจ์๋ฅผ ํ ๋นํ ์ ์๋ค.flexibility
๋ฅผ ์๋ฏธํ๋๋ฐ ์ฆ, ๋ชจ๋ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ์ด๋ ค ์๋ค๋ ๊ฒ.
๊ณ ์ฐจ ํจ์(high order function
๊ฐ ๊ฐ๋ฅํ๋ค. (ex. each, filter, map, every ...)'์ปค๋ง'์ด๋ ํจ์ ํ๋๊ฐ n๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋ ๊ณผ์ ์ n๊ฐ์ ํจ์๋ก ๊ฐ๊ฐ์ ์ธ์๋ฅผ ๋ฐ๋๋ก ์์ฑํ๋ ๊ฒ.
๋ถ๋ถ์ ์ผ๋ก ์ ์ฉ๋ ํจ์๋ฅผ ์ฒด์ธ์ผ๋ก ๊ณ์ ์์ฑํ์ฌ ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ์ ์ฒ๋ฆฌํ๋๋ก ํจ.
2021๋ 8์ 5์ผ์ ์์ฑ๋ <์๋ฌธ : Hello Yarn 2, Goodbye node_modules>์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค :)
3๋ ์ฏค ์ , 2017๋ ์ ํ์ด์ค๋ถ ์์ง๋์ด๋ง ๋ธ๋ก๊ทธ์ Yarn 1.0์ด ๊ณต์์ ์ผ๋ก ๋ฐํ๋์์ต๋๋ค. ์ฒซ ์ถ์ ์ดํ ์ฝ 11๊ฐ์ ๋ง์ 175,000 ์ด์์ ๋ ํฌ์งํ ๋ฆฌ๊ฐ ์๋ก์ด ํจํค์ง ๋งค๋์ ๋ก Yarn 1.0์ ์ฌ์ฉํ๊ธฐ ์์ํ์ต๋๋ค.
Yarn์ ์ฑ๊ณต ์คํ ๋ฆฌ๊ฐ ์์ง๊น์ง๋ ๊ณ์ ๋๊ณ ์์ง๋ง, ์ด ๋๊ตฌ๋ ๋๋ฆผ, ๋ณต์ก์ฑ์ ์ฆ๊ฐ, ๋ฐ์ดํฐ ๊ณต๊ฐ๊ณผ ๊ฐ์ ์ ํต์ ์ธ ํจํค์ง ๊ด๋ฆฌ์ ์ฝ์ ์ ๋ณด์ฌ์ฃผ๊ณ ์์ต๋๋ค. Yarn2๋ ์ด๋ฌํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ ๋ฟ๋ง ์๋๋ผ ์ ๋ฐ์ ์ธ ์ํฌํ๋ก์ฐ๋ฅผ ๊ฐ์ ํ๋ ๋ช ๊ฐ์ง ๊ทผ๋ณธ์ ์ธ ๋ณ๊ฒฝ ์ฌํญ์ ๋ณด์ฌ์ค๋๋ค.
์๋ก์ด ๋ฒ์ ์ ์๋
1์์ ์ด๋ฏธ ๋ฆด๋ฆฌ์ฆ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ง์ ํฐ ํ๋ก์ ํธ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋ก์ด PlugโnโPlay
์ ์ ์ํ๋ ๋ฐ ๊ฝค ์๊ฐ์ด ์ค๋ ๊ฑธ๋ ธ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ผ๋ถ ๋ํ ๋ค์๋ ํ๋ก์ ํธ๋ ์ฌ์ ํ ํธํ์ฑ์ ํ๋ณดํ๊ธฐ ์ํด ๋
ธ๋ ฅ์ค์ธ ์ํ์
๋๋ค(์์ฑ ์์ ์์๋ Angular, RN, Flow ๋ฑ). ์ด์ ์ฌ๋ฌ๋ถ์ ์ฝ๋ ๋ฒ ์ด์ค์ ์ ์ฉํด ๋ณผ ๊ธฐํ์
๋๋ค.
PlugโnโPlay ์ง์์ด Yarn 2์์ ์ค๋ ๊ฐ์ฅ ํฐ ๋ณํ์ธ ๊ฒ์ ์๋๋๋ค. Yarn์ ์
๋ฐ์ดํธ๋ ๋ ๋จ์ํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ๋ง์ ์ข์ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํฉ๋๋ค.
Yarn์ ์ ์ง๋ณด์์๋ค์ ์ด๋ฌํ ๊ฐ์ ์ 1๋
์ ์๊ฐ์ ์์ ๋ถ์๊ณ , Yarn 2๊ฐ ์ถฉ๋ถํ ์ ๋ง๋ค์ด์ก๋ค๋ ๊ฒ์ ํ์คํ ๋๋ ์ ์์ต๋๋ค.
์ด์ ๋ ๊ตฌ์กฐํ๋ CLI ์ถ๋ ฅ์ผ๋ก ์์ํฉ๋๋ค. Yarn ์ฝ์ ํ ์คํธ๋ ๊ธฐ๊ปํด์ผ ์๊ฐ์ ์ธ ํฉ๋ฌด์ง ์ ๋์์ง๋ง, ํฌ๋งทํ ์ด๋ ์์ ๋ฑ์ ๊ธฐ๋ฅ์ ํตํด ๊ฐ๋ ์ฑ์ด ๋์ฑ ํฅ์๋์์ต๋๋ค.
์ ์ฌ์ง์์ ๊ฐ ์ค์ ์๋ฌ ์ฝ๋๊ฐ ์์ด ๋๋ฒ๊ทธํ๊ธฐ๊ฐ ํจ์ฌ ์ฌ์์ก์ต๋๋ค. ์๋ฌ์ฝ๋๋ ์ด ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋ฌผ๋ก Yarn 2
๋ฅผ ์ด์ ๋ฒ์ ์ ๊ฐ์น๋ฅผ ํ๋ฝ์ํด์ผ๋ก์จ ์ค๋ช
ํ๋ ๊ฒ์ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ๊ทธ๋ ์ง๋ง, Yarn
์ ๊ฐ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ ํฐ ์ด์ ํ๊ฐ ๋ฉ๋๋ค. ์๋ก์ด ๋ฒ์ ์ ํ์ผ์ I/O ์์ ์์ฒญ๋๊ฒ ๊ฐ์์ํด์ผ๋ก์จ ์ค์นํ๋ ๋์ ์์ฒญ๋ ์๊ฐ์ ์ ์ฝํด์ค๋๋ค.
Yarn์ ์ด์ pnp.js
ํ์ผ ํ๋์ ํจํค์ง ์ฐธ์กฐ๋ฅผ ์ถ์ ํ ์ ์๋ ์ง๋๋ฅผ ๊ฐ์ง๊ณ ์์ด ์ฌ๋ฌ๋ถ์ด ์ฝ๋๋ฅผ ํ๋ฒ ์คํํ๋ฉด ๋
ธ๋๊ฐ ์ ์ ํ ์์น๋ก ๊ฐ๊ฒ๋ ํด์ค๋๋ค.
์ฌ์ ํ ๋ค์ด๋ก๋๋ ํจํค์ง๋ ์ฌ๋ฌ๋ถ์ ๋์คํฌ _์ด๋๊ฐ_์ ๊ฐ์ผํ๋๋ฐ์. ์ด๊ฒ์ด ๋ฐ๋ก ์ .yarn
ํด๋์ ์ฉ๋์
๋๋ค.
๊ทธ ์์น๋ ์์กด์ฑ์ด ์บ์ฑ๋๋ ์์น๋ก ๋ ์ ์ ์ค์น ๊ณต๊ฐ์ ์ฐจ์งํฉ๋๋ค. (์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์์ ์คํํด๋ณด๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.)
์ค์น๋์ง ์์ ์๊ฒฉ ํจํค์ง๋ฅผ ์ง์ ์คํํ๊ธฐ ์ํด npm์ npx
๋ฅผ ์ฌ์ฉํ์ด์ผ ํ์ต๋๋ค. ์ด์ ๋๋์ด Yarn
์ด ๊ทธ ์ผ์ ์ง์ ํ๊ฒ ๋์ต๋๋ค.
Yarn 2๋ฅผ ์ฌ์ฉํ๋ฉด yarn dlx
์ปค๋งจ๋๋ฅผ ์ด์ฉํ์ฌ ์ค์นํ์ง ์๊ณ ์ผ์์ ์ธ ํ๊ฒฝ์์ ํจํค์ง๋ฅผ ์คํํ ์ ์์ต๋๋ค.
์์กด์ฑ์ ๋ก์ปฌ๋ก ํจ์นญํ๋ ๊ฒ์ด ํจ์ฌ ์ฌ์์ก์ต๋๋ค. ์ฌ๋ฌ๋ถ์ Yarn์ด ์ผ์์ ์ธ ํด๋์ ํจํค์ง๋ฅผ ์ถ์ถํ์ฌ diff๋ฅผ ๊ฐ๋ ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค.
yarn patch node-fetch
yarn patch-commit /private/var/patchfolder > mypatch.patch
ํจ์น ๋๋ ํ ๋ฆฌ๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ ์๋๋ฏ๋ก ํ๋ก์ ํธ์ ์ํฅ์ ์ฃผ๋ ๊ณต๊ฐ์ด ๋ณ๋ก ์์ต๋๋ค. ์ดํ ํจ์น ํ์ผ๋ง ์ฐธ์กฐํ ์๋ ์์ฃ .
{
"dependencies": {
"node-fetch": "patch:[email protected]#./mypatch.patch"
}
}
์ด๋ ์ฌ์ง์ด ๊ฐ์ ์ ์ธ ์์กด์ฑ์๋ ํจ๊ณผ๊ฐ ์์ผ๋ฏ๋ก ๊ณต์ ๋ฆด๋ฆฌ์ฆ ์์ ๋ณธ์ด ๋ฐํ๋ ๋๊น์ง ๋ณด์ ๋ฌธ์ ๋ฅผ ํจ์นํ๋ ์ ์ฉํ ๊ธฐ๋ฅ์
๋๋ค.
์ด์ ๋ํ ๋ ๋ง์ ๋ด์ฉ์ GitHub์ plugin-patch ๋ฌธ์์ patch ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์
์ฌ๋ฌ๋ถ์ด (๋ชจ๋
ธ๋ ํฌ์ฒ๋ผ) ์ฌ๋ฌ ์ํฌ์คํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ณ ์๋ ๊ฒฝ์ฐ ํธ๋ฆฌ์์ ์ฌ์ฉํ๋ ํจํค์ง๋ค์ ๋ฆด๋ฆฌ์ฆํ๊ณ ์์ฐจ์ ์ผ๋ก ์
๊ทธ๋ ์ด๋ํ๋ ๊ฒ์ ์ง๋ฃจํ ์ผ์
๋๋ค.
์ด์์ ์ผ๋ก ์ฌ๋ฌ๋ถ์ ์ํฌ์คํ์ด์ค์ ์๋ก์ด ๋ฒ์ ์ ๋ฆด๋ฆฌ์ฆํ๊ณ ์ ๋ฆด๋ฆฌ์ฆ์ ํจ๊ป ๋ชจ๋ ์์กด์ฑ์ด ์๋์ ์ผ๋ก ์
๊ทธ๋ ์ด๋ ๋์ด์ผ ํฉ๋๋ค.
์ด๋ ์ ํํ Version plugin์ด ํ๋ ์ผ์
๋๋ค. ์๋ก์ด ๋ฆด๋ฆฌ์ฆ ์ํฌํ๋ก์ฐ๋ฅผ ํด์ ํ์ฌ ์
๊ทธ๋ ์ด๋์ ๋์๊ณผ ์์น๋ฅผ ํ์
ํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ ์์ฑ๋๋ค.
์ฌ๋ฌ๋ถ์ ํจํค์ง์ ๋ณต์ก์ฑ์ ๋ฐ๋ผ ์๋ก์ด Yarn ๋ฒ์ ์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ๊ฒ์ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ง๋ง ์ถฉ๋ถํ ๊ฐ์น๊ฐ ์๋ ์์
์
๋๋ค.
๋ ์ข์ ์ด์ ๊ฐ ํ์ํ๋ค๋ฉด ์ด ๋ฆฌ์คํธ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ด๋ฏธ ๋ง์ด๊ทธ๋ ์ด์
์ ํ์ ์ ๊ฐ์ก๋ค๋ฉด ๊ฐ์ด๋๋ฅผ ์ดํด๋ณด์ธ์.
์ด ์
๋ฐ์ดํธ๋ ์ฌ๋ฌ๋ถ๊ณผ ์ฌ๋ฌ๋ถ์ ํ, ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ ํ๋ ๋๋ผ์ด๋ธ๊น์ง ๋ชจ๋๋ฅผ ์ํ ๊ธธ์
๋๋ค.
์์ ๋งํฌ, ์์งํ๋
props
, hooks
๊ฐ ์๋ค.style
, logic
, global state
, remote data schema
(API ์๋ฒ์์ ๋ด๋ ค์ฃผ๋ ๋ฐ์ดํฐ ๋ชจ์)์จ์ ์์กด์ฑ
normalizr
์ฐธ๊ณ ์์ ๋งํฌ, ์ํฌ์ข ๋
ํธ์คํ ํ๊ฒฝ | ํจํค์ง |
---|---|
HTML | react-dom |
iOS, Android ... | react-native |
terminal | ink |
Three.js | react-three-fiber |
JSON | react-test-render |
๋ถ์ : ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ C++ ์ฑ๋ฅ์ ๋ฌ์ฑํ๋ ๋ฐฉ๋ฒ
์๋ฌธ : Secret Behind JavaScript Performance: V8 & Hidden Classes
์ค๋๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ ์น ๊ฐ๋ฐ์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ์ธ์ด๊ฐ ๋์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๋จ๊ณ๊น์ง ์ฌ๋ผ๊ฐ๊ธฐ ์ํด ๋ง์ ์ฅ์ ๋ฌผ์ ํต๊ณผํด์ผ ํ์ต๋๋ค. ๊ทธ ์ค ํ๋๋ ์คํ ์๋์ ๊ดํ ๊ฒ์ธ๋ฐ, C++๊ณผ ๊ฐ์ ์ธ์ด์ ๋น์ทํ ์ฑ๋ฅ์ ๋ฌ์ฑํด์ผ ํ์ต๋๋ค.
์ด๋ฌํ ์ฑ์ทจ๋ V8 ์๋ฐ์คํฌ๋ฆฝํธ ์์ง ์์ด๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
๊ทธ๋์ ์ด ์ํฐํด์์๋ ์ด๋ฌํ ์ฑ๋ฅ์ ์ป์ ์ ์์๋ ๊ธฐ์ ๊ณผ ๋ ๋์ ์ฑ๋ฅ์ ๊ฐ์ง๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด ์์์ผ ํ๋ ๊ฒ๋ค์ ๋ํด ์๊ธฐํด๋ณด๊ณ ์ ํฉ๋๋ค.
V8์ ๊ตฌ๊ธ์ด ์ ์ํ ์คํ์์ค ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋๋ค. C++๋ก ์์ฑ๋์์ผ๋ฉฐ ๊ตฌ๊ธ ํฌ๋กฌ์ ๋น๋กฏํ ํฌ๋ก๋ฏธ์ ์น ๋ธ๋ผ์ฐ์ ๊ทธ๋ฆฌ๊ณ NodeJS๋ฅผ ์ง์ํฉ๋๋ค. ํ๊ฒฝ๊ณผ ์ํธ ์์ฉํ๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋จ์ ์คํํ๊ธฐ ์ํ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์์ฑํ๋ ์ญํ ์ ํฉ๋๋ค. ์ด๊ธฐ์ V8์ ์น ๋ธ๋ผ์ฐ์ ์ ์ฑ๋ฅ ํฅ์ ๋ฉ์ปค๋์ฆ์ผ๋ก์ ์๊ฐ๋์๋๋ฐ์. ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ค๋ฅธ ์์ง๋ค๋ณด๋ค ๋ ํฅ์๋ ์ธํฐํ๋ฆฌํฐ๊ฐ ๋์์ต๋๋ค.
V8๊ณผ ๋ค๋ฅธ ์์ง๋ค์ ๊ฐ์ฅ ๋๋๋ฌ์ง๋ ์ฐจ์ด์ ์ JIT(Just-In-Time) ์ปดํ์ผ๋ฌ๋ผ๋ ์ ์ ๋๋ค.
JIT ์ปดํ์ผ๋ฌ๋ ๋ฐํ์์ ๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋จธ์ ์ฝ๋๋ก ์ปดํ์ผํ๋ฉฐ ์ค๊ฐ ์ฝ๋๋ ์์ฑํ์ง ์์ต๋๋ค.
์ ๋ค์ด์ด๊ทธ๋จ์์ ๋ณผ ์ ์๋ฏ์ด, V8 ์์ง์ 2๊ฐ์ ๋ฉ์ธ ํํธ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ํํธ๋ ์ฝ๋๋ฅผ ๋ฐ์ดํธ์ฝ๋๋ก ํด์ํ๋ ํ์์ ์ญํ ์ ํ๋ฉฐ, V8์ ์ต์ ๋ฒ์ ์ ์ด ๊ณผ์ ์์ Ignition์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ธํฐํ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ํ์์ ์ํด **์ถ์ ๊ตฌ๋ฌธ ํธ๋ฆฌ(AST)**๊ฐ ์์ฑ๋๋๋ฐ ์ธํฐํ๋ฆฌํฐ๋ ์ด๋ฅผ ์ ๋ ฅ๊ฐ์ผ๋ก ๋ฐ์ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ธํฐํ๋ฆฌํฐ๋ณด๋ค ์ปดํ์ผ๋ฌ๊ฐ ํจ์ฌ ๋น ๋ฆ ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ V8 ์์ง์ ์ปดํ์ผ๋ฌ ๋์ ์ ์ธํฐํ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฑธ๊น์?
Ignition ์ธํฐํ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์ฅ ํฐ ์ด์ ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๊ธฐ ์ํด์ ์ ๋๋ค. ์ธํฐํ๋ฆฌํฐ๋ ์ ์ฒด ํ๋ก๊ทธ๋จ์ ์ปดํ์ผํ๋ ์ปดํ์ผ๋ฌ์ ๋ค๋ฅด๊ฒ ์ค์ง ํ์ํ ๋ผ์ธ๋ง ์ปดํ์ผํ๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ฐ์๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ Ignition ์ปดํ์ผ๋ฌ๋ ๊ฐ์ฅ ์ด๊ธฐ์ ๋์ํ๋ ์ฝ๋์ ๋ํด์๋ง ์์ ์ ์ญํ ์ ์ํํฉ๋๋ค. Turbofan์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ปดํ์ผ๋ฌ๊ฐ ์์ฑ๋ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ์ฝ๋๋ฅผ ์คํํ๋ ๋์ ์ป์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ ์ต์ ํํ๊ณ ๋ ์ต์ ํ๋ ๋ฒ์ ์ผ๋ก ๋ค์ ์ปดํ์ผํฉ๋๋ค.
Note: V8์ด ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ต์ ํํ๊ธฐ ์ํด ์ฌ์ฉ๋๊ธฐ๋ ํ๋ C++๋ก ์์ฑ๋์์ผ๋ฉฐ , ํ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง ์์ ๋ค์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ฉํฐ ์ค๋ ๋ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค.
V8์ ๋์ ๋ฐฉ์์ ์ค๋ช ํ ๋ Ignition ์ธํฐํ๋ฆฌํฐ๊ฐ ์ ๋ ฅ๊ฐ์ผ๋ก AST๋ฅผ ๋ฐ๋๋ค๊ณ ํ๋๋ฐ์. ๊ทธ๋ผ AST๊ฐ ๋ฌด์์ธ์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ป๊ฒ AST๊ฐ V8์ด ์๋ฐ์คํฌ๋ฆฝํธ ์ฑ๋ฅ์ ํฅ์ํ๋ ๋ฐ ๋์์ด ๋๋์ง ์ดํด๋ด ์๋ค.
Bit๊ณผ ๊ฐ์ OSS ํด์ ๋ชจ๋ ์ฑ์ ๋น๋ํ๋ ๋ฐ ์๋ก์ด ํจ๋ฌ๋ค์์ ์ ๊ณตํฉ๋๋ค.
๋ชจ๋๋ฆฌํฑ ํ๋ก์ ํธ๋ฅผ ๊ฐ๋ฐํ๋ ๋์ ์ ๋ ๋ฆฝ์ ์ธ ์ปดํฌ๋ํธ๋ฅผ ๋น๋ํด๋ณด์ธ์. ๊ทธ๋ฌ๊ณ ๋์ ์ฌ๋ฌ๋ถ์ ์ปดํฌ๋ํธ๋ฅผ ํจ๊ป ๊ตฌ์ฑํ์ฌ ์ํ๋ ๋งํผ ์ฌ๋ฌ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋น๋ํ ์ ์์ต๋๋ค. ๋น๋ํ๊ธฐ์ ๋ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ ์๋์ง๋ง ๋ ํ์ฅ์ฑ ์์ผ๋ฉฐ ๊ฐ๋ฐ์ ํ์คํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
AST๋ ์ปดํ์ผ๋ฌ๊ฐ ์์ค์ฝ๋๋ฅผ ์ถ์์ ์ธ ๊ตฌ์กฐ๋ก ๊ตฌ์ถํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ํ ์๋ฐ์คํฌ๋ฆฝํธ๋ V8์ ํ์ ๋์ด ์์ง ์์ต๋๋ค. ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๊ณ ์์ค์ ์ฝ๋๋ฅผ ์ ์์ค์ผ๋ก ํํํ๊ธฐ ์ํด AST๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฝ๋๋ฅผ AST๋ก ๋ณํํ ๋ ์ด๋ ๋ณ์ ํ์ , ์์น, ๊ตฌ๋ฌธ์ ์์์ ๊ฐ์ด ์ฝ๋์์ ํ์ํ ์ธ๋ถ์ฌํญ๋ค์ ํฌํจํฉ๋๋ค. ๊ทธ๋์ ์ปดํ์ผ๋ฌ๋ ์ฃผ์๊ณผ ๊ฐ์ด ๋ถํ์ํ ๋ถ๋ถ์ ๋ค๋ฃจ์ง ์์ต๋๋ค.
๋ ์ ์ดํดํ๊ณ ์, ๊ฐ๋จํ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ก AST๋ฅผ ์์ฑํด๋ด ์๋ค.
// ํจ์ ์ ์
function addition(x, y){
var answer = x + y;
console.log(answer);
}
// ํจ์ ํธ์ถ
addition(10,20);
์ด ์ฝ๋์ ๋ํ AST๋ฅผ ์์ฑํ๊ธฐ ์ํด esprima์์ ์ ๊ณตํ๋ ์จ๋ผ์ธ ํ์ฑ ํด์ ์ฌ์ฉํ๋๋ฐ์. ๋ค์ ์ฝ๋ ์ค๋ํซ์ AST์ ํ ํํธ๋ฅผ ๋ณด์ฌ์ฃผ๋๋ฐ ์ ์ฒด AST๋ฅผ ๋ณด๊ณ ์ถ๋ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
{
โtypeโ: โProgramโ,
โbodyโ: [
{
โtypeโ: โFunctionDeclarationโ,
โidโ: {
โtypeโ: โIdentifierโ,
โnameโ: โadditionโ
},
โparamsโ: [
{
โtypeโ: โIdentifierโ,
โnameโ: โxโ
},
{
โtypeโ: โIdentifierโ,
โnameโ: โyโ
}
],
โbodyโ: {
โtypeโ: โBlockStatementโ,
โbodyโ: [
...
],
โkindโ: โvarโ
},
...
โsourceTypeโ: โscriptโ
}
AST๋ ๊ฐ ์ฝ๋ ๋ผ์ธ์ ํด๋นํ๋ ํค-๊ฐ ์๋ค์ ์ ์ํฉ๋๋ค. ์ด๊ธฐ ํ์ ์๋ณ์๋ AST๊ฐ ํ๋ก๊ทธ๋จ์ ์ํ๋ ๊ฒ์ผ๋ก ์ ์ํ๊ณ , ๋ชจ๋ ์ฝ๋ ๋ผ์ธ์ ๊ฐ์ฒด์ ๋ฐฐ์ด ๋ณธ๋ฌธ ๋ด์ ์ ์๋ฉ๋๋ค. ์๊น ์ธ๊ธํ๋ฏ์ด, ๋ชจ๋ ํจ์ ์ ์๋ ๋ณ์ ์ ์, ์ด๋ฆ๊ณผ ํ์ ๋ฑ์ ๋ผ์ธ ๋ณ๋ก ๊ตฌ์ฑ๋๋ฉฐ ์ฃผ์์ ๋ฌด์๋ฉ๋๋ค. ์ต์ ํ ๊ณผ์ ๊ณผ AST๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋ณ๊ฐ๋ก V8์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฑ๋ฅ์ ํฅ์์ ์ํด ๋ค๋ฅธ ํธ๋ฆญ์ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๊ฒ์ด ๋ฌด์์ธ์ง, ์ด๋ป๊ฒ ๋์ํ๋์ง ๋ด ์๋ค.
์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์๋ฏ์ด, ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋์ ํ์ ์ธ์ด์ ๋๋ค. ์ด๋ ๊ทธ๋๊ทธ๋ ๊ฐ์ฒด์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ ๊ฑฐํ ์ ์๋ค๋ ๋ป์ ๋๋ค.
๊ทธ๋ฌ๋ ์ด ๋ฐฉ์์ ๋ ๋ง์ ๋์ ์ธ ๋ฃฉ์ ์ ์๊ตฌํ๋ฏ๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ์ฑ๋ฅ์ ์ ํ์ํต๋๋ค.
V8 ์์ง์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๊ทน๋ณตํ๊ณ ์๋ฐ์คํฌ๋ฆฝํธ ์คํ์ ์ต์ ํํ๊ธฐ ์ํด ํ๋ ํด๋์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์ฌ๋ฌ๋ถ์ด ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, V8 ์์ง์ ๊ทธ์ ๋ง๋ ์๋ก์ด ํ๋ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค. ๊ทธ ํ, ์ฌ๋ฌ๋ถ์ด ๋์ผํ ๊ฐ์ฒด์ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํจ์ผ๋ก์จ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝ์ํฌ ๋ V8 ์์ง์ ์ด์ ์ ํด๋์ค์์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๋ ์๋ก์ด ํ๋ ํด๋์ค๋ฅผ ์์ฑํ๊ณ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํฉ๋๋ค. ๋ค์ ์์ ์์์์ ์ด๋ป๊ฒ ํ๋ ํด๋์ค๊ฐ ์์ฑ๋๋์ง ๋ณผ๊น์?
๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ์ ๋ V8์ ๋๊ทธ์ ์์ํ์ฌ ์ด๋ ํ ์คํ์ ์ด ์๋ ํ๋ ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
๊ทธ ํ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ฌ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝ์ํค๋ฉด V8 ์์ง์ ์๋ก์ด ํ๋ ํด๋์ค๋ฅผ ์์ฑํ๋๋ฐ ์ด ํด๋์ค๋ ์ด์ ์ ํ๋ ํด๋์ค์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์์ํ๋ฉฐ offset 0์ ๋ํ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ํ ๋นํฉ๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ ํตํด ํ๋กํผํฐ ์ด๋ฆ์ด ์ ๊ทผ๋ ๋ ๋์ ๋๋ฆฌ ๋ฃฉ์ ์ ๋ฌด์ํ๋ฉฐ V8์ ํด๋์ค C01์ ์ง์ ๊ฐ๋ฆฌํต๋๋ค. ์ด ๊ฐ์ฒด์ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ฉด ๋์ผํ ๊ณผ์ ์ด ๋ฐ์ํฉ๋๋ค. ๋ ๋ค๋ฅธ ํ๋ ํด๋์ค๊ฐ ์์ฑ๋๋ฉด ์ด๋ ์ด์ ์ ํด๋์ค์ ์๋ก์ด ์ดํธ๋ฆฌ๋ทฐํธ ๋ชจ๋๋ฅผ ๊ฐ์ง๋๋ค.
์ด๋ฌํ ํ๋ ํด๋์ค ๊ฐ๋ ์ ๊ฐ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๊ฑฐ๋ ๋ณ๊ฒฝ๋ ๋ ๋์ ๋๋ฆฌ ๋ฃฉ์ ์ ๋ฌด์ํ ๋ฟ๋ง ์๋๋ผ ์ด๋ฏธ ์์ฑํ ํด๋์ค๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฌ๋ฌ๋ถ์ด article์ด๋ผ๋ ๋น ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค๋ฉด(const articleObject = {}
, V8 ์์ง์ ์๋ก์ด ํ๋ ํด๋์ค๋ฅผ ์์ฑํ์ง ์์ต๋๋ค. ๋์ ์ ์ด๋ฏธ ์์ฑ๋ C01 ํด๋์ค๋ฅผ ๊ฐ๋ฆฌํฌ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋ฌ๋ถ์ด articleName
์ด๋ผ๋ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ฌ articleObject
๋ฅผ ๋ณ๊ฒฝ์ํค๋ฉด V8์ ๋ ์ด์ ์ด์ ์ ์์ฑํname
์ด๋ผ๋ ํ๋กํผํฐ๋ง ๊ฐ์ง๋ C02 ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๋์ ์ฌ๋ฌ๋ถ์ด ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์ ์ฑ๋ฅ์ ๊ทน๋ํํ๊ณ ์ถ๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ๋์ ํ๋กํผํฐ ํ ๋น์ ๊ฐ์ํด์ผ ํ ๊ฒ๋๋ค. NodeJS์์ ๋ฃจํ๋ฅผ ์คํํ๊ณ ์๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค. ์ฌ๋ฌ๋ถ์ด ๊ฐ์ฒด์ ๋์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ค๋ฉด ๋ฃจํ ๋ด์์ ์ฑ๋ฅ์ด ๋ณ๊ฒฝํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ฃจํ ๋ด์์ ๋์ ์ผ๋ก ์ถ๊ฐํ๊ธฐ ๋ณด๋ค๋ ๋ฃจํ ๋ฐ์์ ํ๋กํผํฐ๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. V8์ ์กด์ฌํ๋ ํ๋ ํด๋์ค๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ ๋์ ๋ฐฉ๋ฒ์ธ ๊ฒ์ด์ฃ .
์ด๋ป๊ฒ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋์ํ๋์ง์ ๋ํ ๋
ผ์๊ฐ ์์ ๋๋ง๋ค ์ด๋ฒคํธ ๋ฃจํ, ๋ง์ดํฌ๋กํ์คํฌ, ์ฝ๋ฐฑ ํ์ ๋ํด ์ด์ผ๊ธฐ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๊ฒ๋ค์ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ตฌํ๋๋ ๊ฒ์ด ์๋๋ผ V8 ์์ง์ ํ ๋ถ๋ถ์ผ ๋ฟ์ด๋ฉฐ ์ฌ๋ฌ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ต์ ํํ๋ ์ญํ ์ ํฉ๋๋ค.
๊ทธ๋์ ์ด๋ป๊ฒ V8์ด ๋์ํ๋์ง๋ฅผ ์ค๋ช
ํ๊ณ ์ ํ์ผ๋ฉฐ V8์ด ์ฌ์ฉํ๋ ํ๋ ํด๋์ค ๊ฐ๋
์ ๋ง์๋๋ฆฐ ๊ฒ๋๋ค. ์ฌ๋ฌ๋ถ์ด ์ด ์ํฐํด์์ ์๋ก์ด ๊ฒ๋ค์ ๋ฐฐ์ ๊ธธ ๋ฐ๋ผ๋ฉฐ ๋๊ธ์ฐฝ์์ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๊ณต์ ํด์ฃผ์ธ์.
์๋ฌธ : The JavaScript Call Stack - What It Is and Why It's Necessary
(๋ธ๋ผ์ฐ์ ์ ๊ฐ์ ํธ์คํ ํ๊ฒฝ์์ ๋ณผ ์ ์๋) ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ heap๊ณผ ์ฑ๊ธ call stack์ผ๋ก ์ด๋ฃจ์ด์ง ์ฑ๊ธ ์ค๋ ๋์ ์ธํฐํ๋ฆฌํฐ์ ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ DOM, AJAX, Timer์ ๊ฐ์ web API๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ด ์ํฐํด์ call stack์ด ๋ฌด์์ด๋ฉฐ ์ ํ์ํ์ง์ ๋ํด ์ค๋ช ํ๋ ๊ฒ์ ๋ชฉ์ ์ผ๋ก ํ๋ ๊ธ์ ๋๋ค. call stack์ ์ดํดํ๋ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์์ ์ด๋ป๊ฒ "ํจ์ ๊ณ์ธต๊ณผ ์คํ ์์"๊ฐ ์๋ํ๋์ง์ ๋ํด ๋ช ๋ฃํ๊ฒ ์๋ ค์ค ๊ฒ์ ๋๋ค.
call stack๋ ์ฃผ๋ก ํจ์ ํธ์ถ์ ์ฌ์ฉ๋ฉ๋๋ค. call stack์ ํ๋์ด๋ฏ๋ก ํจ์ ์คํ ๋ํ ํ๋ฒ์ ํ๋์ฉ, ์์์ ์๋๋ก ๊ฐ๋ฅํฉ๋๋ค. ์ฆ call stack์ด ๋๊ธฐ์ ์ด๋ผ๋ ๊ฒ์ ์๋ฏธํ์ฃ .
call stack์ ์ดํดํ๋ ๊ฒ์ (๋์ค์ ์์๋ณผ) ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ํ์์ ์ ๋๋ค.
๋น๋๊ธฐ์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ฐ๋ฆฌ๋ ์ฝ๋ฐฑ ํจ์, ์ด๋ฒคํธ ๋ฃจํ, ํ์คํธ ํ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฝ๋ฐฑ ํจ์๋ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด ์คํ์ push๋ ํ call stack์ ์ํด ์คํ๋ฉ๋๋ค.
๋๋ฌด ์๋๋ฅด์ง ๋ง๊ณ , ๋จผ์ call stack์ด ๋ฌด์์ธ๊ฐ?๋ผ๋ ์ง๋ฌธ์ ๋ํ ๋ต์ ์ฐพ์๋ด ์๋ค.
๊ฐ์ฅ ๊ธฐ์ด์ ์ธ ์์ค์ผ๋ก ์ค๋ช ํ๋ฉด call stack์ ์ผ์์ ์ผ๋ก ์ ์ฅํ๊ณ ํจ์ ํธ์ถ์ ๊ด๋ฆฌํ๋ LIFO(Last In, First Out) ์๋ฆฌ๋ฅผ ๋ฐ๋ฅด๋ ์๋ฃ๊ตฌ์กฐ์ ๋๋ค.
์ ์๋ฅผ ์์ธํ ์ค๋ช ํด๋ด ์๋ค.
call stack์ ๋ํด ๋งํ ๋ LIFO ์๋ฆฌ๋ฅผ ๋ฐ๋ฅธ๋ค๊ณ ํ์ต๋๋ค. ์ด๋ ๋ง์ง๋ง์ ์คํ์ push๋ ํจ์๊ฐ ์ด๋ค ํจ์๊ฐ ๋ฐํ๋ ๋ ๋จผ์ popํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ฝ์์ ์คํ ์ถ์ ์๋ฌ๋ฅผ ์ถ๋ ฅํ๋ LIFO๋ฅผ ์ค๋ช ํ๋ ์ฝ๋ ์์ ๋ฅผ ๋ด ์๋ค.
function firstFunction(){
throw new Error('Stack Trace Error');
}
function secondFunction(){
firstFunction();
}
function thirdFunction(){
secondFunction();
}
thirdFunction();
์ฝ๋๋ฅผ ์คํํ๋ฉด ์๋ฌ๋ฅผ ๋ง๋๊ฒ ๋ฉ๋๋ค. ํจ์๋ค์ด ์ด๋ป๊ฒ ์์ด๋์ง ๋ณด์ฌ์ฃผ๋ ์คํ์ด ์ถ๋ ฅ๋ฉ๋๋ค. ๋ค์ด์ด๊ทธ๋จ์ ๋ด ์๋ค.
์ฌ๋ฌ๋ถ์ ์คํ์ ์์ธ ํจ์๋ค์ด firstFunction()
๋ถํฐ ์์ํ๋ค๋ ๊ฒ์ ์์์ฐจ๋ฆด ๊ฒ๋๋ค. (์ด ํจ์๋ ์คํ์ ๋ง์ง๋ง์ผ๋ก ๋ค์ด๊ฐ ํจ์์ด๊ณ error์ throwํ๊ณ pop๋ฉ๋๋ค.) ๊ทธ ๋ค์์ secondFunction()
์ด๊ณ ๊ทธ ๋ค์์ด ์ฝ๋๊ฐ ์คํ๋ ๋ ๊ฐ์ฅ ๋จผ์ Push๋ thirdFunction()
์
๋๋ค.
ํจ์๊ฐ ํธ์ถ๋ ๋ ํจ์, ํ๋ผ๋ฏธํฐ, ๋ณ์๋ค์ ์คํ ํ๋ ์์์ call stack์ผ๋ก push๋ฉ๋๋ค. ์ด ์คํ ํ๋ ์์ ์คํ์ ๋ฉ๋ชจ๋ฆฌ ์์น์ ๋๋ค. ๋ฉ๋ชจ๋ฆฌ๋ ํจ์๊ฐ ์คํ์์ pop๋ ๋ ๋ฐํ๋๋ฉด ์ง์์ง๋๋ค.
call stack์ ๊ฐ ์คํ ํ๋ ์์ ์์น์ ๊ธฐ๋ก์ ๊ด๋ฆฌํฉ๋๋ค. ์คํ๋ ๋ค์ ํจ์๋ฅผ ์๊ณ ์๋ ๊ฒ์ด์ฃ . (์คํ ํ์๋ ์ ๊ฑฐํฉ๋๋ค.) ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋๊ธฐ์ ์ผ๋ก ์ฝ๋๋ฅผ ์คํํ๊ฒ ํฉ๋๋ค.
๊ฐ๊ฒ ๊ณ์ฐ๋์ ๊ฐ์ ํ์์ ์์๋ค๊ณ ์๊ฐํด๋ณด์ธ์. ์ ์ฌ๋์ด ๋๋์ผ๋ง ์ฌ๋ฌ๋ถ์ ์ฐจ๋ก๊ฐ ์ต๋๋ค. ์ด๊ฒ ๋ฐ๋ก ๋๊ธฐ์
์ธ ๊ฒ์
๋๋ค.
์ด๋ฅผ "ํจ์ ํธ์ถ์ ๊ด๋ฆฌ"๋ผ๊ณ ํ๋ ๊ฒ์ด๊ณ ์.
ํ ํจ์๊ฐ ๋ค๋ฅธ ํจ์๋ฅผ ํธ์ถํ๋ ์ํ ์ฝ๋๋ฅผ ๋ณด๋ฉด์ ๋ต์ ์ฐพ์๋ณด๊ฒ ์ต๋๋ค. ์์ ์ฝ๋๋ฅผ ๋ณด์ธ์.
function firstFunction(){
console.log("Hello from firstFunction");
}
function secondFunction(){
firstFunction();
console.log("The end from secondFunction");
}
secondFunction();
์ฝ๋๊ฐ ์คํ๋๋ฉฐ ์ผ์ด๋๋ ์ผ๋ค์ ๋๋ค.
secondFunction()
์ด ์คํ๋ ๋ ๋น ์คํ ํ๋ ์์ด ์์ฑ๋ฉ๋๋ค. ์ด ํ๋ ์์ ํ๋ก๊ทธ๋จ์ (์ต๋ช
์) ๋ฉ์ธ ์ํธ๋ฆฌ ํฌ์ธํธ๊ฐ ๋ฉ๋๋ค.secondFunction()
๋ ์คํ์ push๋ firstFunction()
๋ฅผ ํธ์ถํฉ๋๋ค.firstFunction()
๋ ๋ฐํ๋๊ณ ์ฝ์์ "Hello from firstFunction"์ ์ถ๋ ฅํฉ๋๋ค.firstFunction()
๋ ์คํ์์ pop๋ฉ๋๋ค.secondFunction()
๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.secondFunction()
๋ ๋ฐํ๋๋ฉฐ ์ฝ์์ "The end from secondFunction"์ ์ถ๋ ฅํฉ๋๋ค.secondFunction()
๋ ์คํ์์ Pop๋๋ฉฐ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ง์์ง๋๋ค.์คํ ์ค๋ฒํ๋ก์ฐ๋ ์ฌ๊ทํจ์๊ฐ ํ์ถ ์ง์ ์์ด ํธ์ถ๋ ๋ ๋ฐ์ํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ์คํ ์๋ฌ๋ฅผ ๋ฐ์์ํค๊ธฐ ์ ์ ์์ฉํ ์ ์๋ ๋งฅ์๋ฉ ์คํ ํธ์ถ ํ์๊ฐ ์ ํด์ ธ ์์ต๋๋ค.
์์๋ฅผ ๋ณด์ญ์์ค.
function callMyself(){
callMyself();
}
callMyself();
callMyself()
๋ ๋ธ๋ผ์ฐ์ ๊ฐ "Maximum call size exceeded"๋ฅผ throwํ๊ธฐ ์ ๊น์ง ์คํ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์คํ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ์ฃ .
call stack
์ ์ฃผ์ ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ค๋ฅธ ์ํฐํด์์ call stack ์ํฐํด์ ๊ธฐ๋ฐ์ผ๋ก ๋น๋๊ธฐ์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์์ ์ฝ๋๋ GitHub repo์์ ๋ณผ ์ ์์ต๋๋ค.
์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋์์ด ๋์๋ค๋ฉด ๋ฐ์๋ฅผ ๋๋ฌ์ฃผ์ธ์. ๊ทธ๋ผ ๋ค๋ฅธ ์ฌ๋๋ค๋ ์ด ์ํฐํด์ ๋ณผ ์ ์์ต๋๋ค. ๋ํ ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉํธ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฒ ์ต๋๋ค.
ํ์ ์คํฌ๋ฆฝํธ ๋ง์คํฐ ์๋ฆฌ์ฆ์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค. ์ด ์๋ฆฌ์ฆ๋ ์ ๋๋ฉ์ด์ ํํ๋ก ํ์ ์คํฌ๋ฆฝํธ์ ์ฝ์ด ์ง์๊ณผ ๊ธฐ์ ๋ค์ ์ค๋ช ํฉ๋๋ค. ๊ฐ์ด ๋ฐฐ์๋ณด์์! ์ด์ ๊ธ๋ค์ ์๋๋ฅผ ์ฐธ๊ณ ํ์ธ์
๋ง์ฝ ์ฌ๋ฌ๋ถ์ด ๋ ์ฃผ๋ฉ์ ํ์ ์คํฌ๋ฆฝํธ ๊ฒฝ๋ ฅ์ ์ผ๋ค๋ฉด, ์๋ง ๋ฉด์ ๊ด์ type๊ณผ interface์ ์ฐจ์ด์ ์ด ๋ฌด์์ธ์ง ๋ฌผ์ด๋ณผ ๊ฒ๋๋ค. ์ด๋ป๊ฒ ๋๋ตํด์ผ ํ ์ง ์์๊ฒ ๋์? ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, ์ด ๊ธ์ ์ฝ๊ณ ์ ์ดํดํ์ค ์๋ ์์ ๊ฒ ๊ฐ๋ค์.
ํ์ ๋ณ์นญ(alias)์ ํ์ ์ ์๋ก์ด ์ด๋ฆ์ ๋ถ์ฌํ๊ธฐ ์ํด ์ฌ์ฉ๋ ์ ์๊ณ , ์์ ํ์ ๊ณผ ๊ฐ์ ๋น๊ฐ์ฒด ํ์ ์ด๋ ํฉ์งํฉ์ ๋ค์ด๋ฐํ ๋๋ ๋์์ด ๋ฉ๋๋ค.
type MyNumber = number;
type StringOrNumber = string | number;
type Text = string | string[];
type Point = [number, number];
type Callback = (data: string) => void;
Typescript 1.6์์ ํ์ ๋ณ์นญ์ ์ ๋๋ฆญ ํ์ ์ ์ง์ํ๊ธฐ ์์ํ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ํํ ์์ ํ ๋ ์์ฃผ ์ฌ์ฉํ๋ Partial, Required, Pick, Record, ๊ทธ๋ฆฌ๊ณ Exclude์ ๊ฐ์ ์ ํธ๋ฆฌํฐ ํ์ ๋ ํ์ ๋ณ์นญ์ผ๋ก ์ ์๋ฉ๋๋ค.
๊ฐ์ฒด ํ์
์ ์ ์ํ ๋ interface
๊ฐ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. Vue 3์ App ๊ฐ์ฒด๋ก interface๋ฅผ ์ฌ์ฉํ์ฌ ์ ์๋์์ต๋๋ค.
์ ์ฝ๋์์ ๋ณผ ์ ์๋ฏ์ด, interface๋ฅผ ์ ์ํ ๋ ๊ฐ์ฒด ํ์ ์ ํ๋กํผํฐ์ ๋ฉ์๋ ๋ชจ๋๋ฅผ ์ ์ธํ ์ ์์ต๋๋ค. ๋์ ๋น์ทํ ์ ์ ๋จผ์ ์๋ ค๋๋ฆฌ๊ณ type๊ณผ interface์ ์ญํ ์ ์ดํดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ํ์ ๋ณ์นญ๊ณผ ์ธํฐํ์ด์ค ๋ชจ๋ ๊ฐ์ฒด๋ ํจ์ ํ์ ์ ์ ์ํ ๋ ์ฌ์ฉ๋๋ค.
type Point = {
x: number;
y: number;
};
โ
type SetPoint = (x: number, y: number) => void;
์ ์ฝ๋์์ ๊ฐ์ฒด ๋ฆฌํฐ๋ด ํ์ ๊ณผ ํฉ์ ํ์ ์ type ํค์๋๋ก ๋ณ์นญ์ ๋ถ์ฌํจ์ผ๋ก์จ ๋ค๋ฅธ ๊ณณ์์๋ ์ด ํ์ ๋ค์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
interface Point {
x: number;
y: number;
}
โ
interface SetPoint {
(x: number, y: number): void;
}
ํ์ ๋ณ์นญ๊ณผ ์ธํฐํ์ด์ค ๋ชจ๋ ํ์ฅ ๊ฐ๋ฅํ๋ค.
ํ์
๋ณ์นญ์ &
์ ์ํด ํ์ฅ๋์ง๋ง ์ธํฐํ์ด์ค๋ extends
์ ์ํด ํ์ฅ๋ฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ธํฐํ์ด์ค๊ฐ ํ์ ๋ณ์นญ์ผ๋ก ์ ์๋ ํ์ ์ extends๋ก ํ์ฅํ ์ ์์๊น์? ๋ต์ '๊ทธ๋ ๋ค'์ ๋๋ค. ์ถ๊ฐ์ ์ผ๋ก ํ์ ๋ณ์นญ ๋ํ & ์ฐ์ฐ์๋ฅผ ์ด์ฉํ์ฌ ์ธํฐํ์ด์ค๋ก ์ ์๋ ํ์ ์ ํ์ฅํ ์๋ ์์ต๋๋ค.
๊ทธ๋ผ ์ด์ ํ์ ๋ณ์นญ๊ณผ ์ธํฐํ์ด์ค์ ์ ์ฌ์ ์ ์๊ฒ ๋์ จ๋์? ๊ทธ๋ผ ์ฐจ์ด์ ์ ๋ํด ์๊ธฐํด๋ด ์๋ค.
type MyNumber = number; // primitive type
type StringOrNumber = string | number; // union type
type Point = [number, number]; // tuple type
์ ์ธ ๋ณํฉ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ฐ๋ฐํ ๋ ์ฌ์ฉ์์๊ฒ ๋ ์ข์ ๋ณด์์ ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด webext-bridge ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ProtocolMap ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ๊ธฐ ์ํด ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด ๋๋ฌธ์ ์ฌ์ฉ์๋ค์ ํธํ๊ฒ ProtocolMap ์ธํฐํ์ด์ค๋ฅผ ํ์ฅํ ์ ์์ต๋๋ค. ๊ทธ ํ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด๋ถ์ ์ ๊ณต๋๋ onMessage ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ปค์คํ ๋ฉ์์ง๋ฅผ ๋ชจ๋ํฐ๋งํ ๋ ์๋ก ๋ค๋ฅธ ๋ฉ์์ง์ ํด๋นํ๋ ๋ฉ์ธ์ง ๋ฐ๋ ํ์ ๋ค์ ์ถ๋ก ํ ์ ์์ต๋๋ค.
import { ProtocolWithReturn } from 'webext-bridge'
โ
declare module 'webext-bridge' {
export interface ProtocolMap {
foo: { title: string }
bar: ProtocolWithReturn<CustomDataType, CustomReturnType>
}
}
import { onMessage } from 'webext-bridge'
โ
onMessage('foo', ({ data }) => {
// type of `data` will be `{ title: string }`
console.log(data.title)
}
์ด ๋ถ๋ถ์ ๋ํด ํฅ๋ฏธ๊ฐ ์์ผ์๋ค๋ฉด webext-bridge์ onMessage์ ๋ํ ํ์ ์ ์๋ฅผ ์ดํด๋ณด์ธ์. ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ์ ์ ๋ํํ์ค ์ ์์ด์. ๋ง์ง๋ง์ผ๋ก ํ์ ๋ณ์นญ๊ณผ ์ธํฐํ์ด์ค์ ๋ํ ๋ช๋ช ์ฌ์ฉ ์๋๋ฆฌ์ค๋ฅผ ์์ฝํด๋ณด๊ฒ ์ต๋๋ค.
type
์ ์ฌ์ฉํ ๊น์?type
์ ์ฐ์ธ์type
์ ์ฐ์ธ์type
์ ์ฐ์ธ์type
์ ์ฐ์ธ์type
์ ์ฐ์ธ์interface
์ ์ฌ์ฉํ ๊น์?interface
๋ฅผ ์ฐ์ธ์interface
๋ฅผ ์ฐ์ธ์์ด ๊ธ์ ์ฝ๊ณ ์ฌ๋ฌ๋ถ๋ค์ด ํ์ ๋ณ์นญ๊ณผ ์ธํฐํ์ด์ค์ ์ฐจ์ด๋ฅผ ์ด๋ฏธ ์ดํดํ์ จ์ผ๋ฆฌ๋ผ ๋ฏฟ์ต๋๋ค.
2020๋ 3์ 17์ผ์ ์์ฑ๋ 5 Recommended Tools for Optimizing Performance in ReactJS์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์๋์ ์ต์ ํ๋ฅผ ํ๊ณ ์ ํ๋ ๋ง์์์, ๋ฆฌ์กํธ์ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง๊ณผ ์ต์ ํ๋ฅผ ์ํด ์ ๊ฐ ์ข์ํ๋ ๋๊ตฌ ๋ชฉ๋ก์ ์ดํด๋ด ์๋ค.
<Profiler />
B. Vaughn๊ฐ ๊ฐ๋ฐํ ๋ฆฌ์กํธ์ ์๋ก์ด ์ปดํฌ๋ํธ Profiler
๋ ์ปดํฌ๋ํธ๊ฐ ์ผ๋ง๋ ๋ฆฌ๋ ๋๋์๋์ง, ๋ ๋๋ง์ด ์๋นํ ์๊ฐ๊ณผ ๋ฆฌ์์ค๋ฅผ ์ธก์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. Profiler
๋ onRender
์ ํจ์ prop์ ์ฌ์ฉํ๋๋ฐ ์ด๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋๊ฑฐ๋ ์
๋ฐ์ดํธ ๋ ๋๋ง๋ค time metrics๋ฅผ ๋ฐ์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ๋ฆฌ์กํธ ์ฑ์์ ๋นํจ์จ์ฑ์ ๊ฒ์ฌํ๊ฑฐ๋ ํ์งํ๋ ๋ฐ ์ข์ ๋ฐฉ์์
๋๋ค.
๊ฐ๋จํ ์์๋ฅผ ๋ด ์๋ค.
import { unstable_Profiler as Profiler } from "react"
<Profiler id="Counter" onRender={callback}>
<Counter />
</Profiler>
id
prop์ ๋ ํฌํธ๋๋ ํ๋กํ์ผ๋ฌ๋ฅผ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. onRender
์ ์ฝ๋ฐฑ ํจ์๋ Counter ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋๊ฑฐ๋ ์
๋ฐ์ดํธ ๋ ๋๋ง๋ค ์๋ ์ธ์์ ํจ๊ป ํธ์ถ๋ฉ๋๋ค.
function callback(id, phase, actualTime, baseTime, startTime, commitTime) {
log("id: " + id, "phase:" + phase, "actualTime:" + actualTime, "baseTime: " + baseTime, "startTime: " + startTime, "commitTime: " + commitTime)
}
ํจ์ ์ธ์๋ Counter
์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋ ์ฌ์ฉ๋๋ time metrics์
๋๋ค. ํ๋์ฉ ์ดํด๋ด
์๋ค.
id
: Profiler
์ปดํฌ๋ํธ์ ์ค์ ๋๋ ๊ณ ์ ์์ด๋phase
: ์ปดํฌ๋ํธ๊ฐ "๋ง์ดํธ"๋ ๊ฒ์ธ์ง, "์
๋ฐ์ดํธ/๋ฆฌ๋ ๋" ๋ ๊ฒ์ธ์ง ์๋ ค์คactualTime
: Profiler์ ํ์ ํญ๋ชฉ๋ค์ด ๋ง์ดํธํ๊ฑฐ๋ ์
๋ฐ์ดํธ ํ๋๋ฐ ๊ฑธ๋ฆฐ ์๊ฐbaseTime
: Profiler ํธ๋ฆฌ์ ๊ฐ ์ปดํฌ๋ํธ๋ค์ด ๋ง์ดํธํ๊ฑฐ๋ ์
๋ฐ์ดํธ ํ๋๋ฐ ๊ฑธ๋ฆฐ ์๊ฐstartTime
: Profiler๊ฐ ๋ง์ดํธ/๋ ๋๋ฅผ ์ธก์ ํ๋ ๊ฒ์ ์์ํ ์๊ฐcommitTime
: ์
๋ฐ์ดํธ๋ฅผ ์ปค๋ฐํ๋๋ฐ ๊ฑธ๋ฆฐ ์๊ฐ์ด ํ๋ผ๋ฏธํฐ๋ค์ ์ด๋ค ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ๋๋ฆฌ๊ฒ ๋ง๋๋์ง, ์ข์ ์ฑ๋ฅ์ ๋ณด์ด๋์ง ํ์ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
Counter 1๊ณผ Counter 2 ๋ ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ์ต๋๋ค. ๊ฐ ์ปดํฌ๋ํธ๋ฅผ Profiler ์ปดํฌ๋ํธ๋ก ๊ฐ์ธ๊ณ "Counter1" "Counter2" ์์ด๋๋ฅผ ์ฃผ์์ต๋๋ค. DOM์์ ๊ฐ ์ปดํฌ๋ํธ์ time metric๋ฅผ ๋ณด์ด๊ฒ๋ ํ์ผ๋ ๊ฐ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธํ๊ฑฐ๋ ์ ๋ฐ์ดํธ๋ ๋ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ๋ณด์ค ์ ์์ต๋๋ค. ํ๋ฒ ์๋ํด๋ณด์ธ์ ๐
โReact Developer toolsโ๋ ๋ฆฌ์กํธ ํ์์ ๊ฐ๋ฐํ ๊ฐ๋ฐ์ ๋๊ตฌ์ ์ต์คํ ์ ์ ๋๋ค. ์ฌ์ค ์๊ฐํ ํ์๋ ์๊ธฐ๋ ํ์ง๋ง ์ฌ๋ฌ๋ถ๋ค์ด ์ฃผ๋ชฉํ์ผ๋ฉด ํ๋ ํ ๊ฐ์ง ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ๋ฐ๋ก "Highlight Updates"์ ๋๋ค. ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋์ง ์ถ์ ํ ์ ์๋ ์์ฃผ ์ข์ ๊ธฐ๋ฅ์ ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง ๋ ๋๋ง๋ค ํด๋น ์ปดํฌ๋ํธ์ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์์์ผ๋ก ๊ฐ์กฐํด์ค๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ์๋ค.
Main์ด ๋ฆฌ๋ ๋๋๋ค๋ฉด, Counter์ Count ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ๊ณ ์๋ ๋ฐ์ด๋๋ฆฌ๊ฐ ์ ๊น ์์์ผ๋ก ๊ฐ์กฐ๋ ๊ฒ์ ๋๋ค.
์ด ๊ธฐ๋ฅ์ ํ์ฑํํ๋ ค๋ฉด ์ฌ๋ฌ๋ถ์ ๊ด๋ฆฌ์ ๋๊ตฌ์์ "React" ํญ์ ํด๋ฆญํ์ธ์. ์ฐ์ธก ์๋จ์ ์๋ ์ค์ ์์ด์ฝ์ ๋๋ฅด๋ฉด ํ์
์ฐฝ์ด ๋น๋๋ค.
"Highlight Updates" ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํ์ธ์.
์ปฌ๋ฌ ๋ฐด๋์ ์ ํ์ ์ผ๋ง๋ ์์ฃผ/๋น๋ฒํ๊ฒ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋๋์ง์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.
| green - ๋น๋๊ฐ ๋ฎ์
| blue - ๋น๋๊ฐ ํ๊ท
v red - ๋น๋๊ฐ ๋์
์ด ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์์์ผ๋ก ์ด๋ค ์ปดํฌ๋ํธ๊ฐ ๋น๋ฒํ๊ฒ ์ ๋ฐ์ดํธ ๋๋์ง ๋น ๋ฅด๊ฒ ์๋ณํ ์ ์๊ณ ์ ์ ํ ์ต์ ํ๋ฅผ ์ทจํ ์ ์์ต๋๋ค.
Bit์ ์ปดํฌ๋ํธ ๊ณต์ , ์กฐ์ง, ์ฌ์ฌ์ฉ์ ํ๋ ๋ฐ ์์ฃผ ์ข์ ํด์ ๋๋ค. ์ ๋ ๋ฏธ๋์์์ ์ฌ์ฌ์ฉ์ ์ํด ํ๊ณผ ํจ๊ป ์ฑ๋ฅ ์ต์ ํ๋ ์ปดํฌ๋ํธ๋ฅผ ๊ณต์ ์ปฌ๋ ์ ์ ํผ๋ธ๋ฆฌ์ฑํ๊ณ ์์ฑํ๊ณ ์ ์ฌ์ฉํฉ๋๋ค. ์ฝ๋ ์ฌ์ฌ์ฉ์ ๊ทน๋ํํจ์ ๋ฐ๋ผ ์ข์ ํ๋ํฐ์ค์ ๋น ๋ฅธ ๊ฐ๋ฐ์ ํ๋๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ฑ๋ฅ ์ต์ ํ ๊ด์ ์์ ๋ ๋ค๋ฅธ ์ค์ํ ๊ฒ์ ์ฌ๋ฌ๋ถ์ด ํ์ํ ๊ฒ๋ง ๋น ๋ฅด๊ณ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ์ ์ฒด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋ผ ํ๋์ ์ปดํฌ๋ํธ๋ง ํ์ํ ๊ฒ์ด์ฃ . ํนํ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ ์์ฃผ ์ค์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ฌ๋ฌ๋ถ์ด ์ ๋ช
ํ Material-UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด ์ ์ฒด๋ฅผ ์ค์นํด์ผ ํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ bit.dev์ ์ปดํฌ๋ํธ๋ฅผ ๊ณต์ ํ๋ค๋ฉด ์ฌ๋ฌ๋ถ์ ์ฑ์์ ์ด๋ค ๋
๋ฆฝ์ ์ธ ์ปดํฌ๋ํธ๋ง ์ ํํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ฃผ ๊ฐ๋จํ to-do app์ผ๋ก๋ถํฐ ์ปดํฌ๋ํธ๋ฅผ ๊ณต์ ํ๋ ์งง์ ์์ ๋ฅผ ๋ณด์ฌ๋๋ฆด๊ฒ์.
๋จผ์ , Bit.dev์ ์ปดํฌ๋ํธ ์ปฌ๋ ์
์ ์์ฑํ์ธ์.
๊ทธ๋ฆฌ๊ณ Bit์ CLI ํด์ ์ ์ญ์ผ๋ก ์ค์นํ๊ณ ๋ก๊ทธ์ธ ํ์ธ์.
$ yarn global add bit-bin
$ bit login
๊ทธ ํ ์ฌ๋ฌ๋ถ์ ํ๋ก์ ํธ์์ ๊ณต์ ๋ฅผ ์์ํ์ธ์.
// Initialize a workspace in your projectโs directory
$ bit init --package-manager yarn
// Add components to track
$ bit add src/components/*
// Configure a compiler to make the usable in other build setups
// I use here the React with TypeScipt compiler
$ bit import bit.envs/compilers/react-typescript --compiler
// Tag your added components (this will also build and test them)
$ bit tag --all 1.0.0
// Export them to your component collection at bit.dev
$ bit export <user-name>.<collection-name>
์ด ์ฑ์ ๋ชจ๋ ์ปดํฌ๋ํธ์ ๊ณต์ ๋ ์ปฌ๋ ์ ์ธ ์ต์ข ๊ฒฐ๊ณผ์ ๋๋ค.
Welldone software์์ ๋ง๋ ์ด ๋๊ตฌ๋ ๋ญ๋น๋๋ ๋ฆฌ๋ ๋์ ๋ํ ํผ๋๋ฐฑ์ ์ค๋๋ค.
์ปดํฌ๋ํธ์ prop์์ ์ฐจ์ด๋ฅผ ํ์ธํ๊ณ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋์๋๋ฐ props๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒฝ์ฐ๋ผ๋ฉด ์ฝ์๋ก ์๋ ค์ค๋๋ค.
์ค๋ณต๋๋ ๋ฆฌ๋ ๋๋ง์ ์์ ์ฑ์์๋ ๋ฐ๊ฒฌ๋ ์ ์์์ง๋ผ๋ ํฐ ์ค์ผ์ผ์ผ ๋๋ ์์ฃผ ๋ถ๋ช
ํ๊ฒ ๋๊ปด์ง๋๋ค.
์ด ๋๊ตฌ๋ ์ค์ ๋ก ๋ฆฌ์กํธ์ ์ฐ๊ฒฐ๋์ด ์ปดํฌ๋ํธ์ ๋ผ์ดํ์ฌ์ดํด์ ๋ฐ๋ฅด๋ฏ๋ก ๋ฆฌ๋ ๋๋ง๋ ๋ ์ปดํฌ๋ํธ prop์ ์ฐจ์ด๋ฅผ ์ํํ ์ ์์ต๋๋ค.
์ฌ์ฉํ๊ธฐ ๊ฝค ์ฝ์ต๋๋ค. ์ฒ์์๋ npm install @welldone-software/why-did-you-render --save
๋ฅผ ํตํด ๋๊ตฌ๋ฅผ ์ค์นํฉ๋๋ค.
๊ทธ ๋ค์์ ์๋์ฒ๋ผ ํด๋์ค ์ปดํฌ๋ํธ์์ whyDidYouRender
ํ๋กํผํฐ๋ฅผ ์ ์ ์ผ๋ก ์ง์ ์ค์ ํฉ๋๋ค.
class Counter extends React.Component {
static whyDidYouRender = true;
render() {
//...
}
}
ํจ์ํ ์ปดํฌ๋ํธ์์๋ ์๋์ฒ๋ผ ์์ฑํฉ๋๋ค.
function Counter() {
return(
// ...
)
}
Counter.whyDidYouRender = true;
์ด ๋๊ตฌ๋ ํฌ๋กฌ ๊ฐ๋ฐ์๋๊ตฌ์ ๋ด์ฅ๋์ด ์์ต๋๋ค. Performance ํญ์์ ์ฐพ์ผ์ค ์ ์์ฃ .
๋์ฐํ๊ฒ ๋ฆฌ๋ ๋๋ง๋๋ ์ปดํฌ๋ํธ๋ฅผ ์๊ฐ์ ์ผ๋ก ์๋ณํ ๋ ํนํ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ถํ์ํ๊ฒ ์
๋ฐ์ดํธ ๋๋ UI์ ์ผ๋ง๋ ์์ฃผ ์ผ์ด๋๋์ง๋ฅผ ์๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
ํด์ ์ฌ์ฉํ๊ธฐ ์ํด ๋จผ์ development ๋ชจ๋๋ก ๋ฆฌ์กํธ ์ฑ์ ์คํํฉ๋๋ค.
localhost:3000
๋ก ์ฌ๋ฌ๋ถ์ ๋ธ๋ผ์ฐ์ ์ ์ฑ์ ๋ก๋ํฉ๋๋ค.
๊ด๋ฆฌ์ ๋๊ตฌ๋ฅผ ์ด์ด "Performance" ํญ์ ํด๋ฆญํ์ธ์. ์๋ฌด๊ฒ๋ ์๋ค๋ฉด "Timeline"์ ํด๋ฆญํ์ธ์. "Performance"์ ๋์ผํฉ๋๋ค.
์ด์ "Record" ๋ฒํผ์ ํด๋ฆญํ๊ฑฐ๋ "Ctrl + E"๋ฅผ ๋๋ฅด๋ฉด ๊ด๋ฆฌ์๋๊ตฌ๊ฐ ๊ธฐ๋ก์ ์์ํฉ๋๋ค.
์ฌ๋ฌ๋ถ์ด ๊ฒ์ฌํ๊ณ ์ถ์ ๋ฐฉ๋ฒ์ผ๋ก ์ฑ์ ์ฌ์ฉํ์ธ์.
20์ด๋ฅผ ๊ธฐ๋กํ๋ ๊ฒ์ ๊ถ์ฅํ๋๋ฐ 20์ด๋ฅผ ๋์ด ๊ธฐ๋กํ๋ฉด ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ์ ๋ถ๋ด์ด ๊ฐ๊ฒ ๋ ๊ฒ๋๋ค.
๋ค ๋์ผ๋ฉด "Stop" ๋ฒํผ์ ๋๋ฌ์ฃผ์ธ์.
ํญ์ด ํ์๋ผ์ธ์ ๋ก๋ํ ๊ฒ์ ๋๋ค.
๋๋๊ทธ๋ฅผ ํตํด ์ค๋ฒ๋ทฐ์์ ๊ด์ฌ์๋ ์์ญ์ ์ ํํ ์ ์์ต๋๋ค. ๋ง์ฐ์ค ํ ๊ณผ WASD ํค๋ฅผ ์ด์ฉํด ํ๋์ถ์, ์ํ์ข์ฐ ์ด๋์ด ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๊ธฐ ๋ฐ๋ชจ๋ก ์์ฑํ Counter ์ฑ์ ์ฌ์ฉํ์ต๋๋ค.
class Counter1 extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
render() {
return (
<div className="counter">
<div>
Count: {this.state.count}
</div>
<div>
<button onClick={() => {this.setState({count: this.state.count + 1})}}>Incr</button>
<button onClick={() => {this.setState({count: this.state.count - 1})}}>Decr</button>
</div>
</div>
)
}
}
class App extends React.Component {
render() {
return (
<Counter1 />
)
}
}
์ฑ์ด ๋ก๋๋ ๋๋ถํฐ Incr
Decr
๋ฒํผ์ ๋ ๋ฒ ๋๋ ์ ๋ ์ฑ์ ํ์ด๋ฐ์ ๊ธฐ๋กํ๊ณ ์ ํ์ต๋๋ค.
Record
๋ฒํผ์ ๋๋ฅด๊ณ ์ฑ์ ๋ก๋ํด์ ๊ฐ ๋ฒํผ์ ํ๋ฒ ๋๋ ์ต๋๋ค.
ํ์๋ผ์ธ ๋ ํฌํธ ๊ฒฐ๊ณผ์ ๋๋ค.
W ํค๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ ์ถ์๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
๊ฐ ์ค๋์ง ์์์ ๋ฐ๋ ์ปดํฌ๋ํธ ํ๋ก์ธ์ค๋ฅผ ๋ํ๋
๋๋ค. ๊ฐ ๋ฐ ๋ด์ ๋์ด๋ ์ปดํฌ๋ํธ ์ด๋ฆ๊ณผ ๋ฐ์ํ ๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋ ๋ํ ์ฐพ์ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ์ ์บก์ณ์์ App์ Counter1์ [mount]๋ฅผ ๊ฐ๊ณ ์๋๋ฐ ์ด๋ DOM์ ๋ง์ดํธ๋ ์ฒ์์ ๋ํ๋ด๊ณ ์ผ๋ง๋ ๊ฑธ๋ ธ๋์ง๋ ๋ณด์ฌ์ค๋๋ค.
ํ์๋ผ์ธ์ ์ด๋ํ์ฌ Incr๊ณผ Decr ๋ฒํผ๋ค์ ๋๋ ์ ๋ Counter1์ด ์
๋ฐ์ดํธ๋๋ ํ์๋ผ์ธ์ ๋ณผ ์ ์์ต๋๋ค.
Incr ๋ฒํผ์ ๋๋ ์ ๋ ์
๋๋ค. Counter1์ด ๋ฆฌ๋ ๋๋ง ๋์์ ๋ ๋์ํ๊ธฐ ๋๋ฌธ์ [update] ํ
์คํธ๊ฐ ์์ต๋๋ค.
Counter1 ์ปดํฌ๋ํธ๊ฐ ์
๋ฐ์ดํธ๋๋ ๋ฐ 24.00ms๊ฐ ๊ฑธ๋ ธ์ต๋๋ค.
Decr ๋ฒํผ์ ๋๋ฌ Counter1 ์ปดํฌ๋ํธ๊ฐ ์
๋ฐ์ดํธ๋ ์ํฉ์
๋๋ค.
์ปดํฌ๋ํธ๊ฐ ๋ ๋๋๋ ๊ฐ ์์ ์ ๊ทธ๋ํ์ ์๋ก์ด ํ์ด ์ถ๊ฐ๋ฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ฌ๋ฒ ๋ฆฌ๋ ๋๋ง ๋๋ ์ํฉ์์ ์ด ๊ทธ๋ํ๋ฅผ ์ฌ์ฉํ๋ฉด ์ํฉ์ ์ง๋จํ๋ ๊ฒ์ด ๋์ฑ ์ฌ์์ง๋๋ค. ๋ํ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ ๋ ํ์ํ ์๊ฐ์ ์ถ์ ํ ์๋ ์์ต๋๋ค. ํ์ด ๊ธธ์๋ก, ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋๋ ๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ๋ ๊ธด ๊ฒ์
๋๋ค. ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์
์ ๋ค์ํ ํ์ด์ง๋ค์ ์ง๋จํ๋ ๋ฐ ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ณ ๋ฌธ์ ๊ฐ ๋๋ ๊ฒ์ด ์๋์ง ํ์ธํด๋ณด์ธ์.
์๋ฌธ : https://blog.devgenius.io/how-javascript-works-behind-the-scenes-88c546173f32
๋ถ์ : An overview walk-through of all the core components that are involved in the execution of JavaScript code.
์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์ ์ ์ธ๊ธฐ๋ฅผ ๋ ๋๊ฒ ๋๋ฉด์ ์ฌ๋ฌ ํ๋ค์ ๋ค์ํ ์์ค์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ๊ณ ์์ต๋๋ค. ํ๋ก ํธ์๋, ๋ฐฑ์๋, ํ์ด๋ธ๋ฆฌ๋ ์ฑ, ์๋ฒ ๋๋ ๋๋ฐ์ด์ค ๋ฑ์์ ๋ง์ด์ฃ . ์ด ์ํฐํด์ ์๋ฐ์คํฌ๋ฆฝํธ์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์ค์ ๋ก ๋์ํ๋ ๋ฐฉ์์ ๋ํด ํ๋ณด๋ ๊ฒ์ ๋ชฉํ๋ก ํ๊ณ ์์ต๋๋ค.
์๋ง ๋๋ถ๋ถ์ V8 ์์ง์ ๊ฐ๋ ์ ๋ค์ด๋ดค์ ๊ฒ์ด๋ฉฐ, ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋จ์ผ ์ค๋ ๋์ด๊ฑฐ๋ ์ฝ๋ฐฑ ํ๋ฅผ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ์๊ณ ์์ ๊ฒ์ ๋๋ค. ์ด ๊ธ์์๋ ์ด๋ฌํ ๊ฐ๋ ๋ค์ ์์ธํ๊ฒ ์ดํด๋ณด๊ณ ์ค์ ๋ก ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํ๊ณ ์ ํฉ๋๋ค. ์ด๋ฌํ ์ธ๋ถ์ฌํญ๋ค์ ์๊ฒ ๋๋ค๋ฉด, ์ ๊ณต๋๋ API๋ฅผ ์ ์ ํ๊ฒ ํ์ฉํจ์ผ๋ก์จ ์ฐจ๋จ๋์ง ์๋ ์ฑ์ ์ ์์ฑํ ์ ์๊ฒ ๋ ๊ฒ๋๋ค.
์ฌ๋ฌ๋ถ์ด ๋น๊ต์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฒ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ผ๋ฉด, ์ด ํฌ์คํธ๋ ์ ๋ค๋ฅธ ์ธ์ด๋ค์ ๋นํด ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ "์ด์ํ" ์ธ์ด๋ผ๊ณ ๋ถ๋ฆฌ๋์ง ์ดํดํ๋ ๋ฐ ๋์์ด ๋๋ฆฌ๋ผ ์๊ฐํฉ๋๋ค. ๋ํ ์ฌ๋ฌ๋ถ์ด ๊ฒฝํ์ด ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ๋ฐ์๋ผ๋ฉด ์ฌ๋ฌ๋ถ์ด ๋งค์ผ ์ฌ์ฉํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์์ด ์ค์ ๋ก ๋์ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ ์ ํ ์ธ์ฌ์ดํธ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
์ด ์ํฐํด์์ ๋ฐํ์ ํ๊ฒฝ๊ณผ ๋ธ๋ผ์ฐ์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ๋ด๋ถ์ ์ผ๋ก ๋์ํ๋ ๋ฐฉ์์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋ ์คํ์ ๊ด๋ จ๋ ๋ชจ๋ ํต์ฌ์ ์ธ ๊ตฌ์ฑ์์๋ค์ ๊ฐ์๊ฐ ๋ ๊ฒ์ด๋ฉฐ ์๋์ ์์๋ค์ ๋ํด ์์๋ณด๊ณ ์ ํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง๋ถํฐ ์์ํด๋ด ์๋ค.
์ด์ ์ ๋ค์ด๋ดค์ ์๋ ์์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ๋ ์ธํฐํ๋ฆฌํฐ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋๋ค. ์ด๋ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ ์ ์์ค ์ฝ๋๋ฅผ ๋ฐ์ด๋๋ฆฌ ์ฝ๋๋ก ์ปดํ์ผํ์ง ์๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ฌ๋ฌ๋ถ์ ์ปดํจํฐ๋ ์ผ๋ฐ์ ์ธ ํ ์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์ด๋ป๊ฒ ์ดํดํ ์ ์๋ ๊ฒ์ผ๊น์?
๊ทธ๊ฒ์ด ๋ฐ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ํ๋ ์ผ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์คํํ๋ ๋จ์ํ ์ปดํจํฐ ํ๋ก๊ทธ๋จ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ค๋๋ ๋ชจ๋ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์ ๋ด์ฅ๋์ด ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ๋ธ๋ผ์ฐ์ ์ ๋ก๋๋๋ฉด ์์ง์ ํ์ผ์ ์์์๋ถํฐ ์๋๋ก ํ์ค์ฉ ์คํํฉ๋๋ค. (๊ฐ๋จํ ์ค๋ช ํ๊ธฐ ์ํด ํธ์ด์คํ ์ ๋ํ ์ค๋ช ์ ์๋ตํ๊ฒ ์ต๋๋ค.) ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ์ฝ๋๋ฅผ ๋ผ์ธ๋ง๋ค ํ์ฑํ์ฌ ์ด๋ฅผ ๋จธ์ ์ฝ๋๋ก ๋ณํํ๊ณ ์คํํฉ๋๋ค.
๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ ๊ฐ์๋ง์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด ์๋๋ฐ ์ด ์ค ๊ฐ์ฅ ์ ์๋ ค์ง ์์ง์ ๊ตฌ๊ธ์ V8์ ๋๋ค. V8 ์์ง์ ๊ตฌ๊ธ ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ๋ฟ๋ง ์๋๋ค ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์์ธ Node.js์์๋ ์ฌ์ฉ๋ฉ๋๋ค.
์์ง์ ๋ ๊ฐ์ ํต์ฌ ์์๋ก ์ด๋ฃจ์ด์ง๋๋ค.
์ด๋ค ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ด๋ ์ฝ์คํ๊ณผ ํ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ฝ ์คํ์ ์ค์ ๋ก ์ฝ๋๊ฐ ์คํ๋๋ ๊ณณ์ ๋๋ค. ํ์ ๊ตฌ์กฐํ๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ํ๋ก ์ดํ๋ฆฌ์ผ์ด์ ์์ ํ์ํ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ ์ฅํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ ๋ํด ์์๋ณด์๋๋ฐ, ์ฌ์ค ์์ง์ ํผ์ ๋์ํ์ง ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์ ํ๊ฒฝ(JRE)์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ํ๊ฒฝ ๋ด์์ ๋ค๋ฅธ ๊ตฌ์ฑ์์๋ค๊ณผ ํจ๊ป ์คํ๋ฉ๋๋ค. JRE๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅด ๋น๋๊ธฐ์ ์ผ๋ก ๋ง๋๋ ์ญํ ์ ํฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ด ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํ๊ณ HTTP ์์ฒญ๋ค์ ๋น๋๊ธฐ์ ์ผ๋ก ํ ์ ์๋ ์ด์ ์ ๋๋ค.
JRE๋ ๋ค์ ๊ตฌ์ฑ์์๋ค๋ก ์ด๋ฃจ์ด์ง ํ๋์ ์ปจํ ์ด๋์ ๋๋ค.
๊ทธ๋ผ ์ด์ ์์ฃผ ์ธ๊ธฐ์๋ ์ด๋ฒคํธ ๋ฃจํ์ ์ฝ๋ฐฑ ํ๊ฐ ์์ต๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ๋ ์ฑ๊ธ ์ค๋ ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ธ๋ฐ ์ด๋ ํ๋์ ์ฝ ์คํ์ ๊ฐ์ง๋ค๋ ์๋ฏธ์ ๋๋ค. ๊ทธ๋์ ํ๋ฒ์ ํ ๊ฐ์ง๋ง ํ ์ ์์ต๋๋ค.
์ฝ ์คํ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก๊ทธ๋จ ๋ด ์์น๋ฅผ ์ ์ฅํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋๋ค. ํจ์ ๋ด๋ถ๋ก ๋ค์ด๊ฐ๊ฒ ๋๋ฉด ์คํ์ ํ์ ํจ์๋ฅผ ๋์ต๋๋ค. ํจ์๋ก๋ถํฐ ๋ฐํ๋ ๋ ์คํ์ ํ์์ ํจ์๋ฅผ ๊บผ๋ ๋๋ค. ์ด๊ฒ์ด ์คํ์ด ํ๋ ์ ๋ถ์ ๋๋ค.
์๋ ์ฝ๋ ์์ ๋ฅผ ๋ด ์๋ค.
function multiply(x, y) {
return x * y;
}function printSquare(x) {
var s = multiply(x, x);
console.log(s);
}printSquare(5);
์์ง์ด ์ด ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์์ํ ๋, ์ฝ ์คํ์ ๋น์ด์์ ๊ฒ๋๋ค. ๊ทธ๋ฌ๊ณ ๋์ ๋ค์๊ณผ ๊ฐ์ ๋จ๊ณ๋ก ์งํ๋ฉ๋๋ค.
์ฝ ์คํ์ ๊ฐ ์ํธ๋ฆฌ๋ ์คํ ํ๋ ์์ด๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค.
์ฑ๊ธ ์ค๋ ๋์์ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ์ ๋ฐ๋๋ฝ๊ณผ ๊ฐ์ด ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์ ๋ฐ์ํ ์ ์๋ ๋ณต์กํ ์๋๋ฆฌ์ค๋ฅผ ๋ค๋ฃฐ ํ์๊ฐ ์์ด ๊ฝค ์ฌ์ธ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฑ๊ธ ์ค๋ ๋์์ ์คํํ๋ ๊ฒ ๋ํ ์ ์ฝ์ด ์์ต๋๋ค. ๊ทธ๋์ ์๋ฐ์คํฌ๋ฆฝํธ๋ ํ๋์ ์ฝ ์คํ์ ๊ฐ์ง๋ ๊ฒ์ด์ฃ .
์ฝ ์คํ์์ ์ฒ๋ฆฌํ ๋ ๊ต์ฅํ ๋ง์ ์๊ฐ์ด ์์๋๋ ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํ ๊น์? ์๋ฅผ ๋ค์ด ๋ธ๋ผ์ฐ์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์์ฃผ ๋ณต์กํ ์ด๋ฏธ์ง ๋ณํ์ ํด์ผ ํ๋ค๊ณ ์๊ฐํด๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ ์ด๊ฒ ์ ๋ฌธ์ ์ธ์ง ์๋ฌธ์ด ๋ค ์ ์์ต๋๋ค. ๋ฌธ์ ๋ ์ฝ์คํ์ด ์คํํ ํจ์๋ค์ ๊ฐ์ง๊ณ ์๋ ๋์ ๋ธ๋ผ์ฐ์ ๋ ์๋ฌด๊ฒ๋ ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ฆ block๋์ด ์์ฃ . ์ด๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋ํ ์ ์๊ณ ๋ค๋ฅธ ์ฝ๋๋ฅผ ์คํํ ์๋ ์์ผ๋ฉฐ ๋งํ๋ฒ๋ฆฌ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ด ์ ๋์ ์ธ UI๋ฅผ ๊ทธ๋ฆฌ๊ณ ์ถ์ ๊ฒฝ์ฐ์ ๋ฌธ์ ๊ฐ ๋ฉ๋๋ค.
์ด๊ฒ๋ง์ด ๋ฌธ์ ๊ฐ ์๋๋๋ค. ์ผ๋จ ๋ธ๋ผ์ฐ์ ๊ฐ ์ฝ ์คํ์์ ๋ง์ ์์ ์ ์ฒ๋ฆฌํ๊ธฐ ์์ํ๋ ์๊ฐ ๊ฝค ์ค๋ซ๋์ ๋ฐ์ํ์ง ์์ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ๋ ์น ํ์ด์ง๋ฅผ ์ข ๋ฃํ ๊ฒ์ธ์ง์ ๋ํด ๋ฌป๋ ๋ฐฉ๋ฒ์ผ๋ก ์กฐ์น๋ฅผ ์ทจํ์ฃ . ๋์์ฑ๊ณผ ์ด๋ฒคํธ ๋ฃจํ์ ๋ํ ๋ ์์ธํ ๋ด์ฉ์ ์๋ ์ํฐํด์ ์ฐธ๊ณ ํ์ธ์.
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ ์งง๊ณ ๊ฐ๊ฒฐํ ๋ฌธ๋ฒ์ด ๋๋ฌ๋ด๋ ๊ฒ๋ณด๋ค ๋ ๋ง์ ๊ฒ๋ค์ ํฌํจํ๊ณ ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉํ๋ ๊ฒ์ ์ฝ๊ณ , ์ด๋ ต์ง ์๊ณ , ์ ์ฐํ๊ธฐ ๋๋ฌธ์ ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๊ฐ์ฒด์ ๋ ๋ง์ ๊ฒ์ด ์๋ค๋ ๊ฒ์ ์์ง ๋ชปํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ ๊ฐ๋ ค์ง ์ ๋ค์ ์ดํด๋ณด๊ณ ๋ณต์กํ ์ ์ ์ดํดํด๋ณผ ๊ฒ๋๋ค. ์ด ์ํฐํด์ ์ฝ๊ณ ๋๋ฉด ์ฌ๋ฌ๋ถ์ ๋ค์๊ณผ ๊ฐ์ ์ง๋ฌธ๋ค์ ๋ตํ ์ ์์ต๋๋ค.
for-in
๋ฌธ์ด๋ Object.keys
์ ๋ณด์ด์ง ์๋๊ฐ?obj.id = 5;
console.log(obj.id)
// => '101' ( 5 in binary )
์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ ๋ํ ๊ธฐ์ด๋ฅผ ๋จผ์ ๋ณด๊ณ ์ถ๋ค๋ฉด ์ ๊ฐ ์ด ๋ค๋ฅธ ์ํฐํด์ ์ฐธ๊ณ ํ์ธ์.
ํ : ์๋ฐ์คํฌ๋ฆฝํธ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ์ฌ์ฌ์ฉํ๋ ค๋ฉด Bit์ ์ฌ์ฉํ์ธ์. ์ด๋ ๋น ๋ฅด๊ฒ ๋น๋ํ๊ณ Lego์ฒ๋ผ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ฐ ์์ผ๋ก ๋ฌด์ํ ๋ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
const obj = {
name: 'Arfat',
id: 5
}
obj.name // => 'Arfat'
obj
๊ฐ์ฒด์์ name
๊ณผ id
ํ๋กํผํฐ๋ ๋ฐ์ดํฐ ํ๋กํผํฐ์
๋๋ค. ๋๋ถ๋ถ์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ด๋ฃจ๋ ํ๋ฒํ ํํ์ ํ๋กํผํฐ์
๋๋ค. ๊ทธ๋ ๋ค๋ฉด ๋ค๋ฅธ ํ๋กํผํฐ ํ์
์ ๋ฌด์์ผ๊น์?
C#์ด๋ ํ์ด์ฌ ๊ฐ์ ๋ค๋ฅธ ์ธ์ด๋ก ์น๋ฉด getter ์ setter ๋ก ์ดํดํ ์ ์๋๋ฐ์. ์ ๊ทผ์ ํ๋กํผํฐ๋ get
๊ณผ set
ํจ์, ๋ ๊ฐ์ง ํจ์์ ์กฐํฉ์
๋๋ค.
์ ํต์ ์ธ key: value
๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ ๋์ ์ ๋ค์์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
const accessorObj = {
get name() {
return 'Arfat';
}
};
accessorObj.name; // => 'Arfat'
const dataObj = {
name: 'Arfat',
};
dataObj.name; // => 'Arfat'
accessorObj
์ dataObj
๋ฅผ ๋ณด๋ฉฐ ๋น๊ตํด๋ณด์ธ์. ๋ ๊ฐ์ฒด๋ ๋์ผํ ๋์์ ํฉ๋๋ค. get
ํค์๋์ ํจ์๋ฅผ ์ ์ํ์์ต๋๋ค. ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฝ์ ๋๋ ํจ์๋ฅผ ํธ์ถํ๊ธฐ ์ํด ์๊ดํธ๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค. ์ฆ, accessorObj.name();
์ผ๋ก ์ฐ๋ฉด ํ๋ฆฐ ๊ฒ์
๋๋ค.
accessorObj.name
์ ์ฝ์ ๋ name
ํจ์๋ ์คํ๋์ด name
key์ ํด๋นํ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
key์ ํด๋นํ๋ ๊ฐ์ ๊ฐ์ ธ์ฌ ๋ ์ฌ์ฉํ์ฌ get ํจ์๋ getter๋ก ๋ถ๋ฆฝ๋๋ค. ๋ง์ฝ ์ฌ๋ฌ๋ถ์ด accessorObj.name = 'New Person';
๋ก ๊ฐ์ ์
๋ฐ์ดํธํ๋ฉด ์ค์ ๋ก ๊ฐฑ์ ์ด ์ผ์ด๋์ง ์์ต๋๋ค. name
ํค์ ํด๋นํ๋ setter ํจ์๊ฐ ์๊ธฐ ๋๋ฌธ์
๋๋ค. setter ํจ์๋ getter ํ๋กํผํฐ์ ๊ฐ๋ค์ ์ค์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
const accessorObj = {
_name: 'Arfat',
get name() {
return this._name;
},
set name(value) {
this._name = value;
}
};
setter ํจ์๋ ํ๋ผ๋ฏธํฐ๋ก ํ ๋น๋ ๊ฐ์ ๋ฐ์ต๋๋ค. ํ๋กํผํฐ์ ๊ฐ์ ์ ์ฅํ๊ฑฐ๋ ์ ์ญ๋ณ์๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์์๋ ์ ํต์ ์ธ "private" ํ๋กํผํฐ์ธ _name
์ ๋ง๋ค๊ณ ํด๋น ๊ฐ์ name ๊ฐ์ ์ ์ฅํฉ๋๋ค.
getter ํจ์์์๋ ํด๋น ๊ฐ์ ๋ฐํํ๊ธฐ ์ ์ ํ๋กํผํฐ๋ฅผ ์์ ํ๊ฑฐ๋ ์ค๋ฒ๋ผ์ด๋ฉ ํ ์ ์์ต๋๋ค. ๋ค์ ์์ ๊ฐ ์ด๋ฅผ ์ค๋ช ํด์ค๋๋ค. ๋ํ ์ ์ง๋ฌธ๋ค์ ๋ํ ๋ต์ ํ๋ ํด์ค๋๋ค.
const obj = {
get name() {
return this._name.toUpperCase();
},
set name(value) {
this._name = value;
},
get id() {
return this._id.toString(2); // Returns binary of a number
},
set id(value) {
this._id = value;
}
}
obj.name = 'Arfat';
obj.name;
// => 'ARFAT'
obj.id = 5;
obj.id;
// => '101
ํ๋ฒํ ๋ฐ์ดํฐ ํ๋กํผํฐ๊ฐ ์๋๋ฐ๋ ์ ์ ๊ทผ์ ํ๋กํผํฐ๋ฅผ ์ฌ์ฉํด์ผ ํ ๊น์? ํ๋กํผํฐ ์ ๊ทผ์ ๊ธฐ๋กํ๊ฑฐ๋ ํ๋กํผํฐ๊ฐ ๊ฐ์ง ๊ฐ๋ค์ ๋ํ ๊ธฐ๋ก์ ์ ์งํด์ผ ํ๋ ๊ฒฝ์ฐ๋ค์ด ๊ฝค ์กด์ฌํฉ๋๋ค. ์ ๊ทผ์ ํ๋กํผํฐ๋ ๊ฐ์ฒด ํ๋กํผํฐ์ ์ฌ์ฉ์ ์ฝ๊ฒ ํ ์ ์๋ ํจ์์ ํ์ ์ ๊ณตํฉ๋๋ค. ์ ๊ทผ์ ์ฌ์ฉ์ ๋ํด ๋ ์์๋ณด์๋ ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฝ์ด๋ณด์ธ์.
์ด๋ป๊ฒ ์๋ฐ์คํฌ๋ฆฝํธ๋ ํ๋กํผํฐ๊ฐ ์ ๊ทผ์ ํ๋กํผํฐ์ธ์ง ๋ฐ์ดํฐ ํ๋กํผํฐ์ธ์ง ์ ์ ์์๊น์? ์์๋ด ์๋ค.
์ธ๋ป ๋ณด๊ธฐ์๋ ๊ฐ์ฒด์ ํค์ ๊ฐ ๊ฐ์ 1:1 ๋งคํ์ด ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์์ง๋ง ์ ํ ์ฌ์ค์ด ์๋๋๋ค.
๊ฐ์ฒด์ ๋ชจ๋ ํค๋ ํค์ ๊ด๋ จ๋ ๊ฐ์ ํน์ฑ์ ์ ์ํ๋ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ์ ์งํฉ์ ํฌํจํฉ๋๋ค. key-value ์์ ์ค๋ช ํ๋ _๋ฉํ ๋ฐ์ดํฐ_๋ก ์๊ฐํ ์ ์๋ ๊ฒ์ด์ฃ . ์งง๊ฒ ๋งํ๋ฉด, ์ดํธ๋ฆฌ๋ทฐํธ๋ ๊ฐ์ฒด ํ๋กํผํฐ์ ์ํ๋ฅผ ์ ์ํ๊ณ ์ค๋ช ํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ ์งํฉ์ ํ๋กํผํฐ ๋์คํฌ๋ฆฝํฐ๋ก ๋ถ๋ฆฝ๋๋ค.
๋์คํฌ๋ฆฝํฐ์๋ 6๊ฐ์ง์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๊ฐ ์์ต๋๋ค.
์ ์ดํธ๋ฆฌ๋ทฐํธ ์ด๋ฆ์ด [[]]๋ก ๊ฐ์ธ์ ธ ์์๊น์? ๋ ๊ฐ์ ๋๊ดํธ๋ ECMA ์คํ์ ๋ฐ๋ผ **๋ด๋ถ ํ๋กํผํฐ(internal properties)**๋ฅผ ์๋ฏธํฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ฝ๋ ๋ด์์ ์ง์ ์ ์ผ๋ก ๊ฑด๋๋ฆด ์ ์๋ ํ๋กํผํฐ์ธ ๊ฒ์ด์ฃ . ๋ด๋ถ ํ๋กํผํฐ๋ฅผ ์กฐ์ํ๊ธฐ ์ํด์๋ ์ธ์ด๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋๊ฐ ํ์ํฉ๋๋ค.
์์ ๋ฅผ ๋ด ์๋ค.
์ ์ด๋ฏธ์ง์์ ๊ฐ์ฒด๋ x
, y
2๊ฐ์ ํค๋ฅผ ๊ฐ์ง๋๋ค. ๊ฐ ํ๋กํผํฐ์ ๋ฐ๋ ์ดํธ๋ฆฌ๋ทฐํธ ๋ชฉ๋ก์ ๋ณผ ์ ์์ฃ .
์๋ฐ์คํฌ๋ฆฝํธ์์ ์ด๋ป๊ฒ ๋์ผํ ์ ๋ณด๋ฅผ ์ป์ ์ ์์๊น์? Object.getOwnPropertyDescriptor
ํจ์๋ฅผ ์ฌ์ฉํด์ ๊ทธ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๊ฐ์ฒด์ ํ๋กํผํฐ ์ด๋ฆ์ ๋ฐ์์ ํ์ํ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ฌ๊ธฐ ์ฝ๋ ์ํ์ด ์์ต๋๋ค.
const object = {
x: 5,
y: 6
};
Object.getOwnPropertyDescriptor(object, 'x');
/*
{
value: 5,
writable: true,
enumerable: true,
configurable: true
}
*/
์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ดํด๋ณด๊ณ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ์์๋ด ์๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์ ์ด ์ด๋ฏธ์ง๋ก ์ค๊ฒ ์ต๋๋ค.
ํ๋กํผํฐ์ ์ ๊ทผํ์ ๋ ๋ฐํ๋๋ value๋ฅผ ์ ์ฅํฉ๋๋ค. ์ ์์์ object.x
๋ก ๊ฐ์ ๊ฐ์ ธ์ค๋ ค ํ ๋ ์ฌ์ค์ [[Value]] ์ดํธ๋ฆฌ๋ทฐํธ์์ ๊ฐ์ ธ์ค๋ ๊ฒ์ด์ฃ . ๋ฐ์ดํฐ ํ๋กํผํฐ์์ .
์ผ๋ก ์ ๊ทผํ๊ฑฐ๋ []
์ผ๋ก ์ ๊ทผํ๋ ๊ฒ๋ ์ด๋ฐ ์์ผ๋ก ์๋ํฉ๋๋ค.
getter ํ๋กํผํฐ๋ฅผ ์์ฑํ ๋ ์ ์ธํ๋ ํจ์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์ฅํฉ๋๋ค. ํ๋กํผํฐ์ ๋ํด ์ ๊ทผํ ๋๋ง๋ค ํ๋กํผํฐ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ ์ํด ๋น ์ธ์ ๋ฆฌ์คํธ์ ํจ๊ป ํธ์ถ๋ฉ๋๋ค.
setter ํ๋กํผํฐ๋ฅผ ์์ฑํ ๋ ์ ์ธํ ํจ์์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์ฅํฉ๋๋ค. ํ๋กํผํฐ์ ๋ํด ์ ๊ทผํ ๋๋ง๋ค ํ ๋น๋ ๊ฐ์ ํฌํจํ ์ธ์ ๋ชฉ๋ก์ ์ ์ผํ ์ธ์๋ก ํจ๊ป ํธ์ถ๋ฉ๋๋ค.
set x(val) {
console.log(val) // => 23
}
}
obj.x = 23;
์ ์์์ ํ ๋น๋ฌธ์ ์ค๋ฅธ์ชฝ์ ๊ฐ์ setter ํจ์์ var
์ธ์๋ก ์ ๋ฌ๋ฉ๋๋ค. ์ฆ๊ฑฐ๋ก ์ด ์ฝ๋๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ด ๊ฐ์ boolean ํ์ ์ ๋๋ค. ๊ฐ์ ๋ฎ์ด์ธ ์ ์๋์ง ์๋์ง์ ๋ํ ๊ฐ์ด์ฃ . false์ธ ๊ฒฝ์ฐ์๋ ํ๋กํผํฐ์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
์ด ๊ฐ๋ boolean ํ์
์
๋๋ค. ์ด ์ดํธ๋ฆฌ๋ทฐํธ๋ for-in
๋ฃจํ์์ ๋ณด์ด๋์ง ์๋์ง๋ฅผ ์๋ ค์ค๋๋ค. ๋ง์ฝ true๋ผ๋ฉด for-in
๋ฃจํ๋ฌธ์์ ์ด ํ๋กํผํฐ๋ฅผ ๋ฐ๋ณตํ ์ ์์ต๋๋ค.
์ด ๊ฐ ์ญ์ boolean์ ๋๋ค.
์ด ๊ฐ์ด false๋ผ๋ฉด
enumerable
configurable
get
set
๋ชจ๋ ๊ณ ์ ๋ ์ํ์
๋๋ค.์ด ํ๋กํผํฐ์ ์ํฅ์ ํ๋กํผํฐ ํ์ ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ์์ ์ค๋ช ํ ํน์ง๊ณผ ๋ณ๋๋ก ๋ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ด ์์ต๋๋ค.
writable
์ true
์์ false
๋ก๋ง ์ค์ ํ ์ ์์ต๋๋ค.writable
์ด false๊ฐ ๋๊ธฐ ์ ์, [[Value]] ์ดํธ๋ฆฌ๋ทฐํธ์ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ๋ฒ writable
์ด false๊ฐ ๋๋ฉด configurable
๋ํ false๊ฐ ๋ฉ๋๋ค. ํ๋กํผํฐ๊ฐ ์ธ ์ ์๊ณ ์ญ์ ํ ์ ์๊ณ ๋ณ๊ฒฝ ๋ถ๊ฐ๋ฅํ๊ฒ ๋๋ ๊ฒ๋๋ค.6๊ฐ์ง ์ดํธ๋ฆฌ๋ทฐํธ ํ๋กํผํฐ๊ฐ ๋ชจ๋ ํ๋กํผํฐ ํ์ ์ ์กด์ฌํ๋ ๊ฒ์ ์๋๋๋ค.
value
writable
enumerable
configurable
๊ฐ ์์ต๋๋ค.value
๋ writable
๋์ ์ get
set
์ด ์์ต๋๋ค.๋์คํฌ๋ฆฝํฐ์ ๋ํด ๋ฐฐ์ ๋๋ฐ ์ด์ ์ฐ๋ฆฌ์ ๊ฐ์ฒด์ ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ด๋ป๊ฒ ์ค์ ํ๊ณ ๋ณ๊ฒฝํ ๊น์? ์๋ฐ์คํฌ๋ฆฝํธ์๋ ์ด ๋์คํฌ๋ฆฝํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ฌ๋ฌ ํจ์๋ค์ด ์์ต๋๋ค. ์ดํด๋ด ์๋ค.
์์์ ๋ดค๋ ํจ์์
๋๋ค. ๊ฐ์ฒด์ ํ๋กํผํฐ ์ด๋ฆ์ ๋ฐ์ ๋์คํฌ๋ฆฝํฐ๋ฅผ ํฌํจํ ๊ฐ์ฒด๋ undefined
๋ฅผ ๋ฐํํฉ๋๋ค.
Object
์ static ๋ฉ์๋๋ก ์ฃผ์ด์ง ๊ฐ์ฒด์ ๋ํด ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ ์ํ๊ฑฐ๋ ์์ ํฉ๋๋ค. ๊ฐ์ฒด, ํ๋กํผํฐ ์ด๋ฆ, ๋์คํฌ๋ฆฝํฐ ์ธ ๊ฐ์ง ์ธ์๋ฅผ ๋ฐ๊ณ ๋ณ๊ฒฝ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์์ ๋ฅผ ๋ด
์๋ค.
const obj = {};
Object.defineProperty(obj, 'id', {
value: 42
});
console.log(obj);
// => { }
console.log(obj.id);
// => 42
Object.defineProperty(obj, 'name', {
value: 'Arfat',
writable: false,
enumerable: true,
configurable: true
});
console.log(obj.name);
// => 'Arfat'
obj.name = 'Arfat Salman'
console.log(obj.name);
// => 'Arfat'
// (instead of 'Arfat Salman')
Object.defineProperty(obj, 'lastName', {
value: 'Salman',
enumerable: false,
});
console.log(Object.keys(obj));
// => [ 'name' ]
delete obj.id;
console.log(obj.id);
// => 42
Object.defineProperties(obj, {
property1: {
value: 42,
writable: true
},
property2: {}
});
console.log(obj.property1)
// => 42
๊ธธ์ด๋ณด์ด์ง๋ง ์ฌ์ค์ ๊ฐ๋จํฉ๋๋ค. ํ๋์ฉ ์ดํด๋ณผ๊น์.
obj
์ ํ๋กํผํฐ ์ด๋ฆ id
, [[Value]] ํ๋๋ฅผ ์๋ฏธํ๋ value
ํค์ 42 ๊ฐ์ ๊ฐ์ง๋ ๋์คํฌ๋ฆฝํฐ ์ธ ๊ฐ์ง ์ธ์๋ฅผ defineProperty
๋ก ์ ๋ฌํฉ๋๋ค.enumberable
์ด๋ configurable
๊ณผ ๊ฐ์ ํ๋กํผํฐ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์์ ํ์ง ๋ชปํ๋ค๋ฉด ๊ธฐ๋ณธ ๊ฐ์ผ๋ก false
๋ก ์ค์ ๋์ด ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ธ์. ์ด ๊ฒฝ์ฐ์๋ writable
, enumerable
, configurable
๋ชจ๋ false
๋ก ์ค์ ๋์ด ์๋ id
๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.obj
๋ฅผ ์ถ๋ ฅํ์ง๋ง id
ํ๋กํผํฐ๊ฐ ์ด๊ฑฐ ๋ถ๊ฐ๋ฅํ ์์ฑ์ด๋ฏ๋ก ์ถ๋ ฅ๋์ง ์์ต๋๋ค. ํ์ง๋ง 10๋ฒ์งธ ์ค์์ ๋ณด์ด๋ฏ์ด ํ๋กํผํฐ๋ ์กด์ฌํฉ๋๋ค.writable
์ false
๋ก ์ค์ ํฉ๋๋ค.name
ํ๋กํผํฐ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. 23๋ฒ์งธ ์ค์์ ๊ฐ์ ์์ ํ์ง๋ง non-writabilityํ๊ธฐ ๋๋ฌธ์ ์์ ํจ๊ณผ๊ฐ ์์ต๋๋ค. ๊ทธ๋์ ๊ธฐ์กด์ ๊ฐ์ด ๋ ๋ฒ ๋ณด์ด๋ ๊ฑฐ์ฃ .id
๋ฅผ ์ ๊ฑฐํ๋ ค ํ์ง๋ง configurable
์ด false
๋ก ๋์ด ์๊ธฐ ๋๋ฌธ์ 39๋ฒ์งธ ์ค์์ ๋ณด์ด๋ ๊ฒ์ฒ๋ผ ์ ๊ฑฐ๋์ง ์์์ต๋๋ค.defineProperty
์ ๋ฐฐ์น ๋ฒ์ ์ธ Object.defineProperties
๋ฅผ ์ฌ์ฉํฉ๋๋ค.Object.defineProperty
๋ ํ๋ฒ์ ํ๋์ ํ๋กํผํฐ๋ง ์ค์ ํฉ๋๋ค. ํ ๋ฒ์ ์ฌ๋ฌ ํ๋กํผํฐ๋ฅผ ์ค์ ํ๋ ค๋ฉด Object.defineProperties
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฌด๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ์ง ๋ชปํ๊ฒ ํ๊ณ ์ถ์ ๋๊ฐ ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ์ ์ฐ์ฑ ๋๋ถ์ ๊ฑด๋๋ฆฌ๋ ค๊ณ ํ์ง ์์์ง๋ง ์ค์๋ก ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ํ ๋นํ๊ธฐ๊ฐ ์ฝ์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ์ฒด๋ฅผ ๋ณดํธํ๋ ์ฃผ์ 3๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. 3๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์์๋ด ์๋ค.
Object.preventExtensions
๋ฉ์๋๋ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ๋ํ์ฌ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ๊ฐ์ฒด๋ฅผ ๋ฐ์ ํด๋น ๊ฐ์ฒด๊ฐ ํ์ฅ๋์ง ๋ชปํ๊ฒ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ํ๋กํผํฐ๋ฅผ ์ญ์ ํ๋ ๊ฒ์ ๊ฐ๋ฅํ๋ ์ฃผ์ํ์ธ์.
const obj = {
id: 42
};
Object.preventExtensions(obj);
obj.name = 'Arfat';
console.log(obj); // => { id: 42 }
Object.isExtensible
์ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๊ฐ ํ์ฅ ๋ถ๊ฐ๋ฅํ์ง ํ์ธํ ์ ์์ต๋๋ค. true
๋ฅผ ๋ฐํํ๋ค๋ฉด ํด๋น ๊ฐ์ฒด์ ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ ์ ์๋ ๊ฒ์ด์ฃ .
seal
๋ฉ์๋๋ ๊ฐ์ฒด๋ฅผ ๋ด์ธํฉ๋๋ค. ๋ด์ธํ๋ค๋ ๊ฒ์ -
Object.preventExtensions
์ ๊ฐ์ด ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ง์ต๋๋ค.const obj = {
id: 42
};
Object.seal(obj);
delete obj.id // (does not work)
obj.name = 'Arfat'; // (does not work)
console.log(obj); // => { id: 42 }
Object.isExtensible(obj); // => false
Object.isSealed(obj); //=> true
๊ฐ์ฒด๊ฐ ๋ด์ธ๋์๋์ง ํ์ธํ๋ ค๋ฉด Object.isSealed
๋ฅผ ์ฌ์ฉํ์ธ์.
freeze
๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ์ฒด๊ฐ ๊ฐ์ง ์ ์๋ ๊ฐ์ฅ ํฐ ๋ณดํธ๋ง์
๋๋ค.
Object.freeze
๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ๋ด์ธํฉ๋๋ค.const obj = {
id: 42
};
Object.freeze(obj);
delete obj.id // (does not work)
obj.name = 'Arfat'; // (does not work)
console.log(obj); // => { id: 42 }
Object.isExtensible(obj); // => false
Object.isSealed(obj); //=> true
Object.isFrozen(obj); // => true
Object.isFrozen
์ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๊ฐ ์ผ์๋์ง ํ์ธํ ์ ์์ต๋๋ค.
์ค์ํ ์ ์ ์ด ๋ฉ์๋๋ค์ ๊ฐ์ฒด์ ์ง์ ์ ์ธ ํ๋กํผํฐ๋ง ๋ค๋ฃฐ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ค์ฒฉ๋ ๊ฐ์ฒด์ ์ํฅ์ ์ค ์๋ ์์ต๋๋ค.
ํ ์ด๋ธ ํ๋ก ์ ๋ฆฌ๋ ๊ฒ์ ๋ณด์ญ์์ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ ๊ฐ์ฒด๋ ๊ต์ฅํ ํํ๊ฒ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด์ ์ง์ง ํ์ ์๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด ์ํฐํด์ด ํจ๊ณผ์ ์ผ๋ก ์ ์ ๋ฌ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋ํ ์ํฐํด ์ด๋ฐ์ ์๋ ์ง๋ฌธ๋ค์ ๋ํด ์ด์ ๋ต์ ํ์ค ์ ์๋ค๋ฉด ์ข๊ฒ ์ต๋๋ค. ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
super
in JavaScriptthis
. (Javascript) โ Jason Yutypeof
and instanceof
: simplifying dynamic type checks โ Dr. Axel RauschmayerPromise
101 โ Igor Irianto๋ถ์ : Get to know the benefits of using the BFF pattern in practice
์๋ฌธ : https://blog.bitsrc.io/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf
์ฌ๋ฌ๋ถ์ด ๋ง์ดํฌ๋ก์๋น์ค๋ฅผ ์ด์ฉํ ์ด์ปค๋จธ์ค ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ ๋ค๊ณ ์์ํด๋ณด์ธ์. ๊ณ ๊ฐ, ์ฃผ๋ฌธ, ๋ฌผ๊ฑด, ์ฅ๋ฐ๊ตฌ๋ ๋ฑ์ ๋ํ ๋ง์ดํฌ๋ก์๋น์ค๊ฐ ์์ ๊ฒ์ ๋๋ค. ๋ง์ดํฌ๋ก์๋น์ค๋ ํ๋ก ํธ์๋์์ ์ฌ์ฉํ๋ API๋ฅผ ๋ ธ์ถํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ๋ก ํธ์๋์ ๋ฐํ๋๋ ๋ฐ์ดํฐ๋ ํ๋ก ํธ์๋๊ฐ ์ ํํ ์ํ๋ ๋๋ก ํฌ๋งทํ ๋๊ฑฐ๋ ํํฐ๋ง ๋์ด ์์ง ์์ ๊ฒ๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ์ ํ๋ก ํธ์๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ํฌ๋งทํ ํ ์ ์๋ ๋ก์ง์ด ํ์ํฉ๋๋ค. ํ๋ก ํธ์๋์ ์ด๋ฐ ๋ก์ง์ด ๋ด๊ธฐ๋ฉด ๋ ๋ง์ ๋ธ๋ผ์ฐ์ ์์์ด ์๋ชจ๋ฉ๋๋ค.
์ด์ ๊ฐ์ ์ํฉ์์ ์ฐ๋ฆฌ๋ ํ๋ก ํธ์๋ ๋ก์ง์ ์ค๊ฐ ๋ ์ด์ด๋ก ์ฎ๊ธฐ๊ณ ์ ํ๋ ๋ชฉ์ ์ผ๋ก BFF๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ค๊ฐ ์ธต์ด BFF์ธ ๊ฒ์ด์ฃ . ํ๋ก ํธ์๋๊ฐ ํน์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ฉด BFF์์ API๋ฅผ ํธ์ถํฉ๋๋ค.
BFF๋ ์๋์ ๊ฐ์ ์ผ์ ํ ๊ฒ์ ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ํ๋ก ํธ์๋์๋ ๋ ์ ์ ๋ก์ง๋ง์ด ๋จ์ต๋๋ค. ๊ทธ๋์ BFF๋ ๋ฐ์ดํฐ๋ฅผ ํํํ๋ ๊ฒ์ ๋ฅ๋ฅ ์ ์ผ๋ก ํด์ฃผ๊ณ ํ๋ก ํธ์๋์ ์ด์ ์ ๋ง์ถ ์ธํฐํ์ด์ค ์ ๊ณต์์ ์ญํ ์ ํฉ๋๋ค.
๋ฐฑ์๋-ํ๋ก ํธ์๋ ๊ด๊ณ๋ ๋ ๋จ์ํ๊ฒ ํด์ฃผ๋ ๋ค๋ฅธ ์ข์ ๋ฐฉ๋ฒ์ ๊ทธ๋ค๋ผ๋ฆฌ ํ์ ์ ๊ณต์ ํ๋ ๊ฒ์ ๋๋ค. ๊ฒฐํฉ๋์ง ์์ ํ๋ก์ ํธ ์ฌ์ด์์ ํ์ (๋๋ ์ฝ๋ ์กฐ๊ฐ)์ ๊ณต์ ํ๊ธฐ ์ํด ์ด๋ป๊ฒ Bit์ ์ฌ์ฉํ๋์ง ์์๋ณด์ธ์.
์๋ ๋ค์ด์ด๊ทธ๋จ์ ๊ฐ ๋ง์ดํฌ๋ก์๋น์ค๊ฐ BFF๋ฅผ ํตํด ํ๋ก ํธ์๋์ ์ฐ๊ฒฐ๋๋ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ด๋ฏธ ์์์ ๋ดค๋ฏ์ด, BFF๋ ํ๋ก ํธ์๋์ ๋ง์ดํฌ๋ก์๋น์ค ์ฌ์ด์์ ๋จ์ํ ์ธํฐํ์ด์ค ์ญํ ์ ํฉ๋๋ค. ์ด์์ ์ผ๋ก, ํ๋ก ํธ์๋ ํ์ BFF๋ฅผ ๊ด๋ฆฌํ๋ ์ฑ ์์ ๊ฐ์ง๋๋ค.
ํ๋์ BFF๋ ํ๋์ UI์ ๋ํด๋ง ์ด์ ์ด ๋ง์ถฐ์ง๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ํ๋ก ํธ์๋๋ฅผ ๋จ์ํ๊ฒ ํ๊ณ ๋ฐฑ์๋๋ฅผ ํตํ ๋ฐ์ดํฐ์ ๋ํด ์ผ๊ด๋ ๋ทฐ๋ฅผ ๋ณผ ์ ์๊ฒ ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ค์ ์ง๋ฌธ์ด ๋์ค๊ฒ ์ฃ . ์ฌ๋ฌ UI์ ๋ํด ์ฌ๋ฌ BFF๋ฅผ ๊ฐ์ง ์ ์๋ ๊ฑธ๊น์? ์ด ์ง๋ฌธ์ ๋ํ ๋ต์ ์ด ์ํฐํด ๋ง์ง๋ง ์น์ ์์ ๋ตํด๋๋ฆฌ๊ณ ํฉ๋๋ค. ๊ณ์ ์ฝ์ด์ฃผ์ธ์. ๐
BFF๋ ํด๋ผ์ด์ธํธ์ ๋ค๋ฅธ ์ธ๋ถ API, ์๋น์ค ๋ฑ ์ฌ์ด์์ ํ๋์ ํ๋ก์ ์๋ฒ์ ์ญํ ์ ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์์ฒญ์ด ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ํตํด์ผ ํ๋ค๋ฉด ๋น์ฐํ ๋๊ธฐ์๊ฐ์ ์ฆ๊ฐ์ํฌ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ BFF์ ๋๊ธฐ์๊ฐ์ ํ๋ก ํธ์๋์ ์ต์ ํ๋์ง ์์ ์ฌ๋ฌ ์๋น์ค๋ฅผ ์ํด ๋ธ๋ผ์ฐ์ ์ ๋ง์ ์์์ ์๋นํด์ผ ํ๋ ๊ฒ์ ๋นํ๋ฉด ์ถฉ๋ถํ ๋ฌด์ํ ๋งํ ์ ๋์ ๋๋ค.
BFF๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ค๋ฅธ ๋ฐฑ์๋/๋ง์ดํฌ๋ก์๋น์ค์ ๋ํด ์ง๋ฅ์ ์ธ ๋ฐฐ์น ํธ์ถ์ ๊ฐ๋ฅํ๊ฒ ํ๊ณ ํ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณํํ์ฌ ๋ ํธ๋ฆฌํ ํํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
์ด๋ ํ ์ปค๋ฅ์ ์ ๋ง๋๋๋ฐ ์ ์ด๊ฐ ๊ฑธ๋ฆด ์ ์๋ 2G๋ 3G ๋คํธ์ํฌ์ ๋ชจ๋ฐ์ผ ํด๋ผ์ด์ธํธ๋ค์๊ฒ ๊ต์ฅํ ์ ์ฉํฉ๋๋ค.
๋ค๋ฅธ ํจํด๋ค๊ณผ ๊ฐ์ด, ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ์์ BFF๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ปจํ ์คํธ์ ์ฌ๋ฌ๋ถ์ด ๋ฐ๋ฅด๊ณ ์ ํ๋ ์ํคํ ์ฒ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ๋ฌ๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋จ์ํ ๋ชจ๋๋ฆฌํฑ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅธ๋ค๋ฉด BFF๋ ํ์ํ์ง ์์ต๋๋ค. ๊ฐ์น๊ฐ ๊ฑฐ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋ฌ๋ ๋ง์ดํฌ๋ก์๋น์ค์ ์์กดํ๊ณ ๋ง์ ์ธ๋ถ API๋ ๋ค๋ฅธ ์๋น์ค๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด, ๋ฐ์ดํฐ ํ๋ฆ์ ๊ฐ์ํํ๊ณ ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ง์ ํจ์จ์ฑ์ ์ ๊ณตํ๋ฏ๋ก BFF๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋๋ถ์ด, ์ดํ๋ฆฌ์ผ์ด์ ์ด ํน์ ํ๋ก ํธ์๋ ์ธํฐํ์ด์ค์ ๋ํด ์ต์ ํ๋ ๋ฐฑ์๋๋ฅผ ๊ฐ๋ฐํด์ผ ํ๊ฑฐ๋ ํด๋ผ์ด์ธํธ๊ฐ ๊ต์ฅํ ๋ง์ ์์ ์งํฉ ์ฐ์ฐ์ ์๊ตฌํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด BFF๋ ๊ฝค ์ ์ ํ ์ ํ์ง๊ฐ ๋ฉ๋๋ค.
๊ทธ๋ผ์! ๊ทธ๊ฒ์ด ๋ฐ๋ก BFF๋ฅผ ์ ํํ๋ ์ด์ ์ ๋๋ค. ์ ํต์ ์ธ ์ ๊ทผ๋ฐฉ์(BFF๊ฐ ์๋ ์ดํ๋ฆฌ์ผ์ด์ )์ ๋ชจ๋ ํด๋ผ์ด์ธํธ์ ๋ํด ๋จ ํ๋์ API ๊ฒ์ดํธ์จ์ด๋ง์ ๊ฐ์ง๋๋ค. ์๋ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ฃ .
๊ทธ๋ฌ๋ BFF๋ฅผ ๋ง๋๋ ๋ชฉ์ ์ ์ฌ๋ฌ๋ถ์ ํด๋ผ์ด์ธํธ์ ๋ ๋ง์ถฐ์ง ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ๋ชจ๋ฐ์ผ UI์ ์ํด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ฐจ์ด๊ฐ ์์ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์์ ๋ ๋์ ๋ฐ์ดํฐ ํํ๋ฐฉ์์ ์ํด ๋ ๊ฐ์ BFF๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ์ฌ๋ฌ BFF๋ฅผ ๊ฐ์ง๋ ์ดํ๋ฆฌ์ผ์ด์ ๋ค์ด์ด๊ทธ๋จ์ ์ดํด๋ด ์๋ค.
์ฌ๋ฌ๋ถ์ด ๋ณผ ์ ์๋ฏ์ด, ๊ฐ ํด๋ผ์ด์ธํธ๋ BFF๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ด๋ ์๋น์ค์ ๋ํ ์๋ต๊ฐ๋ค์ ์ต์ ํํฉ๋๋ค.
BFF์ ๋ํด ์์๋ณด๋ ๋์ ๋๋ผ์ด ๊ฒ๋ค์ด ๋ง์์ต๋๋ค. ๊ทธ๋ฌ๋ BFF๋ ๋ชจ๋ ์ํ์ ๋ฐฉ์งํ ์ ์์๊น์?
๋๋ต์ '์๋์ค'์
๋๋ค! ๋ชจ๋ ๋ค๋ฅธ ๊ธฐ์ ์ด๋ ํจํด๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก BFF๋ ์ํ์ด ์์ต๋๋ค. ์ํ๋ค์ ํผํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ ๋ชจ๋ฒ ์ฌ๋ก๋ค์ ๋ฐ๋ผ์ผ ํฉ๋๋ค.
BFF ํจํด์ ๊ฐ๋ฐ์ ๋์ธ ๋ฟ๋ง ์๋๋ผ UX๋ฅผ ๋งค์ฐ ํฅ์์ํต๋๋ค. ๊ทธ๋์ BFF๋ ํ๋ก ํธ์๋์ ์ง์คํ๋ฉฐ ๋ฐ์ดํฐ ์ต์ ํ์ ์ง๊ณ๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ์ด์ ์ BFF ํจํด์ ์ฌ์ฉํด๋ณธ ์ ์ด ์๋ค๋ฉด ์ง๊ธ์ด ์์ํ ๋์ ๋๋ค. ์ฌ๋ฌ๋ถ์ ๊ฒฝํ๊ณผ ์๊ฒฌ์ ๋์ค์ ์ ์๊ฒ ๊ณต์ ํด์ฃผ์ธ์. ๐
์๋ฌธ : JavaScript Design Patterns Part 1: The Factory Pattern์ ์ฝ๊ณ ๋ฒ์ญํ ๊ธ์ ๋๋ค.
์ต๊ทผ ์์ ํ ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด์, ๋์ฑ ์ ์ง๋ณด์ํ๊ธฐ๊ฐ ์ฉ์ดํ๊ณ ํ์ฅ์ฑ์ด ์ข์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด ๋์์ธ ํจํด์ ๋ํด ๊น๊ฒ ์์๋ณด๋ ์๊ฐ์ ๊ฐ์ก์ต๋๋ค. ๋์์ธ ํจํด์ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ค์ ์๊ฐ์ด๋ ํ ์คํธ ์๋ฃจ์ ์ ์ ์ฉํ๊ธฐ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ๊ทธ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ ์ ์์ฃ .
์ฐ๋ฆฌ๊ฐ ์์๋ณผ ๋๋ถ๋ถ์ ๋์์ธ ํจํด์์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์๊ณ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉฐ ์๋ฐ๋๋ ์ฌ๋ฌ ๋ณต์กํ ๊ฒ๋ค์ด๋ ๋ก์ง์ ์ถ์ํํ๋ฉด์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ช
ํํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ฏ๋ก ์์ creational ํจํด๋ถํฐ ์์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด ํจํด์ ํฉํ ๋ฆฌ ํจํด
์ด๋ผ๊ณ ๋ถ๋ฅด๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ฝ๊ฒ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฒ๋ ํฉ๋๋ค.
๋ค๋ฅธ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ด๋ ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด๋ก๋ถํฐ ๋น๋กฏ๋์๋ค๊ณ ํ์ฌ ์ฐ๋ฆฌ๊ฐ ํด๋์ค๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์ฝ๋๋ฅผ ์ง์ผํ๋ค๊ณ ์๊ฐํ ์๋ ์์ง๋ง ์ฌ์ค ๋ฌธ๋ฒ์ sugar์ ๋ถ๊ณผํ์ฌ ํด๋์ค ๊ธฐ๋ฐ ์ธ์ด์ฒ๋ผ ๋ณด์ด๊ฒ ํ ๋ฟ์ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ํ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ๋กํ ํ์ ์์๊ณผ OLOO(Objects Linking to Other Objects, ๊ณต์ ๋๋ ํ๋กํ ํ์ ์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํด ๊ฐ์ฒด๋ค์ ์ฐ๊ฒฐํ๋ ๊ฒ์ ์๋ฏธ)๋ฅผ ํ์ฉํ๋ ๊ฒ์ ๋๋ค. ํ๋กํ ํ์ ์์ฒด๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์ผ๋ฟ์ด๊ณ ํด๋์ค๋ ์๋๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ์์๊ณผ ํด๋์ค ๊ธฐ๋ฐ ์์๊ณผ์ ์ฐจ์ด๋ฅผ ์ ๊ฐ์ฅ ์ ์ค๋ช ํ๋ ๊ธ์ Eric Elliot์ ์ํฐํด์ ์ฐธ๊ณ ํ์ธ์.
๊ทธ๋ผ ์ด์ ์ฝ๋๋ฅผ ์ดํด๋ด ์๋ค.
์ด ๊ธ์ ์๋ ๋ชจ๋ ์์ ์ฝ๋์ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฐ์ด๋๋ GitHub์์ ๋ณด์ค ์ ์์ต๋๋ค.
์ด ์ํฐํด์ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ํด ์ฌ๋ฌ๋ถ์ Node๋ฅผ ์ค์นํ์ ์ผ ํฉ๋๋ค. ๋ง์ฝ ์ค์นํ์ง ์์ผ์ จ๋ค๋ฉด ์ด ์๋ด์ฌํญ์ ๋ฐ๋ฅด์ธ์. GitHub ๋ ํฌ readme์ ์ฝ๋ ์คํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ผ์ค ์ ์์ต๋๋ค.
๋จผ์ ํด๋๋ฅผ ์์ฑํ์ธ์. ์ด ํด๋๋ฅผ javascript-design-patters
๋ผ ํ๊ณ , ์ด ์์ factory
ํด๋๋ฅผ ์์ฑํฉ๋๋ค.
ํฉํ ๋ฆฌ ํจํด์ ๊ฐ์ฒด์ ์ฌ๋ฌ ํ์ ์ผ๋ก ์์ฑ์๋ฅผ ๊ฐ์ธ๊ณ ๊ฐ๋จํ API๋ฅผ ํตํด ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๋ ๊ตฌ์ฒดํ๋ ๊ฐ์ฒด ํ์ ์ ๋ฆฌํดํ๋ ๊ฐ๋จํ API๋ฅผ ๋ ธ์ถํ์ฌ ์ฌ๋ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ฝ๊ฒ ๋ง๋ค์ด์ค๋๋ค.
์์ฑ์๋ฅผ ์์ฑํด๋ณด๋ ๊ฒ๋ถํฐ ์์ํฉ์๋ค. ์ด ํจ์๋ค์ ํธ์ถ๋์์ ๋ ํน์ ํ์
์ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ์ญํ ์ ํฉ๋๋ค.
factory
ํด๋์์ laptop.js
ํ์ผ์ ์์ฑํฉ๋๋ค.
const Laptop = function({ ram, hdd, name }) {
this.ram = ram || 0;
this.hdd = hdd || 0;
this.name = name || "";
};
module.exports = Laptop;
์ด ํ์ผ์์ Laptop
์์ฑ์ ํจ์๋ฅผ ์์ฑํฉ๋๋ค. ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ๊ฐ ๊ฐ์ฒด์ ์ธ์คํด์ค์ ์ดํธ๋ฆฌ๋ทฐํธ์ ๊ฐ์ผ๋ก ๊ฐ ํ๋กํผํฐ๋ฅผ ๋ฃ์ด์ค๋๋ค. ์ด ๊ฒฝ์ฐ์์๋ RAM ์ฌ์ด์ฆ, HDD ์ฌ์ด์ฆ, ๋๋ฐ์ด์ค ์ด๋ฆ์ ์ฌ์ฉํ์ฃ . ๊ทธ ํ Laptop
์์ฑ์ ํจ์๋ฅผ ๋ชจ๋๋ก๋ถํฐ exportํฉ๋๋ค.
๋ ๋ค๋ฅธ ํ์ผ์ธ tablet.js
๋ฅผ ์์ฑํด๋ด
์๋ค. ๋น์ทํ์ง๋ง ์ข ๋ ํ๋ธ๋ฆฟ์ ๊ด๋ จ๋ ๊ฒ๋ค์ ์ถ๊ฐํด๋ด
์๋ค.
const Tablet = function({ ram, hdd, name, network }) {
this.ram = ram || 0;
this.hdd = hdd || 0;
this.network = network || 0;
this.name = name || "";
};
module.exports = Tablet;
์์ฑ์๋ฅผ ๋ง๋ค์์ผ๋ ์ด๋ฐ ์์ดํ
๋ค์ ๊ฐ์ง๋ ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ API๋ฅผ ๋
ธ์ถํ ํฉํ ๋ฆฌ ํจ์๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค. gadgetFactory.js
ํ์ผ์ ์ถ๊ฐํด์ฃผ์ธ์.
const Laptop = require("./laptop");
const Tablet = require("./tablet");
const gadget = { Laptop, Tablet };
module.exports = {
createGadget(type, attributes) {
const GadgetType = gadget[type];
return new GadgetType(attributes);
}
};
Laptop
๊ณผ Tablet
๊ฐ์ฒด๋ค์ ์์ฑํ๋ ์์ฑ์๋ฅผ import ํ ํ ์์ฑ์ ์ด๋ฆ์ key๋ก ์ฌ์ฉํ๋ gadge
t ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. ์ด ์์ ์์๋ gadget[type]
์ ์ฌ์ฉํ์ฌ ์ํ๋ ์์ฑ์์ ํ์
์ ์ ๊ทผํ ์ ์์ต๋๋ค. ํ์
์ "Laptop"์ด๊ฑฐ๋ "Tablet"์
๋๋ค. ๋ง์ง๋ง์ผ๋ก createGadget
๋ฉ์๋๋ฅผ ํฌํจํ ๊ฐ์ฒด๋ฅผ exportํฉ๋๋ค. ์ด ๋ฉ์๋๋ ์ฒซ ํ๋ผ๋ฏธํฐ๋ก gadget type์ ๋ฐ๊ณ ์ดํธ๋ฆฌ๋ทฐํธ ๊ฐ๋ค์ ํด๋น ์์ฑ์์ ๋๊ฒจ์ฃผ๋ฉด์ ํธ์ถํฉ๋๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์์ new
ํค์๋๋ก ํจ์๋ฅผ ํธ์ถํ ๋ ์คํํ๋ ํจ์์ this ๋ฐ์ธ๋ฉ์ด ๋ ๋น ๊ฐ์ฒด๋ฅผ ๋ฐํ๋ฐ๋ ๊ฒ์ ์ฃผ๋ชฉํ์
์ผ ํฉ๋๋ค. ์ด ๋
ํนํจ์ ์์ฑ์ ํจ์์ ์ด ๋ฐฉ์์ผ๋ก ์์ฑํ ์ ๊ฐ์ฒด ์ฌ์ด์ ํ๋กํ ํ์
๊ด๊ณ๋ฅผ ๋ง๋ญ๋๋ค. ๋ ์์ธํ ๊ฒ์ ๋์ค์ ๋ค๋ฃฐ ๋์์ธ ํจํด์์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๋ ๋ค๋ฅธ ์ฃผ๋ชฉํ ์ ์ ๋๋ฌธ์๋ก ์์ํ๋ ๊ฒ์ ๊ด์ต์ด์ง ํ์๊ฐ ์๋๋ผ๋ ๊ฒ์
๋๋ค. ๋๋ฌธ์๋ก ์์ํ๋๊ฒ์ ์ด๋ค ํน๋ณํ ๊ธฐ๋ฅ๋ ํ์ง ์์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์๋ ํจ์ ์ด๋ฆ์ด๋ ๋ณ์ ์ด๋ฆ์์ ๋ณดํต ์ฌ์ฉํ๋ฏ์ด camelCase๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
์ด์ ํฉํ ๋ฆฌ ํจํด API๋ฅผ ์ฌ์ฉํ๋ ํ์ผ์ ์์ฑํ ์ ์์ต๋๋ค. index.js
ํ์ผ์ ์์ฑํ๊ณ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.
const gadgetFactory = require("./gadgetFactory");
const myLaptop = gadgetFactory.createGadget("Laptop", {
ram: 8,
ssd: 256,
name: "Bab's MacBook Pro"
});
const myTablet = gadgetFactory.createGadget("Tablet", {
ram: 4,
hdd: 128,
name: "Bab's iPad",
network: '4G'
});
console.log(myLaptop);
console.log(myTablet);
์๋ง ์ฌ๋ฌ๋ถ์ ์ฒซ ๋ฒ์งธ๋ก laptop์ด๋ tablet ์์ฑ์๊ฐ ์ง์ ์ ์ผ๋ก ํ์ํ์ง ์๋ค๋ ๊ฒ์ ๋ณด์
จ์ ๊ฒ๋๋ค. ์ฐ๋ฆฌ๊ฐ ํ์ํ ๊ฒ์ gadgetFactory
๋ชจ๋์
๋๋ค. ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ ๋ ๊ฐ์ง ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์ฝ์์ ์ถ๋ ฅํ์ต๋๋ค.
์ด์ ์ฌ๋ฌ๋ถ์ ํฐ๋ฏธ๋์์ ์๊น ์์ฑํ javascript-design-patterns
ํด๋๋ฅผ ์ฐพ์ ํ์ดํํ์ธ์.
$ node ./factory/index.js
์ฝ์์๋ ์ด๋ ๊ฒ ์ถ๋ ฅ๋์ ๊ฒ๋๋ค.
Laptop { ram: 8, ssd: 256, name: 'Bab\'s MacBook Pro' }
Tablet { ram: 4, hdd: 128, network: '4G', name: 'Bab\'s iPad' }
์ฌ๋ฌ๋ถ์ด ๋ณผ ์ ์๋ฏ์ด Laptop
๊ฐ์ฒด ํ์
๊ณผ Tablet
๊ฐ์ฒด ํ์
๋ชจ๋๋ฅผ ์์ฑํ์ต๋๋ค. ์ด ํจํด์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ๋ถ์ ํ์ํ ๋ช
์ธ์ ๋ฐ๋ผ ๋ง์ gadget ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ๋ํ ์ด๊ฒ์ด ํฉํ ๋ฆฌ ํจํด์
๋๋ค. ๋ฌผ๋ก ํจ์ฌ ๊ฐ๋จํ ๊ตฌํ์ด๊ณ ์ฌ๋ฌ๋ถ์ด ์ฌ์ฉํ๋ ค๋ฉด ์์ฑ์ ๋ฑ์ ๋์ฑ ์๊ฒฉํ ๋
ผ๋ฆฌ๊ฐ ์ถ๊ฐ๋์ด์ผ ํ ๊ฒ์
๋๋ค. ์ด ์์์์๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ฑ์ ํจ์๋ฅผ ์ฌ์ฉํ์ง๋ง ํ๋กํ ํ์
์ผ๋ก๋ ๊ตฌํ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ดํ ์์ฑํ ๊ธ์์๋ ์ฝ๋๋ฅผ ๋์ฑ ํจ์จ์ ์ผ๋ก ๋ฆฌํฉํ ๋งํด๋ณด๊ฒ ์ต๋๋ค.
๋ค์ ์ํฐํด ์ฃผ์ ๋ ์ ๋ช ํ Publisher/Subscriber pattern์ ๋ํด ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค. ์๋ฆผ์ ๋ฐ๊ณ ์ถ์ผ์๋ฉด ์ ๋ฅผ ํ๋ก์ฐํ์๊ณ , ๋ง์ฝ ์ด ๊ธ์ด ๋์์ด ๋์ จ๋ค๋ฉด thumbs up์ ๋จ๊ฒจ์ฃผ์ธ์. ์ธ์ ๋ ๊ทธ๋ฌ๋ฏ์ด ์๋ ์ฝ๋ฉํธ์์ ์ฌ๋ฌ๋ถ๋ค์ ์๊ฐ์ ๋ค์ด๋ณด๊ณ ์ถ์ต๋๋ค.
์ ๋ฐ์ดํธ : ์ด ์๋ฆฌ์ฆ์ Part 2์์๋ Publisher/Subscriber pattern์ ๋ํด ๋ค๋ฃน๋๋ค.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.