2021-06-29

YAML

YAML

YAML (데이터 직렬화)

XML, JSON 과 같은 데이터 직렬화 방식
최대한 간결하게 파이프라인을 구성하도록 되어있음

Tag

tag를 통해 데이터 구조를 명확히 지칭
일부 seq, map, object map, set 은 암시적인 tag로 적용됨

map:
  Block style: !!map
    Clark : Evans
    Oren  : Ben-Kiki

데이터 구조 (Collection Types)

seq, array (!!seq)

  Block style:
    - one
    - two
    - three
  Flow style: [one, two, three]

map (!!map)

map:
  # Unordered set of key: value pairs.
  Block style:
    Clark : Evans
    Ingy  : döt Net
    Oren  : Ben-Kiki
  Flow style: { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }

object map (!!omap)

objectMap:
  Block style:
    - one: 1
    - two: 2
    - three : 3
  Flow style: [ one: 1, two: 2, three : 3 ]

set (!!set)

set:
  Block tasks:
    ? Mark McGwire
    ? Sammy Sosa
    ? Ken Griffey
  # Flow style
  Flow style: { Boston Red Sox, Detroit Tigers, New York Yankees }

pair (tag need / !!pairs)

pairs:
  Block tasks: !!pairs
    - meeting: with team.
    - meeting: with boss.
    - break: lunch.
    - meeting: with client.
  Flow tasks: !!pairs [ meeting: with team, meeting: with boss ]

데이터 타입 (Scalar Types)

#========================================== string
string: abcd
swap string every line: |
  a
  long
  string
swap string last line: >
  a
  long
  string
#========================================== bool
bool:
  - true
  - True
  - TRUE
  - false
  - False
  - FALSE
#========================================== float
float:
  canonical: 6.8523015e+5
  exponentioal: 685.230_15e+03
  fixed: 685_230.15
  negative infinity: -.inf
  not a number: .NaN
#========================================== int
int:
  canonical: 685230
  decimal: +685_230
  octal: 0o2472256
  hexadecimal: 0x_0A_74_AE
  binary: 0b1010_0111_0100_1010_1110
#========================================== null
null:
  # This mapping has four keys,
  # one has a value.
  empty:
  canonical: ~
  english: null
  ~: null key
  # This sequence has five
  # entries, two have values.
  sparse:
    - ~
    - 2nd entry
    -
    - 4th entry
    - Null
#========================================== timestamp
timestamp:
  canonical:        2001-12-15T02:59:43.1Z
  valid iso8601:    2001-12-14t21:59:43.10-05:00
  space separated:  2001-12-14 21:59:43.10 -5
  no time zone (Z): 2001-12-15 2:59:43.10
  date (00:00:00Z): 2002-12-14

데이터 구조 병합 (Merge)

override 시, 먼저 참조한 데이터의 값을 먼저 사용

#============================================== object
object:
  foo: &foo
    a: 1
    b: 2
  bar:
    <<: *foo
    c: 3
  marge object a: &moa
    a: 1
    b: 2
  marge object b: &mob
    a: 3
    c: 4
  marge all:
    <<: [*moa, *mob]
  marge all with data:
    <<: [*moa, *mob]
    new data: new
#============================================== list
list:
  - &CENTER { x: 1, y: 2 }
  - &LEFT { x: 0, y: 2 }
  - &BIG { r: 10 }
  - &SMALL { r: 1 }

  - # Explicit keys
    x: 1
    y: 2
    r: 10
    label: nothing

  - << : *CENTER
    r: 10
    label: center

  - << : [ *CENTER, *BIG ]
    label: center/big

  - # Override
    << : [ *BIG, *LEFT, *SMALL ]
    x: 1
    label: big/left/small

2021-05-13

JavaScript 안티 패턴

JavaScript 안티 패턴

참조 문서

