[TIL] 211123

Lee SyongΒ·2021λ…„ 11μ›” 23일
0

TIL

λͺ©λ‘ 보기
97/204
post-thumbnail

πŸ“ 였늘 ν•œ 것

  1. ν…œν”Œλ¦Ώ ν™•μž₯ - extends / block

  2. ν…œν”Œλ¦Ώμ— λ³€μˆ˜ μ „λ‹¬ν•˜κΈ° - #{λ³€μˆ˜} / =λ³€μˆ˜ / res.render()

  3. 쑰건문 / each 문 / mixins


πŸ“š 배운 것

1. templates

μ–΄μ œ κ³΅λΆ€μ—μ„œ μ΄μ–΄μ„œ
pug ν…œν”Œλ¦Ώ 엔진 λ°°μš°λŠ” 쀑
일단 μ‹œμž‘ 전에 edit.pug νŒŒμΌλ„ μΆ”κ°€ν•œ ν›„ res.render("edit")κΉŒμ§€ ν•œ μƒνƒœ

3) ν…œν”Œλ¦Ώ ν™•μž₯

μ•žμ„œ includeλ₯Ό μ΄μš©ν•΄ pug νŒŒμΌμ„ λ§Œλ“€μ—ˆμ§€λ§Œ μ—¬μ „νžˆ λ°˜λ³΅λ˜λŠ” 뢀뢄이 μžˆλ‹€.
home.pug와 see.pug 파일의 상당 뢀뢄이 λ°˜λ³΅λœλ‹€.
이λ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ 상속 및 ν™•μž₯을 μ‚¬μš©ν•  수 μžˆλ‹€.

(1) extends

λ² μ΄μŠ€κ°€ 될 파일둜 base.pugλ₯Ό λ§Œλ“ λ‹€.

doctype html
html(lang="ko")
  head
    title Wetube
  body
    h1 Welcome to Wetube
    include partials/footer.pug

λ‹€λ₯Έ νŒŒμΌλ“€(home.pug, see.pug, edit.pug)은 base.pug νŒŒμΌμ„ ν™•μž₯(extends)ν•΄ λ§Œλ“ λ‹€.

extends base.pug

이제 λͺ¨λ“  νŒŒμΌλ“€μ€ base.pug νŒŒμΌμ„ μƒμ†ν•œλ‹€.
κ·ΈλŸ¬λ‚˜, μ΄λ ‡κ²Œλ§Œ ν•˜λ©΄ λͺ¨λ“  파일이 같은 λ‚΄μš©μ„ κ°€μ§€κ²Œ λœλ‹€.
νŒŒμΌλ§ˆλ‹€ λ‹€λ₯΄κ²Œ ν‘œμ‹œλ  뢀뢄을 μ±„μ›Œλ„£λŠ” 방법이 ν•„μš”ν•˜λ‹€.

cf. pug μ•ˆμ—μ„œ extends ν˜Ήμ€ include μ‚¬μš©μ‹œ .pugλŠ” μƒλž΅ν•΄λ„ λœλ‹€.

(2) block

μΌμ’…μ˜ μ°½λ¬Έ 같은 κ²ƒμœΌλ‘œ 이 μ•ˆμ— μ„œλ‘œ λ‹€λ₯Έ λ‚΄μš©μ„ μ±„μ›Œλ„£μ„ 수 μžˆλ‹€.

πŸ’‘ base.pug νŒŒμΌμ— block λ§Œλ“€κΈ°

doctype html
html(lang="ko")
  head
    block head
  body
    block content
    include partials/footer.pug

base.pug νŒŒμΌμ— head와 contentλΌλŠ” block을 μœ„ν•œ 곡간이 λ§ˆλ ¨λ˜μ—ˆλ‹€.

πŸ’‘ base.pug νŒŒμΌμ„ μƒμ†ν•œ 파일의 block에 λ‚΄μš© μ±„μ›Œλ„£κΈ°

extends base.pug

block head 
  title Home | Wetube

block content 
  h1 Home
extends base.pug

block head 
  title See | Wetube

block content 
  h1 See Video
extends base.pug

block head 
  title Edit | Wetube

