Don't Panic
in React-Vue ☕ 15분 읽기

[Vue] Vue.js 실전 — 라이프사이클·CLI·Firebase·Nuxt

목차

📚 웹 풀스택 정리 — Spring · Vue · React · 배포

Spring 실전 Vue.js 실전 ← 지금 글 React 실전 배포 자동화

Vue.js 라이프사이클



무작정 프로젝트를 진행하면서 적용하다보니, 라이프사이클을 제대로 몰라서 애를 먹고있다. Vue가 가지는 라이프사이클을 제대로 이해하고 넘어가보자.


Vue.js의 라이프사이클은 크게 4가지로 나누어진다.

Creation, Mounting, Updating, Destruction



Creation

컴포넌트 초기화 단계

Creation 단계에서 실행되는 훅(hook)들이 라이프사이클 중 가장 먼저 실행됨

아직 컴포넌트가 DOM에 추가되기 전이며 서버 렌더링에서도 지원되는 훅임


클라이언트와 서버 렌더링 모두에서 처리해야 할 일이 있으면, 이 단계에 적용하자


  • beforeCreate

    가장 먼저 실행되는 훅

    아직 데이터나 이벤트가 세팅되지 않은 시점이므로 접근 불가능

  • created

    데이터, 이벤트가 활성화되어 접근이 가능함

    하지만 아직 템플릿과 virtual DOM은 마운트 및 렌더링 되지 않은 상태임



Mounting

DOM 삽입 단계

초기 렌더링 직전 컴포넌트에 직접 접근이 가능하다.

컴포넌트 초기에 세팅되어야할 데이터들은 created에서 사용하는 것이 나음


  • beforeMount

    템플릿이나 렌더 함수들이 컴파일된 후에 첫 렌더링이 일어나기 직전에 실행됨

    많이 사용하지 않음

  • mounted

    컴포넌트, 템플릿, 렌더링된 DOM에 접근이 가능함

    모든 화면이 렌더링 된 후에 실행


주의할 점

부모와 자식 관계의 컴포넌트에서 생각한 순서대로 mounted가 발생하지 않는다. 즉, 부모의 mounted가 자식의 mounted보다 먼저 실행되지 않음

부모는 자식의 mounted 훅이 끝날 때까지 기다림


Updating

렌더링 단계

컴포넌트에서 사용되는 반응형 속성들이 변경되거나 다시 렌더링되면 실행됨

디버깅을 위해 컴포넌트가 다시 렌더링되는 시점을 알고 싶을때 사용 가능


  • beforeUpdate

    컴포넌트의 데이터가 변하여 업데이트 사이클이 시작될 때 실행됨

    (돔이 재 렌더링되고 패치되기 직전 상태)

  • updated

    컴포넌트의 데이터가 변하여 다시 렌더링된 이후에 실행됨

    업데이트가 완료된 상태이므로, DOM 종속적인 연산이 가능


Destruction

해체 단계


  • beforeDestory

    해체되기 직전에 호출됨

    이벤트 리스너를 제거하거나 reactive subscription을 제거하고자 할 때 유용함

  • destroyed

    해체된 이후에 호출됨

    Vue 인스턴스의 모든 디렉티브가 바인딩 해제되고 모든 이벤트 리스너가 제거됨



추가로 사용하는 속성들


  • computed

    템플릿에 데이터 바인딩할 수 있음

    <div id="example">
      <p>원본 메시지: ""</p>
      <p>역순으로 표시한 메시지: ""</p>
    </div>
    
    <script>
        new Vue({
          el: '#example',
          data: {
            message: '안녕하세요'
          },
          computed: {
            // 계산된 getter
            reversedMessage: function () {
            // `this` 는 vm 인스턴스를 가리킵니다.
            return this.message.split('').reverse().join('')
            }
          }
         })
    </script>

    message의 값이 바뀌면, reversedMessage의 값도 따라 바뀜


    Date.now()와 같이 의존할 곳이 없는 computed 속성은 업데이트 안됨


computed: {
  now: function () {
    return Date.now() //업데이트 불가능
  }
}

호출할 때마다 변경된 시간을 이용하고 싶으면 methods 이용


  • watch

    데이터가 변경되었을 때 호출되는 콜백함수를 정의

    watch는 감시할 데이터를 지정하고, 그 데이터가 바뀌면 어떠한 함수를 실행하라는 방식으로 진행



computed와 watch로 진행한 코드

//computed
<script>
    new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
</script>

//watch
<script>
    new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName: function (val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    })