목차

  1. <script><body>최하단에 배치할 것 +
  2. 외부소스를 로컬로 관리할 것
  3. 전역변수 사용을 하지말 것 +
  4. import는 최상단에 배치할 것 +
  5. 선언없이 변수사용하지 말 것
  6. 생성자(Array/Object/Function)를 사용하지 말것 배열/객체 함수
  7. == 비교연산자를 쓰지 말 것
  8. 중괄호({…})를 생략하지 말것
  9. parseInt()에 진법을 붙일것
  10. switch에서 연속되고 기능이 있는 case사이에 break를 생략하지 말것
  11. 배열 순회시, for-in를 사용하지 말 것
  12. 배열 내에서 delete로 항목을 제거하지 말 것
  13. 반복문에서 절차에 따라 필요한 처리만 진행할 것
  14. 반복문에서 continue처리를 피할 것(불확실)
  15. 반복문안에서 try-catch 를 처리하지 말 것
  16. 돔 객체는 한번만 조회 할 것
  17. 돔 조작을 최소화 할 것
  18. 돔 레이아웃 불필요하게 초기화 하지 말 것
  19. 인라인 메소드 안에서 이벤트 처리를 하지 말 것
  20. eval()를 사용하지 말 것
  21. with()를 사용하지 말 것
  22. setTimeout/setInterval 사용시 문자열로된 callback 사용하지 말 것
  23. 기본 객체를 수정하지 말 것
  24. 증감연산자(++/--)를 사용하지 말 것
  25. this 를 따로 할당해서 쓰지 말 것
  26. 코드끝에 ;을 생략하지 말 것
  27. (ES5)정의하기전에 사용하지 말 것
  28. (Legacy)배열 순회시, array.length값을 정의해서 쓸 것

상세

<script><body>최하단에 배치할 것

script 에 정의된 소스들을 다운받는 과정에서 렌더링이 지연됨 참조

script async
스크립트 다운로드가 완료된 경우, 스크립트 파싱 후 HTML 파싱 재개

script defer
스크립트 다운로드가 완료되더라도 HTML 파싱후, 스크립트 파싱

1. 외부소스를 로컬로 관리할 것

CDN 기능 오류 나 네트워크 문제등의 외부 문제로 오류가 발생하는 것을 방지

2. 전역변수 사용을 하지말 것

다른 위치에서 접근하거나 기능이 덮어써질 가능성이 있음

Namespacing

// Bad - 중복될 가능성이 있음
const name = 'Nicholas'; // window.name === 'Nicholas'
function sayName() {
  alert(name);
}

// Good - Defined a global object MyApp and defined name variable and sayName function inside the MyApp
const MyApp = {
  name: 'Nicholas',
  sayName() {
    alert(this.name);
  }
};

Immediately Invoked Function Expression

// Bad - today variable is global, so still remains after the code has been reset
const today = new Date();

alert(`Today is ${today.getDate()}`);

// Good - today variable is local to an anonymous function, so cannot be accessed from outside of the IIFE
(function() {
  const today = new Date();

  alert( `Today is ${today.getDate()}`);
})();

4. import는 최상단에 배치할 것

가독성 문제

5. 선언없이 변수사용하지 말 것

전역변수로 생성됨으로 추가적인 문제 발생
function 의 경우, eval()을 통해야 함으로 성능 저하 발생

6. 생성자(Array/Object/Function)를 사용하지 말것 배열/객체 함수

성능면이나 가독성 면에서 더 불리함

7. == 비교연산자를 쓰지 말 것

암시적 형변환을 거치게 됨으로 타입오류나 가독성 문제가 발생===

8. 중괄호({…})를 생략하지 말것

가독성 문제

9. parseInt()에 진법을 붙일것

문자열이 0x또는 0X로 시작하면 16 진수를 사용하고 0으로 시작하면 8 진수 또는 10 진수를 사용하여 문제가 발생할 수 있음

// Bad
const month = parseInt('08');
const day = parseInt('09');

// Good
const month = parseInt('08', 10);
const day = parseInt('09', 10);

// Tip : If converting to decimals, using Number() function or '+' operator is faster.
const month = Number('08')
const day = +'09';

