[fastcampus] Ch9. Vue 시작하기 (2)

productuidev·2022년 7월 31일
0

Vue Study

목록 보기
2/3
post-thumbnail

Ch9. Vue 시작하기

4. Vue3 Webpack Template

webpack-template-basic

npx degit 디렉토리/저장소명 vue3-webpack-template

npx degit 설치하지 않고도 명령 실행
버전관리 없이 프로젝트 복제 (cf. npx degit과 git clone의 차이)

💎 Vue VSCODE 공식 추천 Extensions 설치

Vue Language Features (Volar)

https://github.com/johnsoncodehk/volar

1) 기본 프로젝트 설치/설정

Vue3 패키지 설치

npm i vue@next

npm i -D vue-loader@next vue-style-loader @vue/compiler-sfc

vue-loader@next : Vue3 패키지
vue-style-loader : .vue 파일에서 style을 해석해주는 로더

webpack.config.js 수정

💎 webpack

  • 수많은 JS 파일을 하나로 묶어(bundling) 네트워크 비용을 최소화시켜주는 도구 (모듈화)
  • 왜 사용하는가

webpack.config.js 설정 참고

// 현재 프로젝트에서 모듈 경로를 찾을 수 있도록 지정.
// 특히 Windows에서 발생하는 오류 해결을 위한 코드.
// 이 코드가 없어도 잘 동작하는 경우 필요치 않음.
const _require = id => require(require.resolve(id, { paths: [require.main.path] }))

// path: NodeJS에서 파일 및 디렉토리 경로 작업을 위한 전역 모듈
const path = _require('path')
const HtmlPlugin = _require('html-webpack-plugin')
const CopyPlugin = _require('copy-webpack-plugin')
const { VueLoaderPlugin } = _require('vue-loader')

module.exports = {
  resolve: {
    // 경로에서 확장자 생략 설정
    extensions: ['.js', '.vue'],
    // 경로 별칭 설정
    alias: {
      '~': path.resolve(__dirname, 'src'),
      'assets': path.resolve(__dirname, 'src/assets')
    }
  },

  // 파일을 읽어들이기 시작하는 진입점 설정
  entry: './src/main.js',

  // 결과물(번들)을 반환하는 설정
  output: {
    // 주석은 기본값!, `__dirname`은 현재 파일의 위치를 알려주는 NodeJS 전역 변수
    // path: path.resolve(__dirname, 'dist'),
    // filename: 'main.js',
    clean: true
  },

  // 모듈 처리 방식을 설정
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader'
      },
      {
        test: /\.s?css$/,
        use: [
          // 순서 중요!
          'vue-style-loader',
          'style-loader',
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 제외할 경로
        use: [
          'babel-loader'
        ]
      },
      {
        // 파일 로더 설정 규칙
        test: /\.(png|jpe?g|gif|webp)$/,
        use: 'file-loader'
      }
    ]
  },

  // 번들링 후 결과물의 처리 방식 등 다양한 플러그인들을 설정
  plugins: [
    new HtmlPlugin({
      template: './index.html'
    }),
    new CopyPlugin({
      patterns: [
        { from: 'static' }
      ]
    }),
    new VueLoaderPlugin()
  ],

  // 개발 서버 옵션
  devServer: {
    host: 'localhost',
    port: 8080,
    hot: true
  }
}

2) 기본 파일 생성

src/App.vue

<template>
  <h1>{{ message }}</h1>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello Vue!!!'
    }
  }
}
</script>

src/main.js

// CDN mode
import Vue from 'vue'
import App from './App.vue'

Vue.createApp(App).mount('#app')
// CLI mode
import { createApp } from 'vue' // 객체구조분해를 통해 바로 createApp 가져올 수 있음
import App from './App.vue'
createApp(App).mount('#app')

App.vue 파일이 프로젝트의 시작이 될 수 있도록 main.js에 import

root: index.html

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Webpack project!</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css">
</head>
<body>
  <div id="app"></div>
</body>
</html>

div id="app"으로 프로젝트가 동작할 수 있는 구조가 됨

npm run dev

8080 포트로 프로젝트 열림

3) 컴포넌트 생성

  • src/components 폴더에 HelloWorld.vue 컴포넌트 생성
  • 파일 네이밍 규칙 : 파스칼케이스(PascalCase) ex) HelloWorld, DiaryEditor..

npm i -D file-loader

(개발의존성으로) 특정한 파일을 읽어서 브라우저에 출력해주는 로더 설치한 후
위에 webpack.config.js을 참조하여 파일로더 설정, 경로 별칭 설정 추가

src/components/HelloWorld.vue

이미지 삽입하기

<template>
  // 설정한 경로 별칭 ~ 
  <img src="~assets/image.png" alt="productuidev" />
