Node.js와 NPM

Node.js크롬 v8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임이다. 

 

상황에 따라 Node.js의 버전을 변경할 수 있는 환경을 구축해야 한다.

이럴 때 사용할 수 있는 패키지가 nvm으로 Node Version Manager의 약자이다.

 

npm은 Node.js를 설치하면 같이 설치되는데 Node.js Package Manager의 약자이다.

 

npm init

npm init은 Node.js 환경에서 npm이라는 Node.js Package Manager을 통해 init, 즉 초기화 하는 것은 현재 프로젝트를 npm으로 관리하겠다라는 것이다.

 

터미널에 명령어를 입력하면 패키지 이름을 입력하라고 하는데 이는 중복되지 않게 짓는 것이 좋다.

프로젝트라는 것은 어디까지나 하나의 패키지이고 그런 패키지들은 외부에서도 가져올 수도 있는데 그런 패키지와 내가 관리하는 패키지의 이름이 동일하면 충돌이 발생한다.

Vue 프로젝트를 진행한다고 해서 패키지 이름을 vue라고 짓는 등의 행위는 좋지 않다.

 

만일 패키지 이름을 현재 폴더 이름으로 만들거면 아무것도 입력하지 않고 엔터를 눌러도 된다.

 

패키지 이름 다음으로 입력해야 할 것은 버전이다.

마침표로 구분되어 있는 각각의 버전은 유의적 버전(SemVer = Semantic Version)이라고 한다.

Major.Minor.Patch

  • Major - 기존의 버전과 호환되지 않는 새로운 기능
  • Minor - 기존 버전과 호환 가능한 새로운 기능
  • Patch - 간단한 버그, 오타 수정과 같은 비교적 규모가 작은 수정 사항

 

이름과 버전 설정을 마치면 설명을 입력하고, 그 후로 진입점(entry point)를 입력한다.

참고로 진입점은 일반적인 웹 프로젝트에서는 필요하지 않다.

이외에도 test command 등 질문이 계속 이어지는데 모두 작성이 끝나면 package.json이라는 이름의 파일이 생성된다.

 

Package.json

package.json에는 이름과 버전 등 질문에서 대답한 내용들로 구성되어 있다.

수정하고 싶은 부분이 있다면 해당 파일을 수정하면 된다.

 

npm init -y를 입력하면 질문 없이 한 번에 package.json이 만들어진다.

만들어진 파일에서 원하지 않는 방식은 수정하면 된다.

 

package.json 파일이 생성되고 나면 npm으로 외부 패키지를 설치할 수 있다.

npm install [패키지명] = npm i [패키지명]

install 은 i라는 별칭으로 사용할 수도 있다.

 

기존에 CDN을 통해 원격의 Vue를 가져와서 연결했는데 이번에는 로컬 환경에 직절 설치를 해보자.

npm install vue

 

Vue 패키지가 설치되고 나면 package-lock.jsonnode_modules라는 폴더가 생성된다.

package.json 파일을 열어 보면 dependencies라는 옵션에 뷰 패키지가 설치가 된 것을 확인할 수 있다.

 

패키지의 정보를 보고 싶다면 info 명령어를 사용한다.

npm info vue

 

만일 vue의 다음 버전을 설치하고 싶다면 버전 혹은 버전의 별칭을 패키지 이름 뒤에 적어준다.

npm i vue@3.2.9 = npm i vue@next

 

패키지를 제거하고 싶다면 다음 명령어를 입력한다.

npm uninstall vue = npm un vue 

uninstall 은 un이라는 별칭으로 사용할 수도 있다.

 

node_modules

node_modules 폴더에는 설치한 패키지들이 존재한다.

하지만 막상 확인해보니 vue 패키지 말고도 다른 패키지들이 존재하는데 이는 Vue.js가 동작하기 위해 의존하고 있는 다른 패키지들이다.

의존하는 패키지의 목록을 확인하고 싶다면 node_modules/vue/pacakge.jsondependencies를 확인하면 된다.

 