</script>

computed는 선언형, watch는 명령형 프로그래밍 방식

watch를 사용하면 API를 호출하고, 그 결과에 대한 응답을 받기 전 중간 상태를 설정할 수 있으나 computed는 불가능


대부분의 경우 선언형 방식인 computed 사용이 더 좋으나, 데이터 변경의 응답으로 비동기식 계산이 필요한 경우나 시간이 많이 소요되는 계산을 할 때는 watch를 사용하는 것이 좋다.


Vue CLI + Spring Boot 연동하여 환경 구축




프론트엔드는 Vue.js로, 백엔드는 Spring Boot를 이용해서 프로젝트를 진행하려고 한다.

스프링에서 Jsp를 통해 view를 구축해봤지만, 이번엔 Vue.js를 활용해서 View를 모두 넘겨주려고 한다.


스프링에서 컨트롤러를 통해 DB 관리나 데이터에 관한 비즈니스 로직을 잘 처리하고, 이에 대한 값을 활용해 Vue에서 화면으로 뿌려줄 탬플릿을 만들어나가는 진행 방식이 되지 않을까 생각된다.


개발 툴은 VS Code로 진행한다.

VS Code 다운로드


Java와 Node.js도 기본적으로 깔린 상태여야 한다.

Node.js 다운로드



VS Code를 열고, 자신이 프로젝트를 생성할 폴더로 들어가자 (File → Open Folder)


시작하기에 앞서, VS Code에서 필요한 플러그인을 설치한다.

왼쪽 메뉴탭에서 Extensions(단축키 : Ctrl + Shift + X)를 누르고, 검색창에서 아래 3가지를 입력 후 install 한다.

1. Vetur
2. Java IDE Pack
3. Lombok


VS Code 한글 인코딩

현재 상태로는 VS Code에서 한글을 인식해주지 않는다. 인코딩을 따로 해줘야한다.


File → Preferences → Settings로 들어간다.

위의 검색창에 ‘settings.json’을 검색하면 아래와 같이 Edit할 수 있는 링크가 뜬다.



json 파일이 나오게 되는데, 이곳에서 ‘java.jdt.ls.vmargs’를 찾는다.


이곳에 value 값으로 ‘-Dfile.encoding=utf-8’를 추가해줘야한다.

추가 후에 java.jdt.ls.vmargs는 아래와 같이 될 것이다.


"java.jdt.ls.vmargs": "-Dfile.encoding=utf-8 -noverify -Xmx1G -XX:+UseG1GC -XX:+UseStringDeduplication -javaagent:\"lombok 경로~~"


프로젝트 구성하기

이제 프로젝트를 구성해보자!


1.Spring Boot Project


먼저, 스프링 부트 프로젝트를 만든다. (우리는 스프링 부트 프로젝트 안에 Vue 프로젝트를 넣을 것이다)

프로젝트는 Spring Initializr을 이용할 것이다. 스프링 부트 프로젝트를 매우 쉽고 간편하게 만들어주는 곳이다.



자신이 만들 프로젝트 목적에 맞게 설정해주면 된다.

Dependencies도 미리 추가해놓을 수 있다. (Web, JDBC, Lombok, MySQL 등)

나중에 따로 추가할 수 있으니 기억나는 것들만 지정해도 무방하다.


프로젝트 Metadata 부분은 생성할 프로젝트 패키지나 이름 등 옵션을 지정해줄 수 있다. 처음에는 demo로 되어있는데 자신이 만들고 싶은대로 수정할 수 있다.


마지막으로 ‘Generate the project’ 버튼을 클릭하면, zip 파일로 프로젝트가 다운로드 된다. 해당 파일을 압축 해제하고 현재 VS Code에서 접속 중인 폴더에 복사하면 된다.




2.Vue.js Project


이제 스프링 부트에서 Vue.js 프로젝트를 만들어보자. 프로젝트 생성은 Vue CLI를 이용할 것이다.


Vue CLI는 Vue.js 개발을 위한 시스템으로, Vue.js Core에서 공식적으로 제공하는 CLI다. 개발에 집중할 수 있도록 프로젝트 구성을 빠르고 쉽게 도와주는 역할을 하고 있다.

(따라서 반드시 이용해야 한다는 건 아니다. 다만 쉽게 구축할 수 있도록 만들어준거니 이용하면 편하다)


현재는 Vue CLI 버전 3가 나온 상태다. 2보다 더욱 편하고 많은 기능들을 제공한다고 하지만, 많은 정보가 없어서 일단 2로 진행하고자 한다.


