Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

LabofDev/EndofVuejs

Repository files navigation

1. Study Agenda

  • Github Branch Name : vue-endofvue-1.init
  • summary
    • 강좌에서 개발할 웹어플리케이션에 대해서 확인하고 일반적인 웹개발 절차와 API 문서에 대해서 알아본다.

1.1 Introduce Application

  • 회원가입, 로그인, CRUD가 발생하는 기본적인 웹어플리케이션

1.2 Procedure of Front-End Development

  • 웹 개발 절차
    • 요구사항 > 서비스 기획 > UI, UX 상세 설계 > GUI 디자인 > 퍼블리싱 > Back-End API 개발 > Front-End 개발 > QA
  • Front-End 개발자의 역할
    • Client UI에 대한 코드 작성
    • 기획, 디자인, 퍼블리싱, Back-End 개발자와 소통

1.3 Document of API

  • Swagger UI
    • Swagger는 개발자가 RESTfull API를 설계, 빌드, 문서화, 소비하는 일을 도와주는 오픈소스 소프트웨어 프레임워크

2. Configuration of Development Environment

  • Github Branch Name : vue-endofvue-2.environment
  • summary
    • 개발환경 구성에 대해서 알아본다(깃허브, 필수 설치 프로그램, )

2.1 개발 환경(Tools)

2.2 개발 환경 (Visual Studio Code Gitbash Terminal)

  • git bash는 Windows에서도 Linux 명령어를 사용할 수 있는 환경
  • Visual Studio Code에서도 gitbash 터미널을 사용할 수 있다.(본 강좌에서는 사용해야 함)
  • 기존의 terminal.integrated.shell.windows에 대해서 VSCode 업데이트 됨에 사용할 수 없음(참고)
  • Visual Studio Code > ctrl + , > terminal.integrated.shell.windows > setting.json open > 하기의 코드 추가
"terminal.integrated.profiles.windows": {
 "GitBash": {
 // 일반적으로 : "C:\\Git\\bin\\bash.exe"
 "path":["사용자별 git 설치 경로\\bash.exe"],
 "icon":"terminal-bash"
 },
 "PowerShell": {
 "source": "PowerShell",
 "icon": "terminal-powershell"
 },
 "Command Prompt": {
 "path": [
 "${env:windir}\\Sysnative\\cmd.exe",
 "${env:windir}\\System32\\cmd.exe"
 ],
 "args": [],
 "icon": "terminal-cmd"
 },
},
// "GitBash"로 설정하면 "Bash"가 기본으로 설정 됨
"terminal.integrated.defaultProfile.windows": "Command Prompt",