10. switch에서 연속되고 기능이 있는 case사이에 break를 생략하지 말것

코드 누락인지 아니면 의도된 절차인지 가독성의 문제 발생

// Bad - case 사이에 다른 처리를 한상태에서 break 없이 다른 case로 넘어가지 않도록
switch (foo) {
  case 1:
    A()
  case 2:
    B();
    break;
  ...
}

11. 배열 순회시, for-in를 사용하지 말 것

for-in 배열 사용시, 배열내의 빈값이 있을때 생략하는 문제가 발생하며. 배열순회 성능면에서도 for-in을 지양하는 것이 좋음. 그러나 가독성 면에서 array.forEach()가 유리한점도 있음.

12. 배열 내에서 delete로 항목을 제거하지 말 것

배열내에 delete로 삭제된 항목이 undefined 로 남아 배열의 전체 길이는 동일하게 유지됨, 빈 배열 항목을 처리한다는 관점에서는 역으로 이용이 가능한 부분?

// Bad
const numbers = ['zero', 'one', 'two', 'three', 'four', 'five'];
delete numbers[2]; // ['zero', 'one', undefined, 'three', 'four', 'five'];

// Good
const numbers = ['zero', 'one', 'two', 'three', 'four', 'five'];
numbers.splice(2, 1); // ['zero', 'one', 'three', 'four', 'five'];

13. 반복문에서 절차에 따라 필요한 처리만 진행할 것

중복되는 변수나 조건에 부합하지 않는 처리를 반복문에서 제외하여 성능 저하를 막을것

14. 반복문에서 continue처리를 피할 것(불확실)

과도하게 사용될경우, 가독성의 문제와 함께 javascript 엔진이 별도의 컨텍스트로 관리하기에 성능문제가 발생할 수 있음

추가로 찾아봤을때, breakcontinue가 나쁜 프로그래밍 관행입니까?에서 처럼 무조건 안쓰는것이 옳다고는 할수 없는 것으로 보인다. What is the point of the no-continue rule?의 내용에서는 countinuego to 처럼 continue label로 처리되는것에 대해 금지한다는 의미인것으로 애기하고 있다.
차라리 filter()의 형태로 정제된 리스트만 처리하면 되지 않을까?

let loopCount = 0;
// Bad
for (let i = 1; i < 10; i += 1) {
  if (i > 5) {
    continue;
  }
  loopCount += 1;
}

// Good
for (let i = 1; i < 10; i += 1) {
  if (i <= 5) {
    loopCount += 1;
  }
}

15. 반복문안에서 try-catch 를 처리하지 말 것

루프가 반복될때마다 예외 개체가 현재 범위에서 저장되기 때문

// Bad
const {length} = array;
for (let i = 0; i < length; i += 1) {
  try {
    ...
  } catch (error) {
    ...
  }
}

// Good
const {length} = array;
function doSomething() {
  try {
    ...
  } catch (error) {
    ...
  }
}
for (let i = 0; i < length; i += 1) {
  doSomething();
}

16. 돔 객체는 한번만 조회 할 것

성능저하 문제

17. 돔 조작을 최소화 할 것

innerHTML, appendChild() 호출시마다 DOM을 다시 그리게되어 성능문제 발생

18. 돔 레이아웃 불필요하게 초기화 하지 말 것

layout thrashing으로 인해 성능저하 문제

layout thrashing
layout thrashing을 강제하는 것
DOM 요소가 변경될 경우, 기존 layout은 무효화 되어 추가로 layout 호출시 새로 계산이 필요하여 성능지연이 발생

// Bad
elementA.className = "a-style";
var heightA = elementA.offsetHeight; // layout is needed
elementB.className = "b-style"; // invalidates the layout
var heightB = elementB.offsetHeight; // layout is needed again