Node.js를 설치한 상태기 때문에, npm을 통해 터미널에서 Vue CLI 설치가 가능하다.


VS Code에서 터미널을 열고, 아래와 같이 설치를 진행하자

$ npm i -g @vue/cli
$ npm i -g @vue/cli-init

@vue/cli-init은 2버전 템플릿을 가져오기 위한 vue init을 제공해준다.

이제 필요한 설치는 끝났다! Vue 프로젝트를 만들어보자. 이름은 그냥 frontend로 생성했다.


(현재 프로젝트 생성은, 스프링 부트 루트 폴더 위치에서 진행하는 것이다.)

$ vue init webpack frontend

몇가지 설정하는 부분이 나온다.


Project name

Project description

Author


이 3가지는 자신의 프로젝트에 맞게 작성해주면 된다.

Vue build는 standalone

vue-router는 설치(Yes)

Use ESLint to lint your code도 Yes

ESLint preset은 Standard


그 이후 test부분은 진행할 사람들은 Yes, 안할사람은 No로 넘어가면 된다.

터미널 창에서 열심히 파일들이 다운로드되는 모습을 볼 수 있다. (시간 조금 걸림)


끝나면 스프링부트 루트 폴더에 ‘frontend’라는 Vue 프로젝트 폴더가 생성된 모습을 확인할 수 있다.




Webpack 번들링 output 설정


Vue에서 작성한 코드들을 번들링하고, 이 결과를 어느 위치에서 뽑아낼 지 정해야 한다.


Spring Boot에서는 자동설정으로 src/main/resources에 번들링한 결과들을 저장하도록 되어있다.

(이곳에 index.html과 정적 파일(css, img, javascript)들이 인식됨)


이 구역에 잘 번들링 될 수 있도록, Vue 프로젝트에서 경로 지정을 해주자.

config/index.js을 열어 build 부분에 정의한 곳을 수정해야 한다.



해당 위치에 절대 경로로 위와 같이 수정해준다.


이제 터미널에서 ‘npm run build’ 커맨드를 입력하여 빌드를 실행한다.

이제 Spring Boot의 src/main/resources/static 경로에 들어가보면, 번들링 된 정적 파일들이 생성된 모습을 확인할 수 있다.


이제 스프링 부트 애플리케이션을 실행해보자

.vscode 폴더의 launch.json에 들어가서 F5키를 누르면 스프링 부트 서버가 실행된다.


???

에러가 뜰 것이다.


***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

datasource 내용이 없어서 뜬 에러다.


스프링부트에서 프로젝트를 생성할 때, application.properties 파일이 자동생성되나 확인해보면 빈 파일일 것이다.

사용자가 원하는 데이터베이스를 선택하고, 그에 맞는 드라이버 라이브러리 설치와 jdbc 설정을 직접 해야한다.


이 공간이 비어있기 때문에 서버가 실행을 하고 있지 못하는 것이다. 현재는 어떤 데이터베이스를 지정할 지 결정이 되있는 상태가 아니기 때문에 스프링 부트의 메인 클래스에서 어노테이션을 추가해주자



import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

이를 추가한 메인 클래스는 아래와 같이 된다.


package com.example.mvc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MvcApplication {

    public static void main(String[] args) {
        SpringApplication.run(MvcApplication.class, args);
    }

}

이제 다시 스프링 부트 메인 애플리케이션을 실행하면, 디버깅 창에서 에러가 없어진 걸 확인할 수 있다.


이제 localhost:8080/으로 접속하면, Vue에서 만든 화면이 잘 나오는 것을 확인할 수 있다.



Vue.js에서 View에 필요한 템플릿을 구성하고, 스프링 부트에 번들링하는 과정을 통해 연동하는 과정을 완료했다!




Vue.js + Firebase로 이메일 회원가입/로그인 구현



Vue.js와 Firebase를 통한 이메일 로그인을 구현해보자


우선 설치해야할 것

$ npm -i -g @vue/cli
$ npm -i -g @vue/cli-init

@vue/cli-init은 2.0버전을 사용하기 위한 설치!


vue-cli는 템플릿 기반 프로젝트 초기 구성을 간편하게 할 수 있도록 도와준다!


프로젝트 생성

$ vue init webpack "프로젝트 이름"

이름과 같은 환경설정을 해주면 vue 프로젝트가 생성된다.


이제 해당 경로로 들어가서 npm 설치를 진행한다.

$ cd "프로젝트 이름"
$ npm install