2.3 개발 환경(Node js)

  • Node 버전 확인 및 업그레이드 & 다운그레이드
    • 본 강좌의 소스는 node 버전이 v10.16.3으로 진행해야 함
    • 특정 버전의 Node를 설치하는 방법은 2가지
      • 원하는 LTS 버전을 찾아 해당 OS의 실행 파일로 설치 (GUI로 사용)
      • NVM을 사용하여 특정 버전 설치 사용등 (Command Line으로 사용)
    $ node -v
    v14.8.1
    • Node js - v10.16.3에서 OS 버전에 맞는 파일을 다운로드 받아 설치 가능
  • NVM(Node Version Manager)
    • NVM을 이용하여 nodejs 특정 버전을 설치, 업그레이드 및 다운그레이드 가능
    • Node js
    • NVM Github
    • NVM 설치
      $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
    • NVM 명령어 등록
      • VSCode > 터미널을 Bash로 열고 하기 명령어 입력
      $ vi ~/.bashrc
      // i : 쓰기모드 진입
      export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
      [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
      // esc : 쓰기모드 해지
      // :wq : 저장하고 종료 (:q : 저장하지 않고 종료)
      • bash 터미널에서 하기 명령어를 입력하여 정상적으로 NVM이 설치 및 명령어가 적용되었는지 확인
      $ nvm --version
      0.39.0
      $ nvm install 10.16.3
      Downloading and installing node v10.16.3...
      Downloading https://nodejs.org/dist/v10.16.3/node-v10.16.3-win-x64.zip...
      ################################# 100.0% 
      Computing checksum with sha256sum
      Checksums matched!
      Now using node v10.16.3 (npm v6.9.0)
      Creating default alias: default -> 10.16.3 (-> v10.16.3)
      $ node -v
      v10.16.3
      • vue-til-server > package.json 파일내 패키지 설치를 위한 명령어 실행
      $ npm i
      • npm run dev로 서버 실행
      $ npm run dev
      ...중략...
      VUE TIL SERVER IS RUNNING ON 3000
      // '3000'에 대한 포트를 사용중이면 하기에서 변경 가능
      // src > app.js > port 번호 수정
      • http://localhost:3000/api/docs로 접속하여 API 서버 확인

2.4 개발 환경(MongoDB)

  • MongoDB Site
  • src > app.jsconst db에서 하기의 생성된 DB를 연결
  • bash command > npm run dev > Server 기동 > http://localhost:3000/api/docs 접속 > /signup API Test

2.5 개발 환경(Swagger UI API)

  • Node js로 작서된 Back-End API 코드를 Front-End 개발자와 커뮤니케이션하기 위한 API UI
  • RESTfull API를 직접 테스트 할 수 있는 API UI

2.6 개발 환경(프로젝트 구성 - 프로젝트 생성, ESLint & Prettier)

  • 웹팩 데브 서버 설명 글
  • Vue.js 개발 생산성을 높여주는 도구 3가지
  • vue --version 으로 vue/cli 버전 확인
  • vue create vue-til으로 프로젝트 생성 (Manual로 선택하며, 하기의 이미지 참고)
  • ESLint 구문 오류(ESLint 란?)
    • 해결 방법
      • vue.config.js 파일 생성하고 하기와 같은 코드 삽입
      • 빌드 오류는 발생하나 오버레이 안됨
      module.exports = {
       devServer: {
       overlay: false,
       },
      };
    • ESLint 설정 파일 설정 방법
      • root > .eslintrc.js 파일에 하기와 같이 개발자 커스텀 설정 가능
    rules: {
     "no-console": "error", // 정상을 위하여 "off"로 설정 필요
     // "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
     // "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
    },
    • console 명령서 사용시 error 출력으로 설정함으로 하기와 같이 오류 발생
    • ESLint 구문 오류시 해당 구문에 빨간줄이 생기지 않을 경우
      • VSCode 설정 > settings.json에 하기 코드 추가
      "editor.codeActionsOnSave": {"source.fixAll.eslint": true},
      "eslint.workingDirectories": [{"mode": "auto"}],
  • Prettier (일관성 있는 코드 포맷을 위한 웹팩)
    • 하기의 이미지처럼 prettier 구문을 적용하면 코드에 붉은색 라인이 생기며 빌드 오류 발생
    • 해결 방법
      • 설정eslint: validate > settings.json 파일에서 하기 축
      "editor.codeActionsOnSave": {
       "source.fixAll.eslint": true
       },
       "eslint.workingDirectories": [
       {
       "mode": "auto"
       }
       ],
       // ESLint
       "eslint.validate":[
       "vue", 
       "javascript", 
       "javascriptreact", 
       "typescript", 
       "typescriptreact"
       ],
       // don't format on save
       "editor.formatOnSave": false,
      • prettier 확장 프로그램에서 사용안함(작업영역) 설정
      • 설정Format on Save 체크 해지

2.7 개발 환경(기타)

3. Router & Design of Component

// vue-til 소스를 최초에 설치할 경우
$ git clone https://github.com/joshua1988/vue-til
$ git checkout 1_setup
$ npm i

3.1 Router

  • LoginPage, SignupPage 생성 및 라우터 설정
  • router 설치
$ npm i vue-router
  • Code Splitting(코드 스플리팅)
    • 최초 로딩시 리소스를 최소화하여 가져오고 이후 뷰페이지 호출시 리소스를 로딩함
    export default new VueRouter({
     routes: [
     {
     path: '/login',
     component: () => import('@/views/LoginPage.vue'),
     },
     {
     path: '/signup',
     component: () => import('@/views/SignupPage.vue'),
     },
     ],
    });
  • 뷰 라우터 오픈 소스
  • 뷰 라우터 History Mode 주의 사항 문서
    • history 모드의 경우 URL에 #이 없이 나타난다.(서버가 새로운 페이지로 인식하지 못 함)
    • 서버가 새로운 페이지로 인식을 못 함으로 서버에 설정이 필요함.
  • fallback router
    • 지정된 경로가 아닌 경우를 대비
export default new VueRouter({
	mode: 'history',
	routes: [
		{
			path: '/login',
			component: () => import('@/views/LoginPage.vue'),
		},
		{
			path: '/signup',
			component: () => import('@/views/SignupPage.vue'),
		},
		{
			path: '*',
			component: () => import('@/views/NotFoundPage.vue'),
		},
	],
});

4. Development of Member Register

5. Configuration of Project

6. Development of Login

7. Store & Login State Management

  • Github Branch Name : vue-endofvue-7.store_state
  • summary
    • Style, Main Page

7.1 Style

  • css/common.css, css/reset.css
  • App.vue, AppHeader.vue
  • vue router > router-link를 사용(html 레벨)
  • vue router > router.push를 사용(javascript 레벨)

7.3 로그인 후 사용자 정보 표시(store를 사용)

8. API Authentication by Token

9. Development of Retrieve Note Data

  • Github Branch Name : vue-endofvue-9.dev_retrieve
  • summary
    • 목록 조회 개발, style 적용, 컴포넌트화, 로딩 상태 & 로딩 스피너 개발
  • PostItem에 대하여 컴포넌트화 (MainPage에서 props로 컴포넌트로 값 전달)
// MainPage.vue
<template>
	<div>
		<div class="main list-container contents">
			<h1 class="page-header">Today I Learned</h1>
			<ul>
				<PostListItem
					v-for="postItem in postItems"
					v-bind:key="postItem._id"
					v-bind:postItem="postItem"
				></PostListItem>
			</ul>
		</div>
	</div>
</template>
export default {
	components: {
		PostListItem,
	},
}
// PostListItem.vue
<template>
	<li>
		<div class="post-title">
			{{ postItem.title }}
		</div>
		<div class="post-contents">
			{{ postItem.contents }}
		</div>
		<div class="post-time">
			{{ postItem.createdAt }}
		</div>
	</li>
</template>
<script>
export default {
	props: {
		postItem: {
			type: Object,
			required: true,
		},
	},
};
</script>

10. Management of Authentication Value using Browser Storage

  • Github Branch Name : vue-endofvue-10.mgmt_auth_browser_storage
  • summary
    • 로그인한 세션 정보를 위하여 쿠키 사용

10.1 Cookie Save

  • 쿠키 저장
  • store > index.jsstate에서 쿠키값 보존을 위한 코드 추가
state: {
		username: getUserFromCookie() || '',
		token: getAuthFromCookie() || '',
	},

10.2 코드 정리

  • async, await를 왜 사용하는지 반드시 인지하고 넘어 가야 함
  • 자바스크립트는 기본이 비동기 처리 방식이나 async, await를 사용하여 동기화 처리 필요

11. Development of Create Note Data

12. Middle Adjustment

12.1. 개발환경 설정

  • 개발 툴 및 필요 프로그램 설치
  • API 서버 프로젝트 클론

12.2. Vue CLI 프로젝트 생성

  • Prettier
  • ESLint
  • jsconfig

12.3. 뷰 라우터 및 컴포넌트 설계

  • <router-link>
  • <router-view>
  • mode: history와 서버 배포시 주의 사항
  • 코드 스플리팅 component: () => import('경로')

12.4. 회원 가입 페이지 개발

  • 사용자 폼 처리
  • async & await
  • axios
  • swagger API 문서 보는 방법

12.5. 실무 환경 구성

  • axios.create()
  • env 파일 설정 방법
  • Vue CLI 버전 3 이상에서의 env 파일 규칙

12.6. 로그인 페이지 개발

  • 사용자 폼 처리 기능 구현
  • async & await 에러 처리 방법
  • 사용자 폼 유효성 검사

12.7. 로그인 상태 관리

  • 뷰엑스를 이용한 사용자 아이디 관리
  • this.$router.push('/main')

12.8. API 인증 처리를 위한 토큰 관리

  • JSON Web Token
  • Authorization 토큰 값으로 API 인증을 받는 방법
  • axios.interceptors

12.9. 학습 노트 데이터 조회

  • 학습 노트 목록 표시 기능 구현
  • 목록 아이템 컴포넌트화
  • 스피너를 이용한 데이터 로딩 상태 표시

12.10. 브라우저 저장소를 이용한 인증 값 관리

  • 쿠키를 이용한 로그인 인증 값 저장
  • actions를 이용한 컴포넌트 로직 정리

12.11. 학습 노트 데이터 생성

  • 학습 노트 생성 기능 구현
  • 학습 노트 본문 길이 유효성 검사

12.12 13부터 진행할 내용

  • 데이터 성격 별로 API 함수 모듈화
  • 학습 노트 삭제 기능
  • 날짜 형식 포맷팅 filter
  • 라우터 심화
  • 프런트엔트 테스트

13. API Function Modularity

  • Github Branch Name : vue-endofvue-13.api_modularity
  • summary
    • API function의 모듈화로 기능의 성격별로 또는 서브-도메인의 성격별로 분리(모듈화) 진행
    • 추후 시스템이 확장될 경우를 대비하여 처음부터 확장성을 고려하여 API 호출 함수 모듈화 필요
  • Key Sample Code
    • api > index.js 파일에서 기능적으로 유사한 함수끼리 모아 분리 모듈화
    • 인스터스를 2개로 구분하는데 인증전(로그인전)인증후(로그인후)
    import axios from 'axios';
    import { setInterceptors } from './common/interceptors';
    // 엑시오스 초기화 함수 (인증전 즉, 로그인 전)
    function createInstance() {
     return axios.create({
     baseURL: process.env.VUE_APP_API_URL,
     });
    }
    // 액시오스 초기화 함수 (인증후 즉, 로그인 후)
    function createInstanceWithAuth(url) {
     const instance = axios.create({
     baseURL: `${process.env.VUE_APP_API_URL}${url}`,
     });
     return setInterceptors(instance);
    }
    export const instance = createInstance();
    export const posts = createInstanceWithAuth('posts');
    • api > auth.js 로그인 관련 API function 모듈
    // 로그인, 회원 가입, 회원 탈퇴 등을 위한 API
    import { instance } from './index';
    // 회원가입 API
    function registerUser(userData) {
     return instance.post('signup', userData);
    }
    // 로그인 API
    function loginUser(userData) {
     return instance.post('login', userData);
    }
    export { registerUser, loginUser };
    • api > posts.js 게시물 관련 API function 모듈
    // 학습 노트 조작과 관련된 CRUD API 함수
    import { posts } from './index';
    // 학습 노트 데이터를 조회하는 API
    function fetchPosts() {
     return posts.get('/');
    }
    // 학습 노트 데이터를 생성하는 API
    function createPost(postData) {
     return posts.post('/', postData);
    }
    export { fetchPosts, createPost };

14. & 15. Development of Delete Note Data & Modify Note Data

  • Github Branch Name : vue-endofvue-14.dev_delete
  • summary
  • 게시물 삭제
    • API에 삭제 함수 생성 PostListItem에서 deleteItem 이벤트 처리
    async deleteItem() {
     		if (confirm('You want to delete it?')) {
     			await deletePost(this.postItem._id);
     			this.$emit('refresh');
     		}
     	},
  • 게시물 수정
    • API에서 id를 인자로 게시물을 조회하는 함수 추가
    • PostEditPage.vuePostEditForm.vue를 생성하여 데이터 변경
  • 삭제수정push를 사용하여 main으로 이동
this.$router.push('/main');

16. Data Formatting

  • Github Branch Name : vue-endofvue-16.data_format
  • summary
  • 16.1 Filter 함수 사용
    • utils > filters.js 정의
    export function formatDate(value) {
     const date = new Date(value);
     const year = date.getFullYear();
     let month = date.getMonth() + 1;
     month = month > 9 ? month : `0${month}`;
     const day = date.getDate();
     let hours = date.getHours();
     hours = hours > 9 ? hours : `0${hours}`;
     const minutes = date.getMinutes();
     return `${year}-${month}-${day} ${hours}:${minutes}`;
    }
    • main.js에 전역으로 사용할 필터 정의
    //main.js
    import { formatDate } from '@/utils/filters';
    Vue.filter('formatDate', formatDate);
    • 전역으로 정의한 필터 사용
    <div class="post-time">
     {{ postItem.createdAt | formatDate }}
     <i class="icon ion-md-create" @click="routeEditPage"></i>
     <i class="icon ion-md-trash" @click="deleteItem"></i>
    </div>

17. Router Advanced

//routes > index.js
const router = new VueRouter({
	mode: 'history',
	routes: [
 {
 path: '/post/:id',
 component: () => import('@/views/PostEditPage.vue'),
 meta: { needAuth: true },
 },
 ]
});
router.beforeEach((to, from, next) => {
	if (to.meta.needAuth && !store.getters.isLogin) {
		console.log('인증이 필요합니다.');
		next('/login');
		return;
	}
	next();
});

18. Introduce of Front-End Testing

  • Github Branch Name : vue-endofvue-18.front_end_test
  • summary
  • 18.1 Jest 테스트를 위한 환경 설정
    //`package.json` 설정
     "scripts": {
     "test": "vue-cli-service test:unit --watchAll",
    },
    //--watchAll : 변경즉시 반영 됨
    //jest.config.js 설정
    module.exports = {
     preset: '@vue/cli-plugin-unit-jest',
     testMatch: [
     '<rootDir>/src/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
     ],
    };
    // 테스트 실행 명령어
    $npm t
    // jest 함수들의 eslint 인식 빨간펜 처리
    // .eslintrc.js
    env: {
     node: true,
     jest: true,
    },
    
  • 18.2 Jest 일반 사항
    • 제일 먼저 jest.config 파일의 설정을 참고하며, 설정 파일이 없다면 하기의 기본 설정 폴더를 참고
      • test > unit > *.spec.js
    • 일반적으로 테스트 스크립트 파일은 테스트 대상의 인근에 생성하고 관리
    • 또는 jest.config.js파일에서와 같이 __tests__와 같이 폴더 생성하여 관리
  • 18.3 Jest Test Code 작성
    • vuejs test library
    import { shallowMount } from '@vue/test-utils';
    • find() function sample
    import LoginForm from './LoginForm.vue';
    import { shallowMount } from '@vue/test-utils';
    describe('LoginForm.vue', () => {
     test('ID는 이메일 형식이여야 한다.', () => {
     const wrapper = shallowMount(LoginForm);
     const idInput = wrapper.find('#username');
     console.log(idInput.html());
     });
    });
    • 인스턴스를 생성한 vue 페이지의 computed에도 접근 가능
    describe('LoginForm.vue', () => {
     test('ID는 이메일 형식이여야 한다.', () => {
     const wrapper = shallowMount(LoginForm, {
     data() {
     return {
     username: 'test@abc.com',
     };
     },
     });
     const idInput = wrapper.find('#username');
     console.log('InputBox Value ', idInput.element.value);
     console.log(wrapper.vm.isUsernameValid);
     });
    });
    • LoginForm.vue에서 로그인 버튼의 활성/비활성화 코드 추가후 테스트 코드 작성
    // LoginForm.vue
    <button
     :disabled="!isUsernameValid || !password"
     type="submit"
     class="btn"
     v-bind:class="!isUsernameValid || !password ? 'disabled' : null"
    >
    // LoginForm.spec.js
    test('#3. ID와 PWD가 입력되지 않으면 로그인 버튼이 비활성화 된다.', () => {
     	const wrapper = shallowMount(LoginForm, {
     		data() {
     			return {
     // 값이 없으면 통과, 값이 있으면 실패
     				username: 'a@a.com',
     				password: '1234',
     			};
     		},
     	});
     	const button = wrapper.find('button'); // '.btn'
     	expect(button.element.disabled).toBeTruthy();
     });

19. End of

  • Github Branch Name : vue-endofvue-19.end
  • summary
    • 프로젝트 구성 방법
      • ESLint, Prettier
      • env
    • REST API를 이용한 CRUD Application 구현 방법
    • Back-End API 문서 보는 방법 및 Back-End 개발자와 협업할때의 주의 사항
    • axios 인터셉터와 모듈화를 이용한 API 함수 설계
    • Router 페이지 권한 처리
    • Front-End 테스트 방법

About

Vuejs실무

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /