[SeSACX코딩온] Node.js - module, express, 비동기처리

JUHEE·2024년 1월 25일
0

SeSACX코딩온

목록 보기
4/26

모듈

- commonjs vs ES6(2015)
- commonjs의 모듈 사용법

//require, exports사용

//모듈 생성
function addNum(a, b) {
  return a + b;
}
//한번에 내보내기
module.exports = {
 addNum 
}
//각각 내보내기(함수 표현식, 화살표만 가능)
exports.sayHi = function(name) {
 console.log(name); 
}

//가져오기
const {sayHi} = require('./파일경로확장자는 생략가능'); //각각
sayHi('juhee');
const export1 = require('./파일경로확장자는 생략가능'); //한번에
export1.sayHi('juhee');

- ES6의 모듈 사용법

//export, import

//모듈생성
let apple='맛있다';
function addNum(a, b) {
  return a + b;
}
//한번에 내보내기, as로 별칭사용가능
export {addNum, apple as ap};
//각각 내보내기(모든 함수 방식 사용가능)
export function sayHi(name) {
 console.log(name); 
}
//가져오기
import {addNum, ap} from './파일경로.확장자'; //각각
console.log(ap);
import * as everythings from './파일경로.확장자'; //한번에
console.log(everythings.addNum());

//export default 한개만 내보낸다
export default function sayName() {
 //실행문 
}
//가져올때 구조 분해 필요없어서 배열X
import sayName from './파일경로.확장자';

Express

API

- REST API: HTTP통신에서 CRUD요청을 특정 형태로 전달하는 방식, resource를 특정 method로 요청
- GET: Read, 내용가져오기
- POST: Create, 입력, 등록
- PUT: Update, POST로 대체하는 경우 많다
- DELETE: 삭제
- PATCH: 일부수정, POST로 대체해서 많이 사용

http통신

- node.js를 통해 서버를 구축하는 두가지방법(http, express), 수업에서는 express를 이용하기 때문에 참고만!
- 에러처리가 매우 중요하다
- 1. 서버생성: http모듈을 require해서 http변수에 넣고, createServer메소드로 server를 생성한다

const http = require("http"); //기본제공모듈
const fs = require("fs");