만약 npm install 후에 vulnerabilities 알림이 뜨면, npm audit fix를 통해 충돌나는 부분에 대한 문제를 해결하자


이제 npm 설치가 끝났으니 프로젝트를 실행해보자

$ npm run dev

화면이 잘 나온다! 순조롭게 잘 실행했다는 뜻~


현재 만들어진 기본적인 Vue.js 파일 구조를 이해하지 못한 사람은 먼저 구조를 이해하고 다음 과정을 진행합시다.



vue-router 활용하기

회원가입과 로그인 과정을 진행하기 위해, 3개의 view에 해당하는 컴포넌트를 src/components 폴더 아래에 만들고 vue-router를 통해 이동해볼 것이다.

  • Login 컴포넌트 : 로그인 하는 곳
  • Signup 컴포넌트 : 회원가입 하는 곳
  • Show 컴포넌트 : 로그인해야 볼 수 있는 곳 (기존의 HelloWorld.vue)


로그인 구현



src/components에 Login.vue를 만들자


<template>
  <div class="login">
    <h3>Login</h3>
    <input type="text" placeholder="email"><br>
    <input type="password" placeholder="password"><br>
    <button>로그인</button>
    <p>만약 계정이 없다면, 회원가입을 먼저 진행해주세요!</p>
  </div>
</template>

<script>
  export default {
    name: 'login',
    data() {
      return {
      }
    },
    methods: {}
  }
</script>

<style scoped>
  .login {
    margin-top: 40px;
  }
  input {
    margin: 10px 0;
    width: 20%;
    padding: 15px;
  }
  button {
    margin-top: 20px;
    width: 10%;
    cursor: pointer;
  }
  p {
    margin-top: 40px;
    font-size: 15px;
  }
  p a {
    text-decoration: underline;
    cursor: pointer;
  }
</style>

이제 로그인을 router/index.js에 라우터를 추가해주자.


import Vue from 'vue'
import Router from 'vue-router'

import HelloWorld from '@/components/HelloWorld'
import Login from '@/components/Login'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    }
  ]
})

url 중간에 ”#“을 지우기 위해서는 라우터에서 mode: ‘history’를 위와 같이 추가해주면 된다.


이제 http://localhost:8080/login로 접속하면 아래와 같은 로그인 화면이 나온다.

style을 적용시켜서 이쁘게 화면을 구현시킬 수 있다ㅎㅎ


회원가입 구현


로그인처럼 같은 방식으로 회원가입에 해당하는 컴포넌트와 라우터 연결을 진행해보자

src/components/SignUp.vue

<template>
  <div class="sign-up">
    <p>회원가입</p>
    <input type="text" placeholder="email"><br>
    <input type="password" placeholder="password"><br>
    <button>가입하기</button>
    <span>또는 로그인으로 돌아가기</span>
  </div>
</template>

<script>
  export default {
    name: 'signUp',
    data() {
      return {
      }
    },
    methods: {}
  }
</script>

<style scoped>
  .signUp {
    margin-top: 40px;
  }
  input {
    margin: 10px 0;
    width: 20%;
    padding: 15px;
  }
  button {
    margin-top: 20px;
    width: 10%;
    cursor: pointer;
  }
  p {
    margin-top: 40px;
    font-size: 20px;
  }
  span {
    display: block;
    margin-top: 20px;
    font-size: 15px;
  }
</style>

router/index.js

import Vue from 'vue'
import Router from 'vue-router'

import HelloWorld from '@/components/HelloWorld'
import Login from '@/components/Login'
import SignUp from '@/components/SignUp'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/signup',
      name: 'SignUp',
      component: SignUp
    }
  ]
})

이제 http://localhost:8080/signup 경로로 들어가면 아래와 같이 회원가입 창이 잘 나오는 것을 확인할 수 있다.




컴포넌트간 이동하기


컴포넌트와 컴포넌트간 이동을 하기 위해서는 router-link를 사용한다.

로그인과 회원가입 vue 폴더에서 서로 이동하도록 link를 사용해보자

Login.vue

<template>
  <div class="login">
    <h3>Login</h3>
    <input type="text" placeholder="email"><br>
    <input type="password" placeholder="password"><br>
    <button>로그인</button>
    <p>만약 계정이 없다면, <router-link to="/signup">회원가입</router-link>을 먼저 진행해주세요!</p>
  </div>
</template>

SignUp.vue

