TIL
코딩 부트캠프에 뛰어든 지 벌써 9주 차가 되었다. 총 10주 간 진행되는 코딩 부트캠프 중 9주 차라니 그야말로 고지를 앞두고 있는 상황이다. 지난주만 해도 자바스크립트의 비동기 호출이나 Timer API 등을 공부하고 있어서 끝이 다가왔다고 크게 느끼지 못하고 있었는데, 이번 주 수료 안내 메일과 pre course에 이어 진행되는 immersive course 안내를 받고 나니 10주간의 여정이 거의 다 끝나간다는 생각이 확연히 들었다.
학교를 졸업할 때와 마찬가지로 코스의 끝은 "끝"이 아닌 "시작"인걸 알기에 이번 한 주는 앞으로 소프트웨어 엔지니어가 되기 위한 학습 과정이나 지금까지 내가 쌓아온 병아리 실력에 대해 이리저리 생각해보는 시간이 꽤 길었다.
물론 이 모든 것은 마지막 recursion(재귀 함수 구현하기) 과제를 완성하고 수료를 마친 후 일어날 과정들이기 때문에 고민만 하고 있을 순 없었다.
마지막 과제인 재귀 함수 구현은 개념을 파악하는 것이 관건이었고, JSON.Stringify나 DOM getElementsByClassName 같은 method를 재귀로 구현하는 것이었는데 이틀 정도 자리에 눌러앉아서 하나하나 구현을 해낸 것 같다. 이 복잡한 구문을 하나의 함수로 구현해두고 사용자들에게 제공하다니!
이미 구현된 라이브러리에 대한 감사함과 경의를 표하는 시간이기도 했다.
매주 토요일 진행되는 오프라인 세션도 막바지에 접어들고 있는데, 이번 주는 지난주에 이어서 2명이 한 팀이 되어 [카페 주문 POS기 만들기]를 완성했다. 첫 주는 함께 HTML 구조를 짜고 JS와 CSS에서 공용으로 사용할 Selector id/class를 정하고 CSS 디자인은 지난 Twitter 유사 버전 만들기 과제에서 구현했던 것들을 가지고 왔다.
이번 주는 페어가 구성해준 CSS Layout에 메뉴나 주문내역을 렌더 하는 부분을 위해서 Java Script logic을 적용시키는데 많은 시간을 보냈다.
분명히 Twittler 작업을 할 때 알았고 구현했던 기초 내용들인데 또 새롭다. 완성한 순간 페어와 짧은 환호를 하고 난 뒤 곧바로 '아, 그냥 보기엔 슥슥 만들면 될 것 같은데 토요일 내내 시간을 쏟은 나는 진짜 멀었구나' 싶어서 이내 초라함이 나를 뒤덮었다.
지난 9주간 코스 과정을 밟아오면서 이런 류의 초라함을 많이 마주했는데 그때마다 내가 지금 어느 위치에 있는지(난 아직 개발자가 아니고 개발 공부를 막 시작한 사람이라는 것)를 깨닫고 겸허히 공부하는 수순을 밟았던 것 같다. 이번 주도 그러했다.
[할 수 있는 만큼 배우고 흡수하는 것] 그게 앞으로의 개발 공부에서 내가 제일 중요하게 생각해야 하는 지점인 것 같다.
Recursion - 재귀 함수
Prototype
서버에 요청하기 Fetch API
JSON.Stringify를 재귀로 구현하기
재귀의 개념: 스스로 함수를 호출하는 프로그래밍 콘셉트
재귀를 짤 때는 무한 반복을 피하기 위해 ‘탈출 조건(base case 혹은 termination case라고 부름)’이 필요, 언젠가는 끝나도록!
재귀는 반복할 구문을 함수 단위로 분리해서 특정 조건이 만족할 때까지 실행하는 패턴(recursive case)
재귀의 장점: 재귀로 작성했을 때 표현식이 직관적
재귀의 단점: 값이 리턴되기 전까지 호출을 해야 하고, 그때마다 call stack을 새로 생성해 쌓아 올리기 때문에 메모리 할당이 높음(비효율적)
대표적인 예제: Factorial n! = n * (n-1)! **n이 2가 될 때까지 구문 반복
재귀로 구현한 Factorial
function factorial(n) {
if(n === 0) {
return 1;
}
return n * factorial(n-1)
}
반복문으로 구현한 Factorial
function factorial(n) {
let result = 1;
for(let i = n; i > 0; i--) {
result = result * i;
}
return result;
}
다른 예제 1) fibonacci 수열 : Fn= Fn-1 + Fn-2 **n>1라는 조건 하에 앞의 2 수의 합이 다음번 수열의 합
재귀로 구현한 Fibonacci
function fib(n) {
if(n === 0 || n === 1) { // 탈출 조건
return n;
}
return fib(n-1) + fib(n-2);
}
반복문으로 구현한 Fibonacci ①
function fibonacci(num) {
let a = 1, b = 0, temp;
while(num > 0) {
temp = a;
a = a + b;
b = temp;
num--;
}
return b;
}
반복문으로 구현한 Fibonacci ②
function fibonacci2(num) {
if(num === 0 || n === 1) return n;
let a = 0;
let b = 1;
let temp;
while(num > 1) {
temp = b;
b = a + b;
a = temp;
num--;
}
return b;
}
memoize 기법: 미리 계산한 값을 cashing 해서 보여주는 방법
memoize 읽어보기: https://ithub.tistory.com/230, https://jsbin.com/nihisaq/5
memoize로 구현한 Fibonacci
let memo = [0,1];
function fibMemoization(n) {
if(typeof memo[n] !== 'number') {
memo[n] = fibMemoization(n-1) + fibMemoization(n-2);
}
return memo[n];
}
Q: 재귀는 반복문이 될 수 있나? 반복문은 재귀가 될 수 있을까?
A: 이론 상으로 가능
참고: 반복문으로 작성하는 경우 실행 콘텍스트가 같기 때문에 실행 결과가 n번 반복되어 나오고, 재귀의 경우는 호출하는 근원(함수, call stack)이 달라서 실행 결과가 1줄씩 각각 나오게 됨
다른 예제 2) json(javascript object notation의 줄임말) 구조 탐색
json:객체-배열의 관계를 가리킴, 배열 안에 객체가 담긴 모양
json 구조의 예시
tree 구조에서 원하는 값을 찾을 때 재귀를 이용하면 유용함!
prototype: 모델의 청사진(Class)을 만들 때 쓰는 원형 객체(original form)
Array.something(): something은 Array라는 Class에서만 작동
ex) Array(Array가 Class).isArray(value)
array.prototype.something() : something은 Array의 Instance에서만 작동
Array Class를 사용해서 만들어진 Instance에서는 모두 작동
ex) arr(arr이 instance).map(function(){});
Prototype의 의미: 원형 객체
- 인스턴스가 생성(instantiation)될 때 원형(original form), 즉 프로토타입(prototype)의 모양대로 인스턴스가 생성됨
- 인스턴스의 메서드는 Object.prototype.something으로 표현됨
prototype과 instance의 관계: 빵틀과 빵
js는 prototype 기반 언어
prototype을 기반으로 객체 지향 프로그래밍(OOP)을 흉내 내고 있음
prototype 확장하기: JS에서 기본적으로 제공되는 객체에 사용자 정의 메서드를 직접 추가할 수 있음(그러나 다른 코드와 충돌을 일으킬 수 있어서 추천하지는 않음)
예시) pluck이라는 method 만들기
서버와 클라이언트?
정보를 요청하는 주체: 클라이언트 / 요청에 따른 응답을 주는 주체: 서버
ex) 날씨 앱(클라이언트): 어떤 지역의 날씨 요청
날씨 api 서버: 요청받은 지역의 날씨 정보를 어떠한 형태로 전달
서버에게 요청하기: 일반적으로 서버에게 HTTP라는 프로토콜(형태: URL)로 요청한 후 응답을 처리하는 과정
응답 형태는 다양: JSON(객체 형태로 전달), HTML, XML, plain text 등
HTTP 요청은 fetch라는 API를 사용함
fetch API 형태: promise
fetch(‘http://서버주소’)
.then(function(resp) {
// 응답 형식에 따라 resp.text(), resp.html(), resp.json 등이 될 수 있음
return resp.json();
}.then(function(json) {
// api의 정보 set을 이용해서 하고 싶은 작업 삽입
}
mdn에 using fetch 참고:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
korean api: koreanjson.com
API 사용 시 유의할 점: API 사용 시 서비스 제공자로부터 권한을 받아 key로 통신, 그래서 API key는 암호처럼 취급되어야 함
서버에 기록하기: HTTP 요청으로 GET이 아니라 POST를 이용해서 기록 가능
POST 시 내용(payload)과 함께 전달
POST의 예: 게시판에 새로운 글 작성 시, 아이디/비밀번호 로그인 시
POST 시 fetch API 형태:
let newPost = {
"userId": 1,
"title": "새 글을 써봤습니다",
"body": "안녕하세요?"
}
fetch('http://서버주소/posts', {
method: 'POST',
body: JSON.stringify(newPost)
}).then(function(resp) {
return resp.json();
}).then(function(json) {
console.log(json); // { id: 123 }
});
다양한 api 정보: https://www.apistore.co.kr
서버 개발과 관련된 환경 구축을 위해서는 node.js 공부 필요!
JSON이란? Java Script Object Notation의 약자, 브라우저와 서버 사이에 오고 가는 데이터 형식
JSON.stringify 특징
1. 해당 method는 parameter로 받은 value를 문자 열화 시켜주는 기능을 한다.
2. 반대로는 JSON.parse method가 있다.
3. parameter를 value(필수), replace(선택), space(선택)으로 가진다.
1) value는 숫자, boolean, null, 문자열, 배열, 객체 등이 입력되었을 때 유효하다.
(1) value가 숫자일 때 숫자 자체를 문자 열화 시켜준다.
(2) value가 boolean일 때는 해당 진리 값 자체를 문자 열화 시켜준다.
(3) value가 null일 때는 null을 문자 열화 시켜준다.
(4) value가 배열일 때는 배열 자체를 문자 열화 시켜준다.
i. 배열 안에 undefined, Symbol, 함수가 있으면 해당 값은 null로 변경된다.
(5) value가 객체일 때는 객체 자체와 키값을 문자 열화 시켜준다.
i. 객체 안에 undefined, Symbol, 함수가 값으로 있으면 해당 key-value는 생략된다.
ii. 객체의 속성은 꼭 순서대로 문자 열화 되지는 않아서 순서가 뒤바뀌어서 변환될 수 있다.
2) value에 undefined, 함수, Symbol 등이 들어오면 undefined가 반환된다.
3) replacer는 선택 값으로 null이거나 언급되지 않으면 value 전체를 문자 열화 시킨다.
(1) replacer에는 배열이나 함수가 들어갈 수 있다.
(2) replacer가 배열이고, value가 객체일 때 배열이 가진 값이 value 객체의 key값과 동일한 것만 문자 열화 시킨다.
(3) replace가 함수일 때는 해당 함수의 parameter는 key와 value 2개이며 함수를 걸쳐서 나온 value값이 문자 열화 된다.
4) space는 선택 값으로 문자열이나 숫자가 들어온다.
(1) space에 문자열이 들어오면 문자 열화 시킬 value 공백에 해당 문자열이 들어간다.
(2) space에 숫자가 들어오면 문자 열화 시킬 value 공백에 해당 숫자만큼 space가 들어간다.
재귀가 필요한 구간: arr의 요소를 돌면서 각 요소의 문자열화를 확인해야 할 때, obj의 키와 밸류의 문자열화를 확인해야 할 때 recursive case 적용