의존성 옵션에는 dependenciesdevDependencies가 존재하는데 전자는 일반 의존성 패키지를 의미하고, 후자는 개발 의존성 패키지를 의미한다.

 

npm install로 설치하는 패키지들은 기본적으로 main 옵션을 통해 최초에 어디로 접근해서 해당 패키지를 사용해야 하는지 명시해야 한다.

하지만 누군가에게 제공하는 용도의 패키지가 아니라면 외부에서 접근할 진입점이 필요하지 않기 때문에 main 옵션이 존재하지 않아도 된다.

 

지금까지의 과정을 정리하자면 프로젝트 단위로 필요한 패키지들을 프로젝트에 설치하고 설치된 패키지들은 pacakge.json이라는 파일을 통해 관리되며 node_modules 폴더 안에 실제 설치가 되는 것이다.

 

Node.js

Node.js자바스크립트 런타임이다.

런타임이란 무엇인가가 동작하는 환경을 의미한다. 

 

우리는 자바스크립트라는 프로그래밍 언어를 통해서 웹 브라우저 혹은 컴퓨터를 제어할 수 있는데 컴퓨터를 제어하려면 자바스크립트가 동작할 수 있는 환경이 제공되어야 한다.

그때 설치하는 것이 바로 Node.js라는 런타임이고 Node.js가 설치 된 컴퓨터는 로컬 환경이라고 이야기 할 수 있다.

 

자바스크립트를 통해서 우리의 컴퓨터를 제어하는 용도로 Node.js를 설치했고 Node.js가 설치되어 있는 우리의 컴퓨터에서 웹 브라우저에서 동작할 프로젝트를 개발하는 것이 지금의 상황이다.

이때 유용하게 사용할 수 있는 것이 패키지 매니저인 npm이다.

 

npm을 통해 Vue, React 혹은 Webpack, Parcel 같은 번들러, 누군가가 만들어 둔 다양한 기능의 패키지를 우리의 프로젝트에 설치해서 그런 것들을 통해 개발을 하고, 그 개발된 결과를 웹 브라우저에서 동작할 수 있는 형태로 빌드(변환)해서 그것을 웹 브라우저에 출력해서 사용자에게 보여주는 것이 프론트엔드 개발이다.

 

Node.js를 설치해서 개발을 시작한다는 것은 Node.js에서 제공하는 다양한 기능들을 활용하기 위함이다.

엄밀히 따지면 Node.js 환경에서 프론트엔드 개발을 하지 않아도 상관은 없다.

다만 개발의 난이도가 어려워질 뿐이다. 

 

Node.js는 자바스크립트를 통해 컴퓨터를 제어하는 것이 주용도이고, 그렇게 제어되는 것을 통해서 프론트엔드 개발에 일부 도움을 받는 것이다.

참고로 vscode에서 라이브 서버를 오픈하거나 npx 기능을 통해 serve라는 패키지를 바로 실행하는 것도 전부 Node.js의 기능을 활용하는 것이다.

로컬 서버를 Node.js로 열어서 브라우저에서 개발 테스트를 할 수 있게 환경을 제공하는 것이다.

 

npx serve

기존에는 프로젝트의 index.html 파일을 기준으로 해서 개발 서버를 오픈해서 테스트를 진행했다.

vscode의 라이브 서버라는 확장 프로그램 혹은 npx serve라는 명령을 활용했다.

 

[참고]

스크립크 태그는 head 태그 내에 작성되는 것이 권장되는데 defer 옵션을 사용하면 스크립트 실행을 뒤로 미룬다. 

따라서 index.html을 다 읽고 나서 스크립트가 실행되는 것이다.

 

[참고]

port는 항구를 의미한다.

서버 포트란 로컬 환경(컴퓨터)에서 개발 서버를 오픈해서 서버로 접근할 때 어떤 번호에서 접속할 것인지를 의미한다. 

 

npx serve

현재 경로에 있는 실행 파일을 엮어서 5000번 포트로 개발 서버를 오픈한다.

개발 환경을 브라우저에서 테스트할 수 있게 된다.

 

npm이 설치되면 npx도 설치된다.

x는 패키지를 실행시키는 running의 의미이다.

따라서 npx serve라는 명령어의 의미는 serve라는 패키지를 동작시킨다는 의미가 된다.

 

 

serve

Static file serving and directory listing. Latest version: 14.1.2, last published: 19 days ago. Start using serve in your project by running `npm i serve`. There are 655 other projects in the npm registry using serve.

www.npmjs.com

serve로컬 서버를 오픈하는 용도로 사용하는 패키지이다.

 

npx serve를 입력하면 패키지를 로컬 환경에 설치하는 것이 아니라 단순히 메모리상에 설치하고 실행한다.

 

만일 serve라는 패키지를 메모리상에 일시적으로 설치해서 실행할 것이 아니고 프로젝트에서 직접 설치하고 싶다면 npm i serve를 입력한다.

하지만 serve라는 패키지는 개발 서버를 오픈하는 용도로, 개발할 때만 활용이 되는 패키지이다.

프로젝트가 실제 웹 브라우저에서 동작할 때 serve라는 패키지는 필요하지 않다.

실제 서버는 호스팅 서버를 이용하거나 AWS ec2, Heroku같은 실제 서버 환경으로 구축하기 때문이다.

 

결국 이 serve라는 패키지는 개발할 때만 사용되는데 이를 알리는 표시를 남길 수 있다.

npm i serve --save-dev

혹은 압축해서 -D로 사용할 수도 있다.

npm -i serve -D

 

[참고]

npm i vue 명령어를 입력할 때는 --save-dev-D를 붙일 필요가 없다.

개발할 때만 사용하는게 아니라 브라우저에서도 필요한 패키지이기 때문이다.

 

npm -i serve -D 명령어를 입력하면 serve 패키지는 개발할 때만 의존하는 devDependencies에 설치된다.

  "devDependencies": {
    "serve": "^14.1.2"
  }

^ 기호는 ~이상을 의미한다.

그로인해 이 프로젝트를 오픈한 컴퓨터마다 버전이 달라질 수 있다는 문제가 있다. 

 

그래서 필요한 것이 package-lock.json 파일이다.

package-lock.json 파일은 패키지를 설치할 당시의 정확한 버전 정보를 저장하고 있으며, 패키지들 간의 의존성까지 관리한다.

따라서 package.json과 package-lock.json 파일만 있다면 node_modules 폴더를 제거하더라도 터미널을 통해 완전히 동일한 환경으로 다시 설치할 수 있다. 

즉, node_modules라는 폴더는 따로 관리할 필요가 없기 때문에 깃허브 저장소에 업로드 할 필요가 없다.

 

그럼 이제 serve 패키지를 설치했으니 터미널에 serve를 치면 개발 서버가 실행될까?

아니다. 그렇게 사용하려면 로컬 환경 전체에서 사용할 수 있도록 npm -i serve g같은 명령어를 통해 전역 설치가 되어 있어야 한다.

 

전역으로 설치하지 않은 경우 현재 프로젝트에서만 serve라는 패키지를 사용할 수 있는데 이때 사용할 수 있는게 scripts 옵션이다.

  "scripts": {
    "dev": "serve"
  },

dev라는 스크립트 키워드를 통해 serve 명령을 동작하겠다는 의미다.

스크립트에 있는 명령들을 시작할 때run 키워드를 붙인다.

따라서 터미널에 npm run dev 명령어를 입력하면 serve 명령이 동작하게 된다.

 

SFC 프로젝트 구성 w.Parcel

Parcel 번들러를 통해서 Vue.js 프로젝트를 구성해보자.

[참고] Parcel 번들러는 Node.js 버전 14 이상에서만 동작한다.

 

npm init -y

npm i vue

[참고]

npm을 통해 설치하는 vue는 빌드 과정을 거쳐서 브라우저에서 동작할 수 있는 코드로 변환이 될 것이기 때문에 

변환되기 전의 개발 용도의 내용으로 구성이 되어 있다.

CDN을 통해 가져오는 vue와 다르다.

 

import * as Vue from "vue";

import 키워드를 통해 Vue라는 이름으로 내용을 한 번에 가져오려면 export default로 내보내기가 된 것만 가져올 수 있다.

하지만 vue 패키지는 export default가 아니라 모두 이름을 가진 내보내기로 구성되어 있다.

따라서  * as Vue를 통해 그러한 내보내기를 모두 모아 Vue라는 이름으로 사용하는 것이다.

 

[참고] npm 프로젝트에서 따로 상대경로를 명시하지 않고 가져오는 이름은 node_modules에 설치된 패키지를 가져오는 것이다.

 

main.js은 vue라는 확장자를 가지고 있는 파일을 브라우저 상에서 제대로 해석할 수 없다.

그렇기 때문에 이를 해석해서 브라우저에서 동작할 수 있는 자바스크립트로 변환해주는 패키지가 필요하다.

그때 사용할 수 있는 패키지는 번들러에 따라 달라진다.

 

Parcel 번들러에서는 다음과 같이 typemodule로 설정하면 내용을 해석해서 브라우저에 출력한다.

  <script src="./main.js" type="module"></script>

참고로 모듈 형태로 가져오면 전역 범위를 더럽히지 않고 main.js를 활용할 수 있기 때문에 defer 속성은 필요하지 않다.

 

npm i -D parcel

번들러는 무엇인가 묶음 처리 한다는 뜻이다.

프로젝트를 브라우저에서 동작할 수 있는 파일들로 처리해서 묶어서 내보내준다.

 

Parcel 번들러의 진입점을 설정을 다음과 같이 해준다.

  "scripts": {
    "dev": "parcel ./src/index.html"
  },

명령을 실행할 때의 진입점을 잘 설정하면 진입점에 연결이 된 다양한 내용을 파악해서 필요한 패키지들을 자동으로 설치한 뒤 개발 서버를 자동으로 오픈해준다.

 

실제 배포용으로 결과를 만들때는 build라는 명령을 추가해서 진입점을 명시한다.

  "scripts": {
    "dev": "parcel ./src/index.html",
    "build": "parcel build ./src/index.html"
  },

main 옵션을 그대로 두면 번들러와 충돌이 발생하니 제거한다.

 

명령을 실행하고 나면 distribution, 즉 배포라는 의미의 dist라는 폴더가 생기는데 실제로 배포할 파일이 담겨져 있다.

언제든지 명령을 통해 다시 만들 수 있으므로 dist도 깃허브에 올릴 필요가 없다.

세팅값에 따라 public, build라는 폴더로도 만든다.

 

App.vue에 스타일 코드를 넣어보자.

<style lang="scss">
$color: orange;
h1 {
  color: $color;
}
</style>

그 후 npm run dev를 하면 에러가 발생한다.

번들러가 기본적인 내용은 최대한 파악을 해주지만 모든 패키지들을 자동으로 설치해주지는 않는다.

따라서 필요한 패키지는 직접 설치를 해야 한다.

npm i sass -D

 

Parcel 번들러를 사용하면 설치할 패키지나 구성 옵션들을 대부분 신경쓰지 않고도 최소의 노력으로 하나의 프로젝트를 시작할 수 있다.

이는 Parcel 번들러가 구성 옵션이 없는 번들러를 지향하고 최대한 빠르게 프로젝트를 시작할 수 있는 환경을 제공하려고 하기 때문이다. 

물론 아주 세밀한 번들러 제어는 가능하지 않다는 단점이 있다.

 

SFC 프로젝트 구성 w.Webpack

Webpack디테일하게 번들 옵션들을 결정하여 원하는 구조를 만들 수 있다.

따라서 parcel과 달리 구성 옵션이나 설치해야 하는 패키지가 많다.

 

webpack

웹팩은 모듈 번들러입니다. 주요 목적은 브라우저에서 사용할 수 있도록 JavaScript 파일을 번들로 묶는 것이지만, 리소스나 애셋을 변환하고 번들링 또는 패키징할 수도 있습니다.

webpack.kr

 

 

webpack.config.js라는 구성 옵션 파일에 대해 알아보자.

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
};

require를 통해서 path라는 패키지를 가져오고 있다.

requireNode.js 환경에서 동작하는 가져오기 패턴이다.

 

path라는 패키지는 Node.js에 이미 내장이 되어 있는 패키지(모듈)로 경로에 대한 여러 기능이 탑재되어 있다.

따로 설치하지 않아도 Node.js 환경에서 언제든지 가지고 올 수 있다.

 

module.exportsNode.js의 내보내기 방식으로 하나의 객체 리터럴을 내보내는데 이 객체 리터럴이 바로 웹팩의 옵션이다.

entry 옵션은 진입점을 의미한다.

웹팩이 어떤 파일로 들어가서 연결된 내용들을 읽으면 되는지에 관한 정보로 진입점부터 시작하는 여러 연결 부분들을 웹팩이 해석해서 output에 있는 위치로 결과물을 출력한다. 

output 옵션은 결과물이 어디에 출력될 것인가에 대한 path를 가지고, 결과가 어떤 파일 이름으로 반환될 것인가에 대한 정보를 지닌다. 

 

path는 resolve 메소드를 사용하고 있는데 resolve는 경로를 해석하는 용도의 메소드이다.

__dirname은 Node.js에서 사용하는 전역 변수로 webpack.config.js 라는 구성 옵션 파일에 대한 현재 경로 정보를 가지고 있는 전역 객체이다.

__dirname이 가진 현재 경로 정보와 dist라는 이름을 path.resolve를 통해 하나로 합친다.

 

npm i -D webpack webpack-cli

cli는 command line interface로 터미널에서 입력하는 내용들을 의미한다.

웹팩의 본연의 기능과 터미널을 통해서 웹팩을 동작시킬 것이기 때문에 그것을 가능하게 만들어주는 패키지를 같이 설치하는 것이다.

 

package.json에 스크립트 키워드를 적어주자.

  "scripts": {
    "build": "webpack"
  },

 

웹팩이 동작할 때 필요한 구성 옵션이 필요하기 때문에 루트 경로에 webpack.config.js 파일을 생성한다.

const path = require("path");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
  },
};

이 파일은 Node.js 환경에서 동작한다.

 Node.js 환경에서 로컬(컴퓨터)을 제어할 수 있는 다양한 기능들을 통해서 번들 과정을 진행할 수 있는 것이다.

그래서 import, export가 아닌 Node.js의 가져오기, 내보내기 패턴을 사용해야 한다.

 

filename을 생략하면 엔트리 포인트에서 접근한 이름 그대로 파일명이 출력된다.

 

경로를 지정하는 부분은 path.resolve를 사용하는 것이 중요하다.

entrywebpack.config.js에서 시작하기 때문에 상대경로를 입력해도 되지만 outputwebpack.config.js 파일이 있는 주변에서 찾는 것을 보장할 수가 없기 때문에 꼭 path.resolve를 사용해야 한다. 

만일 path.resolve를 사용하지 않는다면 이 기능이 내장되어 있을 가능성이 높다.

 

[참고]

export default는 이름이 없어도 내보낼 수 있다. (익명함수 가능)

 

다음 두 가지 경우는 동일하다.

import * as Vue from "vue";
import App from "./App.vue";

Vue.createApp(App).mount("#app");
import { createApp }  from "vue";
import App from "./App.vue";

createApp(App).mount("#app");

 

웹팩 번들러는 자바스크립트 번들러이기 때문에 자바스크립트가 아닌 파일은 해석하지 못한다.

그렇기 때문에 다른 확장자들을 해석할 수 있도록 로더(loader)의 도움을 받아 자바스크립트가 아닌 다른 파일도 해석할 수 있게 된다.

 

npm i -D vue-loader