block content
  h1 Edit Video

이제 각각의 νŒŒμΌλ“€μ€ base.pug νŒŒμΌμ„ μƒμ†ν•˜λ©΄μ„œλ„ 각자 λ‹€λ₯Έ 뢀뢄듀을 가진닀.
κ·ΈλŸ¬λ‚˜, μ—¬μ „νžˆ title νƒœκ·Έμ™€ | wetube ν…μŠ€νŠΈκ°€ 반볡되고 μžˆμ–΄ κ°œμ„ μ΄ ν•„μš”ν•˜λ‹€.

4) ν…œν”Œλ¦Ώμ— λ³€μˆ˜ μ „λ‹¬ν•˜κΈ°

(1) #{λ³€μˆ˜}

μœ„μ˜ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ ~pug 파일의 block head 뢀뢄을 λͺ¨λ‘ μ‚­μ œν•œ ν›„ base.pug νŒŒμΌμ„ μ•„λž˜μ™€ 같이 μˆ˜μ •ν•œλ‹€.

doctype html
html(lang="ko")
  head
	title #{pageTitle} | Wetube
  body
	block content
	include partials/footer.pug

λ°°μš΄λŒ€λ‘œλΌλ©΄ #{ } μ•ˆμ—λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œκ°€ 와야 ν•œλ‹€.
κ·ΈλŸ¬λ‚˜ pageTitle은 κ·Έ 자체둜 값을 κ°€μ§€λŠ” μ½”λ“œκ°€ μ•„λ‹Œ λ³€μˆ˜μ΄κΈ° λ•Œλ¬Έμ— ν…œν”Œλ¦Ώμ— ν•΄λ‹Ή λ³€μˆ˜μ˜ 값을 λ³΄λ‚΄μ€˜μ•Ό ν•œλ‹€.

(2) res.render("view의 이름", {ν…œν”Œλ¦Ώμ— 보낼 λ³€μˆ˜λ“€})

λ Œλ”λ§μ„ ν•˜λŠ” 것은 controller ν•¨μˆ˜μ΄λ―€λ‘œ controller ν•¨μˆ˜μ— ν…œν”Œλ¦ΏμœΌλ‘œ 보내고 싢은 λͺ¨λ“  λ³€μˆ˜λ₯Ό μΆ”κ°€ν•œλ‹€.

μš°μ„ , videoController.js 파일의 trending controllerλ₯Ό μˆ˜μ •ν•΄λ³΄μž.

export const trending = (req, res) => res.render("home", { pageTitle: "Home" });

이제 localhost:4000 으둜 λ“€μ–΄κ°€λ©΄ titleλž€μ— Home | Wetube 라고 λœ¬λ‹€.
λ°±μ—”λ“œλ‘œλΆ€ν„° λ³€μˆ˜μ˜ 값을 λ°›μ•„μ™€μ„œ ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ λžœλ”λ§ν•œ 것이닀.

5) 쑰건문(Conditionals)

μ΄λ²ˆμ—λŠ” ν…œν”Œλ¦Ώμ—μ„œ 쑰건문을 μ‚¬μš©ν•˜λŠ” 방법을 λ°°μ›Œλ³΄κ³ μž ν•œλ‹€.

λ“€μ–΄κ°€κΈ° 전에 잠깐, κ°„λ‹¨ν•˜κ²Œ CSSλ₯Ό μž…νžˆκ³  κ°€μž.

πŸ’‘ MVP.css

MVPλž€ HTML νƒœκ·Έμ— λͺ‡ 가지 κΈ°λ³Έ μŠ€νƒ€μΌμ„ μž…ν˜€μ£ΌλŠ” λ―Έλ‹ˆλ©€λ¦¬μŠ€νŠΈ μŠ€νƒ€μΌμ‹œνŠΈλ₯Ό λ§ν•œλ‹€.

base.pug

doctype html
html(lang="ko")
  head
    title #{pageTitle} | Wetube
    link(rel="stylesheet" href="https://unpkg.com/mvp.css") <!-- MVP.css 적용 -->
  body
    main <!-- κ°€μš΄λ° μ •λ ¬ -->
      block content
    include partials/footer.pug

