본문 바로가기

WINK-(Web & App)/Express.js (Node.js) 스터디

[2024 여름방학 Node.js 스터디] 김지나 #1주차

반응형

1장. 노드 시작하기

1.1. 핵심 개념 이해하기

- Node.js는 Chrome V8 Javascript 엔진으로 빌드된 자바스크립트 런타임임. 

ㄴ 서버로 많이 이용되지만 서버 외의 자바스크립트 프로그램을 실행하는 런타임으로도 사용

=> 서버랑 런타임이 뭘까 ???? 

 

1.1.1. 서버 

- 서버: 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램

- 클라이언트: 요청을 보내는 주체 (브라우저, 데스크톱 프로그램, 모바일 앱 ... 등등 다양한 형태)

ex) 웹 사이트 주소 입력(요청), 웹 브라우저 띄우기(응답) / 앱 설치(요청), 설치하기(응답)

- 서버는 요청에 대한 응답 뿐만 아니라 요청을 직접 보낼 수도 있음 -> 서버가 클라이언트가 됨

- 서버가 응답할 때는 무조건 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 등등...)나 이벤트 리스너들이 대기하는 곳, 여러 작업이 동시에 실행될 수도 있음

- 태스크 큐(콜백 큐): 이벤트가 발생하면, 백그라운드에서 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수가 이동함. 콜백들은 보통 완료된 순서대로 줄을 서있지만 바뀌기도 함

- setTimeout이 실행되면 타이머와 함께 run 콜백을 백그라운드로 보내고 호출 스택에서 빠짐. -> anonymous 호출 스택에서 빠짐 - 백그라운드에서는 3초를 센 후 run 함수를 태스크 큐로 보냄.
- 호출 스택이 비어있으면 태스크 큐에서 하나씩 함수를 가져와 호출 스택에 넣고 실행함. 다 실행하면 태스크 큐에 콜백 함수가 들어올 때까지 대기

 

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
- 프로세스 내에서 실행되는 흐름의 단위
- 프로세스는 스레드를 여러 개 생성해서 여러 작업을 동시에 처리할 수 있음
- 스레드는 부모 프로세스의 자원을 공유
- 같은 주소의 메모리에 접근 가능 -> 데이터 공유 가능

 

 

- 노드가 싱글 스레드라고 여겨지는 이유: 노드를 실행하면 프로세스 하나가 생성됨 -> 프로세스에서 스레드 여러 개 생성, 여기서 내가 직접 제어할 수 있는 스레드는 하나 뿐이기 때문에 싱글 스레드라고 여겨짐..하지만 싱글 스레드로 동작하지는 않음!!

- 요청이 많이 들어오면 한 번에 하나씩 요청을 처리함(내가 제어 가능한 스레드는 하나이기 때문) 

근데 블로킹이 심하게 일어나는 작업만 아니면 스레드는 하나로도 충분함... 블로킹이 발생할 것 같으면 논블로킹 방법으로 대기 시간을 최대한 줄이자

- 멀티 스레드(여러 개 일 동시에 처리)가 싱글 스레드보다 좋아보일 수 있지만..,꼭 그런건 아님!! 

  -> 예시를 생각해보자. 스레드 = 점원, 요청된 일 = 손님 이라고 생각해보자!!

       손님이 여러 명, 점원이 한 명(싱글 스레드)일 경우에도 효율적인 일 처리 가능함.

       손님 한 명이 올 때마다 점원 한 명이 늘어나는 경우(멀티 스레드)일 경우에 장단점이 있음 -> 손님이 늘 때마다 점원도 늘어나야 함.

       손님 수가 줄었을 때는 노는 점원이 생김. ==> 별로다...

- 그럼 멀티 스레드를 논블로킹 방식으로 하는 건?? ==> 프로그래밍하기 어려움 -> 멀티 프로세싱 방식 사용

- I/O 작업을 처리할 때는 멀티 스레딩보다 멀티 프로세싱이 효율적

 

 

1.2. 서버로서의 노드

- 노드를 서버로 사용할 때의 특성과 장단점을 알아보자!?!

- 노드는 싱글 스레드, 논블로킹 모델을 사용하므로 노드 서버 또한 동일한 모델임 = 노드의 장단점은 싱글 스레드, 논블로킹의 장단점과 비슷

- 노드는 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는 데 적합

장점 - 노드는 libuv 라이브러리를 사용해 I/O 작업을 논블로킹 방식으로 처리 -> 스레드 하나가 많은 수의 I/O를 혼자서도 감당 가능
- 싱글 스레드 프로그래밍은 쉬워서 입문하기 좋음
- 노드에는 웹 서버가 내장되어 있음
- 자바스크립트를 언어로 사용함
단점 - 노드는 CPU 부하가 큰 작업에는 적합하지 않음
- 멀티 스레드 프로그래밍이 어려움. 하더라도 C, C++, Rust와 같은 언어에 비해 속도가 느림
- 싱글 스레드 방식으로 서버를 운영할 때는 유일한 스레드가 에러에 걸리지 않도록 잘 관리해줘야 함
- 유일한 스레드가 에러에 걸려서 죽게 되면 서버 전체가 멈춤
- 내장된 웹 서버가 있지만 나중에 서버 규모가 커지면 다른 웹 서버(nginx...)를 노드 서버와 연결해 줘야 함
- 비동기에 강점을 보이는 언어(Go), 정적 파일 제공, 로드밸런싱에 특화된 웹 서버(nginx)에 비해서는 속도가 느림

 

1.3. 서버 외의 노드

- 노드는 사용 범위가 점점 늘어나서 웹, 모바일, 데스크톱 애플리케이션 개발에도 사용되기 시작함.

- 노드 기반 웹 프레임워크: 앵귤러, 리액트, 뷰 ... 등등

 

1.4. 개발 환경 설정하기

- 에디터로는 VScode를 이용하겠습니다!

1.4.1. 노드 설치하기 (Mac)

(제가 맥을 써서 맥으로 설치하는 방법만 적겠씁니다...ㅎ.ㅎ)

 

- 노드 공식 사이트 접속 -> 설치하려는 버전 설정하고 나오는 코드를 터미널에 치면 되나봐요 

npm 버전 업데이트도 해줬어요!!

 

- 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-로 시작하는 것들을 넣기 => 데이터 속성

- 장점: 자바스크립트로 쉽게 접근 가능

 

반응형