// Good
elementA.className = "a-style";
elementB.className = "b-style";
var heightA = elementA.offsetHeight; // layout is needed and calculated
var heightB = elementB.offsetHeight; // layout is up-to-date (no work)
// Bad
function resizeWidth(paragraphs, boxElement) {
  const {length} = paragraphs;

  for (let i = 0; i < length; i += 1) {
    paragraphs[i].style.width = `${boxElement.offsetWidth}px`;
  }
}

// Good
function resizeWidth(paragraphs, box) {
  const {length} = paragraphs;
  const width = boxElement.offsetWidth;

  for (let i = 0; i < length; i += 1) {
    paragraphs[i].style.width = `${width}px`;
  }
}

19. 인라인 메소드 안에서 이벤트 처리를 하지 말 것

소스 관리나 이벤트 처리 관점에서 혼란을 일으킴

20. eval()를 사용하지 말 것

구문 분석을 처리하는 과정에서 성능 문제가 크게 발생하며 보안측면에서도 매우 문제가 많음

21. with()를 사용하지 말 것

처리되는 과정에 대해 가독성 문제가 있으며 별도의 영역을 생성하여 성능문제도 발생

// Bad
with(document.getElementById('myDiv').style) {
  background = 'yellow';
  color = 'red';
  border = '1px solid black';
}

// Good
const {style} = document.getElementById('myDiv');
style.background = 'yellow';
style.color = 'red';
style.border = '1px solid black';

22. setTimeout/setInterval 사용시 문자열로된 callback 사용하지 말 것

내부적으로 문자열 함수에 대해 eval()이 처리 됨으로 20. 과 같은 문제 발생

// Bad
function callback() {
  ...
}
setTimeout('callback()', 1000);

23. 기본 객체를 수정하지 말 것

예측할 수 없는 오류가 발생할 가능성이 큼, 하지만 polyfill 처럼 긍정적인 사용방향도 있음

Monkey Patch
몽키패치- 런타임 중에 코드를 수정하는 것
Polyfill 처럼 구형 브라우저를 지원하기 위해 구형 브라우저의 코드를 수정해야 하거나, 개발 후 테스트를 진행할때 임시로 데이터 요청을 다른곳으로 요청하던지 하는 방식으로 사용될 수 있다. 그러나 동적으로 수정한다는 점에서 문제의 소지가 될 수 있다는점

24. 증감연산자(++/–)를 사용하지 말 것

i++++i와 같이 처리와 할당의 관점이 혼란을 야기해서 편의에 비해 문제소지가 있음

// Increment
let a = 1;
console.log(a++);    // 1 
console.log(++a);    // 3
// Decrement
let b = 1;
console.log(b--);    // 1
console.log(--b);    // -1

25. this 를 따로 할당해서 쓰지 말 것

클로저로 사용할 수 있지만 가독성의 문제, 관련하여 다른 의견에서는 오히려 명시적인 구분이 된다는점에서 장점도 있다는 의견이 있음

// Bad
function() {
  const self = this;
  return function() {
    console.log(self);
  };
}
function() {
  const that = this;
  return function() {
    console.log(that);
  };
}
function() {
  const _this = this;
  return function() {
    console.log(_this);
  };
}

// Good
function printContext() {
  return function() {
    console.log(this);
  }.bind(this);
}
function printContext() {
  return () => console.log(this);
}

26. 코드끝에 ;을 생략하지 말 것

구문의 분리가 명확하지 않고 내부적으로 누락된 ;을 처리하는 과정에서 성능 문제 발생

27. (ES5)정의하기전에 사용하지 말 것

가독성 문제와 함께 호이스팅으로 인해 혼란 발생

28. (Legacy)배열 순회시, array.length값을 정의해서 쓸 것

IE10 과 같은 브라우저에서는 큰 성능문제를 일으킴

2021-03-22

2021-03-22 GraphQL

2021-03-22 GraphQL

GraphQL

페이스북에 의해 REST 구조를 개선하기 위한 방식으로 개발된 시스템

구조

