Coding (164)

07
27

같이 알바하는 동기가 일을 동기적으로 하면...? 더이상 동기사랑은 어렵게 된다.

1. 사건의 발단.

 나는 다양한 알바와 일들을 했었다. 카페부터 고깃집, 건축, 상하차, 대학 사무실 등 다양한 일들을 하며 많은 동기들을 만났다. 그럴 때마다 함께 일하는 친구들을 분석하곤 했다. 정말 다양한 사람들이 있었다. 어떤 사람은 일을 똑바로 가르쳐 주지 않아도 주어진 시간에 안에 완벽히 수행해 내고, 어떤 사람들은 정해진 시간도 모자라서 몇 명의 인원이 도움을 줘야 겨우 일을 마치는 그런 친구들도 있었다. 그런 친구들의 주된 특징은 '비효율'적인 행동에 있다.

 

2. 동기

  • 코드가 적혀있는 순서대로 실행된다.
  • 그래서 하나의 코드가 끝나기 전에 다음 코드는 실행되지 않는다.
  • 위의 비효율적인 일을 하는 친구들이 하는 행동과 같다.
  • 예를 들어, 오븐에 빵을 넣고 구워지는 동안 설거지라도 할 수 있지만, 그렇지 않고 오븐 앞에서 빵을 지키고 있다가, 다 되면 서빙을 하고 난 후에 돌아와 다른 일을 한다.

3. 비동기

  • 꼭 코드가 적혀있는 순서대로는 실행되지 않는다.
  • 그래서 코드가 실행되는 도중 먼저 필요한 코드를 실행하고 중간에 다른 코드를 실행하며 알맞은 일을 할 수 있다.
  • 효율적으로 일을 하는 친구들에 해당된다.
  • 예를 들어, 오븐에 빵을 넣어놓고 온도와 타이머를 정확히 맞춰 놓고 빵이 타이머가 울리기 전에, 설거지도 하고, 시간이 남아 바닥도 한번 쓸고, 손도 씻고 난 후에 타이머가 완료된 빵을 가지고 서빙을 하는 것이다.
  • 여러 가지 스레드가 돌아간다고 생각할 수 있다. 너무 느린 속도를 가진 일을 다른 스레드에서 실행하게 해 두고 그 보다 빠른 일을 막히지 않게 끝내는 것이다.

4. 자바스크립트의 비동기

  • 자바스크립트는 싱글 스레드를 가진다. 그렇다면 어떻게 비동기적으로 코드를 실행시킬 수 있을까?
  • '콜백 함수'를 사용한다.
    • 함수는 스택 형태로 사용되지만, 큐 형태로 사용해야 맞다. 하지만 웹 API가 시간을 처리하는 요소들을 담당하기 때문에 가능하다.
    • 그렇게 비동기 요소는 따로 처리되어 태스크 큐에 저장되고, 콜백 함수들을 받아 실행시킨다.
  • 결국은 콜백 지옥이 되고 말 것이다.

5. Promise

  • 콜백 지옥을 막기 위해서 ES6 이상부터 사용 가능한 함수
  • 첫 번째 인자로 수행할 비동기 작업, 두 번째 인자로 콜백 함수에 전달하는 함수를 넣는다.
  • 이를 체이닝 방식으로 비동기 작업을 순서대로 적어 보기 쉽게 작성 가능하다.

6. Async & Await

  • promise보다 더 직관적으로 함수를 실행할 수 있게 한다.
  • 비동기 함수 앞에 async를 적으면 동기 작업처럼 비동기 함수를 작성할 수 있다.
  • 이후 비동기 함수로 조회된 데이터를 변수에 할당할 때도 await을 적어서 멈추게 할 수 있다. 마지막 변수에만 await을 안 적으면 그것부터 위로 실행되게 될 것이다.

 

COMMENT
 
07
25

이런 그래프를 코드로 작성 한다면 어떻게 될까? 

1. Graph

  • 우리가 생각하는 그 그래프가 맞다.
  • 하지만 이것을 코드로, 그리고 글로 작성한다는 것을 생각해 보면 된다.

2. Graph에서 사용하는 용어

  • 정점(vertex) : 그래프에서 볼 수 있는 하나의 점
  • 간선(edge) : 연결된 선
  • 무(방)향 그래프(undirected graph) : 서로 연결되어 있어서 서로가 서로에게 접근이 가능한 그래프.
  • 단방향 그래프(directed graph) : 한쪽에서만 연결되어 있는 그래프
  • 진입 차수(in degree)와 진출 차수(out degree) : 몇 개의 간선으로 들어오고 몇 개의 간선으로 나가는지
  • 인접(adjacency) : 정점들 사이에 아무것도 없고 서로 한 번에 간선으로 연결된 경우
  • 자기 루프(self loop) : 간선이 진출되어 다시 자신에게 돌아오는 경우
  • 사이클(cycle) : 다시 돌아서 각각의 정점들을 거쳐 자신으로 돌아오는 형태의 그래프

3. Tree

  • 나무를 뒤집어 놓은것 처럼 계층으로 나누어 뻗어나가는 그래프
  • 토너먼트 대진표 같은 모양을 생각하면 된다.

4. Tree에서 사용하는 용어

  • 노드(Node) : 각각 하나의 요소에 해당하는 데이터
  • 루트(Root) : 트리의 시작점이 되는 노드
  • 부모 노드(parent node) : 부모가 되는 상위의 노드
  • 자식 노드(child node) : 자식이 되는 하위의 노드
  • 리프(leaf) : 더 이상 자식이 없는 끝이 되는 노드