home.pug

extends base.pug

block content
  h1 Home
  input(placeholder="What's your name?") <!-- μ˜ˆμ‹œλ‘œ μΆ”κ°€ν•œ 것 -->
  button send <!-- 〃 -->

(1) =λ³€μˆ˜

μ•žμ„œ νƒœκ·Έμ— λ³€μˆ˜ 값을 λ„£λŠ” λ°©λ²•μœΌλ‘œ #{λ³€μˆ˜}λ₯Ό λ°°μ› λ‹€.

doctype html
html(lang="ko")
  head
    title #{pageTitle} | Wetube
    link(rel="stylesheet" href="https://unpkg.com/mvp.css")
  body
    main
      block content
    include partials/footer.pug

κ·ΈλŸ¬λ‚˜, νƒœκ·Έμ— ν•˜λ‚˜μ˜ λ³€μˆ˜ κ°’λ§Œ 경우라면 =λ³€μˆ˜ 라고 μ“Έ μˆ˜λ„ μžˆλ‹€.

doctype html
html(lang="ko")
  head
    title #{pageTitle} | Wetube
    link(rel="stylesheet" href="https://unpkg.com/mvp.css")
  body
    header
      h1=pageTitle <!-- μΆ”κ°€ -->
    main
      block content
    include partials/footer.pug

(2) pug νŒŒμΌμ—μ„œ 쑰건문 μ‚¬μš©ν•˜κΈ°

home.pug 파일의 header에 navλ₯Ό μΆ”κ°€ν•΄ loginκ³Ό log out 링크λ₯Ό λ§Œλ“ λ‹€.
userκ°€ 둜그인 μƒνƒœλΌλ©΄ log out 링크λ₯Ό, λ‘œκ·Έμ•„μ›ƒ μƒνƒœλΌλ©΄ login 링크λ₯Ό λ³΄μ—¬μ€˜μ•Ό ν•œλ‹€.
이λ₯Ό μœ„ν•΄ 쑰건문을 μ‚¬μš©ν•  수 μžˆλ‹€.

μš°μ„ , 예제λ₯Ό μœ„ν•΄ κ°€μ§œ μœ μ €λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.

/(Home)에 λ“€μ–΄κ°ˆ μ‹œ μ‹€ν–‰λ˜λŠ” trending controller ν•¨μˆ˜κ°€ μžˆλŠ” videoController.js νŒŒμΌμ— κ°€μ§œ μœ μ € 객체λ₯Ό λ§Œλ“  ν›„ 이λ₯Ό home.pug νŒŒμΌμ— 보낸닀.

videoController.js

const fakeUser = {
  username: "Syong",
  loggedIn: "false" // λ‘œκ·Έμ•„μ›ƒ μƒνƒœ
}

export const trending = (req, res) => res.render("Home", { pageTitle: "Home", fakeUser: fakeuser });
// κ·Έλƒ₯ fakeUser이라고만 써도 됨

base.pug νŒŒμΌμ—μ„œ 쑰건문을 μž‘μ„±ν•œλ‹€.

base.pug

doctype html
html(lang="ko")
  head
    title #{pageTitle} | Wetube
    link(rel="stylesheet" href="https://unpkg.com/mvp.css")
  body
    header
      if fakeUser.username 
        small Hello #{fakeUser.username}
      nav
        ul
          if fakeUser.loggedIn
            li 
              a(href="/users/logout") Log out
          else
            li 
              a(href="/login") Login
      h1=pageTitle
    main
      block content
    include partials/footer.pug

이제 μ„€μ •ν•œ 쑰건에 맞게 링크가 보이게 λœλ‹€.

예제λ₯Ό μœ„ν•œ μ½”λ“œμ˜€μœΌλ―€λ‘œ κ΄€λ ¨ μ½”λ“œλ₯Ό λͺ¨λ‘ μ§€μ›Œμ€¬λ‹€.

6) 반볡문(Iteration)

pug - Iteration μ°Έκ³ 