<template>
  <div class="sign-up">
    <p>회원가입</p>
    <input type="text" placeholder="email"><br>
    <input type="password" placeholder="password"><br>
    <button>가입하기</button>
    <span>또는 <router-link to="/login">로그인</router-link>으로 돌아가기</span>
  </div>
</template>

이처럼 link 태그에 to=“/경로”를 통해 컴포넌트 이동이 가능하다.

다시 화면으로 돌아가면, a태그와 같이 링크가 걸려있고 클릭 시 컴포넌트가 잘 이동되는 것을 확인할 수 있을 것이다.



현재는 인증 단계가 진행되지 않은 상태이므로, 로그인이 완료되었을 때 helloWorld.vue 화면으로 이동이 되도록만 replace 메소드를 적용시켜보자

Login.vue

<template>
  <div class="login">
    <h3>Login</h3>
    <input type="email" placeholder="email"><br>
    <input type="password" placeholder="password"><br>
    <button v-on:click="login">로그인</button>
    <p>만약 계정이 없다면, <router-link to="/signup">회원가입</router-link>을 먼저 진행해주세요!</p>
  </div>
</template>

<script>
  export default {
    name: 'login',
    data() {
      return {
      }
    },
    methods: {
      login() {
        this.$router.replace('hello')
      }
    }
  }
</script>

<style scoped>
 ...
</style>

로그인 button에 v-on:click을 통해 버튼을 눌렀을 때 login() 메소드가 실행되도록 해둔 상태다. methods에서 구현한 login 메소드가 실행되며, hello라는 경로를 가진 페이지로 이동하는 메소드다.


현재 hello라는 경로가 없기 때문에, 기존의 root 경로를 hello로 변경해주자


import Vue from 'vue'
import Router from 'vue-router'

import HelloWorld from '@/components/HelloWorld'
import Login from '@/components/Login'
import SignUp from '@/components/SignUp'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/hello',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/signup',
      name: 'SignUp',
      component: SignUp
    }
  ]
})

root 경로의 path를 /에서 /hello로 변경했다.

이제 로그인 창에서 이메일과 패스워드를 입력 후 로그인을 누르면 HelloWorld.vue로 이동하는 것을 확인할 수 있을 것이다.



파이어베이스 연동


프론트 구현은 끝났다. 이제 가장 중요한 파이어베이스 연동이다.

파이어베이스를 사용하기 위해, 파이어베이스 콘솔에서 새로운 프로젝트를 생성하자

파이어베이스 콘솔 링크


프로젝트 추가

프로젝트 추가버튼 클릭



이제 파이어베이스 프로젝트 생성이 완료되었다.

해당 프로젝트에 들어가면 코드 스니펫 모양이 있는데, 웹 앱을 추가하는 곳이다. 클릭해서 웹 앱에 파이어베이스를 추가하자

앱 닉네임을 정하고, 등록을 누르면 스크립트가 나올 것이다.

이 스크립트에 있는 config를 우리 vue 프로젝트에 적용시킬 것이다.


var firebaseConfig = {
    apiKey: "개인 API KEY",
    authDomain: "개인 프로젝트 ID.firebaseapp.com",
    databaseURL: "https://vue-firebase-tutorial-da26f.firebaseio.com",
    projectId: "vue-firebase-tutorial-da26f",
    storageBucket: "",
    messagingSenderId: "173286603007",
    appId: "1:173286603007:web:2258c081f9102650"
  };
  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);

코드 중에서 이 부분만 가져와서 활용할 것이다.


적용시키기 전에 터미널에서 firebase를 설치하자

$ npm install --save firebase

설치가 끝나면, main.js 파일에다 Firebase를 아래와 같이 적용시키자


import Vue from 'vue'
import App from './App'
import router from './router'
import firebase from 'firebase'

Vue.config.productionTip = false

var firebaseConfig = {
    apiKey: "개인 API KEY",
    authDomain: "개인 프로젝트 ID.firebaseapp.com",
    databaseURL: "https://vue-firebase-tutorial-da26f.firebaseio.com",
    projectId: "vue-firebase-tutorial-da26f",
    storageBucket: "",
    messagingSenderId: "173286603007",
    appId: "1:173286603007:web:2258c081f9102650"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})


회원가입 컴포넌트에서 파이어베이스 사용자 생성하기


이제 회원가입을 통해 가입한 사용자 데이터를 파이어베이스에게 전송해줘야 한다.

회원가입 시 필요한 email과 password를 받아서 전송해야 하는데, 양방향 데이터 바인딩을 지원하는 v-model을 활용하자

