반응형

HTML을 작성하기 위해서 컨트롤러에서 res.send()메소드로 보내주어도 되만 이렇게 작성했을 시에는 코드가 길어지고 유지보수가 매우 힘들어지며 가독성도 떨어진다.

이를 위해 Express문서 Guide에 Using template engines with Express에보면 다른 많은 Template Engine이 있지만 그 중 Pug를 소개하고 있다.

Pug

https://pugjs.org/api/getting-started.html

 

Getting Started – Pug

Getting Started Installation Pug is available via npm: $ npm install pug Overview The general rendering process of Pug is simple. pug.compile() will compile the Pug source code into a JavaScript function that takes a data object (called “locals”) as an

pugjs.org

pug를 설치하고 pug사용한다는 것을 선언하기 위해 server.js에 아래 문장을 추가해준다.

app.set("view engine", "pug");
app.set("views", "./views");

이렇게 setting을 해주게 되면 ./views라는 디렉토리에 pug 템플릿을 만들어 사용을 해주어야한다. 

 

주의할 점

 API reference 문서에 따르면 views의 파일은 process.cwd()+'./view'로 추적이된다. process.cwd()는 node가 실행되는 rootfile이 있는 곳 즉 package.json이 기준점이 된다 . 따라서 "./views"를 "./src"에 두었다면 밖으로 빼주면 인식이 pug가 인식이 될것이다.

만약 src 폴더 안에 두고 싶다면

app.set("views", process.cwd() + "/src/views");

같이 설정한다.

 

"./views"에 pug 파일을 만들고 이것을 렌더링하기 위해 controller에서 res.render("파일 이름")을 작성하면 된다.

정리하자면 다음과 같다

//server.ts js

import express from "express";
import morgan from "morgan";
import globalRouter from "./routers/globalRouter";

const PORT = 5040;
const app = express();

app.set("view engine", "pug");
app.set("views", process.cwd() + "/src/views");

/* global middelware */
app.use(morgan("dev"));

/* routers */
app.use("/", globalRouter);

const handleListen = () =>
	console.log("✅ Server is Listenin on http://localhost:5040");
app.listen(PORT, handleListen);

////////////

//globalRouter.ts js
import express from "express";
import { home } from "../controllers/globalController";

const globalRouter = express.Router();

globalRouter.get("/", home);

export default globalRouter;

//////////

//globalController.js
export const home = (req, res) => {
	return res.render("home", { title: "hello" });
};

////////////

// ./views/home.pug
doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Document
    body 
        h1=title
        footer= new Date().getFullYear()
        footer #{new Date().getFullYear()} ©

 

Includes

include로 컴포넌트처럼 pug파일을 추가 할 수 있다. 또한 mark down 파일도 포함시켜 html로 변환이 가능하다.

//home.pug
doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Document
    body 
        h1= title
        include partials/footer
        
// ./partials/footer.pug
footer 
    p #{new Date().getFullYear()} © SoundStream

Inheritance : Extends and Block

Extends를 쉽게 설명하자면 Layout라고 말할 수 있겠다. 반복되는 HTML을 Layout에 작성하여 불와서 작성할 수 있게 만들 수 있다.

또한 block을 지정해서 원하는 템플릿에서 불러와 작성할 수 도 있다.

// ./layout/layout.pug

doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Document
    body 
        h1= title
        block contents
        include ../partials/footer
        
// ./home.pug
	extends layout/layout
    
    block contents 
    h1 this is homepage

 

Interpolation

pug는 템플릿엔진이기도 하지만 javascript로 이루어져 있어서 변수 생성도 가능하고 backend와 변수로 소통도 가능하다.

// layout.pug

- const hi = "hahahoho"

doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title #{pageTitle} | SoundStream
    body 
        h2= hi
        block contents
        include ../partials/footer


//globalControllers.js

import { ExpressRouter } from "../types/type";

export const home: ExpressRouter = (req, res) => {
	return res.render("home", { pageTitle: "HOME" });
};