vue-loader는 말 그대로 웹팩 내부에서 vue라는 확장자를 가진 파일을 로드해와서 읽을 준비까지만 한다.

그래서 실제 안에 있는 내용을 읽기 위해서는 그것을 해석할 수 있는 패키지의 도움을 받아야 한다.

npm i -D @vue/compiler-sfc

이 패키지는 vue 패키지와 버전이 일치하는 것이 중요하다.

일치하지 않으면 compiler-sfc가 해석할 수 있는 기능에 제한이 생길 수 있다.

const path = require("path");
const { VueLoaderPlugin } = require("vue-loader");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: "vue-loader",
      },
    ],
  },
  plugins: [new VueLoaderPlugin()],
};

 

웹팩을 동작 시킬 때는 현재 어떤 모드(development/production)로 동작하는 것인지 명시하는 mode 옵션이 필요하다.

  "scripts": {
    "build": "webpack --mode production"
  },

 

빌드 명령을 동작시킬 때 index.html파일이 dist에 같이 들어가게 하기 위해서는 웹팩의 html 플러그인이 필요하다.

npm i -D html-webpack-plugin

...
const HtmlPlugin = require("html-webpack-plugin");

module.exports = {
  ...
  plugins: [
    new VueLoaderPlugin(),
    new HtmlPlugin({
      template: "./src/index.html",
    }),
  ],
};

html 플러그인은 template 옵션이 필요하다.

이는 웹팩이 해석해야 하는 html 파일의 위치를 의미한다.

path.resolve를 써줘야 하겠지만 html 웹팩 플러그인은 템플릿에 지정한 경로를 처리할 때 path.resolve를 자체적으로 실행한다.

 

웹팩이 dist 폴더로 결과를 출력할 때 그 안에 있는 내용을 따로 제거하지는 않기 때문에 불필요한 파일이 남아있을 수 있다

이때 사용할 수 있는 옵션이 clean이다.

module.exports = {
  output: {
    path: path.resolve(__dirname, "dist"),
    clean: true,
  },
};

 

dist 폴더의 index.html 파일을 라이브 서버로 브라우저에서 내용을 오픈할 수 있지만 이런 과정은 불편하다.

개발하는 용도로만 로컬 환경에 서버를 구성해서 좀 더 편하게 개발할 수 있는 방법이 있다.

npm i -D webpack-dev-server

  "scripts": {
    "dev": "webpack-dev-server --mode development",
    "build": "webpack --mode production"
  },

이제 npm run dev 명령어를 입력하면 webpack-dev-server를 통해 개발 서버가 오픈된다.

webpack-dev-serve는 코드를 수정하면 수정된 사항이 바로 반영이 되어 출력된다.

이런 것을 HMR, Hot Module Replacement라고 한다. 

 

만일 포트 번호를 바꾸고 싶다면 다음과 같이 옵션을 추가하면 된다.

module.exports = {
  devServer: {
    port: 1234,
  },
};

webpack.config.js 구성 파일이 바뀌면 바뀌어진 구성 파일로 다시 개발 서버가 오픈되도록 서버를 끄고 다시 켜야 한다

포트 번호는 웹팩 프로젝트에서는 기본적으로 8080을 권장하니 굳이 바꿀 필요는 없다.

 

App.vue에 스타일 코드를 추가해보자

<template>
  <h1>{{ msg }}</h1>
</template>

<script>
export default {
  data() {
    return {
      msg: "Hello Vue",
    };
  },
};
</script>

<style>
h1 {
  color: red;
}
</style>

npm run dev를 입력하면 에러가 발생한다. 

 

웹팩은 자바스크립트 내용만 이해할 수 있기 때문에 css 내용을 해석하지 못한다.

css 내용을 해석할 수 있는 로더가 추가적으로 필요하다.

npm i -D css-loader vue-style-loader

 

로더는 module 옵션에 지정한다.

module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.css$/,
        use: ["vue-style-loader", "css-loader"],
      },
    ],
  },
};

