1장. 노드 시작하기
1.1. 핵심 개념 이해하기
- Node.js는 Chrome V8 Javascript 엔진으로 빌드된 자바스크립트 런타임임.
ㄴ 서버로 많이 이용되지만 서버 외의 자바스크립트 프로그램을 실행하는 런타임으로도 사용
=> 서버랑 런타임이 뭘까 ????
1.1.1. 서버
- 서버: 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램
- 클라이언트: 요청을 보내는 주체 (브라우저, 데스크톱 프로그램, 모바일 앱 ... 등등 다양한 형태)
- 서버는 요청에 대한 응답 뿐만 아니라 요청을 직접 보낼 수도 있음 -> 서버가 클라이언트가 됨
- 서버가 응답할 때는 무조건 yEs로만 하는 것은 아님 .. 요청 거절할수도 (사이트 차단 당했을 때)
1.1.2. 자바스크립트 런타임
- 런타임: 특정 언어로 만든 프로그램들을 실행할 수 있는 환경 (-> 노드는 자바스크립트 프로그램을 컴퓨터에서 실행할 수 있음)
- libuv 라이브러리는 노드의 특성인 이벤트 기반, 논블로킹 I/O 모델을 구현하고 있음.
1.1.3. 이벤트 기반
- 이벤트 기반: 이벤트(클릭, 네트워크 요청 등등 ...)가 발생할 때 미리 지정해둔 작업을 수행하는 방식
- 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두어야 함 = 이벤트 리스너에 콜백 함수를 등록한다
ex) 버튼을 클릭할 때 경고창을 띄우도록 설정해보자
- 클릭 이벤트 리스너에 경고창을 띄우는 콜백 함수를 등록 -> 클릭 이벤트 발생시에 콜백 함수 실행, 경고창 뜸
- 노드는 이벤트 기반 방식으로 동작하기 때문에 이벤트가 발생하면 콜백 함수를 호출.
- 만약 발생한 이벤트가 없거나 발생한 이벤트를 다 처리했다면 다음 이벤트가 발생할 때까지 대기
1.1.3.1 이벤트 루프
function run() {
console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
- 콘솔창에 어떻게 찍힐까?? -> 시작, 끝, 3초 후 실행
- 호출 스택으로는 설명하기 어려움 <- setTimeout 함수의 콜백인 run이 호출 스택에 언제 들어가는지 알기 어려움
=> 이를 알기 위해서 이벤트 루프, 태스크 큐, 백그라운드를 알아야 함
- 이벤트 루프: 이벤트 발생 시 호출할 콜백 함수들을 관리, 호출된 콜백 함수의 실행 순서를 결정
- 백그라운드: 타이머(setTimeout 등등...)나 이벤트 리스너들이 대기하는 곳, 여러 작업이 동시에 실행될 수도 있음
- 태스크 큐(콜백 큐): 이벤트가 발생하면, 백그라운드에서 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수가 이동함. 콜백들은 보통 완료된 순서대로 줄을 서있지만 바뀌기도 함
1.1.4. 논블로킹 I/O
- 자바스크립트 코드는 동시에 실행될 수 없지만, I/O 작업은 동시에 처리될 수 있음
- I/O(Input/Output) 작업: 파일 시스템 접근, 네트워크를 통한 요청 등등... -> 노드: 논블로킹 방식으로 처리
- 논블로킹: 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행
- 블로킹: 이전 작업이 끝나야만 다음 작업을 수행
- 블로킹보다 논블로킹 방식이 같은 작업들을 더 빠르게 처리할 수 있지만, 작업들이 모두 동시에 처리될 수 있는 작업이어야 함
- 노드는 I/O 작업을 백그라운드로 넘겨 동시에 처리함. -> 동시에 처리될 수 있는 작업들은 최대한 같이 묶어서 백그라운드로 보내야 함
//블로킹 방식의 코드
function longRunningTask() {
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
longRunningTask();
console.log('다음 작업');
// 논블로킹 방식의 코드
function longRunningTask() {
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
setTimeout(longRunningTask, 0);
console.log('다음 작업');
- setTimeout의 콜백 함수인 longRunningTask가 태스크 큐로 보내져 순서대로 실행되지 않음
- setTimeout의 밀리초를 0으로 설정했을 때, 바로 실행되는 건 아님. 기본적인 지연 시간 있음
- 하지만 코드가 서로 동시에 실행되지는 않음 코드의 실행 순서만 바뀔 뿐......
- 논블로킹과 동시는 같은 의미가 아님 <- 동시성은 동시 처리가 가능한 작업을 논블로킹 처리해야 얻을 수 있음!!
1.1.5. 싱글 스레드
- 싱글 스레드: 스레드가 하나 뿐이다 (<- 자바스크립트 코드가 동시에 실행될 수 없는 이유)
프로세스 | 싱글 스레드 |
- 운영체제에서 할당하는 작업의 단위. - 노드, 웹 브라우저 같은 프로그램은 개별적인 프로세스. - 프로세스 간에는 메모리 등의 자원 공유 X |
- 프로세스 내에서 실행되는 흐름의 단위 - 프로세스는 스레드를 여러 개 생성해서 여러 작업을 동시에 처리할 수 있음 - 스레드는 부모 프로세스의 자원을 공유 - 같은 주소의 메모리에 접근 가능 -> 데이터 공유 가능 |
- 노드가 싱글 스레드라고 여겨지는 이유: 노드를 실행하면 프로세스 하나가 생성됨 -> 프로세스에서 스레드 여러 개 생성, 여기서 내가 직접 제어할 수 있는 스레드는 하나 뿐이기 때문에 싱글 스레드라고 여겨짐..하지만 싱글 스레드로 동작하지는 않음!!
- 요청이 많이 들어오면 한 번에 하나씩 요청을 처리함(내가 제어 가능한 스레드는 하나이기 때문)
근데 블로킹이 심하게 일어나는 작업만 아니면 스레드는 하나로도 충분함... 블로킹이 발생할 것 같으면 논블로킹 방법으로 대기 시간을 최대한 줄이자
- 멀티 스레드(여러 개 일 동시에 처리)가 싱글 스레드보다 좋아보일 수 있지만..,꼭 그런건 아님!!
-> 예시를 생각해보자. 스레드 = 점원, 요청된 일 = 손님 이라고 생각해보자!!
손님이 여러 명, 점원이 한 명(싱글 스레드)일 경우에도 효율적인 일 처리 가능함.
손님 한 명이 올 때마다 점원 한 명이 늘어나는 경우(멀티 스레드)일 경우에 장단점이 있음 -> 손님이 늘 때마다 점원도 늘어나야 함.
손님 수가 줄었을 때는 노는 점원이 생김. ==> 별로다...
- 그럼 멀티 스레드를 논블로킹 방식으로 하는 건?? ==> 프로그래밍하기 어려움 -> 멀티 프로세싱 방식 사용
1.2. 서버로서의 노드
- 노드를 서버로 사용할 때의 특성과 장단점을 알아보자!?!
- 노드는 싱글 스레드, 논블로킹 모델을 사용하므로 노드 서버 또한 동일한 모델임 = 노드의 장단점은 싱글 스레드, 논블로킹의 장단점과 비슷
- 노드는 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는 데 적합
장점 | - 노드는 libuv 라이브러리를 사용해 I/O 작업을 논블로킹 방식으로 처리 -> 스레드 하나가 많은 수의 I/O를 혼자서도 감당 가능 - 싱글 스레드 프로그래밍은 쉬워서 입문하기 좋음 - 노드에는 웹 서버가 내장되어 있음 - 자바스크립트를 언어로 사용함 |
단점 | - 노드는 CPU 부하가 큰 작업에는 적합하지 않음 - 멀티 스레드 프로그래밍이 어려움. 하더라도 C, C++, Rust와 같은 언어에 비해 속도가 느림 - 싱글 스레드 방식으로 서버를 운영할 때는 유일한 스레드가 에러에 걸리지 않도록 잘 관리해줘야 함 - 유일한 스레드가 에러에 걸려서 죽게 되면 서버 전체가 멈춤 - 내장된 웹 서버가 있지만 나중에 서버 규모가 커지면 다른 웹 서버(nginx...)를 노드 서버와 연결해 줘야 함 - 비동기에 강점을 보이는 언어(Go), 정적 파일 제공, 로드밸런싱에 특화된 웹 서버(nginx)에 비해서는 속도가 느림 |
1.3. 서버 외의 노드
- 노드는 사용 범위가 점점 늘어나서 웹, 모바일, 데스크톱 애플리케이션 개발에도 사용되기 시작함.
- 노드 기반 웹 프레임워크: 앵귤러, 리액트, 뷰 ... 등등
1.4. 개발 환경 설정하기
- 에디터로는 VScode를 이용하겠습니다!
1.4.1. 노드 설치하기 (Mac)
(제가 맥을 써서 맥으로 설치하는 방법만 적겠씁니다...ㅎ.ㅎ)
- 노드 공식 사이트 접속 -> 설치하려는 버전 설정하고 나오는 코드를 터미널에 치면 되나봐요
- npm 버전 업데이트, VScode 설치는 이미 했으니 넘어가겠씁니다... ㅎ.ㅎ
2장. 알아둬야 할 자바스크립트
2.1. ES2015+
2.1.1. const, let
- 변수 선언 방식. 블록 스코프를 가짐
if (true) {
var x = 3;
}
console.log(x); // 3
if (true) {
const y = 3;
}
console.log(y); // Uncaught ReferenceError: y is not defined
- x는 정상 출력되지만 y는 에러 발생함
=> var는 함수 스코프를 가지므로 if문의 블록과 관계없이 접근 가능. const, let은 블록 스코프이므로 블록 밖에서는 변수에 접근 x
- 블록의 범위: 중괄호( {, } ) 사이
- const: 한 번 값을 할당하면 다른 값 할당 x (상수)
- let: 다른 값 할당 가능
2.1.2. 템플릿 문자열
- 백틱(`)으로 감싸는 문자열
- 문자열 안에 변수를 넣을 수 있음
const num3 = 1;
const num4 = 2;
const result2 = 3;
const string2 = `${num3} 더하기 ${num4}는 ' ${result2}'`;
console.log(string2); // 1 더하기 2는 '3'
- $(변수) 형식으로 변수를 더하기 기호 없이 문자열에 넣어서 사용할 수 있음 ( num3 + ' 더하기 ' + num4 + '는' .... )
2.1.3. 객체 리터럴
var sayNode = function() {
console.log('Node');
};
var es = 'ES';
var oldObject = {
sayJS: function() {
console.log('JS');
},
sayNode: sayNode,
};
oldObject[es + 6] = 'Fantastic';
oldObject.sayNode(); // Node
oldObject.sayJS(); // JS
console.log(oldObject.ES6); // Fantastic
const newObject = {
sayJS() {
console.log('JS');
},
sayNode,
[es + 6]: 'Fantastic',
};
newObject.sayNode(); // Node
newObject.sayJS(); // JS
console.log(newObject.ES6); // Fantastic
- 객체의 메서드에 함수를 연결할 때 콜론과 function을 붙이지 않아도 됨 (sayJS)
- 속성명과 변수명이 동일한 경우에는 한 번만 써도 됨 (sayNode : sayNode)
- 객체의 속성명은 동적으로 생성 가능
2.1.4. 화살표 함수
- 기존의 function 선언 대신 => 기호로 함수 선언 가능
- 변수에 대입하면 나중에 재사용 가능
- 내부에 return 문밖에 없는 경우, return문을 줄일 수 있음(return할 식을 바로 적으면 됨)
const add1 = (x, y) => x + y;
- 기존의 function과 this 바인드 방식에서 차이 발생
ar relationship1 = {
name: 'zero',
friends: ['nero', 'hero', 'xero'],
logFriends: function () {
var that = this; // relationship1을 가리키는 this를 that에 저장
this.friends.forEach(function (friend) {
console.log(that.name, friend);
});
},
};
relationship1.logFriends();
const relationship2 = {
name: 'zero',
friends: ['nero', 'hero', 'xero'],
logFriends() {
this.friends.forEach(friend => {
console.log(this.name, friend);
});
},
};
relationship2.logFriends();
- function 선언문을 사용한 relationship1.logFriends()의 forEach문에서는 각자 다른 함수 스코프의 this를 가지므로 that이라는 변수를 사용해서 relationship1에 간접적으로 접근
- 화살표 함수를 사용한 relationship2.logFriends()의 forEach문에서는 바깥 스코프인 logFriends()의 this를 그대로 사용 가능
2.1.5. 구조 분해 할당
- 객체와 배열로부터 속성이나 요소를 쉽게 꺼낼 수 있음
- 객체 구조 분해 할당
var candyMachine = {
status: {
name: 'node',
count: 5,
},
getCandy: function () {
this.status.count--;
return this.status.count;
},
};
var getCandy = candyMachine.getCandy;
var count = candyMachine.status.count;
const candyMachine = {
status: {
name: 'node',
count: 5,
},
getCandy() {
this.status.count--;
return this.status.count;
},
};
const { getCandy, status: { count } } = candyMachine;
- candyMachine 객체 안의 속성을 찾아서 변수와 매칭
- count처럼 여러 단계 안의 속성도 찾을 수 있음
- getCandy와 count 변수가 초기화된 것
- 구조 분해 할당을 사용하면 함수의 this가 달라질 수 있음, 달라진 this를 원래대로 바꾸고 싶으면 bind 함수를 따로 사용해줘야함
- 배열에 대한 구조 분해 할당
var array = [‘nodejs’, {}, 10, true];
var node = array[0];
var obj = array[1];
var bool = array[3];
- array: 배열의 첫 번째, 두 번째 요소와 네 번째 요소를 변수에 대입
const array = [‘nodejs’, {}, 10, true];
const [node, obj, , bool] = array;
- node: 배열의 첫 번째 요소, obj: 두 번째 요소, bool: 네 번째 요소
2.1.6. 클래스
- 다른 언어처럼 클래스 기반으로 동작하는 것이 x 프로토타입 기반으로 동작
var Human = function(type) {
this.type = type || 'human';
};
Human.isHuman = function(human) {
return human instanceof Human;
}
Human.prototype.breathe = function() {
alert('h-a-a-a-m');
};
var Zero = function(type, firstName, lastName) {
Human.apply(this, arguments);
this.firstName = firstName;
this.lastName = lastName;
};
Zero.prototype = Object.create(Human.prototype);
Zero.prototype.constructor = Zero; // 상속하는 부분
Zero.prototype.sayName = function() {
alert(this.firstName + ' ' + this.lastName);
};
var oldZero = new Zero('human', 'Zero', 'Cho');
Human.isHuman(oldZero); // true
- Human 생성자 함수, 이 함수를 Zero 생성자 함수가 상속
// 클래스 기반 코드로 바꾸기
class Human {
constructor(type = 'human') {
this.type = type;
}
static isHuman(human) {
return human instanceof Human;
}
breathe() {
alert('h-a-a-a-m');
}
}
class Zero extends Human {
constructor(type, firstName, lastName) {
super(type);
this.firstName = firstName;
this.lastName = lastName;
}
sayName() {
super.breathe();
alert(`${this.firstName} ${this.lastName}`);
}
}
const newZero = new Zero('human', 'Zero', 'Cho');
Human.isHuman(newZero); // true
- class 안으로 그룹화
2.1.7. 프로미스
- 실행은 바로 하되 결괏값은 나중에 받는 객채
- ES2015부터 자바스크립트와 노드의 API들이 콜백 대신 프로미스 기반으로 재구성됨
- 프로미스 객체 생성
const condition = true; // true이면 resolve, false이면 reject
const promise = new Promise((resolve, reject) => {
if (condition) {
resolve('성공');
} else {
reject('실패');
}
});
// 다른 코드가 들어갈 수 있음
promise
.then((message) => {
console.log(message); // 성공(resolve)한 경우 실행
})
.catch((error) => {
console.error(error); // 실패(reject)한 경우 실행
})
.finally(() => { // 끝나고 무조건 실행
console.log('무조건');
});
- new Promise로 프로미스 생성, 안에 콜백 함수
- promise 변수에 then, catch 메서드
- 프로미스 내부에서 resolve 호출 -> then 실행, reject 호출 -> catch 실행, finally: 실패/성공 상관없이 실행
- resolve, reject에 넣어준 인수는 then, catch의 매개변수에서 받을 수 있음
- 결괏값은 실행이 완료된 후 then이나 catch 메서드를 통해 받음
- then이나 catch에서 다시 다른 then이나 catch를 붙일 수 있음. 이전 then의 리턴값을 다음 then의 매개변수로 받음. 프로미스를 리턴한 경우에는 프로미스가 수행된 후 다음 then이나 catch가 호출됨
- 모든 콜백 함수를 프로미스로 바꿀 수 있는 건 아님. 메서드가 프로미스 방식을 지원해야 함
- Promise.all: 프로미스 여러 개를 한 번에 실행
- Promise.resolve: 즉시 resolve하는 프로미스 생성
- Promise.reject: 즉시 reject하는 프로미스 생성
- Promise.allSettled: 정확히 어떤 프로미스에서 reject되었는지 확인 <- 사용 권장
2.1.8. async/await
- 프로미스를 사용한 코드를 한 번 더 깔끔하게 줄일 수 있음
function findAndSaveUser(Users) {
Users.findOne({})
.then((user) => {
user.name = 'zero';
return user.save();
})
.then((user) => {
return Users.findOne({ gender: 'm' });
})
.then((user) => {
// 생략
})
.catch(err => {
console.error(err);
});
}
//async/await 사용해서 코드 줄이기
async function findAndSaveUser(Users) {
let user = await Users.findOne({});
user.name = 'zero';
user = await user.save();
user = await Users.findOne({ gender: 'm' });
// 생략
}
- 일반 함수 대신 async function으로 함수 선언. 프로미스 앞에 await
- 해당 프로미스가 resolve될 때까지 기다린 뒤 다음 로직으로 넘어감
async function findAndSaveUser(Users) {
try {
let user = await Users.findOne({});
user.name = 'zero';
user = await user.save();
user = await Users.findOne({ gender: 'm' });
// 생략
} catch (error) {
console.error(error);
}
}
- 에러 처리 부분(프로미스가 reject된 경우) 추가
- 화살표 함수도 async와 같이 사용 가능
- for문과 async/await을 같이 써서 프로미스를 순차적으로 실행시킬 수 있음
- async 함수의 반환값은 항상 Promise로 감싸짐 -> 실행 후 then을 붙이거나 또 다른 async 함수 안에서 await을 붙여서 처리 가능
2.1.9. Map/Set
- Map: 객체와 유사, 속성들 간의 순서 보장, 반복문 사용 가능, 속성명으로 값 사용 가능
- Set: 배열과 유사, 중복 불가
const m = new Map();
m.set('a', 'b'); // set(키, 값)으로 Map에 속성 추가
m.set(3, 'c'); // 문자열이 아닌 값을 키로 사용 가능합니다
const d = {};
m.set(d, 'e'); // 객체도 됩니다
m.get(d); // get(키)로 속성값 조회
console.log(m.get(d)); // e
m.size; // size로 속성 개수 조회
console.log(m.size) // 3
for (const [k, v] of m) { // 반복문에 바로 넣어 사용 가능합니다
console.log(k, v); // 'a', 'b', 3, 'c', {}, 'e'
} // 속성 간의 순서도 보장됩니다
m.forEach((v, k) => { // forEach도 사용 가능합니다
console.log(k, v); // 결과는 위와 동일
});
m.has(d); // has(키)로 속성 존재 여부를 확인합니다
console.log(m.has(d)); // true
m.delete(d); // delete(키)로 속성을 삭제합니다
m.clear(); // clear()로 전부 제거합니다
console.log(m.size); // 0
const s = new Set();
s.add(false); // add(요소)로 Set에 추가합니다
s.add(1);
s.add('1');
s.add(1); // 중복이므로 무시됩니다
s.add(2);
console.log(s.size); // 중복이 제거되어 4
s.has(1); // has(요소)로 요소 존재 여부를 확인합니다
console.log(s.has(1)); // true
for (const a of s) {
console.log(a); // false 1 '1' 2
}
s.forEach((a) => {
console.log(a); // false 1 '1' 2
})
s.delete(2); // delete(요소)로 요소를 제거합니다
s.clear(); // clear()로 전부 제거합니다
- 기존 배열에서 중복을 제거하고 싶을 때도 Set 사용
- new Set(배열): 배열의 중복된 요소들 제거
- Array.from(Set): Set을 배열로 되돌리기
const arr = [1, 3, 2, 7, 2, 6, 3, 5];
const s = new Set(arr);
const result = Array.from(s);
console.log(result); // 1, 3, 2, 7, , 5
2.1.10. 널 병합/옵셔널 체이닝
- ??(널 병합) 연산자: | | 연산자 대용, falsy 값 중 null과 undefined만 따로 구분
- ?(옵셔널 체이닝) 연산자: null이나 undefined의 속성을 조회하는 경우 에러 발생을 막음
// 널 병합
const a = 0;
const b = a || 3; // || 연산자는 falsy 값이면 뒤로 넘어감
console.log(b); // 3
const c = 0;
const d = c ?? 3; // ?? 연산자는 null과 undefined일 때만 뒤로 넘어감
console.log(d); // 0;
const e = null;
const f = e ?? 3;
console.log(f); // 3;
const g = undefined;
const h = g ?? 3;
console.log(h); // 3;
// 옵셔널 체이닝
const a = {}
a.b; // a가 객체이므로 문제없음
const c = null;
try {
c.d;
} catch (e) {
console.error(e); // TypeError: Cannot read properties of null (reading 'd')
}
c?.d; // 문제없음
try {
c.f();
} catch (e) {
console.error(e); // TypeError: Cannot read properties of null (reading 'f')
}
c?.f(); // 문제없음
try {
c[0];
} catch (e) {
console.error(e); // TypeError: Cannot read properties of null (reading '0')
}
c?.[0]; // 문제없음
2.2. 프론트엔드 자바스크립트
2.2.1. AJAX
- 비동기적 웹 서비스를 개발할 때 사용하는 기법
- 페이지 이동 없이 서버에 요청을 보내고 응답을 받는 기술
- jQuery, axios 같은 라이브러리 사용
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
// 여기에 예제 코드를 넣으세요
</script>
- GET 요청 보내기
- axios.get 함수의 인수로 요청 보낼 주소 입력
axios.get('https://www.zerocho.com/api/get')
.then((result) => {
console.log(result);
console.log(result.data); // {}
})
.catch((error) => {
console.error(error);
});
- axios.get 내부에 new Promise가 있으므로 then, catch 사용 가능
- result, data에 서버로부터 보낸 데이터가 들어 있음
- async/await 방식으로 변경 가능
(async () => {
try {
const result = await axios.get('https://www.zerocho.com/api/get');
console.log(result);
console.log(result.data); // {}
} catch (error) {
console.error(error);
}
})();
- POST 방식의 요청을 보내보자!
- POST 요청에서는 데이터를 서버로 보낼 수 있음
(async () => {
try {
const result = await axios.post('https://www.zerocho.com/api/post/json', {
name: 'zerocho',
birth: 1994,
});
console.log(result);
console.log(result.data);
} catch (error) {
console.error(error);
}
})();
- GET 요청일 때는 axios.get, POST 요청일 때는 axios.post 사용
2.2.2. FormData
- HTML form 태그의 데이터를 동적으로 제어할 수 있는 기능
- FormData 생성자로 formData 객체 생성
const formData = new FormData();
formData.append('name', 'zerocho');
formData.append('item', 'orange');
formData.append('item', 'melon');
formData.has('item'); // true
formData.has('money'); // false;
formData.get('item');// orange
formData.getAll('item'); // ['orange', 'melon'];
formData.append('test', ['hi', 'zero']);
formData.get('test'); // hi, zero
formData.delete('test');
formData.get('test'); // null
formData.set('item', 'apple');
formData.getAll('item'); // ['apple'];
- 생성된 객체의 append 메서드로 키-값 형식의 데이터 저장 가능
- append 메서드를 여러 번 사용해서 키 하나에 여러 개 값 추가 가능
- has 메서드: 주어진 키에 해당하는 값이 있는지 여부
- get 메서드: 주어진 키에 해당하는 값 하나를 가져옴
- getAll 메서드: 해당하는 모든 값 가져옴
- delete 메서드: 현재 키를 제거
- set 메서드: 현제 키를 수정
- axios로 폼데이터를 서버에 보내기
(async () => {
try {
const formData = new FormData();
formData.append('name', 'zerocho');
formData.append('birth', 1994);
const result = await axios.post('https://www.zerocho.com/api/post/formdata', formData);
console.log(result);
console.log(result.data);
} catch (error) {
console.error(error);
}
})();
- 두 번째 인수에 데이터 넣어 보내기
2.2.3. encodeURIComponent, decodeURIComponent
- 한글로 되어있는 서버를 읽게 해 주는 기능
(async () => {
try {
const result = await axios.get(`https://www.zerocho.com/api/search/${encodeURIComponent('노드')}`);
console.log(result);
console.log(result.data); // {}
} catch (error) {
console.error(error);
}
})();
- encodeURIComponent로 '노드'라는 한글 주소가 문자열로 반환 -> decodeURIComponent로 받는 쪽에서 문자열을 한글로 반환
2.2.4. 데이터 속성과 dataset
<ul>
<li data-id="1" data-user-job="programmer">Zero</li>
<li data-id="2" data-user-job="designer">Nero</li>
<li data-id="3" data-user-job="programmer">Hero</li>
<li data-id="4" data-user-job="ceo">Kero</li>
</ul>
<script>
console.log(document.querySelector('li').dataset);
// { id: '1', userJob: 'programmer' }
</script>
- HTML 태그의 속성으로, data-로 시작하는 것들을 넣기 => 데이터 속성
- 장점: 자바스크립트로 쉽게 접근 가능
'WINK-(Web & App) > Express.js (Node.js) 스터디' 카테고리의 다른 글
[2024 여름방학 Node.js 스터디] 이종윤 #1주차 (0) | 2024.07.18 |
---|---|
[2024 여름방학 Node.js 스터디] 백채린 #1주차 1~2장 (0) | 2024.07.18 |
[2024 Node.js 스터디] 김수아 #4주차 "Node.js 6,7,9장" (0) | 2024.05.25 |
[2024 Node.js 스터디] 장민우 #5주차 "인생이란" (0) | 2024.05.25 |
[2024 Node.js 스터디] 조상혁 5주차 "Node.js 6 ,7 장" (0) | 2024.05.25 |