2020-10 
๋งํฌ & ์ฝ์๊ฑฐ๋ฆฌ
Introducing the New JSX Transform
JSX๋ ์ผ๋ฐ JavaScript ์ฝ๋๋ก transpile ๋์ง ์์ผ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ์ดํดํ์ง ๋ชปํ๋ค. ๋ฐ๋ผ์ ์๋ ์์ ์ฝ๋์ ๊ฐ์ด ์์ฑ๋ ์ฝ๋๋ React.createElement๋ฅผ ์ฌ์ฉํ๋๋ก ๋ณํ๋๋ค.
import React from 'react';
// ์์ฑ๋ ์ฝ๋
function App() {
return <h1>Hello World</h1>;
}
// ๋ณํ๋ ์ฝ๋
function App() {
return React.createElement('h1', null, 'Hello world');
}
๊ทธ๋ฌ๋, React.createElement
์ ์ฌ์ฉ์ ๋ค์์ 2๊ฐ์ง ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค.
- React ์ค์ฝํ ๋ด์ ์์ด์ผ ํ๋ ๋ฌธ์ (์ฆ, React import๋ฅผ ํ์)
- ์ ์ฉ๋ ์ผ๋ถ ์ฑ๋ฅ ํฅ์๊ณผ ๋จ์ํ๋ฅผ ์ง์ํ์ง ๋ชปํ๋ ๋ฌธ์
์๋ก์ด Transform์ Babel ๊ฐ๋ฐํ๊ณผ์ ํ์ ์ ํตํด ๋ค์์ ์ด์ ๋ค์ ์ ๊ณตํ๋ค.
- React import ์์ด JSX๋ฅผ ์ฌ์ฉ
- ๋ฒ๋ค ํฌ๊ธฐ์ ๊ฐ์ (์ฌ์ฉ์์ ์ค์ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์๋ค.)
- ํ์ต์ด ํ์ํ React์ ๊ฐ๋ ์ ๋ถ๋ถ์ ๊ฐ์์์ผ ์ฃผ๋ ๊ฐ์ ์ ํ์ฑํํ๋ค.
์๋ก์ด Transform์ React 17
(ํฅํ 0.14.x, 15.x, 16.x ๋ค๋ ์ง์ ์์ )์ ํตํด ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ปดํ์ผ๋ฌ(Babel, TS) ์ ์ฉ entry point๋ฅผ ์ ๊ณตํด React.createElement
๋์ ํน๋ณํ ํจ์๋ฅผ ์๋์ผ๋ก import ํ๊ณ ์ฌ์ฉํ๋๋ก ๋ณํ๋๋ค.
// ์์ฑ๋ ์ฝ๋ (React import ์์ด ์์ฑ)
function App() {
return <h1>Hello World</h1>;
}
// ๋ณํ๋ ์ฝ๋ (์๋ ๋ชจ๋์ ์ปดํ์ผ๋ฌ๋ฅผ ํตํด ์๋ import)
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
We now generally consider Moment to be a legacy project in maintenance mode
Moment ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ ์ด์์ ๊ธฐ๋ฅ ์ถ๊ฐ ์์ด ์ ์ง ๋ณด์๋ง ํ๋ค.
๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- Luxon: Moment์ ์งํ๋ก ์๊ฐํ ์ ์๋ค. ์ค๋ ๊ธฐ๊ฐ Moment ์ปจํธ๋ฆฌ๋ทฐํฐ์ธ Isaac Cambron์ด ๊ฐ๋ฐํ๊ณ ์๋ค.
- Day.js: ์ ์ฌํ API๋ฅผ ์ฌ์ฉํ์ฌ Moment๋ฅผ ์ต์ํ์ผ๋ก ๋์ฒดํ๋๋ก ์ค๊ณ๋์๋ค.
- date-fns: Date ๊ฐ์ฒด๋ฅผ ์กฐ์ํ๊ธฐ ์ํ ๋ค์ํ ํจ์๋ฅผ ์ ๊ณตํ๋ค.
- js-Joda: JSR-310 ๊ธฐ๋ฐ์ Java SE8 java.time ํจํค์ง๋ฅผ ํฌํ ํ์๋ค.
Effective limited parallel execution in JavaScript
๋ณ๋ ฌ ์คํ์ ํจ๊ณผ์ ์ผ๋ก ์ ํ์ ๋๋ ๋ฐฉ๋ฒ์ด๋ค.
๊ฐ๋จํ ์์ ๋ฅผ ํตํด์ ์ ์ ํ๊ฒ ๋ณ๋ ฌ ์คํ์ ์ ํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์๋ ค ์ค๋ค. promise-pool
The Ugly Side of React Hooks
์์ฆ ๋ง์ React ๊ด๋ จ ๊ธ๋ค์ด class component๋ณด๋ค๋ hooks๋ฅผ ๊ถ์ฅํ๋๋ฐ, ์ ๋ชฉ์์ ์ ์ ์๋ฏ, ์ด ๊ธ์ ๊ทธ์ ๋ฐ๋์ด๋ค. React ๊ณต์ ๋ฌธ์์์ ๋งํ๋ hooks์ motivation์ ํ๋ํ๋ ์ง์ผ๋ฉฐ ๋นํํ๋ค.
Vue.js 3.0 "One Piece"
์ค๋ ๊ฐ๋ฐ ๊ธฐ๊ฐ ๋์ ๋๋์ด Vue 3.0(์ฝ๋๋ช "One Piece")์ ๊ณต์ ๋ฆด๋ฆฌ์ค๊ฐ ๊ณต๊ฐ๋์๋ค. Progressive framework ์ฝ์ ํธ๋ฅผ ์งํฅํ๋ Vue.js์ ์๋ก์ด ์ถ๋ฐ์ ์ฃผ๋ชฉํด ๋ณด์.
Deno 1.4
TypeScript ๋ฐํ์์ธ Deno์ ์๋ก์ด ๋ฒ์ ์ธ 1.4๊ฐ ๋ฆด๋ฆฌ์ค๊ฐ ๊ณต๊ฐ๋์๋ค. ์ด๋ฒ ๋ฆด๋ฆฌ์ค์๋ ์น์์ผ ์ง์๊ณผ ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ฌ์ฉํ ์ ์๋ watch ๋ชจ๋ ์ง์์ด ์ถ๊ฐ๋์๋ค. ์ ์ ์ค๋ฌด์์ ํ๋ฐํ ์ฌ์ฉ์ด ์ฆ๊ฐํ ๊ฒ์ผ๋ก ๊ธฐ๋๋๋ค.
ํํ ๋ฆฌ์ผ
React Component Patterns
๋ค์ํ React Component ํจํด(Compound, Flexible Compound ๊ทธ๋ฆฌ๊ณ Provider Pattern)๋ค์ ์๊ฐํ๊ณ , ๊ฐ ํจํด๋ค์ ์ฌ์ฉ์ด ์ด๋ค ๊ฒฝ์ฐ์ ์ ํฉํ์ง ๊ทธ๋ฆฌ๊ณ ๊ฐ๊ฐ์ trade-offs ๋ค์ ์๊ฐํ๋ค.
React-use hooks
React์์ ์ฌ์ฉํ๋ ์ฌ์ฉ์ ์ ์(custom) hook ์ด๋ค. ์ ์ฉํ hook์ด ๋ง์ด ์์ผ๋ ๊ฐ๋ฐํ ๋ ๋ง๋ค๊ธฐ ๋ณด๋ค ํ์ํ hook์ ์ฐพ๊ณ ์ด์ฉํด ๋ณด๋ฉด ์ข๋ค.
Logical assignment operators in JavaScript
๋ ผ๋ฆฌ ํ ๋น ์ฐ์ฐ์๊ฐ (EcmaScript 2021)์ ์ถ๊ฐ๋ ์์ ์ด๋ค. stage-4
๊ฐ๋ตํ๊ฒ ์์๋ณด๋ฉด,
OR ์ฐ์ฐ
x ||= y;
x || (x = y)
๋ ํํ์์ ๋์ผํ๋ค.
AND ์ฐ์ฐ
x &&= y;
x && (x = y);
๋ ํํ์์ ๋์ผํ๋ค.
A Gentle Introduction to Code Splitting with React
React๋ฅผ ์ฌ์ฉํ ํ๋ก์ ํธ์์ ์ฝ๋ ๋ถํ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ค.
๋ถํ ํ๋ ๋ฐฉ๋ฒ
- Route level
import React, { Suspense } from 'react'; import { Location, Router } from '@reach/router'; import Loading from './components/Loading'; const Home = React.lazy(() => import('./components/Home')); const AppointmentForm = React.lazy(() => import('./components/AppointmentForm')); const PreviousAppointments = React.lazy(() => import('./components/PreviousAppointments')); class App extends React.Component { render() { return ( <Location> {({ location }) => ( <Suspense fallback={<Loading />}> <Router location={location}> <Home path="/" /> <AppointmentForm path="/newAppointment" /> <PreviousAppointments path="/previousAppointments" /> </Router> </Suspense> )} </Location> ); } }
- Component level
class PreviousAppointments extends Component { constructor(props) { super(props); this.state = { map: null }; this.handleClick = this.handleClick.bind(this); } handleClick() { import('./components/Map').then(module => this.setState(() => ({ map: module.default, })), ); } render() { const { map: Map } = this.state; return ( <> <div>Previous Appointments</div> ... {Map ? <Map /> : <button onClick={this.handleClick}>Show Map</button>} </> ); } }
๋ ๋ถํ ๋ฐฉ๋ฒ์ ์ ์ด์ฉํด์ ์ฑ๋ฅ์ ๋์ด๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ์ต์ ํ ์ํค์.
Decorators
2020๋ 9์์ ์ ์๋ ๋ฐ์ฝ๋ ์ดํฐ๋ค์ด๋ค.
๋ช ๊ฐ์ง๋ง ์ดํด๋ณด๋ฉด,
@logged
๋ฉ์๋์ ์์๊ณผ ๋์ ๋ก๊ทธ๋ฅผ ์ถ๋ ฅํ๋ค.
import { logged } from "./logged.mjs";
class C {
@logged
m(arg) {
this.#x = arg;
}
@logged
set #x(value) { }
}
new C().m(1);
// starting m with arguments 1
// starting set #x with arguments 1
// ending set #x
// ending m
@tracked
ํ๋ ๊ฐ์ ์ถ์ (tracking)ํด ๊ฐ์ ๋ณ๊ฒฝ์ด ๋ฐ์๋๋ฉด, render ๋ฉ์๋๋ฅผ ํธ๋ฆฌ๊ฑฐ ํ๋ค.
import { tracked } from "./tracked.mjs";
class Element {
@tracked counter = 0;
increment() { this.counter++; }
render() { console.log(counter); }
}
const e = new Element();
e.increment(); // logs 1
e.increment(); // logs 2
๋๊ตฌ
Comlink
์์ ์ฝ๋ ์ด๋ฏธ์ง (ํด๋ฆญํ๋ฉด ํ๋ํด์ ๋ณผ ์ ์๋ค.)
ํฌ๋กฌ ๊ฐ๋ฐํ์์ ๊ณต๊ฐํ ์์ฃผ ์์ ํฌ๊ธฐ(1.1kb)์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, WebWorkers ์ฌ์ฉ์ ๋ํ ์ด๊ธฐ ์ ๊ทผ ์ฅ๋ฒฝ์ ์ ๊ฑฐํด ์ค๋ค. ์ข ๋ ์ถ์์ ์์ค์์ ๋ณด์๋ฉด, postMessage์ ES6 Proxies์ ๋ํ RPC ๊ตฌํ์ด๋ผ ํ ์ ์๋ค.
Webpack์ ๋ฒ๋ค๋ฌ๋ก ์ฌ์ฉํ๊ณ ์๋ค๋ฉด comlink-loader๋ฅผ ๊ฐ์ด ์ฌ์ฉํด, ์ฝ๋์ ์ผ๋ถ ์์ (๋๋ ์์ด)์ ํตํด ์ฌ์ฉ๋๋ ๋ชจ๋๋ค์ WebWorkers ์ค๋ ๋์์ ์คํ๋ ์ ์๋๋ก ๋ง๋ค ์๋ ์๋ค.
GitHub CLI
GitHub์ ๊ณต์ CLI ๋๊ตฌ๋ก Beta ๊ธฐ๊ฐ์ ๋๋ด๊ณ , ์ผ๋ง ์ 1.0 ๋ฒ์ ์ ์ ๋ณด์๋ค. ํฐ๋ฏธ๋ ์์์ GitHub PR์ ๋ง๋ค๊ฑฐ๋ ๊ด๋ฆฌ๋ ํ ์ ์๋ค.