use 옵션에 배열 리터럴을 통해서 로더의 이름을 아이템으로 여러개 명시할 때는 뒷쪽 요소부터 앞 요소로 평가가 이루어진다.

그래서 더 먼저 해석이 되어야 하는 로더가 뒷쪽에 작성되어야 한다.

 

CDN으로 뷰를 불러왔을 때는 템플릿에서 컴포넌트를 사용할 때 대쉬 케이스로 태그를 작성했다.

하지만 웹팩 프로젝트에서는 vue-compiler-sfc 패키지로 인해 파스칼 케이스도 잘 동작한다.

<template>
  <h1>{{ msg }}</h1>
  <Hello />
</template>

<script>
import Hello from "./components/Hello.vue";

export default {
  components: {
    Hello,
  },
  data() {
    return {
      msg: "Hello Vue!!!!",
    };
  },
};
</script>

<style>
h1 {
  color: red;
}
</style>

Hello.vue를 다음과 같이 작성한다.

<template>
  <h1>Hello</h1>
</template>

<style>
h1 {
  color: blue;
}
</style>

Hello 컴포넌트에 스타일 태그를 작성하고 앱 컴포넌트에서는 스타일 태그를 지워보자.

결과를 확인해보면 앱 컴포넌트의 내용인 Hello Vue도 파란색인 것을 확인할 수 있다.

 

Hello 컴포넌트가 가진 스타일이 외부의 다른 컴포넌트에도 영향을 미치고 있는 상황인 것이다.

이러한 문제를 컴포넌트가 지니고 있기 때문에 사용할 수 있는 기능이 scoped 속성이다. 

scoped 속성은 스타일의 유효범위를 지정해준다.

<style scoped>
h1 {
  color: blue;
}
</style>

scoped 옵션이 있는 컴포넌트에서는 스타일 해쉬를 추가해서 해당하는 스타일이 다른 컴포넌트에 영향을 미치는 것을 방지한다. 

특별한 상황이 아니면 대부분 scoped 추가하는 것이 좋다.

 

만일 스타일 코드에 scss를 사용하고 싶다면 패키지와 로더가 필요하다.

<style scoped lang="scss">
$color: orange;
h1 {
  color: $color;
}
</style>

npm i -D sass sass-loader

module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.s?css$/,
        use: ["vue-style-loader", "css-loader", 'sass-loader'],
      },
    ],
  },
};

 

App.vue의 import문은 상대경로를 사용하고 있다.

import Hello from "./components/Hello.vue";

경로가 바뀌는 순간 해당하는 내용을 같이 수정해줘야 하는데 프로젝트가 커지면 관리하는 것이 힘들기 때문에 절대경로를 쓰는 것이 좋다.

웹팩에서 지원하는 경로 별칭 개념과 확장자 생략 기능을 적용해보자.

module.exports = {
  resolve: {
    extensions: ['.vue', '.js'],
    alias: {
      '~': path.resolve(__dirname, 'src')
    }
  },
};

resolveextensions 옵션을 통해 확장자를 생략할 수 있고, alias 옵션을 통해 경로 별칭을 사용할 수 있다. 

경로를 입력할 때 경로 별칭을 사용하게 되면 루트 경로의 src 디렉토리에서 components안에 있는 Hello라는 뷰 컴포넌트를 찾는다.

특정한 절대적인 위치에서 파일을 찾아나갈 수 있다는 장점이 있다. 

import Hello from "~/components/Hello";

 

파비콘을 추가하고 싶다면 dist 폴더 내부로 파비콘, 기타 이미지 같은 자원을 따로 넣어주는 플러그인이 필요하다.

npm i -D copy-webpack-plugin

...
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  ...
  output: {
    path: path.resolve(__dirname, "dist"),
    clean: true,
  },
  plugins: [
    ...
    new CopyPlugin({
      patterns: [{ from: "static" }],
    }),
  ],
};

to라는 옵션은 기본적으로 output 옵션에 지정해둔 path를 참조하게 되므로 따로 명시하지 않아도 dist로 들어간다.

 