μ•žμ—μ„œλŠ” λ¬Έμžμ—΄μ„ κ°’μœΌλ‘œ κ°€μ§€λŠ” λ³€μˆ˜λ₯Ό HTML둜 μ „λ‹¬ν•˜λŠ” 방법을 λ°°μ› λ‹€.
κ·Έλ ‡λ‹€λ©΄ λ¬Έμžμ—΄ λŒ€μ‹  배열을 μ „λ‹¬ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒ?
이 λ¬Έμ œμ— λ‹΅ν•˜λ €λ©΄ Iteration에 λŒ€ν•΄ λ°°μ›Œμ•Ό ν•œλ‹€

iterationλŠ” 기본적으둜 list의 λͺ¨λ“  elementsλ₯Ό HTML에 보여쀀닀.

(1) each λ¬Έ

μš°μ„ , 예제λ₯Ό μœ„ν•΄ κ°€μ§œ λΉ„λ””μ˜€ 배열을 λ§Œλ“€μ–΄μ•Ό ν•œλ‹€.

/(Home)에 λ“€μ–΄κ°ˆ μ‹œ μ‹€ν–‰λ˜λŠ” trending controller ν•¨μˆ˜κ°€ μžˆλŠ” videoController.js νŒŒμΌμ— κ°€μ§œ λΉ„λ””μ˜€ 배열을 λ§Œλ“  ν›„ 이λ₯Ό home.pug νŒŒμΌμ— 보낸닀.

videoController.js

export const trending = (req, res) => {
  const videos = [1, 2, 3, 4, 5, 6, 7, 8];
  res.render("Home", { pageTitle: "Home",  videos });
}

home.pug νŒŒμΌμ— 배열을 κ°’μœΌλ‘œ κ°€μ§€λŠ” λ³€μˆ˜λ₯Ό λ§Œλ“ λ‹€. (each ~ in ~)
pugλŠ” 배열에 값이 μžˆλŠ”μ§€ μ—†λŠ”μ§€ μ²΄ν¬ν•œ 후에 μžˆλ‹€λ©΄ λ°°μ—΄μ˜ 각 μš”μ†Œλ“€μ„ 보여주고, μ—†λ‹€λ©΄ λ”°λ‘œ μ„€μ •ν•œ λ‚΄μš©μ„ 보여쀀닀. (else ~)

home.pug

extends base.pug

block content
  h1 Welcome here you will see the trending videos
  ul 
    each video in videos
      li=video
    else
      li sorry nothing found

πŸ’‘ 객체λ₯Ό iterate ν•œ 경우

videoController.js

export const trending = (req, res) => {
  const videos = [ // μˆ˜μ •
    {
      title: "a"
    },
    {
      title: "b"
    },
    {
      title: "c"
    }
  ];
  return res.render("Home", { pageTitle: "Home", videos });
}

home.pug

extends base.pug

block content
  h1 Welcome here you will see the trending videos
  ul 
    each video in videos
      li=video.title <!-- μˆ˜μ • -->
    else
      li sorry nothing found

πŸ’‘ λ§Œμ•½ Cannot read property 'length' of undefined λΌλŠ” μ—λŸ¬κ°€ λ‚˜μ˜¨λ‹€λ©΄, each x in y μ—μ„œ yκ°€ undefined λΌλŠ” λœ»μ΄λ‹€.

(2) Mixins

πŸ”Ž partials와 mixin의 차이점

전에 λ§Œλ“€μ—ˆλ˜ footer.pug νŒŒμΌμ€ HTML의 ν•œ μ‘°κ°μœΌλ‘œμ„œ 데이터λ₯Ό λ°›μ§€λŠ” λͺ»ν•˜λŠ” partial이닀.
λ˜‘κ°™μ€ μ½”λ“œλ₯Ό λ°˜λ³΅ν•˜μ§€ μ•ŠκΈ° μœ„ν•΄ λ§Œλ“  κ²ƒμœΌλ‘œ νŽ˜μ΄μ§€κ°€ λ°”λ€Œμ–΄λ„ λ‚΄μš©μ€ λ°”λ€Œμ§€ μ•ŠλŠ”λ‹€.