Conditionals

또한 pug는 if문을 작성할 수 있다. 또한 controller와 연동해서 사용도 가능하다 backend에서 object를 보내 그것을 읽어 내는 것도 가능하다.

//layout.pug
doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title #{pageTitle} | SoundStream
    body 
        header 
            include ../partials/navigation
        block contents
        include ../partials/footer
        
// navigation.pug

nav
    ul 
        if user
            li 
                a Logout 
            li 
                a My Page 
        else 
            li 
                a LogIn
                
//globalControllers.js
import { ExpressRouter } from "../types/type";

export const home: ExpressRouter = (req, res) => {
	return res.render("home", { pageTitle: "HOME", user: true });
};

 

Iteration

iteration은 쉽게 말하자면 react에서 map 메소드와 vue에서 v-for 라고 생각하면 된다. 또한 backend에서 object를 보내면 읽어 낼수 있다.

- const a = [1,2,3,4,5]
- const b = {1:"hoho",2:"haha",3:"hehe"}
- const c = []


  ul
                each number,index in a
                    li=number+`${index}`
                each number,key in b 
                    li=`${number} ${key}`
                each number,key in c 
                    li=`${number} ${key}`
                else 
                    li Nothing
                each number,key in c.length >0 ? c :['no value'] 
                    li=`${number} ${key}`
                    
// controller.js
import { ExpressRouter } from "../types/type";
export const home: ExpressRouter = (req, res) => {
	const movies = [
		{ id: 1, title: "hoho", desc: "fhj" },
		{ id: 2, title: "heeh", desc: "werte" },
		{ id: 3, title: "hahah", desc: "ryftujkty" },
		{ id: 4, title: "asdf", desc: "asfdasdf" },
	];
	return res.render("home", { pageTitle: "HOME", movies });
};


// **.pug
      each movie in movies 
            li
                p movie.id
                p movie.titlr
                p movie.desc

Mixins

interation을 사용하다보면 반복되는 사용이 많아질 수가 있다. 이럴 때 mixins를 사용하면 아주 유용하다. mixins는 function과 비슷하다. Mixins pug파일을 만들어주고 iteration과 object를 보내주면 반복되는 결과물을 쉽게 얻어 낼수 있다.

// controller.js or ts
import { ExpressRouter } from "../types/type";
export const home: ExpressRouter = (req, res) => {
	const videos = [
		{ id: 1, title: "hoho", desc: "fhj" },
		{ id: 2, title: "heeh", desc: "werte" },
		{ id: 3, title: "hahah", desc: "ryftujkty" },
		{ id: 4, title: "asdf", desc: "asfdasdf" },
	];
	return res.render("home", { pageTitle: "HOME", videos });
};


// videoMixin.pug
mixin videoMixin(video)
    div 
        ul 
            li #{video.id}
            li #{video.title}
            li #{video.desc}
            
            