[참고]

ico 파일은 브라우저의 아이콘 정보를 가진 파일을 의미한다.

이걸 사용하면 index.html에 별도로 파비콘이 지정되어 있지 않을 때 파비콘이라는이름의 ico파일을 자동으로 찾는다.

 

ESLint

린터(linter)는 소스 코드를 분석하여 프로그램 오류, 버그, 스타일 오류, 의심스러운 구조체에 표시를 달아놓기 위한 도구로 대표적으로 Prettier나 ESLint가 존재한다. 

 

사용하고자 하는 린터의 확장 프로그램을 vscode에서 설치해야 한다.

설치 후 vscode의 [보기] - [명령 팔레트]에 json을 검색해서 settings.json파일에 다음 코드를 작성한다.

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

에디터 내에서 파일을 저장하게 되면 그 파일을 eslint를 통해서 규칙에 맞게 수정을 하겠다라는 것을 등록하는 것이다.

 

웹팩 프로젝트에 ESLint를 적용하기 위해서는 플러그인을 설치해야 한다.

npm i -D eslint eslint-plugin-vue

 

플러그인 설치 후 루트 경로에 .eslintrc 파일을 만들면 된다.

확장자는 js 혹은 json으로 지정하면 된다.

 

ESLint는 기본적으로 미리 선언하지 않고 접근하는 변수에 대해서는 오류를 내기 때문에 각 실행 환경(runtime)에서 기본적으로 제공되는 전역 객체에 대해 설정을 통해 알려줘야 한다.

이러한 역할을 담당하는 것이 env 옵션이다.

{
  "env": {
    "browser": true,
    "node": true,
  },
  "extends": ["eslint:recommended", "plugin:vue/vue3-recommended"]
}

만일 browser 옵션의 값과 node 옵션의 값을 false로 둔다면 브라우저의 window, document 객체들이나 Node.js의 require, modul_exports, __dirname 같은 전역 객체들을 eslint로 확인하지 않겠다라는 의미가 된다. 

자바스크립트 코드가 브라우저에서 실행될 수도 있고, NodeJS에서도 실행될 수 있다면 두 가지 실행 환경에서 접근 가능한 모든 전역 객체를 등록할 수 있도록 값을 true로 주면 된다.

 

extends 옵션의 첫 번째 규칙은 eslint의 추천되는 규칙을 그대로 사용한다는 의미이고, 두 번째 규칙은 eslint-plugin-vue라는 패키지를 통해서 적용되는 규칙을 사용하겠다는 의미이다.

 

뷰에서 기본적으로 제공하는 규칙 eslint-plugin-vue는 시작 태그가 닫히는 꺾쇠를 새로운 줄에 작성하게 한다.

  <h1
    v-if="msg"
    class="message"
    @click="log"
  >

 

이러한 규칙을 수정하고 싶다면 해당 규칙의 링크에서 옵션에 대한 설명을 확인할 수 있다. 

{
  "vue/html-closing-bracket-newline": ["error", {
    "singleline": "never",
    "multiline": "always"
  }]
}

multiline의 값을 never로 바꾸고 이 코드를 .eslintrc 파일의 rules에 작성하며 된다.

{
  "env": {
    "browser": true,
    "node": true
  },
  "extends": ["eslint:recommended", "plugin:vue/vue3-recommended"],
  "rules": {
    "vue/html-closing-bracket-newline": ["error", {
      "singleline": "never",
      "multiline": "never"
    }]
  }
}

 

자바스크립트 코드에 세미콜론을 붙이지 않고, 따옴표를 작은 따옴표로 사용하고 싶다면 다음과 같이 규칙을 추가한다.

  "rules": {
    "semi": ["error", "never"],
    "quotes": ["error", "single"],
    ...
   }

이런식으로 eslint 규칙을 통해 하나의 코드 스타일을 유지할 수 있다.

 


출처: 프로그래머스 프론트엔드 데브코스 

[Day 36] Vue (4)

복사했습니다!