</template>

src/App.vue

HelloWorld 컴포넌트 불러오기

<template>
  <HelloWorld /> // 컴포넌트 삽입
</template>

<script>
// 설정한 경로 별칭 ~ 으로 (상대경로)
import HelloWorld from '~/components/HelloWorld'

export default {
  components: {
    HelloWorld
  },
  data() {
    return {
      message: 'Hello Vue!'
    }
  }
}
</script>

5. Vue3 Webpack Template - ESLint

1) ESLint 기본 설정

npm i -D eslint eslint-plugin-vue babel-eslint

  • (개발의존성으로) ESLint, vue플러그인, babel eslint 기본 패키지 설치
  • root 경로에 .eslintrc.js 생성
module.exports = {
  // 브라우저와 node에서 동작하는 전역 개념 코드 검사 규칙 설정
  env: {
    browser: true,
    node: true
  },
  // Vue와 JavaScript 코드 검사 규칙 설정
  extends: [
    // Vue (Lv2로 설정)
    // 'plugin:vue/vue3-essential', // Lv1
    'plugin:vue/vue3-strongly-recommended', // Lv2
    // 'plugin:vue/vue3-recommended', // Lv3

    // JavaScript
    'eslint:recommended'
  ],
  // 코드 분석기 (구문 분석)
  parserOptions: {
    parser: 'babel-eslint' // es6 > es5
  },
  // extends에서 기본적인 규칙을 설정한 경우 rules를 별도로 설정하지 않아도 됨
  // 예외 규칙이 있다면 추가
  rules: {

  }
}

💎 ESLint Plugin

ESlint를 통해 규칙(컨벤션)을 설정할 수 있고, 여러명이 작성하는 코드일 경우
팀에서 사용할 경우 합의하여 설정을 변경하여 사용도 가능하다.

vue-eslint vue-eslint2

💎 ESLint

ESLint는 코드를 정적으로 분석하여 문제를 빠르게 찾습니다. 대부분의 텍스트 편집기에 내장되어 있으며 지속적 통합 파이프라인의 일부로 ESLint를 실행할 수 있습니다.
Rules

권장되는 코드 규칙을 협업 시 합의하여 설정 가능 (단, 절대적인 개념은 아님)

💎 ESLint + Prettier

2) ESLint Rule 설정

예시) vue/html-self-closing

1. <YourComponent></YourComponent>
2. <YourComponent/> (self-closing)
{
  "vue/html-self-closing": ["error", {
    "html": {
      "void": "never",
      "normal": "always",
      "component": "always"
    },
    "svg": "always",
    "math": "always"
  }]
}
  • .eslintrc.js에 rules에 Vue3 Rules를 참조해 사용할 규칙을 정의해놓을 수 있다.
  • 혼자 개발할 때는 규칙 설정이 다소 번거로울 수 있으나 여러 명의 개발자가 함께 프로젝트를 할 경우에는 유용하게 사용된다.

💎 eslint 규칙으로 코드 자동 수정

VSCODE > F1 > Preferences : Open Settings (JSON) 설정 변경

    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true,
    },

3) 기타

💎 template 내 에러 해결 참고

컴포넌트 작성 시 template나 작성한 tag에 빨간줄(에러) 뜰 경우 해결 방법

"vetur.validation.template": false,
"vetur.validation.script": false,
"vetur.validation.style": false,
  • .eslintrc의 rules 추가
rules: {
    "vue/no-multiple-template-root": "off",
    "vue/valid-template-root": "off",
}

6. 선언적 렌더링과 입력 핸들링

완성한 Vue3 템플릿을 npx degit 하여 새로운 프로젝트 복제하여 생성

1) SFC (Single File Component)

.vue 확장자를 사용하는 단일 컴포넌트

vue-sfc
  • HTML : template (Vue 문법)
  • JavaScript : script (Vue 문법)
  • CSS/SCSS : style

현재 템플릿에서는 SCSS 설정도 추가되어 있음 (webpack.config.js)

2) 반응성 (Reactivity)

count라는 데이터가 변경되면 브라우저가 갱신된다 (모던 프론트엔드 프레임워크의 핵심)

<template>
  <!-- h1을 클릭하면 함수 실행 -->
  <h1 @click="increase">
    {{ count }}
  </h1>
</template>


<script>
export default {
  data() { // data 정의
    return {
      count: 0 // 초기값 지정
    }
  },
  methods: { // methods
    increase() { // function
      this.count += 1 // this = script 전체, count에 접근하여 함수가 실행되면 1씩 증가
    }
  }
}
</script>

<style>
  h1 { font-size:50px; color:royalblue; }
</style>

7. 조건문과 반복문