<input type="text" v-model="email" placeholder="email"><br>
<input type="password" v-model="password" placeholder="password"><br>
<button v-on:click="signUp">가입하기</button>

이처럼 회원가입의 template에서 v-model과 메소드를 실행할 v-on을 추가한다.


signUp() 메소드 구현

<script>
  import firebase from 'firebase'

  export default {
    name: 'signUp',
    data() {
      return {
        email: '',
        password: ''
      }
    },
    methods: {
      signUp() {
        firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(
          function(user) {
            alert('회원가입 완료!')
          },
          function(err) {
            alert('에러 : ' + err.message)
          }
        );
      }
    }
  }
</script>

createUserWithEmailAndPassword 메소드는 onResolve, onReject 콜백과 파이어베이스의 프로미스를 반환해준다.



파이어베이스 로그인 공급자 활성화시키기


다시 파이어베이스 콘솔로 돌아가자

왼쪽 사이드바를 열고, DEVELOP의 Authentication으로 들어간다.


로그인 방법으로 들어가서 이메일/비밀번호를 활성화 시킨다.


사용 설정됨으로 표시되면, 이제 사용자 가입 시 파이어베이스에 저장이 가능하다!


회원가입 view로 가서 이메일과 비밀번호를 입력하고 가입해보자

회원가입이 정상적으로 완료되었다는 alert가 뜬다. 진짜 파이어베이스에 내 정보가 저장되어있나 확인하러 가보자

오오..사용자 목록을 눌러보면, 내가 가입한 이메일이 나오는 것을 확인할 수 있다.

이제 다음 진행은 당연히 뭘까? 내가 로그인할 때 파이어베이스에 등록된 이메일과 일치하는 비밀번호로만 진행되야 된다.



사용자 로그인

회원가입 시 진행했던 것처럼 v-model 설정과 로그인 버튼 클릭 시 진행되는 메소드를 파이어베이스의 signInWithEmailAndPassword로 수정하자

<template>
  <div class="login">
    <h3>Login</h3>
    <input type="text" v-model="email" placeholder="email"><br>
    <input type="password" v-model="password" placeholder="password"><br>
    <button v-on:click="login">로그인</button>
    <p>만약 계정이 없다면, <router-link to="/signup">회원가입</router-link>을 먼저 진행해주세요!</p>
  </div>
</template>

<script>
  import firebase from 'firebase'

  export default {
    name: 'login',
    data() {
      return {
        email: '',
        password: ''
      }
    },
    methods: {
      login() {
        firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
          function(user) {
            alert('로그인 완료!')
          },
          function(err) {
            alert('에러 : ' + err.message)
          }
        );
      }
    }
  }
</script>

이제 다 끝났다.

로그인을 진행해보자! 우선 비밀번호를 제대로 입력하지 않고 로그인해본다

에러가 나오면서 로그인이 되지 않는다!


다시 제대로 비밀번호를 치면?!

제대로 로그인이 되는 것을 확인할 수 있다.


이제 로그인이 되었을 때 보여줘야 하는 화면으로 이동을 하거나 로그인한 사람이 관리자면 따로 페이지를 구성하거나를 구현하고 싶은 계획에 따라 만들어가면 된다.


.# Vue.js + Firebase로 페이스북(facebook) 로그인 연동하기




우선, 기존의 파이어베이스 콘솔에서 Authentication의 로그인 방법으로 들어가자

우리는 이메일/비밀번호를 활성화 시켜서 회원가입과 로그인을 가능하도록 구현했었다.



위 사진처럼 페이스북도 상태를 사용으로 만들어야 한다.



아래에 나오는 OAuth 리디렉션 URI를 복사하고, facebook for developers로 이동한다.

Facebook for developers 링크


해당 사이트에서 페이스북 아이디를 통해 로그인이 가능하다.

앱을 새로 하나 생성하자. 앱 이름은 알아서 정하면 된다.



앱을 생성하면 대시보드 화면이 나올 것이다.

(현재 스크린샷은 라이브 상태로 되어있지만, 처음 만들었을 때는 개발모드 상태일 것이다.)

페이지를 아래로 내려보면 제품 추가 항목이 존재한다.


이중에 ‘Facebook 로그인’항목이 우리가 필요한 것이다.



유효한 OAuth 리디렉션 URI의 공란에 아까 파이어베이스에서 복사한 URI를 붙여넣기 하고 저장해주면 된다.


이제 우리 Facebook 앱을 배포시에도 정상 작동할 수 있도록 공개상태로 전환시켜야한다.



설정 → 기본 설정으로 들어가면, 다음과 같은 화면이 나올 것이다.

