asyncawait을 사용하는 경우에, 이미 조회한 리스트의 각 요소에 대해 추가로 조회하여 반환해야하는 경우에 대해 어떻게 처리해야할까 찾아보았다.

stack overflow에서 찾아보니 아래와 같이 Promise.allArray.map을 사용하여 처리하는 것을 보았다.

const arr = [1, 2, 3, 4, 5];

const results: number[] = await Promise.all(arr.map(async (item): Promise<number> => {
    await callAsynchronousOperation(item);
    return item + 1;
}));

동일한 방법으로 사용자의 목록을 불러온 뒤에 개별 사용자의 사진을 불러올 때 사용하니 의도한대로 동작하였다.

  @get('/users')
  async find(
    @param.query.string('filter') filter: Filter,
  ): Promise<UserInterface[]> {
    const users: User[] = await this.userRepository.find(filter);
    return await Promise.all(
      users.map(
        async (user: User): Promise<UserInterface> => {
          const picture: Picture = await this.pitureRepository.findById(
            user.pictureId,
          );
          return {
            id: user.id,
            email: user.email,
            name: user.name,
            picture: picture,
            role: user.role,
          } as UserInterface;
        },
      ),
    );
  }

개발중인 사이트에서 새창을 띄우는데, 새창을 오픈 중에 팝업이 차단되어 뜨지 못하는 경우가 있었다. 문제는 팝업이 차단되어 노출되지 않는 것보다, 사용자가 스스로가 차단하지 않고 브라우저가 기본적으로 팝업을 차단하는 경우에 팝업이 열리지 않아 오류로 인해 팝업이 뜨지 않는 것으로 보이는 부분이었다.

이를 해결하기 위해 stackoverflow를 찾아보니, 여러 방법중에 아래의 방법이 가장 적합하다고 생각하여 사용하였다.

추가적으로 hasPopupBlocker의 작동시점을 setTimeout으로 조절해주어야하는 문제점이 있다.

function hasPopupBlocker(poppedWindow) {
    let result = false;

    try {
        if (typeof poppedWindow === 'undefined') {
            // Safari with popup blocker... leaves the popup window handle undefined
            result = true;
        }
        else if (poppedWindow && poppedWindow.closed) {
            // This happens if the user opens and closes the client window...
            // Confusing because the handle is still available, but it's in a "closed" state.
            // We're not saying that the window is not being blocked, we're just saying
            // that the window has been closed before the test could be run.
            result = false;
        }
        else if (poppedWindow && poppedWindow.test) {
            // This is the actual test. The client window should be fine.
            result = false;
        }
        else {
            // Else we'll assume the window is not OK
            result = true;
        }

    } catch (err) {
        //if (console) {
        //    console.warn("Could not access popup window", err);
        //}
    }
    return result;
}

사실 원글에서는 아래와 같이 부모, 자식 창 간에 postMessage를 사용하여 통신하는 방법이 모던하다고 첨언되어있었다. 이 방법은 자식이 cross-domain 인 경우에도 작동을 하겠지만, 필자의 경우에는 새창이 필자가 수정할 수 없는 경우여서 해당 방법을 사용할 수 없었다.

// child
window.addEventListener('load', function() {
  this.opener.postMessage({'loaded': true}, "*");
  this.close();
});

// parent
window.addEventListener('message', function(event) {
  alert(event.originalEvent.data.loaded)
});

Coding The Matrix를 보다보면 후반부에 갈수록 앞서 본 용어들에 대해서 잊어버려 찾는 것을 반복하게 되어 정리해보며 읽어나가고자 한다.

집합(Set)

수학 객체를 모아 놓은 것으로, 집합에 속하는 각 객체는 많아야 한 번 그 집합에 나타나는 것으로 간주한다. 집합은 원소들 사이에 순서가 없으므로 집합 내 원소의 순서는 중요하지 않다.

집합의 포함 관계는 위와 같이 나타내며, 두 집합이 같다는 것은 다음 두 단계를 사용하여 증명한다.

  1. 첫 번째 집합이 두 번째 집합에 포함됨을 증명한다.
  2. 두 번째 집합이 첫 번째 집합에 포함됨을 증명한다.

집합 S가 유한집합이면, |S|를 사용하여 집합의 크기(원소의 개수)를 나타낸다.

Ref

카테시안 곱(Cartesian product)

두 집합 AB의 카테시안 곱(데카르트 곱)은 a ∈ Ab ∈ B 의 모든 쌍 (a, b)으로 이루어진 집합이다.

Ref

함수(Function)

Ref

비공식