//layout.pug
include ../mixins/videoMixin
doctype html
html(lang="ko")
    head
        meta(charset="UTF-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title #{pageTitle} | SoundStream
    body 
        header 
            include ../partials/navigation
        each video in videos 
            +videoMixin(video)


        block contents
        include ../partials/footer
728x90
반응형

Node.js란?

v8 자바스크립트 엔진으로 빌드 된 자바스크립트 런타임. 브라우저 밖에서 돌아가는 자바스크립트

프로젝트생성

1.먼저  해당 폴더를 git을 활성화 해준다.

git init

 

2. VScode에서 터미널에

npm init

 

작성후 package.json을 만들어주고 작성해준다.

index.js를 만들어주고 package.json의 script에 index.js를 실행하게 만들어주는 텍스트 작성 후 저장

"dev": "node src/server.js"

index.js에서 console.log로 아무 글이 나오게 만들고

npm run dev

 

를 실행하면 vscode 터미널에 내용이 나온다.

----

babel로 최신 javascript compile하는 방법

https://babeljs.io/

 

Babel · Babel

The compiler for next generation JavaScript

babeljs.io

node가 최신 javascript를 이해하기 위해 babel을 설치해주어한다.

해당 홈페이지의 setup에 들어가 Language APIs에 있는 node를 클릭하고 설치해주고 설명서대로 진행하면 된다. 또한 Nodemon을 사용하게 되는 경우에는 Utilities의 nodemon을 눌러 진행해준다.

 

** typescript로 진행하게 될 경우 (babel 설치 필요가 없음)

npm install --save-dev @types/node ts-node typescript

tsconfig.json을 만들기 위해 아래 입력

npx tsc --init

tsconfig.json이 만들어지고 혹시 include와 exclude를 찾을 수 없다고 하면 아래와 같이 입력

{
  "compilerOptions":{
    어쩌고 저쩌고
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

package.json에서 아래와 같이 변경

"dev": "ts-node src/server"

다시 아래의 명령어를 입력하여 잘 작동되는지 확인

npm run dev

** typescript를 설치 했다면 간혹 다른 도구를 설치하면 설치한 도구가 뭔지 몰라 빨간 줄이 그어질때가 있는데 당황하지 말고 마우스를 올리면 @types/도구이름 을 설치하라고 나오니 설치하면 잘 작동될것이다.

nodemon 설치

작업을 하면서 계속해서 'dev'명령어를 칠 수 없으니 nodemon을 사용해줘서 개발환경에서 백엔드가 지속적으로 동작할 수있게 만들어주어야 하는데 이때 도움을 줄수 있는 것이 nodemon이다.

npm i nodemon --save-dev

실행문을 바꿔준다.

"dev": "nodemon --exec ts-node src/server"

 

nodemon 파일 변경 감지 설정

//nodemon.json

{
  "ext": "ts,json,tsx"
}

ESLint / Prettier 설정

npm init @eslint/config
//프로젝트 루트 폴더 위치에서 터미널에
npm i -D prettier eslint-config-prettier

//명령어를 입력하여 prettier와 eslint-config-prettier 패키지를 설치합니다.
//프로젝트 루트 폴더 위치에 .prettierrc 파일 (prettier 설정 파일)을 생성합니다.
// 아래를 참고하여 prettier 옵션들을 .prettierrc 파일에 작성합니다. 추가적인 옵션들은 Prettier Options를 참고하시면 됩니다.

{
  // 쌍따옴표 대신 홑따옴표 사용
  "singleQuote": true,
  // 모든 구문 끝에 세미콜론 출력
  "semi": true,
  // 탭 대신 공백으로 들여쓰기
  "useTabs": false,
  // 들여쓰기 공백 수
  "tabWidth": 2,
  // 가능하면 후행 쉼표 사용
  "trailingComma": "all",
  // 줄 바꿈할 길이
  "printWidth": 80,
  // 객체 괄호에 공백 삽입
  "bracketSpacing": true,
  // 항상 화살표 함수의 매개 변수를 괄호로 감쌈
  "arrowParens": "always",
  // OS에 따른 코드라인 끝 처리 방식 사용
  "endOfLine": "auto"
}

.eslintrc에 가서

extends: ['기존 설정들', 'prettier']

또한 extent에서 eslint와 prettier를 설치해주고

vscode setting.json에 아래 추가

// 파일을 저장할 때마다 `eslint` 규칙에 따라 자동으로 코드를 수정
"editor.codeActionsOnSave": { "source.fixAll.eslint": true },
// `prettier`를 기본 포맷터로 지정
"editor.defaultFormatter": "esbenp.prettier-vscode",
// 파일을 저장할 때마다 포매팅 실행
"editor.formatOnSave": true,

 

Server란?

서버는 항상 켜져있고, 인터넷에 연결되어 있으며 request를 listening하고 있는 컴퓨터이다.

request란?

request는 우리가 서버에게 요청하는 것들이다. 브라우저로 웹사이트로 들어가는 행위가 request를 보내는것이다. 이 행위는 행위를 listening 하고 있는 서버에만 적용된다. 또한  get이외에 CRUD가 기반이 되는 post, delete, put 등등이 있다.

controllers

해당 url로 이동하려고 하면 그에 대한 동작을 실행하는게 controller이다. 여기서 request 와 response를 제공하게 되는데  request에는 누가 웹사이트를 request 했는지 cookies, 브라우저 정보 , IP 주소 같은 정보들이 있다. response에는 여러 메소드가 있다. cookie 설정부터 무엇을 보내고 렌더링하고 응답을 끝내는 등 많은 메소드가 있다.

 

middleware란? 

request와 response 중간에서 동작하는 함수 따위를 middleware라고 한다. 

middleware는 controller와 비슷하다. 보안이나 CRUD를 구현할때 같이 쓰인다.

NodeJS server 만들기  /  동적 및 정적 라우팅

import http, { IncomingMessage, ServerResponse } from "http";
import url from "url";

type HandleMap = {
	// eslint-disable-next-line no-unused-vars
	[path: string]: (req: IncomingMessage, res: ServerResponse) => void;
};
const server = http.createServer(
	(req: IncomingMessage, res: ServerResponse) => {
		const path = url.parse(req.url + "", true).pathname; // 패스명 할당
		res.setHeader("Content-Type", "text/html"); //응답 헤더 설정
		if (path && path in urlMap) {
			urlMap[path](req, res);
		} else {
			notFound(req, res);
		}
		// if (path === "/user") {
		// 	user(req, res);
		// } else if (path === "/feed") {
		// 	feed(req, res);
		// } else {
		// 	notFound(req, res);
		// }
	},
);

server.listen("5040", () => console.log("server is good"));
//동적
const user = (req: IncomingMessage, res: ServerResponse) => {
	const userInfo = url.parse(req.url + "", true).query;
	res.end(`[user] name : ${userInfo.name}, age : ${userInfo.age}`);
};
//정적
const feed = (req: IncomingMessage, res: ServerResponse) => {
	res.end(`
        <ul>
        <li>pictuer1</li>
        <li>pictuer2</li>
        <li>pictuer3</li>
        </ul>`);
};
const notFound = (req: IncomingMessage, res: ServerResponse) => {
	res.statusCode = 404;
	res.end("404 page not found");
};
const urlMap: HandleMap = {
	"/": (req: IncomingMessage, res: ServerResponse) => res.end("Home"),
	"/user": user,
	"/feed": feed,
};

express로 서버만들기

express를 사용하면 순수 nodejs로 서버를 만드는것보다 좀 더 쉽게 만들수있다.

import express, { Request, Response } from "express";

const PORT = 5040;
const app = express();

const middleWare: express.RequestHandler = (req, res, next) => {
	console.log("hohoho");
	next();
};
const user = (req: Request, res: Response) => {
	return res.send("user Page");
};
app.use(middleWare); //global 하게 미들웨어를 동작시킬 수 있다.

app.get("/", (req, res) => {
	return res.send("hi");
});
app.get("/music", (req, res) => {
	return res.send("music page");
});

app.get("/user", middleWare, user); // 해당 url에서만 미들웨어를 동작시킬 수 있다.

const handleListen = () =>
	console.log("✅ Server is Listenin on http://localhost:5040");
app.listen(PORT, handleListen);

 

 

 

app.get()으로 request를 요청 할 수 있다.

app.use()로 글로벌하게 MiddleWare를 동작시킬수 있다. 주의할점은 app.use 보다 위에 작성해야한다.

 

morgan - middle ware

node용 request logger middle ware이다.

npm i morgan
app.use(morgan("dev"));
// dev 말고도 다른것들도 있음

이렇게 하면 백엔드에서 morgan은 request method , path , status code 응답시간 정보를 가지고 있다.

728x90

+ Recent posts