여기서 ‘개인정보처리방침 URL’을 등록해야만 앱을 공개상태로 바꿀 수 있다.

현재는 연습단계이므로, 아무 url이나 작성하고 저장한다.

이제 중앙 위쪽에 설정을 키면, 앱이 정상적으로 실행될 것이다!


이제 설정창에 존재하는 앱 ID와 앱 시크릿 코드를 파이어베이스에서 페이스북 연동을 하기 위해 사용할 것이다.

(시크릿 코드는 비밀번호를 한번더 입력하면 볼 수 있다.)


다시 파이어베이스로 돌아가서, 앱ID와 앱 비밀번호를 입력하자

이제 Facebook 사용 설정이 모두 끝났다.


코드로 파이어베이스를 로그인 화면에서 불러오는 메소드를 작성해주면 된다.


Login.vue의 템플릿 부분

<template>
<div class="login">
  <h3>로그인</h3>
  <input type="text" v-model="email" placeholder="email"><br>
  <input type="password" v-model="password" placeholder="password"><br>
  <button v-on:click="login">로그인</button>
  <p>또는 페이스북 로그인 <br>
    <button class="social-button" v-on:click="facebookLogin">
      <img alt="Facebook Logo" src="../assets/facebook-logo.png">
    </button>
  </p>
  <p>만약 계정이 없다면, <router-link to="/signup">회원가입</router-link>을 먼저 진행해주세요!</p>
</div>
</template>

기존 화면에서 페이스북 로그인 부분을 추가했다.


인터넷에서 페이스북 로고 이미지(facebook-logo.png)를 다운받아서, 프로젝트 폴더의 src/assets에다가 추가하자.


페이스북 로그인 연동 script

<script>
import firebase from 'firebase'

var provider = new firebase.auth.FacebookAuthProvider()
provider.addScope('public_profile')
provider.setCustomParameters({
  'display': 'popup'
})

export default {
  name: 'login',
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    login() {
      ...
    },
    facebookLogin() {
      firebase.auth().signInWithPopup(provider).then((result) => {
        var token = result.credential.accessToken
        var user = result.user

        console.log("token : " + token)
        console.log("user : " + user)

        this.$router.replace('welcome')

      }).catch((err) => {
        alert('에러 : ' + err.message)
      })
    }
  }
}
</script>

파이어베이스에서 facebookauth를 불러오고, provider 변수로 작업한다.

setCustomParameters의 display를 popup으로 줘서, 버튼을 클릭했을 때 팝업창으로 페이스북 로그인이 진행되도록 한 것이다.

버튼에 작성한 facebookLogin 메소드를 firebase.auth().signInWithPopup로 가져와서 페이스북 로그인을 진행할 수 있다.


Login.vue의 전체 소스코드

<template>
<div class="login">
  <h3>로그인</h3>
  <input type="text" v-model="email" placeholder="email"><br>
  <input type="password" v-model="password" placeholder="password"><br>
  <button v-on:click="login">로그인</button>
  <p>또는 페이스북 로그인 <br>
    <button class="social-button" v-on:click="facebookLogin">
      <img alt="Facebook Logo" src="../assets/facebook-logo.png">
    </button>
  </p>
  <p>만약 계정이 없다면, <router-link to="/signup">회원가입</router-link>을 먼저 진행해주세요!</p>
</div>
</template>

<script>
import firebase from 'firebase'

var provider = new firebase.auth.FacebookAuthProvider()
provider.addScope('public_profile')
provider.setCustomParameters({
  'display': 'popup'
})

export default {
  name: 'login',
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    login() {
      firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
        (user) => {
          this.$router.replace('welcome')
        },
        (err) => {
          alert('에러 : ' + err.message)
        }
      );
    },
    facebookLogin() {
      firebase.auth().signInWithPopup(provider).then((result) => {
        var token = result.credential.accessToken
        var user = result.user

        console.log("token : " + token)
        console.log("user : " + user)

        this.$router.replace('welcome')

      }).catch((err) => {
        alert('에러 : ' + err.message)
      })
    }
  }
}
</script>

<style scoped>
.login {
  margin-top: 40px;
}

input {
  margin: 10px 0;
  width: 20%;
  padding: 15px;
}

button {
  margin-top: 20px;
  width: 10%;
  cursor: pointer;
}

p {
  margin-top: 40px;
  font-size: 15px;
}

p a {
  text-decoration: underline;
  cursor: pointer;
}