가능한 입력 집합 D의 각 원소에 대해 가능한 출력을 할당하는 규칙이다.

  • 출력 : 함수에 의한 입력의 상(image), 함수값
  • 입력 : 출력의 원상(pre-image)
  • 정의역 : 가능한 입력 집합
  • 공역 : 함수값이 선택되는 집합, 모든 원소가 함수값이 되어야하는 것은 아님
  • 치역 : 모든 정의역 원소들에 대한 함수값들의 집합, 공역의 원소들 중 실제로 함수값이 되는 공역 원소들의 집합

공식

(a, b)들의 집합(무한 집합도 가능)이다.

정의역 {1, 2, 3,...} × {1, 2, 3,...}을 가지는 곱셈 함수는 아래와 같이 나타낼 수 있다.

매핑

함수 f에 대해, f에 의한 q의 상을 f(a)로 나타낼때,

이면, qf에 의해 r로 매핑된다고 한다. (q ↦ r)

D에서 F로의 함수 or DF로 매핑하는 함수

  • f : 함수
  • 집합 D : 정의역
  • 집합 F : 공역

주어진 정의역과 공역을 가지는 함수들의 집합에 대한 표기법

집합 DF에 대해, D에서 F로의 모든 함수는 아래와 같이 나타낸다.

Fact 1.3.9

임의의 유한 집합 DF에 대해,

Ref

항등함수

임의의 정의역 D에 대해, 아래를 만족하면 함등함수라 한다.

모든 d ∈ D 에 대해, 항등함수는 다음과 같이 정의된다.

Ref

함수의 합성

두 개의 함수를 결합하여 하나의 새로운 함수를 얻는 것이다.

위와 같이 주어진 함수 fg에 대해,

합성 함수 g∘f는 정의역 A, 공역 C인 함수가 된다.(반드시, 함수 f의 치역이 함수 g의 정의역에 포함되어야 한다.)

Ref

함수 합성의 결합법칙

함수를 합성할 때 결합법칙이 성립한다.

Proposition 1.3.12

Ref

  • Ch1 - 6p

단사함수, 전사함수(Definition 1.3.14)

  • 단사함수

단사함수

함수 f : D ⟶ F 일때, 모든 x, y ∈ D에 대해, f(x) = f(y)x = y이면 단사함수이다.

  • 전사함수

전사함수

함수 f : D ⟶ F 일때, 모든 z ∈ F에 대해, f(x) = z를 만족하는 x ∈ D가 존재하면 전사함수이다.

Ref

역함수(Definition 1.3.13)

다음 두 조건을 만족하면 함수 fg는 서로의 역함수이다.

  • g∘f가 정의되고, g의 정의역에 대해 항등함수이다.
  • f∘g가 정의되고, f의 정의역에 대해 항등함수이다.

모든 함수가 역함수를 가지는 것은 아니며, 역함수를 가지는 함수를 가역적이라고 한다.

  • 가역함수는 단사함수이다. (Lemma 1.3.16)
  • 가역함수는 전사함수이다. (Lemma 1.3.17)
  • 함수가 가역적이 될 필요충분조건은 그 함수가 단사함수이며 동시에 전사함수인 경우이다.(전단사함수, Theorem 1.3.18)
  • 모든 함수는 많아야 하나의 역함수를 가진다. (Lemma 1.3.19)

Ref

가역함수를 합성한 함수의 가역성(Lemma 1.3.20)

만약 fg가 가역함수이고 f∘g가 존재하면, f∘g는 가역함수이고,

이다.

Ref

  • Ch1 - 9p

프로시저(Procedure)

입력(매개변수)을 받아들여 출력(리턴값)을 생산하는 계산 절차에 대한 정확한 기술이다.

def mul(p, q): return p*q

Ref

계산 문제(Computational problem)

프로시저가 필요할 수도 있는 입력-출력에 대한 사양(스펙)(input-output specification)이다.

- input: 1보다 큰 정수의 쌍 (p, q)
- output: 곱 pq

Ref

  • Ch1 - 4p

프로시저, 계산 문제, 함수의 연관 관계

  • 프로시저와는 달리, 함수 또는 계산 문제는 입력을 사용하여 출력을 어떻게 계산하는지에 대한 정보를 주지 않는다.
    • 동일한 입출력 사양을 만족하거나 동일한 함수를 구현하는 많은 다른 프로시저가 존재한다.
  • 때로는 동일한 프로시저가 다른 함수를 위해 사용될 수 있다.
  • 함수와는 달리, 계산 문제는 모든 입력에 대해 하나의 유일한 출력을 명시할 필요는 없다.
  • 함수와 계산 문제는 다르게 정의되지만 서로 연관되어 있다.
  • 정의역 각 원소에 대해 프로시저를 적용하여 출력을 확인하는 방법으로 원상 문제를 풀면 비용이 클 수 있지만, 모든 함수에 적용 가능한 더 나은 방법은 없다.
  • 원상 문제를 임의의 함수가 아니라 특정 종류의 함수에 적용하는 방법을 사용하면, 원상 문제를 풀기위한 빠른 프로시저가 존재하여도 실질적인 문제를 해결하는데 도움이되지 않을 수 있다.
  • 계산산의 어려움과 가능성 사이에서 길을 찾는 것이 필요하다.
  • 선형 함수들을 사용하여 실질적인 문제를 모델링하고 이 함수들을 사용하여 원상 문제를 풀 수 있다.