기존 REST는 우측과 같이 서버에서 데이터를 가져올때 연관된 요청을 모두 요청 해야한다. 하지만 그 과정에서 항상 모든 정보가 쓰이진 않으며 처리될때 어떤 정보를 받게될지 명확하지 않다.
이점을 개선하여 SQL 과 같이 필요한 정보만을 타입 과 데이터 구조를 요청하게 된다.

내부 구조는 간단히 키워드로만 구성된 계층구조로 조회하는 형태로 보인다.
상세한 구조는 document에 심층적으로 소개되어있으니 그걸 참조

{
  hero {
    name
  }
}
{
  "data": {
    "hero": {
      "name": "R2-D2"
    }
  }
}

장단점

REST의 일부 단점을 개선 하였지만 그렇다고 완벽한것은 아닌것
알아서 상황에 맞는 구조로 설계하기

  • 필요한 데이터만 요청
  • 어떤 데이터구조가 이용될지 명확
  • 한번의 요청으로 필요한 데이터 조회가능

  • 기존 http 캐싱 구조를 사용할 수 없음
  • 파일 업로드의 명확한 구현이 되어있지않음
  • 요청 필터링의 어려움

    사용될 데이터를 요청할때 구조가 정의되는 탓에 항상 최적의 데이터를 조회한다고 볼수없기때문

  • 구조가 복잡해지는 문제
  • 이미 REST 구조로도 처리가 가능한 경우가 존재

Written with StackEdit

참조
5 reasons you shouldn’t be using GraphQL
GraphQL의 단점과 대안

2021-03-22 Pub-Sub 구조

2021-03-22 Pub-Sub 구조

Publish - Subsclibe

구조

아래와 같이 publisher 가 topic 계층으로 전달한 메세지를 broker 에서 해당 topic 을 보고있는 subscriber에게 메세지를 전달하는 구조

subscriber
publisher
topic/location
topic/state
topic/state
topic/location
topic/state
topic/location
state
location
state,location
update
broker

Written with StackEdit.

2020-11-30

js Proxy & Reflect (like observer)

js Proxy & Reflect (like observer)

MDN Proxy / MDN Reflect

proxy 와 reflect는 동일하게 동작하지만
reflect로 정의된 객체를 proxy로 재정의하여
동작을 할당한다고 보면 될것으로 생각됨

아래와 같은 관계로 재정의 되지않은 기본동작 정의

new Proxy(obj, {
  get: Reflect.get,
});

정리

MDN handler

var 대상Object = {} ;
var hander = new handler(....참조);
var obj = new Proxy(대상Object,  handler);

handler props

get
prop 값 호출시

get: function (대상_object,대상_prop_명) {}

set
prop 값 설정시

set: function (대상_object, 대상_prop_명, 설정값) {}

deleteProperty
prop delete시

deleteProperty: function (대상_object, 대상_prop_명) {}

ownKeys
Object.keys(대상obj) 호출시

ownKeys: function (object_내부의_모든_props) {}

has
prop 조회시

has: function (대상_object, 찾을_prop_명) {}

defineProperty
prop 조회시

defineProperty: function (대상_object, 추가된_prop_명, 정의된_값의_속성) {}

getOwnPropertyDescriptor
설명 요청시

getOwnPropertyDescriptor: function (대상_object, 설명을_검색할_prop_명) {}

Written with StackEdit.

2019-12-16

2019-12-12 피드백 || RDB 와 NO-sql

2019-12-12 피드백 || RDB 와 NO-sql

RDB (Relational Database)

ACID rules

  • 원자성(Atomicity) - 중간 단계까지 실행되고 실패하는 일이 없도록 하는 것
  • 일관성(Consistency) - 트랜잭션 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것
  • 고립성(Isolation) - 다른 트랜잭션의 작업이 끼어들지 못하도록 보장하는 것
  • 지속성(Durability) - 성공적으로 수행된 트랜잭션은 영원히 반영되는 것

NO-sql (Not Only SQL)

Key-Value

DynamoDB에 키-값 쌍으로 저장된 데이터의 예를 보여주는 다이어그램

  • Set 처럼 자료 저장