1) v-if/v-for

  • v- : Directive (디렉티브)
  • v-if : 조건문
  • v-for : 반복문
<template>
  <!-- h1을 클릭하면(onClick) 함수 실행 -->
  <h1 @click="increase">
    {{ count }}
  </h1>
  <!-- v-if 조건문 -->
  <div v-if="count > 4">
    4보다 큽니다!
  </div>
  <ul>
    <!-- v-for 반복문 -->
    <!-- fruit in fruits : fruits 배열 데이터 반복, fruit라는 변수에 담기 -->
    <!-- 해당 data가 고유한지 증명 :key="fruit" -->
    <li
      v-for="fruit in fruits"
      :key="fruit">
      {{ fruit }}
    </li>
  </ul>
</template>


<script>
export default {
  data() {
    return {
      count: 0,
      fruits: ['Apple', 'Banana', 'Cherry'], // 배열 추가
    }
  },
  methods: { 
    increase() { 
      this.count += 1
    }
  }
}
</script>

<style lang="scss">/* scss 사용 시 lang 설정 */
  h1 { font-size:50px; color:royalblue; }
  ul {
    li { font-size:40px; }
  }
</style>

참고자료

2) 컴포넌트 생성

src/components/Fruit.vue

<template>
  <li>{{ name }}</li> <!-- 데이터 출력 -->
</template>

<script>
export default {
  props: {
    name: {  
      type: String, // 데이터 타입
      default: '' // 데이터가 들어오지 않으면 빈 문자
    }
  }
}
</script>

<style lang="scss">

</style>

src/App.vue

Fruit 컴포넌트 import

<template>
  <h1 @click="increase">
    {{ count }}
  </h1>
  <div v-if="count > 4">
    4보다 큽니다!
  </div>
  <ul>
    <Fruit
      v-for="fruit in fruits"
      :key="fruit"
      :name="fruit">
      {{ fruit }}
    </Fruit>
  </ul>
</template>


<script>
import Fruit from '~/components/Fruit'

export default {
  components: { 
    Fruit: Fruit // 같으면 :Fruit이 생략가능
  },

  data() { 
    return {
      count: 0, 
      fruits: ['Apple', 'Banana', 'Cherry'],
    }
  },
  methods: { 
    increase() { 
      this.count += 1
    }
  }
}
</script>

<style lang="scss">
  h1 { font-size:50px; color:royalblue; }
  ul {
    li { font-size:40px; }
  }
</style>

3) 컴포넌트 style

<style scoped lang="scss">
  h1 { color:red !important; }
</style>

scoped : 다른 컴포넌트에는 영향을 미치지 않고, 현재 컴포넌트에만 영향을 줌 (유효범위를 잡는 속성)
이 속성을 활용하면 컴포넌트 내부에 스타일을 복잡하게 작성하지 않더라도 손쉽게 관리할 수 있음

참고자료


💬 모던 프론트엔드 개발을 하려면... 설치와 설정이 50% 이상이므로
처음 프로젝트 시작 시 알 수 없는 에러로 다소 지연이 되더라도
마음의 여유를 갖고 시작하지 않으면 초반부에 에너지를 다 써버려서 지칠 수 있다.
(🔑 모던 프론트엔드 개발 리빙포인트 : 구글링을 하면 개발이 수월해진다.)

💬 패스트캠퍼스 초격차 패키지 챕터 순서상 Vue.js가 먼저였는데 작년 말~올해 초 의욕이 너무 앞선 나머지 React부터 들었었는데...

이 강의 들으니 Vue부터 들었으면 이해가 더 빨랐겠다는 생각..(SPA 비교 시 대부분 리액트가 러닝커브가 높다고도 했는데, Vue 강의 들어보니 리액트랑 비슷하면서도 전반적인 방식의 흐름을 알 거 같다) 물론 한 입 크기로 먹는 리액트를 듣지 않았다면 힘들었겠지..(그 강의는 리액트 강의지만 진짜 백미는 자바스크립트를 정말 쉽게 알려준다 😀) 그리고 대부분 리액트를 쓰는 프론트엔드 개발자 모집을 보면 리액트보다 자바스크립트를 잘하는 게 더 중요한 거 같고... 결국 기본은 자바스크립트

💬 박영웅 강사님이 설명이 쉬워서 찾아보니 타입스크립트 강의도 있어서 구름EDU도 가입했다.
문서로 된 강의인데 책같아서 짬짬히 보는 중..

💬 이 강의를 들으면서 올해 초 실습해보고 싶었던 것을 조금씩 할 수 있을 거 같다.. 백엔드 몰라도 혼자 서비스 만들 수 있어요 (퇴근하고 천천히 학습하다보니 무려 반년이나 걸렸군 😳 나름 다 계획이 있었으나..)

profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글