λ°˜λ©΄μ—, MixinsλŠ” 데이터λ₯Ό 받을 수 μžˆλŠ” partial이닀.
즉, ν˜•νƒœλŠ” κ°™μ§€λ§Œ μ„œλ‘œ λ‹€λ₯Έ 데이터가 λ°˜λ³΅ν•΄μ„œ λ“±μž₯ν•˜λŠ” HTML 블둝을 λœ»ν•œλ‹€.

πŸ”Ž component

videoController.js

  • videos λ°°μ—΄ μ•ˆμ˜ 객체λ₯Ό μ’€ 더 λ³΅μž‘ν•˜κ²Œ μˆ˜μ •ν–ˆλ‹€.
export const trending = (req, res) => {
  const videos = [
    {
      title: "First Video",
      rating: 5,
      comments: 2,
      createdAt: "2 months ago",
      views: 59,
      id: 1,
    },
    {
      title: "Second Video",
      rating: 5,
      comments: 2,
      createdAt: "2 months ago",
      views: 59,
      id: 1,
    },
    {
      title: "Third Video",
      rating: 5,
      comments: 2,
      createdAt: "2 months ago",
      views: 59,
      id: 1,
    },
  ];
  return res.render("home", { pageTitle: "Home", videos });
};

home.pug

  • home.pug νŒŒμΌμ„ ν™•μž₯ν–ˆλ‹€. 각각의 video에 divλ₯Ό λ§Œλ“€μ–΄ 이 div μ•ˆμ— 정보λ₯Ό 담도둝 μˆ˜μ •ν–ˆλ‹€.
extends base.pug

block content
  h1 Welcome here you will see the trending videos
  each video in videos 
    div 
      h4=video.title
      ul 
        li #{video.rating}/5.
        li #{video.comments} comments.
        li Posted #{video.createdAt}.
        li #{video.views} views.
  else
    li sorry nothing found

이λ₯Ό μ–΄λŠ κ³³μ—μ„œλ‚˜ μž¬μ‚¬μš© κ°€λŠ₯ν•œ component라고 ν•œλ‹€.

예λ₯Ό λ“€μ–΄, μœ νŠœλΈŒμ— λ“€μ–΄κ°€λ©΄ ν”νžˆ λ³Ό 수 μžˆλŠ” 썸넀일, 제λͺ©, 쑰회수 λ“±μ˜ video block이 이에 ν•΄λ‹Ήν•œλ‹€. 직접 μ˜μƒμ„ λ³Ό λ•Œλ„ 보이고 μΆ”μ²œ μ˜μƒλž€μ—λ„ 보인닀. κ·Έ μ™Έ μ—°κ΄€ λ™μ˜μƒμ΄λ‚˜ λ‹€λ₯Έ μ‚¬λžŒμ˜ ν”„λ‘œν•„μ„ 눌러 뜬 μ˜μƒμ—λ„ 이와 λ˜‘κ°™μ€ 것듀을 λ³΄μ—¬μ€˜μ•Ό ν•œλ‹€.

이처럼 ν˜•νƒœλŠ” κ°™μ§€λ§Œ λ°μ΄ν„°λŠ” μ„œλ‘œ λ‹€λ₯Έ HTML 블둝을 μ—¬λŸ¬ νŽ˜μ΄μ§€μ—μ„œ 보여주고 싢을 λ•Œ, UI componentλ₯Ό μ΄μš©ν•  수 μžˆλ‹€. 볡뢙은 μ΅œμ†Œν™”ν•˜λ©΄μ„œ λ˜‘κ°™μ€ ν˜•νƒœλ₯Ό μ‚¬μš©ν•˜λ €λŠ” 것이닀.

πŸ”₯ Mixin λ§Œλ“€κΈ° πŸ”₯

views 폴더 μ•ˆμ— mixins 폴더λ₯Ό λ§Œλ“  ν›„, κ·Έ μ•ˆμ— video.pug νŒŒμΌμ„ μΆ”κ°€ν•œλ‹€.

video.pug

mixin video(info)
  div 
    h4=info.title
    ul
      li #{info.rating}/5.
      li #{info.comments} comments.
      li Posted #{info.createdAt}.
      li #{info.views} views.

