hon9g / til Goto Github PK
View Code? Open in Web Editor NEWNote taking on issue tab
Home Page: https://github.com/hon9g/TIL/issues
Note taking on issue tab
Home Page: https://github.com/hon9g/TIL/issues
브라우저는 DNS에 요청하여 도메인이 해당하는 아이피 주소 얻어낸다.
브라우저와 서버는 3 Way Handshake 을 한다.
어떤 번호 = Random Sequence
브라우저는 서버에 HTTP Request를 보내 필요한 자원을 받는다.
서버는 브라우저에게 HTML, JS, CSS 등 화면 렌더링에 필요한 자원을 보내준다.
렌더링엔진이 Render Tree에 있는 노드들을 배치. (x, y 배치)
Render Tree에 있는 노드들에 UI를 그림.
z-index에 맞춰 화면을 구성.
브라우저는 최종적으로 사용자에게 화면을 표시함.
실행이 종료된 스코프의 지역 변수를 참조할 수 있는 현상.
어떤 함수 A에서 선언한 변수 x를 참조하는 내부함수 B를 외부로 전달할 경우, A의 실행 컨텍스트가 종료된 이후에도 변수 x가 사라지지 않는 현상.
mutation
을 하지말고 그냥 기존의 view
를 날려버리고 새로운 view
를 만들면 어떨까?view
를 그리면 성능적으로 문제가 생기므로Virtual DOM
에 일단 view를 그려보고 바뀐 부분만 실제 DOM에 patch
해준다.function
은 first-class Object
입니다.function
는 호출될 수 있다는 점에서 다른 Object
와 구분된다.function
은 Function
Object
입니다.function myFunction () {}
myFunction = function () {}
myFunction
contain function.var name = function () {}
var
keyword
var myObject = { myFunction: function () {} }
Object
var
keyword
myObject = { myFunction: function () {} }
리덕스 문서에 목차 Deriving Data with Selectors를 보면 Selector들의 목적과 동기, 왜 memoized Selector들이 유용한지, 일반적인 Reselect 사용 패턴, React-Redux에서의 Selector 사용법을 다룹니다.
Redux 어플리케이션에서 state는 최소한으로 유지하고, 언제든지 가능할 때에 추가적인 값들을 state에서 파생시키는 것을 추천합니다.
여기에는 필터링된 목록 연산과 값들을 합산하는 연산 또한 포함됩니다.
이러한 방식의 장점은 다음과 같습니다.
일반적인 Redux 애플리케이션에서 데이터를 파생시키는 로직은 일반적으로 Selector라고 하는 함수로 작성됩니다.
Selector들은 다음의 로직을 캡슐화하는데에 사용됩니다.
모든 state 조회에 Selector를 사용할 필요는 없지만, 이는 표준 패턴이며 널리 사용됩니다.
"selector function"은the Redux store state (or part of the state)를 인자로 받고, state를 기반으로 한 데이터를 반환하는 (아무) 함수를 말합니다. Selector들은 특별한 라이브러리를 통해 작성될 필요가 없습니다. 또한, 화살표 함수로 작성하든, function 키워드를 통해 작성하든 전혀 상관 없습니다.
아래의 함수들은 모두 Selector 입니다.
// Arrow function, direct lookup
const selectEntities = state => state.entities
// Function declaration, mapping over an array to derive values
function selectItemIds(state) {
return state.items.map(item => item.id)
}
// Function declaration, encapsulating a deep lookup
function selectSomeSpecificField(state) {
return state.some.deeply.nested.field
}
// Arrow function, deriving values from an array
const selectItemsWhoseNamesStartWith = (items, namePrefix) =>
items.filter(item => item.name.startsWith(namePrefix))
Selector 함수는 종종 상대적으로 "비싼" 계산을 수행하거나 새로운 객체 및 배열 참조들인 파생 값을 생성해야 합니다. 다음과 같은 몇 가지 이유로 애플리케이션 성능에 문제가 될 수 있습니다.
useSelector
또는 mapState
와 함께 사용되는 Selector들은 Redux root state의 어떤 섹션이 실제로 업데이트되었는지에 관계없이 모든 dispatch된 action 후에 다시 실행됩니다. input state 섹션들이 변경되지 않았을 때, 값비싼 계산을 다시 실행하는 것은 CPU time 낭비입니다. 그리고 input의 대부분이 변경되지 않을 가능성이 매우 높습니다.useSelector
및 mapState
는 반환 값에 대해 ===
reference equality 검사에 의존하여 컴포넌트를 다시 렌더링해야 하는지 여부를 결정합니다. 만약 selector가 항상 새 참조를 반환하는 경우, 파생된 데이터가 이전 것과 사실상 동일하더라도 컴포넌트가 강제로 다시 리렌더링됩니다. 일반적으로 이는 새 배열 참조를 반환하는 map()
, filter()
와 같은 배열 조작에서 발생합니다.이 때문에 동일한 입력이 전달되는 경우 결과를 다시 계산하는 것을 피할 수 있는 최적화된 selector�들을 작성하는 방법이 필요합니다. 이 필요가 memoization에 대한 아이디어가 나오게된 동기입니다.
Memoization은 caching의 한 형태입니다. 여기에는 함수에 대한 입력을 추적하고, 나중에 참조할 수 있도록 입력들과 �결과들� 저장하는 작업이 포함됩니다. 이전과 동일한 입력으로 함수를 호출하면, 함수는 실제 작업을 건너뛸 수 있으며, 해당 입력 값을 마지막으로 받았을 때 생성한 것과 동일한 결과를 반환할 수 있습니다. 이렇게 하면 입력이 변경된 경우에만 작업을 수행하고 입력이 동일한 경우 동일한 결과 참조를 일관되게 반환하여 성능을 최적화합니다.
Reselect는 memoized selector를 작성하기 위해 Redux 생태계에서 오랫동안 사용해온 라이브러리입니다.
createSelector
OverviewReselect는 memoized selector들을 생성하기 위해 createSelector
라는 함수를 제공합니다. createSelector
는 하나 이상의 "input selector" 함수와 "output selector" 함수를 인자로 받고, 사용할 수 있는 새로운 selector 함수를 반환합니다.
createSelector
는 input selector를 인자로 받을 때 개별 인수들로 받을 수도 있고, 또는 한 개의 배열로 받을 수도 있습니다. 모든 input selector들의 결과 값들은 output selector에 별도의 인수들로 제공됩니다.
const selectA = state => state.a
const selectB = state => state.b
const selectC = state => state.c
const selectABC = createSelector([selectA, selectB, selectC], (a, b, c) => {
// do something with a, b, and c, and return a result
return a + b + c
})
// Call the selector function and get a result
const abc = selectABC(state)
// could also be written as separate arguments, and works exactly the same
const selectABC2 = createSelector(selectA, selectB, selectC, (a, b, c) => {
// do something with a, b, and c, and return a result
return a + b + c
})
Selector를 호출하면 Reselect는 사용자가 인수로 제공한 모든 input selector들을 실행하고 반환된 값을 확인합니다. 결과 중 하나라도 ===
이전과 다른 경우, input selector들의 새로운 결과를 output selector에 인수로 전달하며 재실행시킵니다. input selector들의 모든 결과값이 이전의 값과 같으면 output selector 재실행을 건너뛰고 이전의 캐시된 최종 결과만 반환합니다.
이는 input selector에서는 항상 값을 추출해야하고, output selector에서는 데이터를 transformation하는 작업을 해야만 한다는 말 입니다.
Reselect 는 memoized "selector" function들을 생성하기 위한 라이브러리이다. 주로 리덕스와 사용되며, 공식 Redux Toolkit Package에 이미 포함되어있다.(별도 install 필요없음) 별개로 그냥 불변 JS 데이터에도 사용할 수 있다.
React & History API를 사용하여 SPA Router 기능 구현하려고 한다.
구현에 앞서 이미 잘 구현되어있는 라이브러리 react-router 의 코드가 어떻게 작성되어 있는지 확인해보려고 한다.
'use strict';
use strict;
would,Layout could done with floats or positioning
GraphQL은 단순히 specification으로 출시되었다.
mutation
을 하지말고 그냥 기존의 view
를 날려버리고 새로운 view
를 만들면 어떨까?view
를 그리면 성능적으로 문제가 생기므로Virtual DOM
에 일단 view를 그려보고 바뀐 부분만 실제 DOM에 patch
해준다.Array.prototype.map()
map()
method creates new arrayexample 1.
const arr = [ 0, 1, 2, 3 ];
const m = arr.map( x => x**2 );
console.log(arr); // [ 0, 1, 2, 3 ]
console.log(m); // [ 0, 1, 4, 9 ]
.forEach()
.const arr = [ 0, 1, 2, 3 ];
const m = [];
arr.forEach( x => {
m.push(x**2);
}
);
console.log(arr); // [ 0, 1, 2, 3 ]
console.log(m); // [ 0, 1, 4, 9 ]
example 2.
const arr = [ [0,1], [2,3], [4,5] ];
const m = arr.map( x => x[0]**2 + x[1]**2);
console.log(arr); // [ [0,1], [2,3], [4,5] ]
console.log(m); // [1, 13, 41]
const arr = [ [0,1], [2,3], [4,5] ];
const m = [];
arr.forEach(x => {
m.push(x[0]**2 + x[1]**2);
});
console.log(arr); // [ [0,1], [2,3], [4,5] ]
console.log(m); // [1, 13, 41]
Array.prototype.reduce()
const arr = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
console.log(arr.reduce(reducer)); // 1 + 2 + 3 + 4 => 10
console.log(arr.reduce(reducer, 5)); // 5 + 1 + 2 + 3 + 4 => 15
const arr = [ [0,1], [2,3], [4,5] ];
const reducer = (accumulator, currentValue) => (
accumulator + currentValue[0] + currentValue[1]
);
console.log(arr.reduce(reducer, 0)); // 1 + 2 + 3 + 4 + 5 => 15
console.log(arr.reduce(reducer, 5)); // 5 + 1 + 2 + 3 + 4 + 5 => 20
Some property values flow down the document tree (most are not)
We can access rewrite the contents or style of DOM by JS.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p id='text-area'> Contents will be changed. </p>
<button id='ok-button'>OK!</button>
<script src='script.js'></script>
</body>
</html>
let textArea = document.getElementById('text-area');
let okButton = document.getElementById('ok-button');
okButton.addEventListener('click', function() {
textArea.innerText = 'changed';
});
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p id='text-area'> It wil be appeared after click `OK!`. </p>
<button id='ok-button'>OK!</button>
<script src='script.js'></script>
</body>
</html>
let paragraph = document.getElementById('text-area');
let okButton = document.getElementById('ok-button');
paragraph.style.display = 'none';
okButton.addEventListener('click', function() {
paragraph.style.display = 'block';
});
<객체지향의 사실과 오해>를 읽는 중.
책과 무관하게 일반적으로 객체지향은 4가지 특성으로 설명하곤 한다.
어떤?.. 디자인 패턴 책을 읽고 일기장에 적어뒀던 내용.
객체를 모델링 할 때, 실제 세계를 그대로 가져오지 않는다. 필요한 부분만 가져와서 (feature & behavior) 모델링한다.
외부에 노출할 인터페이스를 결정하는 것. 객체의 일부분을 private하게 구현.
private이란 객체 안에서만 해당 feature 또는 behavior를 사용할 수 있음을 말한다.
좀 더 규제가 약한 protected는 sub class들까지 어떠한 feature 또는 behavior를 공유하는 것을 말한다.
이미 존재하는 상위 클래스를 가지고 새로운 클래스를 만들 수 있다.
이떄 상위 클래스를 super class, 하위 클래스를 sub class라고 부른다.
subclass에서는 메소드를 오버라이드 할 수 있다.
이를 통해, 각기 다른 객체를 표현할 수 있게 한다
(각기 다른 객체가 아니라, 한 객체 내에서도 다양한 방식으로 특정한 목적을 이룰 수 있게 해준다는 의미에 가깝 않나?)
The Number type is a double-precision 64-bit binary format IEEE 754 value
.
It could have a value of number between -(2^53 -1)
and 2^53 -1
.
It also contains 3 special symbolic values.
+Infinity
-Infinity
NaN
0 is only value that could use in 2 different way. +0
-0
+0 === -0
is true
.22 / + 0
is Infinity
22 / - 0
is -Infinity
Protype은 객체를 생성할 때 활용되는 creational design pattern의 일종.
어떤 객체의 복사본을 같고 싶을 때 같은 Class의 instance 객체를 새로 생성한 한 후 기존 객체의 필드 값들을 모두 복사해오면 될까요?
다음과 같은 문제 상황을 마주할 수 있습니다.
clone
메소드만 가지고 있도록 구현합니다.clone
을 지원하는 객체를 prototype이라 부릅니다.만약, 아주 많은 필드들이 다양한 방식으로 설정될 가능성이 있는 경우.
모든 경우에 대해 subclass를 만드는 것 대신 복제를 지원하는 방식을 택할수 있다.
세포분열이 일어나면, 1개의 세포가 -> 동일한 1쌍의 세포들.
원본 세포가 protype으로서 복사본을 만드는 역할을 했다.
Prototype 패턴을 사용하여 클래스에 접근하지 않고도개체의 정확한 복사본을 생성하는예제.
모든 Shape 클래스는 clone
을 제공하는 동일한 인터페이스를 따릅니다. Shape의 하위 클래스는 자신의 필드 값을 결과 객체에 복사하기 전에 부모의 clone
메서드를 호출할 수 있습니다.
data -> ( stateful component ) -> output
msw | miragejs | |
---|---|---|
mock Rest API | Y | Y |
mock GraphQL | This is the first party | Y |
runs | in browser or node | in browser ( also in node but only browser like environment ) |
to intercept network requests | uses a Service Worker ( so reqs are shown in the Network tab in DevTools) | uses Pretender.js |
set up | need to generate a Service Worker file in the public dir | only import it on FE code |
서버에서 클라이언트로 데이터를 가져오기 위한 통신 방법들.
동시에 이벤트에서 각각 state를 업데이트 하는 경우 값이 누락되는 현상.
우선 setState는 항상 state를 비동기적으로 업데이트 한다는 점을 알고있으면 도움이 될 것 같습니다.
이런 특성 때문에 앞서 전달드린 문제가 발생할 수 있습니다.
THE NEW FRONT-END STACK
by @bilmann on JamStackRise of the JAMstack
by @MathiasBiillman on JamStackstudent
를 자원의 표현으로 정하는 등.사물 또는 사람을 데이터로 표현한다면? 그리고 그 데이터가 코드라면?
const cat = {
name: '먼지',
age: 10,
face: '납짝',
makeSound: () => {
alert('이야옹')
}
}
TypeScript와 함께라면 데이터를 (손쉽게) 추상화 해서 메타데이터를 만들 수 있음.
Cat 데이터 설명서 ->
interface Cat {
name: string
age: number
face: string
makeSound: function
}
Motivation
How
To-do
Reference
-A variable that stores a primitive value is accessed by value
Symbol
is new in ES2015TypeName | value |
---|---|
Number |
only a double-precision 64-bit binary format IEEE 754 value |
String |
a set of "elements" of 16-bit unsigned integer values |
Boolean |
only true or false |
Symbol |
a value symbol id token that serve as unique ID |
null |
a value null represents intentional absence of any object value |
undefined |
A variable that has not been assigned a value |
TypeName |
---|
Object |
Object
TypeName |
---|
Function |
Array |
Date |
RegExp |
display
속성의 값에 따라 레이아웃이 달라진다Flex box
은 일차원 레이아웃(row나 column)에 아이템들을 배치할 때 사용한다.Grids
row와 column에 따라 아이템을 배치할 수 있도록 돕는 레이아웃 시스템이다.float
text blocks 사이에서 image를 floating시키는 등에 사용할 수 있다.position
하나의 원소를 normal document layout flow에서 빼내 올 수 있도록 해주는 속성이다.터미널에 yarn start
을 입력하면 다음과 같은 안내 문구와 함께 포트 3000 에 로컬 서버가 시작됩니다.
> yarn start
yarn run v1.22.19
$ next start
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
yarn start
는 nextjs의 cli 명령어인 next start
를 실행합니다. package.json은 npm 프로젝트의 세부 사항을 핸들링 할 수 있는 파일인데요. 그런 로컬 프로젝트의 package.json 에 스크립트 명령어로 "start": "next start"
라고 명시해두었기 때문입니다.
{
...
{
"scripts": {
...
"start": "next start",
...
},
...
}
이제 next start
라는 cli 명령어가 실행될 때, 실행되는 코드를 nextjs 레포지토리에서 소스코드에 찾아보려고 합니다.
프로젝트 최상위에 존재하는 package.json을 보면 "workspaces"
가 "packages/*"
으로 설정되어있는 것을 확인할 수 있습니다.
이는 packages/
폴더 하위에는 또다른 유효한 packages.json 파일이 존재한다면, packages/
폴더 하위가 workspace로 인식될 것이라는 뜻 입니다. 의미를 정확하게 이해한 것 같진 않지만, 대략적으로 packages/
폴더 하위 부분이 nextjs 패키지 동작에 핵심적인 소스 코드들이 위치하고 있는 것으로 이해했습니다.
packages/
폴더 하위에는 create-next-app
, next
등등 여러 폴더가 위치하고 있고, 각각의 폴더는 고유한 packages.json을 가지고 있습니다. 각 폴더가 하나의 workspace로 인식되는 것으로 보입니다.
최상위 packages.json에서 next
라는 명령어의 path가 packages/next/...
로 설정되어 있는 만큼, next 파일 하위를 살피면 될 것 같습니다.
"scripts": {
...
"next": "node --trace-deprecation --enable-source-maps packages/next/dist/bin/next",
...
}
next/package.json
에는 실행 가능한 패키지를 만들기 위한 설정값인 "bin"
이 있는데, 다음과 같이 설정되어 있습니다.
"next": "./dist/bin/next"
next 라는 이름으로 "./dist/bin/next" 위치의 파일을 실행시킨다는 의미입니다. next/
폴더 하위에는 dist/
폴더는 없으나, bin/next
파일이 존재하고 있습니다. (path에 dist가 끼어들게 된 경위는 일단 건너뛰려고 합니다.)
bin/next
파일을 보면 우선 디펜던시인 react, react-dom의 패키지를 무사히 불러올 수 있는지 확인하고 cli 명령어로 들어온 키워드에 따라 다른 동작을 실행시킵니다.
예를들어, yarn next --version
명령어를 실행시킨다면, 다음의 코드가 동작하여 Next.js v12.3.1
과 같은 문자열을 터미널에 보여줍니다. 키워드가 --version
인 경우, 여기서 버전 문자열 출력 후 프로그램을 종료하는 것을 확인할 수 있습니다.
if (args['--version']) {
console.log(`Next.js v${process.env.__NEXT_VERSION}`)
process.exit(0)
}
bin/next
에서는 키워드가 예약된 명령어로 존재하는지를 확인 하기 위해 commands 모듈을 활용 합니다.
import { commands } from '../lib/commands'
...
// Check if we are running `next <subcommand>` or `next`
const foundCommand = Boolean(commands[args._[0]])
lib/commands
모듈은 각 명령어 키워드를 key로 이를 실행하기 위한 콜백함수를 value로 갖고 있는 객체를 export 합니다. 키워드 "start"는 ../cli/next-start
모듈에서 nextStart를 반환하는 콜백함수를 value로 갖고 있습니다. 따라서 Boolean(commands["start"])
는 true
입니다.
export const commands: { [command: string]: () => Promise<cliCommand> } = {
build: () => Promise.resolve(require('../cli/next-build').nextBuild),
start: () => Promise.resolve(require('../cli/next-start').nextStart),
export: () => Promise.resolve(require('../cli/next-export').nextExport),
dev: () => Promise.resolve(require('../cli/next-dev').nextDev),
lint: () => Promise.resolve(require('../cli/next-lint').nextLint),
telemetry: () =>
Promise.resolve(require('../cli/next-telemetry').nextTelemetry),
info: () => Promise.resolve(require('../cli/next-info').nextInfo),
}
다시 bin/next
를 보면, 실행가능한 명령어가 존재하는 경우 import 해온 콜백함수를 실행시키는 것을 확인할 수 있습니다.
'build'의 경우 실행 이후 프로그램을 종료하고, 'start'등 다른 키워드의 경우 실행시킨 후 프로그램을 계속 살려두는 것을 확인할 수 있습니다.
const command = foundCommand ? args._[0] : defaultCommand
...
commands[command]()
.then((exec) => exec(forwardedArgs))
.then(() => {
if (command === 'build') {
// ensure process exits after build completes so open handles/connections
// don't cause process to hang
process.exit(0)
}
})
lib/commands
모듈에서 확인했듯이, next start
명령어의 경우 cli/next-start
의 nextStart를 가져옵니다. nextStart는 다음과 같습니다. 별다른 argv를 전달하지 않았다면 host는 0.0.0.0으로 port는 3000번으로 설정하여 startServer 모듈을 이용해서 서버를 실행시킵니다. 그리고 성공했다면, 처음에 로컬 프로젝트에서 yarn start
를 했을 때 본 문자열인 started server on ${host}:${app.port}, url: ${appUrl}
를 출력합니다. 만약 error가 발생했다면 error log를 출력합니다.
import { startServer } from '../server/lib/start-server'
...,
const nextStart: cliCommand = (argv) => {
...,
let port: number =
args['--port'] || (process.env.PORT && parseInt(process.env.PORT)) || 3000
const host = args['--hostname'] || '0.0.0.0'
...,
startServer({
dir,
hostname: host,
port,
keepAliveTimeout,
})
.then(async (app) => {
const appUrl = `http://${app.hostname}:${app.port}`
Log.ready(`started server on ${host}:${app.port}, url: ${appUrl}`)
await app.prepare()
})
.catch((err) => {
console.error(err)
process.exit(1)
})
}
...
/server/lib/start-server 파일의 startServer는 다음과 같습니다. http 모듈을 활용해서 서버를 만들고 next app을 서버가 listening 하도록 합니다.
사용된 모듈은 http-proxy로 보입니다. next workplace의 package.json이 가지고 있는 http 관련 의존성이 http-proxy와 http-browserify인데, http-proxy 쪽이 createServer, server.on 등의 메소드를 제공하고 있기 때문입니다.
import http from 'http'
...
export function startServer(opts: StartServerOptions) {
let requestHandler: RequestHandler
const server = http.createServer((req, res) => {
return requestHandler(req, res)
})
...,
return new Promise<NextServer>((resolve, reject) => {
...,
server.on('listening', () => {
const addr = server.address()
const hostname =
!opts.hostname || opts.hostname === '0.0.0.0'
? 'localhost'
: opts.hostname
const app = next({
...opts,
hostname,
customServer: false,
httpServer: server,
port: addr && typeof addr === 'object' ? addr.port : port,
})
requestHandler = app.getRequestHandler()
resolve(app)
})
server.listen(port, opts.hostname)
})
}
React UI Testing
을 번역
enzyme
을 사용 할 수도 있지만 Jest’s snapshot testing을 사용하는게 더 간단.enzyme
을 사용하는 것.JEST snapshot
으로 테스트할 수 있지만, 그렇지 않다면 BackstopJS
Gemini
Happo
을 사용하는걸 고려해보는게 좋다.React Testing Library
enzyme
storybook
(doc)
using storybook-addon-specifications
jest
@storybook/addon-jest
JS 닌자 읽는 중
var
var
in Function Scopefunction sum(a, b) {
// Function Scope
var result = a + b;
}
sum(2, 2);
console.log(result); // VM431:1 Uncaught ReferenceError: result is not defined
var
is function scope, so can not access to variable result
at outside of function.
var
in Block Scopefor (var i=0; i<10; i++) {
// Block Scope
}
console.log(i) // 10
var
is function scope, so can access to variable i
at outside of block.
60fps
유지하기. (사용자가 인지하기에 자연스러운 프레임 수)layout
) 변경이나 painting
를 유발하는 애니메이션 속성은 특히 비용이 많이 듬transforms
과 opacity
변경 애니메이션만 사용하기will-change
를 사용해서 브라우저가 스스로 애니메이션을 계획할 수 있도록 하기compositor thread
라고 불리는 스레드에서 처리된다. 스타일 지정, 레이아웃, 페인트 및 자바스크립트가 실행되는 브라우저의 main thread
는 이와 다르다. 즉, 브라우저가 main thread
에서 비용이 많이 드는 작업을 실행 중인 경우에도 compositor thread
의 애니메이션들은 방해받지 않고 계속 실행된다.paint
및 layout
을 트리거하는 경우, CSS든 JS든 작업을 수행하기 위해 main thread
가 필요하다. 따라서 paint
및 layout
의 오버헤드는 CSS 또는 JS 실행과 연관된 모든 작업에 악영향을 미친다.USE CSS | USE JS |
---|---|
상대적으로 작고 스스로의 state가 포함된 UI 요소의 애니메이션의 경우 CSS를 사용 | 애니메이션을 세밀하게 제어해야 하는 경우 JS를 사용 |
CSS transitions & animations 은 side menu나 tooltip같은데 사용하면 좋다. 애니메이션 자체는 CSS에서 동작하게하면서 상태관리는 JS로 하는 것도 가능. | Web Animations API는 modern browser들의 표준적인 접근법. JS는 stop, pause, slow down, reverse the animations 이 필요할 때 유용. |
jQuery's .animate()
나 GreenSock's TweenMax
자바스크립트 프레임워크가 익숙하다면 그것을 사용하는게 효과적.(발표자료)
발표했던 내용을 복기할 겸 글로 정리해보려고 함.
흠..
렌더링 방법
성능
how to select elements from HTML file in CSS
h1
HTML tagh1 {
color: blue;
}
class
set to btn--blue
.btn--blue {
color: blue;
}
id
set to entry-textarea
#entry-textarea {
border: 2px solid #ccc;
}
p
elements that have a div
element as parentdiv p {
text-align: center;
}
h1, h2, p {
color: blue;
}
자바스크립트에서 프로토타입이란 객체에 프로퍼티를 정의하고, 객체 인스턴트에 자동으로 적용되게 해주는 함수의 기능.
CSS is called Cascading Style Sheets. because properties are applied in a specific order based on priority.
html tag
< class
< id
< !important
Structural Design Pattern들은 객체와 클래스들을 더 큰 구조로 (그 구조의 유연성과 효율성을 해치지 않으며) 조합하는 방법을 소개합니다.
Composite 패턴은 Structural Design Pattern의 일종으로, 객체(object)들을 트리(tree)구조로 구성(compose)하게 해줍니다. 그리고 트리 구조들이 각각 개별 객체인 것으로 취급하며 작업할 수 있습니다.
Composite 패턴은 객체들을 트리 구조로 구성하는 패턴입니다. 따라서 패턴을 적용하고자하는 어플리케이션의 코어 모델이 트리 형태로 나타낼 수 있어야 의미가 있습니다.
트리로 표현 할 수 있는 모델의 예는 군대가 있습니다.
거의 모든 나라의 군대는 위계로 이루어져 있습니다. 군사령부는 군단으로 이루어져있고, 군단은 사단으로 이루어져있고, ..., 소대에는 전투원들이 소속되어 있습니다.
주어진 클래스 Product와 Box를 이용하여 주문시스템 Order를 만들고자 합니다. 하나의 Order의 총 가격은 어떻게 구할 수 있을까요?
모든 포장을 풀고 각 Product의 가격을 확인한다면 Order의 총 가격을 구할 수 있습니다. 이 직관적인 접근은 Real-world에서 충분히 실행 가능한 방법이기는 하나, Program 상에서 구현하기에는 어려움이 있습니다.
Product와 Box의 구체적인 클래스를 알아야만하고, 모든 중첩된 레벨, 또 지저분한 세부사항까지 모두 알아야만 하기 때문입니다. 이를 구현하는 것은 어색하게 느껴집니다. 또한 구현이 아예 불가능 할 수도 있습니다.
우선 Product와 Box의 공통적인 인터페이스를 만듭니다. 주문 프로그램의 목표는 총 가격을 알아내는 것이었으니, 총 가격을 계산하는 메소드가 정의된 인터페이스라면 적당할 것 같습니다.
총 가격을 계산하는 메소드를 totalPrice()
라고 부르겠습니다. totalPrice()
은 다음과 같이 동작합니다.
totalPrice()
는 단순히 상품의 가격을 반환하도록 정의합니다.totalPrice()
는 박스에 속한 모든 아이템을 순회하며 가격을 조회하고 모두 합해 반환하도록 구현합니다.totalPrice()
가 실행됩니다. 이는 가장 안 쪽의 component의 가격이 계산될 때까지 재귀적으로 반복됩니다.totalPrice()
에 패키징 가격을 덧붙이는 등 추가 로직을 포함시킬 수도 있습니다.Composite 패턴을 활용한 접근법의 가장 큰 장점은 트리를 구성하고 있는 객체의 구체적인 클래스를 신경쓰지 않아도 된다는 점 입니다. 객체가 단순한 상품인지 또는 포장된 박스인지의 차이 또한 신경쓰지 않아도 됩니다. 공통 인터페이스를 통해 객체를 동일한 방식으로 다룰 수 있기 때문입니다.
Composite 패턴으로 Graphical Editor에서 기하 도형 쌓기 기능 구현하기.
⚡️ Composite에서는 동일한 공통 인터페이스를 공유하는 2가지 기본 element 타입을 제공합니다.
이 element type들로 재귀적으로 중첩된 객체구조를 트리로 나타낼 수 있도록 해줍니다.
⚡️ Composite 패턴을 통해 정의된 모든 element들은 동일한 인터페이스를 공유하고 있으므로, client는 작업 중인 객체의 구체적인 클래스를 고려할 필요가 없습니다.
props
is short for propertiesprops
are used to pass data from component
to component
.props
are Read-Only<Image />
is one of React Native Component<Image />
has source
as props<Image source={{uri:'https://dummyimage.com/600x400/000/fff'}/>
소프트웨어는 이해관계자들에게 행위 behavior, 구조 structure 라는 두가지 가치를 제공한다.
행위(기능) 를 통해서는 수익을 창출하거나 비용을 절감할 수 있다. 이를 위해 요구 명세서를 구체화하고 코드로 구현한다.
구조(아키텍처) 는 소프트웨어가 soft웨어 답게 추후에도 행위를 쉽게 바꿀 수 있도록 하기 위한 것 이다.
둘 중 무엇이 더 중요할까?
대체로 개발자들은 업무 관리자의 요구대로 기능을 우선 동작하게하는 데에 우선순위를 두곤 한다.
하지만 완벽하게 동작하지만 변경이 전혀 불가능한 프로그램과 동작은 하지 않지만 변경에 유연한 프로그램 을 비교해보자.
후자는 변경을 통해 동작하게 만들 수 있지만,
전자는 다음 요구사항이 왔을 때 변경이 불가능하므로 변화가 필요할 때 프로그램 전체를 폐기해야 할 것 이다.
주로 긴급한 것은 기능이지만, 구조는 중요하다.
�긴급한 것에 집중하다 중요한 것을 놓치지 않도록 주의해야한다.
프로그래밍 패러다임이란 개발자에게 관점을 갖게 해주는 규율로 프로그래밍을 하는 방법을 알려준다. 규율이란 지켜야 할 규칙이 있다는 뜻 이다. 프로그래밍 패러다임에서의 규율은 해야하는 것 이 아니라 하지 말아야하는 것 에 대해 말하며 코딩하는 방식을 한정시킨다.
지난 반세기 동안 발견된 프로그래밍 패러다임은 세가지가 있다. 1946년 앨런 튜링이 기계어로 코드를 작성했을 때부터 지금까지 프로그래밍 도구는 많은 변화가 있었지만, 프로그래밍 규칙은 변하지 않았다. 프로그램은 순차 sequence, 분기 selection, 반복 iteration, 참조 indirection 로 구성되는 것일 뿐입니다. 따라서 앞으로도 (적어도 프로그래밍에 제한을 주는) 프로그래밍 패러다임이 더 발견되는 일은 없을 것�이다.
제어흐름의 직접적인 전환에 부과되는 규율
데이크스트라는 인간의 인지적인 한계로 인해 요구되는 세부사항을 모두 감당하기 힘들다 것에 문제의식을 가지고, 이 문제를 풀기위해 수학적인 관점에서 접근했다. 수학적 원리인 증명 proof 를 활용하는 것 인데, 증명을 가능하게 만들려면 분할 정복 접근법을 사용해야만 했고, 분할정복 접근법을 사용하려면 증명가능한 모듈 단위로 프로그램을 분할 할 수 있어야 했다. 그런데 당시에는 무분별한 goto 문이 사용이 허용되어있어서 프로그램을 반증가능한 단위로 만들 수 없었다. 제어흐름이 순차적이지 않고 뒤죽박죽이였기 때문이다.
따라서 데이크스트라는 goto 문장의 좋은 사용방식인 분기( if / then / else ) 와 반복( do / while ) 을 발견했다. (최초로 발견한건 아님) 이 제어구조를 순차 실행과 결합하면 모듈을 증명가능하게 하는 단위를 만들 수 있다. 또한 이는 모든 프로그램을 만들 수 있는 최소의 제어구조에 해당한다.
구조적 프로그래밍은 순차, 분기, 반복이라는 세가지 제어구조를 따르는 것을 말한다.
결국 프로그램을 엄밀하게 증명하는 일은 일어나지 않았지만, 프로그램이 증명 가능한 단위로 분해될 수 있게 됨으로써, 테스트가 가능해졌다. 프로그램의 옳음을 증명하는 일은 일어나지 않았지만, 거짓임을 증명하는 과학적 방식을 활용할 수 있게 되었다. 우리는 테스트를 수행함으로써 작은 단위로 쪼개진 프로그램의 모듈을 거짓인지에 대해 증명을 시도한다. 테스트 결과 거짓이 아님이 확인되면 프로그램이 제 역할을 수행할 정도로는 참이라고 여기고 사용하는 것이다.
제어흐름의 간접적인 전환에 부과되는 규율
(소프트웨어 아키텍트 관점에서) 객체 지향은 다형성을 이용하여 시스템내의 소스 코드 간 의존성에 대한 절대적인 제어 권한을 획득할 수 있는 능력을 말한다.
객체 지향 언어가 있기 이전에도 다형성을 표현하는 방법은 있었다. 함수를 가르키는 포인터를 활용하는 방식이다. 객체 지향 언어가 최초로 다형성을 지원해준 것은 아니지만, 다형성을 더 안전하고 편리하게 사용할 수 있게 해준다. 사실 함수 포인터를 사용하는 것은 위험하기 때문이다. (매번 포인터를 초기화하고 포인터를 통해서 모든 함수(?)를 호출해야한다.)
다형성을 활용하지 못한다면 소스코드는 제어흐름에 따라 의존성이 결정된다. 고수준의 모듈이 저수준의 모듈에 의존할 수 밖에 없는 것이다. 다형성을 활용하면 이 문제를 해결할 수 있다.
중간에 인터페이스를 넣어주고 고수준 모듈이 인터페이스에 의존하도록 만든다. 그리고 저수준 모듈이 인터페이스를 상속받아 다형성을 이용해 저수준 모듈 나름의 구현을 하도록 한다. 그러면 더이상 의존성이 고수준 모듈에서 저수준 모듈로 흐르지 않는다.
의존성 역전을 활용하면 의존성을 원하는 대로 설정할 수 있다. 이를 통해 원하는 아키텍처를 구현할 수 있게 된다.
변수 할당에 부과되는 규율
함수형 프로그래밍 언어인 클로져로 정수 1부터 25까지의 제곱을 출력하는 코드
(printIn (take 25 (map (fn [x] (* x x)) (range)))))
객체 지향 언어로 구현한다면 흔히 볼 수 있는 제어 구조는 보이지 않고 온통 함수만 보인다.
또한 클로저에서는 x와 같은 변수가 한 번 초기화되면 절때 변하지 않는다고 한다. 함수형 언어에서는 변수가 변하지 않기 때문이다.
아키텍처를 고려할 때 이와 같은 변수의 불변성이 중요한 이유가 있다. 동시성 어플리케이션에서 만나는 모든 문제인 경합 조건, 교착상태 조건, 동시 업데이트 문제 모두 가변 변수로 인해 일어나는 문제이기 때문이다. 이러한 동시성 문제를 제어하기 위해 불변성을 다루는 것이 중요한 것이다.
우리는 불변 컴포넌트를 최대한 늘려서 안전지대를 넓혀두고, 최소화된 가변 컴포넌트에 동시성 문제에 대응할 수 있는 솔루션을 적용하는 방식을 활용할 수 있다.
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.