확률

확률이론

무엇이 일어날 수 있는지, 그리고 그것이 일어날 가능성이 얼마나 되는지에 관한 것이다.

Ref

확률분포

유한한 정의역 𝛀에서 음수가 아닌 실수의 집합 R+로의 함수 Pr(⋅)는 만약

이면 (이산) 확률분포이다.

  • 정의역 : 실험결과(outcome)
  • 치역 : 실험결과의 확률

확률은 실험결과의 상대적인 가능도(relative likelihoods)에 비례한다고 가정한다. 확률은 가능도의 수학적 개념을 의미하기 위해 사용한다.

가능도(likelihood) : 상식적인 개념을 의미하기 위해 사용

  • 균등(uniform)분포 :모든 실험결과가 동일한 가능성을 가지며 동일한 확률이 할당되는 경우이다.
  • 비균등분포 : 서로 다른 실험결과가 서로 상이한 확률을 가지는 경우이다.

Ref

사건과 확률의 합(Priciple 1.4.5 확률이론의 기본 원칙)

어떤 사건에 대한 확률은 그 사건을 구성하는 실험 결과들에 대한 확률의 합이다.

Ref

  • Ch1 - 12p

랜덤 입력에 함수 적용

  • 함수가 가역함수이면 확률이 보존된다.
  • 다양한 출력에 대한 확률은 입력에 대한 확률과 매칭된다.
  • 입력이 균등분포에 따라 선택되면, 출력의 분포도 또한 균등분포가된다.

Ref

  • Ch1 - 12~13p

function A () {
  this.name = 'A1';
  this.prop = 123;
  return {
    name: 'A2',
    prop: 456
  };
}
let a = new A();

JS에서 생성자 함수를 통해 new 호출할 때, 명시적으로 객체를 반환한다면 해당 객체로 재정의(override)하게 된다. 위 코드의 결과를 결과를 보면 변수 a에 할당된 객체는 A 생성자 함수에서 반환한 {name:"A2", prop: 456} 객체이다.

function B () {
  A.call(this);
  this.name = 'B1';
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
let b = new B();

만약 위 코드와 같이 생성자 함수 A를 상속하는 생성자 함수 B가 있을때, 변수 b에 할당된 객체는 생성자 함수 A에서 반환된 객체와 관계없이 {name:"B1", prop:123}이다. 생성자 함수 A에서 생성될 때 name:"A2"prop:123가 할당되고, 생성자 함수 B에서 생설될 때 name:"B1"이 재정의 된다.

class A {
  constructor() {
    this.name = 'A1';
    this.prop = 123;
    return {
      name: 'A2',
      prop: 456
    };
  }
}
let a = new A();

ES2015에 도입된 class 키워드를 사용해서 A를 생성하면 위에서 보았던 것과 같이 변수 a에는 반환된 객체인 {name:"A2", prop: 456}가 들어있다.

class B extends A {
  constructor() {
    super();
    this.name = 'B1';
  }
}
let b = new B();

반면 Prototype 상속을 통해 상속하였던 것과 마찬가지로 classextends 키워드를 사용하여 상속하여 반환값을 비교해보면 {name: "B1", prop: 456}Prototype 상속과 다른 값이 할당되어 있는 것을 볼 수 있다. A에서 반환된 객체가 부모가 되고, B에서 할당한 값들이 재정의되는 것에서 차이점이 있다.

ES2015에 도입된 class 키워드가 단순히 문법적 양념(syntac sugar)라고 생각해왔는데, 위와 같이 일부 다르게 동작되는 부분이 있다는걸 알 수 있었다. 새롭게 추가되는 스펙들에 대해서 좀 더 면밀히 알아봐야됨을 느꼈다.

Reference

$ git branch
feature/...
feature/...
release/...
release/...
hotfix/...
hotfix/...

Source Tree를 사용하건, Shell을 사용하건 관계없이 Git Branch들을 자주 정리해주지 않으면 금방 쌓이기 마련이다. Branch가 너무 많이 쌓이다보니 작업이 완료된 Brnach들과 작업하고 있는 Branch들이 구분되지 않아 불편하다. Source Tree를 통해서 일일이 지우기는 곤란하고 한번에 복수의 Branch를 지우고자 알아보니 아래와 같은 명령어를 사용하면 손쉽게 정규 표현식을 사용하여 필요한 Branch만 제거가 가능하다.

git branch -D `git branch | grep -E 'feature/*'`

Reference