μ—¬κΈ°μ„œ videoλŠ” mixin의 이름이닀
mixin videoλŠ” info 객체λ₯Ό λ°›λŠ”λ‹€. ( μ•žμ—μ„œλŠ” video둜 μ μ—ˆμ§€λ§Œ videoκ°€ λ„ˆλ¬΄ λ°˜λ³΅λΌμ„œ info둜 κ³ μΉ¨ )
infoλŠ” mixin videoκ°€ λ°›κ²Œ 될 데이터λ₯Ό μ €μž₯ν•œλ‹€.

divλΆ€ν„° μ‹œμž‘λ˜λŠ” μ½”λ“œλŠ”, info에 μ˜κ±°ν•˜μ—¬ μ–»κ²Œ λ˜λŠ” HTML μ½”λ“œμ΄λ‹€.
즉, mixin videoλŠ” HTML μ½”λ“œλ₯Ό return ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€.

πŸ”₯ Mixin μ‚¬μš©ν•˜κΈ° πŸ”₯

home.pug νŒŒμΌμ„ μˆ˜μ •ν•œλ‹€.

home.pug

extends base.pug
include mixins/video.pug

block content
  h1 Welcome here you will see the trending videos
  each potato in videos 
    +video(potato)
  else
    li sorry nothing found

home.pug νŒŒμΌμ— mixins/video.pug νŒŒμΌμ„ κ°€μ Έμ˜¨λ‹€.
videos(λ°°μ—΄) μ•ˆμ˜ 각각의 potato(객체)에 λŒ€ν•΄μ„œ, video mixin을 ν˜ΈμΆœν•˜μ—¬ potatoλ₯Ό video mixin에 보낸닀.
video mixin은 potatoλ₯Ό λ°›μœΌλ©΄μ„œ video.pug νŒŒμΌμ— μž‘μ„±ν•œ λŒ€λ‘œ potato 즉, info의 λͺ¨λ“  정보에 μ ‘κ·Όν•΄ HTML μ½”λ“œλ₯Ό return ν•œλ‹€.

이 mixin은 μ–΄λ””μ—μ„œλ“  μ“Έ 수 μžˆλ‹€.
즉, ν•΄λ‹Ή HTML μ½”λ“œλŠ” μ–΄λ””μ„œλ“  μž¬μ‚¬μš©ν•  수 μžˆλ‹€.


2. μ—λŸ¬ ν•΄κ²°

(1) μ—λŸ¬ λ‚΄μš©

Error: listen EADDRINUSE: address already in use :::4000

VS code ν™•μž₯ ν”„λ‘œκ·Έλž¨μ„ μ„€μΉ˜ν•˜λŠ” 쀑에 node.jsκ°€ λΉ„μ •μƒμ μœΌλ‘œ μ’…λ£Œλ˜μ—ˆλ‹€.
κ·Έ λ‹€μŒλΆ€ν„° μœ„μ™€ 같은 μ—λŸ¬κ°€ λœ¨λ©΄μ„œ 연결이 μ•ˆλλ‹€.

(2) ν•΄κ²° 방법

μ„œλ²„λ₯Ό μ’…λ£Œν•œλ‹€.
wslμ—μ„œ 4000 포트λ₯Ό μ‚¬μš© 쀑인 ν”„λ‘œμ„ΈμŠ€ λͺ©λ‘μ„ ν™•μΈν•œλ‹€.
μ„œλ²„κ°€ μ—΄λ €μžˆμ§€λ„ μ•Šμ€λ° 4000 포트λ₯Ό μ°¨μ§€ν•˜κ³  μžˆλŠ” ν”„λ‘œμ„ΈμŠ€κ°€ μžˆμ„ 것이닀.

lsof -i :4000

ν•΄λ‹Ή ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°•μ œ μ’…λ£Œν•œλ‹€.

kill -9 [PID]

λ‹€μ‹œ μ„œλ²„λ₯Ό μ—°λ‹€. 정상 μž‘λ™λœλ‹€.


✨ 내일 ν•  것

  1. κ°•μ˜ 계속 λ“£κΈ°
profile
λŠ₯λ™μ μœΌλ‘œ μ‚΄μž, ν–‰λ³΅ν•˜κ²ŒπŸ˜

0개의 λŒ“κΈ€