.social-button {
  width: 75px;
  background: white;
  padding: 10px;
  border-radius: 100%;
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
  outline: 0;
  border: 0;
}

.social-button:active {
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
}

.social-button img {
  width: 100%;
}
</style>

style을 통해 페이스북 로그인 화면도 꾸민 상태다.



이제 서버를 실행하고 로그인 화면을 보자



페이스북 로고 사진을 누르면?

페이스북 로그인 창이 팝업으로 뜨는걸 확인할 수 있다.

이제 자신의 페이스북 아이디와 비밀번호로 로그인하면 welcome 페이지가 정상적으로 나올 것이다.


마지막으로 파이어베이스에 사용자 정보가 저장된 데이터를 확인해보자


페이스북으로 로그인한 사람의 정보도 저장되어있는 모습을 확인할 수 있다. 페이스북으로 로그인한 사람의 이메일이 등록되면 로컬에서 해당 이메일로 회원가입이 불가능하다.


위처럼 간단하게 웹페이지에서 페이스북 로그인 연동을 구현시킬 수 있고, 다른 소셜 네트워크 서비스들도 유사한 방법으로 가능하다.


Nuxt.js




vue.js를 서버에서 렌더링할 수 있도록 도와주는 오픈소스 프레임워크

서버, 클라이언트 코드의 배포를 축약시켜 SPA(싱글페이지 앱)을 간편하게 만들어준다.

Vue.js 프로젝트를 진행할 때, 서버 부분을 미리 구성하고 정적 페이지를 만들어내는 기능을 통해 UI 렌더링을 보다 신속하게 제공해주는 기능이 있다.



들어가기에 앞서

  • SSR(Server Side Rendering) : 서버 쪽에서 페이지 컨텐츠들이 렌더링된 상태로 응답해줌

  • CSR(Client Side Rendering) : 클라이언트(웹브라우저) 쪽에서 컨텐츠들을 렌더링하는 것

  • SPA(Single Page Application) : 하나의 페이지로 구성된 웹사이트. index.html안에 모든 웹페이지들이 javascript로 구현되어 있는 형태

SPA는 보안 이슈나 검색 엔진 최적화에 있어서 단점이 존재. 이를 극복하기 위해 처음 불러오는 화면은 SSR로, 그 이후부터는 CSR로 진행하는 방식이 효율적이다.


Nuxt.js는 왜 사용하나?

vue.js를 서버에서 렌더링하려면 설정해야할 것들이 한두개가 아니다ㅠ

보통 babel과 같은 webpack을 통해 자바스크립트를 빌드하고 컴파일하는 과정을 거치게 된다. Node.js에서는 직접 빌드, 컴파일을 하지 않으므로, 이런 것들을 분리하여 SSR(서버 사이드 렌더링)이 가능하도록 미리 세팅해두는 것이 Nuxt.js다.

Vue에서는 Nuxt를, React에서는 Next 프레임워크를 사용함


Nuxt CLI를 통해 쉽게 프로젝트를 만들고 진행할 수 있음

$ vue init nuxt/starter <project-name>

기본적으로 vue-routervuex를 이용할 수 있게 디렉토리가 준비되어 있기 때문에 Vue.js로 개발을 해본 사람들은 편하게 활용이 가능하다.


장점


  • 일반적인 SPA 개발은, 검색 엔진에서 노출되지 않아 조회가 힘들다. 하지만 Nuxt를 이용하게 되면 서버사이드렌더링으로 화면을 보여주기 때문에, 검색엔진 봇이 화면들을 잘 긁어갈 수 있다. 따라서 SPA로 개발하더라도 SEO(검색 엔진 최적화)를 걱정하지 않아도 된다.

    일반적으로 많은 회사들은 검색엔진에 적절히 노출되는 것이 매우 중요함. 따라서 검색 엔진 최적화는 개발 시 반드시 고려해야 할 부분

  • SPA임에도 불구하고, Express가 서버로 뒤에서 돌고 있다. 이는 내가 원하는 API를 프로젝트에서 만들어서 사용할 수 있다는 뜻!

단점


Nuxt를 사용할 때, 단순히 프론트/백엔드를 한 프로젝트에서 개발할 수 있지않을까로 접근하면 큰코 다칠 수 있다.

ex) API 요청시 에러가 발생하면, 프론트엔드에게 오류 발생 상태를 전달해줘야 예외처리를 진행할텐데 Nuxt에서 Express 에러까지 먹어버리고 리디렉션시킴

API부분을 Nuxt로 활용하는 게 상당히 어렵다고함