5. Binary Search Tree

  • 트리는 자료를 탐색할때 사용할 수 도 있다.
  • 이때, 처음 루트에서 두 가지 노드로 빠져나오는 형태를 가진 이진트리(Binary Tree)를 대표적으로 사용할 수 있다.
아무리 자료구조를 안다고 해도 알고리즘 문제를 풀기는 쉽지 않았다.
그래서 가장 처음으로 다시 돌아가서 용어 정리부터 다시 시작해본다.
COMMENT
 
07
22

1. Stack

사막여우 '스택'이 쌓여있다. 넘어지지 않고 사막여우들이 내려오려면 어떻게 해야할까?

  • 우리가 주로 사용하는 'stack'을 쌓다 라는 말을 생각해 보면 쉽게 알 수 있다.

우리 팀 나서스 20분에 스택 700개, 그는 신이야...!

  • 스택은 자료를 받아와 마지막에 받아온(가장 최근에 들어온) 자료부터 빠져나간다.
  • 우리는 이미 스택을 잘 사용하고 있다. Array 같은 거 말이다. 일상생활에서는 페이지 앞, 뒤로 가기 기능이 있다.
  • 주로 push, pop, top(가장 상단의 데이터를 보여줌), size(얼마나 데이터가 쌓였는지 보여줌)를 사용한다.

2. Queue

게임에서도 '큐'형식으로 줄을 선다. 게임을 하기전에도 줄을 서서 입장하고, 들어 가서도 또 줄을 선다! 질서의 민족!

  • 우리가 주로 사용하는 'Queue'를 잡다 라는 말을 생각해 보면 쉽게 알 수 있다.

ex) 큐 돌려놓고 화장실 가라 빨리 시작하게

  • 큐는 데이터를 순서대로 쌓아 들어온 순서대로 빠져나온다.
  • 일상생활의 줄 서기, 프린터의 작동원리 등으로 볼 수 있다.
  • 주로 push, shift, size를 사용한다.

3. 자료구조를 문제에 적용하는 나의 태도

  • 대부분 알고리즘 문제에 주로 사용된다.
  • 스택과 큐의 특징을 이용하여 문제를 푸는 것이지, 꼭 직접적으로 사용할 필요는 없다.
  • 주로 스택과 큐 둘 다 배열을 잘 사용하며, 배열에 유리한 메서드들을 이용해 데이터를 가공한 후 스택과 큐의 특징처럼 저장소를 사용해 문제를 해결하는 형식이 많다.
문제를 무조건적으로 많이 풀어 보아야 한다. 이미 스택과 큐의 특징은 우리 모두 잘 알고 있을 것이다.
하지만 어떻게 문제에 접근해야 하는가? 에 대한 부분이 매우 시간이 오래 걸린다.
가장 빠른 왕도는 다양한 문제를 접해보고 생각의 범위를 넓이는 것이라고 한다.
요즘 꽤나 공부할 양이 말도 안 되게 늘어서 고통받고 있지만 질질 끌려다니면서 어떻게든 해내고 있는 것 같다.
어떻게든 되겠지, 죽기밖에 더 하겠어
COMMENT
 
07
21

계속 보면 어지럽습니다. 그만 보세요. 재귀함수도 그렇습니다!

1. 재귀 함수?

  • 재귀 함수는 자기 자신을 다시 리턴하는 재귀 함수를 가지는 자기 자신을 다시 리턴하는 재귀 함수를 가지는 자기 자신을 다시 리턴하는 재귀 함수를 가지는 자기 자신을 다시 리턴하는 재귀 함수를 가지는...
  • 자기 자신을 다시 리턴하는 함수이다.
  • 이게 무슨 의미인가?
    • 반복문과 똑같이 작동한다.
    • 반복문처럼 '조건'을 가지고 그 조건에 맞으면 함수를 끝내게 된다.
    • 가독성이 다른 반복의 코드보다 좋다.

2. 예시

  • 한동안 우리를 한참 괴롭히던 피보나치 함수의 재귀 함수 버전이다.
function fibonacci(num) {
  if(num === 0) {
    return 0;
  } else if(num === 1) {
    return 1; // 앞의 if와 else if로 탈출 조건을 만들어 주었다.
  } else {
    num = fibonacci(num - 2) + fibonacci(num - 1) // 우리가 원하는 답을 다시  num에 넣는다.
    return num;
  }
}
  • 반복문 버전보다 훨씬 간단하다.
  • 하지만 효율적이지는 않다. 계속해서 함수를 불러오기 때문에 스택에 무리가 간다.

3. 재귀 함수를 어떻게 쓸 수 있을까?

입력값과 출력 값을 확인한다.

  • 어떤 입력을 받아서 출력을 하는지를 정확히 알아야 함수가 리턴하는 값이 다시 자신으로 들어와 작동할 수 있는지를 알아야 한다.

문제를 쪼개서 생각한다.

  • 입력값을 기준으로 경우의 수를 생각해 본다.
  • 원하는 답으로 가기 위해 한 단계씩 진행되는 과정을 생각해 본다.

탈출 지점 만들기

  • 재귀 함수를 돌다가 원하는 답이 리턴되는, 즉, 가장 작은 단위로 해결된 결과를 리턴한다.
  • 이를 base case라고 한다.

문제를 계속 쪼개어 준다.

  • 더 작은 단위로 문제를 쪼개어 준다. 재귀함수를 탈출하지 못하고 돌 때마다 해결해야 할 문제가 계속 줄어드는 것이다.
  • 이를 recursive case라고 한다.
대충은 알겠지만 계속 사용해 보아야 부족함 없이 쓸 수 있을 것 같다. 재귀 함수는 반복문으로 사용할 수 도 있는데 이것도 생각을 해 보아야 할 문제이다.
COMMENT