document

[
    {
        "year" : 2013,
        "title" : "Turn It Down, Or Else!",
        "info" : {
            "directors" : [ "Alice Smith", "Bob Jones"],
            "release_date" : "2013-01-18T00:00:00Z",
            "rating" : 6.2
        }
    },
    ....
    {...}
]
  • json 과 같은 비슷한 형태

그래프

소셜 네트워크 그래프의 사례

인 메모리

  • 디스크 대신 RAM에 저장
  • 휘발성

RDB vs NO-sql

관계형 데이터베이스 NO-sql 데이터베이스
최적의 워크로드 관계형 데이터베이스는 트랜잭션 및 강력히 일관된 온라인 트랜잭션 프로세싱(OLTP) 애플리케이션을 위해 설계 NoSQL 키 값, 문서, 그래프 및 인 메모리 데이터베이스는 낮은 지연 시간의 애플리케이션을 포함한 수많은 데이터 액세스 패턴에 맞도록 OLTP를 위해 설계되었습니다. NoSQL 검색 데이터베이스는 반정형 데이터에서 분석을 위해 설계되었습니다
데이터 모델 테이블, 행, 열, 인덱스, 테이블 간 관계, 기타 데이터베이스 요소를 정확하게 규정 문서, 그래프, 키 값, 인 메모리, 검색 등 다양한 데이터 모델
ACID 속성 ACID(atomicity, consistency, isolation, durability)의 속성을 제공 관계형 데이터베이스의 일부 ACID 속성을 완화
성능 디스크 하위 시스템에 따름. 쿼리, 인덱스, 테이블 구조 최적화 필요 하드웨어 클러스터 크기, 네트워크 지연 시간 및 호출 애플리케이션에 따름
확장 머신성능 향상 분산형 아키텍처
API 요청 SQL(구조화 질의 언어)을 준수하는 쿼리 객체 기반 API

성능

데이터 모델 성능 확장성 유연성 복잡성 기능
키-값 스토어 높음 높음 높음 없음 가변적 (없음)
컬럼 지향 스토어 높음 높음 준수 낮음 최소
도큐먼트 지향 스토어 높음 가변적 (높음) 높음 낮음 가변적 (낮음)
그래프 데이터베이스 가변적 가변적 높음 높음 그래프 이론
관계형 데이터베이스 가변적 가변적 낮음 준수 관계대수

2019-12-14

2019-12-12 피드백 || API 요청조절 - 스로틀링(Throttling), 디바운스(Debounce)

2019-12-12 피드백 || API 요청조절 - 스로틀링(Throttling), 디바운스(Debounce)

스로틀 (Throttle)

정해진 시간보다 많은 요청을 제한적 수용

디바운스 (Debounce)

연속적인 요청 발생 후 일정 시간 후 수용

버킷 알고리즘

FIFO 큐 형태로 패킷을 버킷에 담듯 쌓아서 처리 알고리즘에 따라 패킷제어

토큰 버킷 (Token bucket)

https://i.imgur.com/XCfQQ0K.png
정해진 양의 토큰을 순환적으로 전달될 요청에 담아 토큰을 포함한 요청만 처리하는 패킷제어

소요시간 계산식
time = bucketSize ÷ (packetRate - tokenArrivalRate) × 1000m

리키 버킷 (Leaky Bucket)

Leaky Bucket
최대 대역폭을 정해 일정한 요청이 발생하도록 패킷제어

초기값

limit = 1000
packet = [200, 700, 500, 450, 400, 200]

limit 을 초과하지 않는 패킷을 network로 전송

limit = 1000 - 200 = 800
packet = [200, 700, 500, 450, 400]
limit = 1000 - 400 = 400
packet = [200, 700, 500, 450]

pacaket[firstIn] > limit 인 경우, 절차 중단후 limit = 1000 으로 초기화 후 다음 절차 진행

소요시간 계산식
time = bucketSize × packetRate ÷ 1000m

참조

Written with StackEdit.