//포트번호는 변수 설정해서 관리 쉽도록함
const PORT = 8080;
const server = http.createServer(function (request, response){
  //기본적으로 request, response객체를 받는다.
}

- 2. html파일을 가져와서 server연결 시 로드되도록한다

const server = http.createServer(function (request, response){
  //fs모듈을 가져와서 readFileSync메소드로 html파일 가져옴
  const data = fs.readFileSync("./index.html");
  //응답헤더 설정을 해주어야 글자가 깨지지 않는다
  response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
  //앞서 가져온 파일을 write()메서드로 로드되도록 설정!(응답본문)
  response.write(data); 
  //end를 안쓰면 계속 로딩중이 되어 write와 end는 반드시 같이 작성해야한다(응답종료)
  response.end();
}

- 3. 오류발생 시 서버가 아예 멈추기 때문에 try ~ catch문으로 예외처리

try {
  //위의내용
} catch(error) {
 //에러 발생 시 404페이지를 띄워보자 
 const data = fs.readFileSync("./404.html");
 response.writeHead(200, { "content-type": "text/html; 	    charset=utf-8" });
 response.write(data);
 response.end();
} finally {
 //에러여부와 관계없이 반드시!! 실행하는 내용 적으면된다
}

- server의 이벤트: on(), listen()

//on: server객체에 이벤트 등록
//1. server request event: 클라이언트가 요청할 때
server.on("request", function (req, res) {
  console.log("request 이벤트 실행!");
  //새로고침해도 계속 발생
});
//2. server connection event: 클라이언트가 접속했을 때
server.on("connection", function (req, res) {
  console.log("connection 이벤트 실행!");
  //처음 접속할때만 발생
});
//listen: 서버를 실행함, 콘솔창에 서버 주소 띄우도록해서 접근한다
server.listen(PORT, function () {
  console.log("server is open");
  console.log(`http://localhost:${PORT}`);
});

Express모듈

- 웹 서버 생성에 관한 기능을 담당하는 프레임워크
- http 모듈보다 가독성이 높고 확장성이 있다
- cmd창에서 node에 접근하여 npm install express로 다운로드
- 서버생성: express 모듈로 express함수를 불러와서 app객체를 생성한다

const express = require("express");
const app = express(); //서버 생성 express application
const PORT = 8080;

- 라우팅: app.get()메소드로 로컬호스트주소 이후 어떤 접근에 대하여 어떤 페이지를 로드할 지 설정한다

//http://로컬호스트:8080 + /로 접근시 보여줄 페이지
app.get("/", (request, response) => {
//send() = http의 write랑 end가 합쳐짐(send랑 render는 절대 같이 하면안된다고 한다) 한글 안깨짐!!
//response.send("hello express!! 안녕하세요 익스프레스");
  
//이 페이지를 보여주세요 명령 render()
response.render("index.ejs");
});

//라우팅(.확장자 생략가능) 위에것도 라우팅임
app.get("/register", (req, res) => {
  res.render("register");
});
app.get("/login", (req, res) => {
  res.render("login");
});
//라우팅 하는 것 중에 제일 마지막에 적어서 페이지 못찾으면 404페이지 오도록 설정함
app.get("*", (req, res) => {
  res.render("404");
});

EJS 템플릿

- Embedded JavaScript의 약자, 자바스크립트가 내장된 html파일을 말한다. 확장자 .ejs
- node에 접근해서 npm install ejs로 다운로드
- server를 설정한 app.js 파일에서 express()로 만든 app객체 .set()메서드로 view engine을 ejs로 설정한다

//ejs를 쓰기 위한 미들웨어 설정
app.set("view engine", "ejs"); //viewengine을 ejs로 쓰겠다고 선언
app.set("views", "./views"); //('view가 있는 곳은', '내 뷰 있는 폴더명') 여기 view파일이 있다고 알려줌
//이 작업을 통해 라우팅 할때 .ejs라는 확장자를 생략해도 되는듯?

- EJS문법: 기본적으로 <% js code %>의 형식으로 작성한다
- <% %>: js code
- <%= %>: 변수나 특정 값을 html화면에 출력할때
- <%- %>: 다른 파일을 include할때

<!--아래와 같이 사용, 두번째 파라미터로 변수값을 넘길 수도 있다-->
<%- include('./includes/header', {title: 'HOME'}) %>

- 미들웨어: 요청과 응답까지의 중간 과정을 함수로 분리한 것(?), use()를 통해 등록한다
- static한 파일을 설정하는 법

//사진, css 등의 static한 요소 가져오기
app.use("/static", express.static(__dirname + "/public"));
// public 폴더에 있는 애들을 /static으로 쓸거라는 의미이다

비동기처리

- 난이도 상당히 어려움;;
- 동기: 순서대로 진행되는 코드
- 비동기: 순서대로 X, 먼저 읽힌코드 먼저 실행
- 자바스크립트는보통 동기적 언어이지만 비동기적 코드 처리가 되는 경우도 있다. ex) setTimeout, 파일읽기, fetch등 특정 메소드(수업에서는 setTimeout을 통해 알아보고있다)
- 비동기코드를 순서대로 처리하기위한 방법에는 3가지가 있다

1. callback 함수

- 인자(매개변수)로 대입되는 함수를 말한다. A함수가 실행되고 나서 B함수가 실행되는 것을 보장하기 위해 A함수의 마지막 매개변수로 callback함수를 받도록 하고 A함수 호출시 선언된 B함수를 A함수의 매개변수로 대입하여 A함수의 실행문에서 실행되도록 하는 것이다

//pickDrink함수의 실행문은 setTimeout함수에 의해 3초후에 실행된다
//pay함수는 pickDrink함수 이후에 실행되어야한다
//callback함수를 매개변수로 설정하고, 실행하는 코드를 맨 마지막에 작성한다
function pickDrink(callback) {
  //3초 고민
  setTimeout(() => {
    console.log("고민끝!");
    product = "콜라";
    price = 2000;
    callback();
  }, 3000);
}
function pay() {
  console.log(`상품명: ${product}, 가격: ${price}`);
}
//선언된 pay함수를 매개변수로 넘긴다
//callback으로 넘길때 소괄호 없이 넘겨야함!!!!(넣으면안됨)
pickDrink(pay);

- 함수의 개수나 복잡도가 늘어나면 가독성이 떨어지는 코드가 만들어진다 그래서 거의 사용되지 않는다

Promise

- ES6에서 추가된 js문법
- new Promise객체를 사용하고, excutor(실행함수)가 자동으로 실행되어 인수인 reject와 resolve(콜백함수)를 통해 성공, 실패의 경우에 따라 다르게 작동하는 구조
- 사용법
1. 함수 작성시 new promise객체를 return하도록 작성
2. new promise함수는 내부에 resolve와 reject매개변수를 가지는 익명함수 function을 가지게되고 해당 function안에 함수 실행문을 작성
3. 함수 실행문 맨 마지막에 resolve(); 콜백함수를 호출함
4. 함수 호출시 new promise객체가 있는
함수 호출.then().catch(err).finally()를 통해 성공시 then실행, 실패시 catch실행, 성공실패 여부와 상관없이 finally실행의 순서대로 진행하게 된다.

//예시코드
function pickDrink() {
  //3초 고민
  //promise객체를 이용하는 방식입니다! (내장된객체)
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("고민끝!");
      product = "콜라";
      price = 2000;
      resolve("구매완료!!");
      // reject("실패");
    }, 3000);
  });
}
function pay() {
  console.log(`상품명: ${product}, 가격: ${price}`);
}
//pickDrink함수의 작업이 성공하면 then을 통해 pay함수가 실행된다 
pickDrink()
  .then(() => {
    pay();
  })
//then(pay)로도 사용가능 위는 화살표 함수를 이용함
  .catch((err) => {
    console.log(err);
  })
  .finally(() => {
    console.log("마트에서 나왔어요");
  });

Q. return의 개념이 헷갈리기 시작함...모르면 return해보는걸루..

Async/Await

- promise객체를 활용하는 또 다른 방법이다
- then().then().then()의 형식으로 코드가 꼬리를 물고 가독성이 떨어지는 것을 방지한다
- async: 함수 앞에 붙여 promise반환
- await: 프로미스 앞에 붙여 처리될때까지 기다리는 역할
- 사용법
1. 원하는 함수를 promise객체로 작성하는 것까지는 동일
2. async키워드를 붙여 실행함수를 하나 더 만들어준다
3. async 함수 내부에서 실행하려는 함수를 불러오고, 대기시키고 싶은 함수 앞에 await키워드를 붙여준다

//1초마다 배경색이 바뀌는 함수
function colorChange(color) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      document.body.style.backgroundColor = `${color}`;
      resolve("성공");
    }, 1000);
  });
}

async function execute() {
  //awati a함수 -> a함수를 기다리세요
  await colorChange("red");
  await colorChange("orange");
  await colorChange("yellow");
  await colorChange("green");
  await colorChange("blue");
}
execute();
profile
초보개발자

0개의 댓글