기본 콘텐츠로 건너뛰기

[Angular Architecture] 애플리케이션 구조 설계 - 2

[Angular Architecture] 애플리케이션 구조 설계 - 2

Angular CLI v6.* 이후 Multi Application을 위한 Workspace개념이 도입되었다. 공통 Module을 통해 하나의 폴더안에서 여러 애플리케이션을 만들 수 있는 방법에 대해 알아본다.

Schematics

스케메틱스는 workflow 툴이다.

- 프로젝트에 파일을 생성하고

- 기존 코드를 변경하고

- 환경 옵션을 추가하거나 프레임워크를 추가할 수 있다.

스케메틱스는 Angular CLI의 코드 스케폴딩에 사용하며 다음 목표를 지향하여 개발되었다.

- 사용 및 개발이 쉬워야 한다

- 확장 및 재상용성이 좋아야 한다

- CLI동작시 부작용을 제거할 수 있어야 한다.

- 비동기성을 지원한다.

Tree

- 이미 존재하는 파일 관계를 작는 데이터 구조체이다.

- 파일을 수정하거나 생성하고 찾아 갈때 사용한다.

- 스케메틱의 Start point가 된다.

- 하나의 스케메틱 Tree를 다른 스케메틱 Tree로 전달할 수 있다.

- create, delete, rename, overwrite 내가지 함수를 제공한다.

나만의 스케메틱스 만들기

- Node v6.9 이상 설치

- schematics 실행환경을 만들기 위해 shcematics-cli를 설치한다.

$ npm install -g @angular-devkit/schematics-cli

// 빈 스케메틱스 프로젝트 생성 $ schematics blank --name=my-project $ cd my-project

Collections

- 이름을 갖는 schematics의 집합이다. 이것은 사용자에 의해 발행되고 설치될 수 있다.

- 예로 @schematics/angular collection이 있다. 이것은 component, module, application 등에 대한 schematics를 가지고 있다.

- 생성한 my-project는 하나의 schematics만을 가지고 있고, my-project/src/collection.json 에 정의되어 있다.

- schematics key안에 하나의 my-project schematic 이 설정되어 있다.

- factory key는 자바스크립트 펑션 위치를 설정한다. 이것은 RuleFactory라 한다.

// src/collection.json { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-project": { "description": "A blank schematic.", "factory": "./my-project/index#myProject" } } }

// src/my-project/index.ts import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';

export function myProject(_options: any): Rule { return (tree: Tree, _context: SchematicContext) => { return tree; }; }

Rule

- Tree를 받아 Tree를 반환하는 함수이다.

- Rule이 스케메틱스의 핵심이다.

- Factory 함수는 입력 options 아규먼트를 받아 원하는 것을 처리 후 다시 Rule을 반환한다.

- 옵션은 CLI의 경우 command line 아규먼트로 전달되는 값이다. (보통 --name= 같이 전달함)

사용자가 만든 스케메틱스를 수행하기

- dry-run은 스케메틱스 자신안에서 수행할 수 있게 한다. default는 false 이다.

- 우리가 만든 스케메틱스는 애플리케이션안에서 사용하는 것이다. 따라서 자기 자신안에서 스케메틱스 검증을 해보려면 dry-run 옵션을 준다.

- 만들어진 스케메틱스를 디버깅 할 수 있다.

$ npm run build

// dry-run 수행시, 가급적 사용하지 말자, 별도의 temporary 폴더에서 dry-run없이 테스트 한다. $ schematics .:my-project --name=test --dry-run=true

// 디버깅 $ node --inspect-brk $(which schematics) .:my-project --name=test

다른 스케메틱스를 함께 사용하기

- chain을 통해 기존 @schamatics/angular의 component 생성하는 것을 이용한다.

- Angular component를 만든 다음 상단에 license 문구를 추가한다.

import { Rule, SchematicContext, Tree, chain, externalSchematic } from '@angular-devkit/schematics';

const licenseText = ` /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ `;

export function myProject(options: any): Rule { return chain([ externalSchematic('@schematics/angular', 'component', options), (tree: Tree, _context: SchematicContext) => { tree.getDir(options.sourceDir) .visit(filePath => { if (!filePath.endsWith('.ts')) { return; } const content = tree.read(filePath); if (!content) { return; }

// Prevent from writing license to files that already have one. if (content.indexOf(licenseText) == -1) { tree.overwrite(filePath, licenseText + content); } }); return tree; }, ]); }

수행해 보자.

// my-project schematics 폴더안에서 의존관계있는 @schematics/angular 설치 $ npm install --save @schematics/angular $ npm run build

// 신규 프로젝트 생성하고, my-project schematics 를 npm link 건다. $ cd ../ $ ng new $ cd $ npm link

// schematics:schematic 을 호출한다. angular module의 declarations에도 자동 추가된다. $ ng g my-project:my-project ? What name would you like to use for the component? hi CREATE src/app/hi/hi.component.css (0 bytes) CREATE src/app/hi/hi.component.html (21 bytes) CREATE src/app/hi/hi.component.spec.ts (600 bytes) CREATE src/app/hi/hi.component.ts (253 bytes) UPDATE src/app/app.module.ts (537 bytes)

Multi Application을 위한 Nx Workspace

Nx Workspace는 nrwl에서 만든 multi application 개발을 위한 Angular CLI에 대한 확장팩이다. 다음 3가지의 향상시키기 위해 만들어졌다.

- 생산성: 초시 셋업시간을 절약한다.

- 일관성: 기업용 애플리케이션을 위한 좀 더 향상된 코드 제너레이터를 제공하고, 일관된 물리적 공간과 컨벤션을 제공한다.

- 안정성: 분석기능 강화

Workspace에서 작업하기

- 단일 레파지토리에서 Multi Application과 Library에 대한 개발을 수행한다.

+ Unified versioning: 하나의 레파지토리 사용에 따른

+ Promotes code sharing and reuse: lib모듈을 통한 공유

+ Easier dependency management: 하나의 node_modules만 사용, 하나의 build setup

+ Refactoring benefits: code editors 지원, 변경이 전체 애플리케이션에 반영

+ Consistent developers experience: 공유 코드 변경에 대한 전체 애플리케이션 유효성 체크 가능

Nx Workspace 만들기

create-nx-workspace 명령어를 통해 nx 기반 angular workspace를 생성한다. 마치 create-react-app과 같은 역할이다.

- npmScope: 그림처럼 NPM Scope로 library를 접근하는 @my-company와 같은 npm scope를 설정

예로 @angular가 npm scope이다.

- directory workspace의 폴더명 변경

$ npm i -g @nrwl/schematics @angular/cli

// command: create-nx-workspace --directory= --npm-scope= $ create-nx-workspace my-project-suite --npm-scope=apple

Multi Application & Library 생성하기

Nx Workspace에 application과 library를 생성한다. Angular CLI Workspace에서 만들어 지는 폴더 구조와 다음과 같은 차이가 있다.

- apps: apps폴더 밑으로 Application별 폴더가 존재한다.

- libs: application에서 공유하는 Angular Module별 폴더가 존재한다.

애플리케이션 프로젝트에 대한 정보는 angular.json에서 확인할 수 있다.

{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "", "projects": {}, <-- 프로젝트 즉, 애플리케이션은 아직 등록되지 않았다. "cli": { "warnings": { "typescriptMismatch": false, "versionMismatch": false }, "defaultCollection": "@nrwl/schematics", <-- nrwl/schematics를 사용한다. "packageManager": "npm" } }

nx.json은 Nx Workspace특화된 환경값을 갖는다.

{ "npmScope": "apple", "implicitDependencies": { "angular.json": "*", "package.json": "*", "tsconfig.json": "*", "tslint.json": "*", "nx.json": "*" }, "projects": {} }

그외 tsconfig.json에 paths와 tslin.json의 nx-enforce-module-boundaries 설정, 그리고 package.json에 Nx를 위한 별도 script들이 존재한다.

apps폴더 밑으로 프로젝트 추가하기

- 명령: ng g app

- ng g app --help 로 생성 옵션을 볼 수 있다. 예로 --routing 옵션을 주면 routing module이 자동 설정된다. 또는 생성시 yes 를 선택해되 된다.

$ ng g app app-one

// 다음을 선택했다. ? In which directory should the application be generated? ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS [ http://sass-lang.com] ? Which Unit Test Runner would you like to use for the application? Jest [ https://jestjs.io ] ? Which E2E Test Runner would you like to use for the application? Cypress[ https://www.cypress.io ] ? Which tags would you like to add to the application? (used for linting)

애플리케이션 app-one을 위해 다음과 같은 두개 폴더가 생성된다.

만들어진 애플리케이션을 실행해 보자.

- ng serve

- default port는 4200이다. 여러개의 애플리케이션을 동시 실행하고 싶다면 --port 옵션으로 포트를 서로 틀리게 설정한다. 또는 angular.json에 설정할 수 있다.

$ ng serve app-one

libs폴더 밑으로 공유 라이브러리 추가하기

- 라이브러리는 Angular Module이다.

- ng g lib

$ ng g lib adk ? In which directory should the library be generated? ? Which module should import the library? ? Would you like to add a routing configuration to the library? No ? Will this library be lazy loaded? No ? Would you like to generate an NgModule within the library? Yes ? Which tags would you like to add to the library? (used for linting) ? Which Unit Test Runner would you like to use for the library? Jest (https://jestjs.io/)

생성을 하게되면 libs/adk 폴더가 생성되고, angular.json에 projectType으로 library가 자동 등록된다. (nx.json에도 자동 등록됨)

lazy loading되는 library module 생성

- --routing이 설정된 모듈

- lazy loading되는 상위 모듈: 어차피 애플리케이션도 라이브러리도 모듈이다.

- --lazy 옵션을 직접주거나 아래처럼 선택할 수 있다.

$ ng g lib login --routing --parent-module=./apps/app-one/src/app/app.module.ts

? In which directory should the library be generated? ? Will this library be lazy loaded? Yes ? Would you like to generate an NgModule within the library? Yes ? Which tags would you like to add to the library? (used for linting) ? Which Unit Test Runner would you like to use for the library? Jest (https://jestjs.io/)

routing 설정을 하게되면 login.module.ts와 app-one의 app.module.ts 안의 설정은 다음과 같다.

- @apple 이라는 npm scope가 자동으로 붙는다.

// libs/login/src/lib/login.module.ts @NgModule({ imports: [ CommonModule,

RouterModule.forChild([ /* {path: '', pathMatch: 'full', component: InsertYourComponentHere} */ ]) ] }) export class LoginModule {}

// apps/app-one/src/app/app.module.ts @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, NxModule.forRoot(), RouterModule.forRoot( [{ path: 'login', loadChildren: '@apple/login#LoginModule' }], { initialNavigation: 'enabled' } ) ], providers: [], bootstrap: [AppComponent] }) export class AppModule {}

루트의 tsconfig.json에는 library module에 대한 paths 정보가 자동 설정된다.

"lib": [ "es2017", "dom" ], "baseUrl": ".", "paths": { "@apple/adk": [ "libs/adk/src/index.ts" ], "@apple/login": [ "libs/login/src/index.ts" ] }

Multi Application 빌드하기

angular.json의 architect에는 build와 serve에 대한 환경설정이 있다.

"architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/apps/app-one", "index": "apps/app-one/src/index.html", "main": "apps/app-one/src/main.ts", "polyfills": "apps/app-one/src/polyfills.ts", "tsConfig": "apps/app-one/tsconfig.app.json", "assets": [ "apps/app-one/src/favicon.ico", "apps/app-one/src/assets" ], "styles": [ "apps/app-one/src/styles.scss" ], "scripts": [] }, "configurations": { "production": { .... } }

빌드 명령

애플리케이션을 빌드한다

- ng build --prod

- nx workspace command 목록

$ ng build app-one --prod

라이브러리를 빌드하려면 라이브러리 생성할 때 --publishable 옵션을 주어서 생성한다. 그러면 angular.json파일의 "architect"에 "build"옵션이 추가된다. library build할 때는 ng-packagr를 이용하여 어디에서든 사용할 수 있는 APF v6가 적용된다. APF는 Angular Package Format의 약어이다.

$ ng g lib ui --publishable --routing --parent-module=./apps/app-one/src/app/app.module.ts

// angular.json "ui": { "root": "libs/ui", "sourceRoot": "libs/ui/src", "projectType": "library", "prefix": "apple", "architect": { "build": { "builder": "@angular-devkit/build-ng-packagr:build", "options": { "tsConfig": "libs/ui/tsconfig.lib.json", "project": "libs/ui/ng-package.json" } },

Angular Pakage Format v6 지원 목록

ui라는 라이브러리 빌드하기

$ ng build ui Building Angular Package Building entry point '@apple/ui' Compiling TypeScript sources through ngc Bundling to FESM2015 Bundling to FESM5 Bundling to UMD Minifying UMD bundle Copying declaration files Writing package metadata Removing scripts section in package.json as it's considered a potential security vulnerability. Built @apple/ui Built Angular Package! - from: /Users/dowonyun/mobicon/projects/bistel/prototyping/my-project-suite/libs/ui - to: /Users/dowonyun/mobicon/projects/bistel/prototyping/my-project-suite/dist/libs/ui

// 다양한 번들 파일이 생성됨

$schema와 schema.json 개념

Angular Workspace에 대한 schema를 강제하기 위하여 schema.json 파일을 angular.json의 $schema에 설정한다.

- Angular Workspace Schame에 대한 Json 스펙

- Angular CLI의 Schematics 에 목록: 각 폴더 밑에 schema.json 파일이 존재한다.

- schematics 키의 값은 workflow를 수행할 때 적용할 옵션을 설정할 수 있다.

지정가능한 옵션 목록

"schematics": { "@schematics/angular:component": { "styleext": "scss", "changeDetection": "OnPush", "viewEncapsulation": "None", "export": true } },

<참조>

- Schematics 소개

- 2018 FEConf, 고재도님의 Schematics 소개영상

- Angular CLI의 Workspace 과 Schematics 개념

- Angular CLI command 목록

- Nrwl Nx Workspace 홈페이지

- Nx Github

- Nx Workspace 온라인 강좌 (Free)

- Angular Package Format(APF) 개념 강좌

- APF를 만들어주는 ng-packagr 소스 및 설명

- APF v6 스펙

- ng-packagr 소개

from http://mobicon.tistory.com/566 by ccl(A) rewrite - 2020-03-06 04:54:31

댓글

이 블로그의 인기 게시물

[django] django rest framework 로그인 과정 | 장고 로그인 | 인증...

[django] django rest framework 로그인 과정 | 장고 로그인 | 인증... django 는 기능이 참 너무 많다 ^^; 지금은 서버는 django로, 프론트는 angular를 붙여서 간단한 웹을 만들어 보려고 한다. 웹 만들때 항상 회원가입/로그인 기능은 맨 앞에 구현한다. 어떻게 구현하면 좋을까... 찾아보다가 이 기능을 구현할 수 있는 방법이 너무 많아서 정보를 찾기 더 어려웠다. 일단 나는 django에서 django rest framework라는 것을 사용해서 API를 만드려고 한다. 순수 django 튜토리얼에는 바로 template 랑 연결해서 설명하는 부분이 많았다. 나는 그냥 API 만 만들고 싶다고!! 그래서 찾은 것이 django REST framework. https://www.django-rest-framework.org/api-guide/authentication django REST framework 설치 using pip pip install djangorestframework settings.py INSTALLED APPS 에 추가해야함 INSTALLED_APPS = [ ... 'rest_framework', ] django REST framework 에서도 인증 관련해서 제공하는 것이 1개가 아닌 여러 개다. 나는 그중에 TokenAuthentication을 이용해서 로그인을 구현해 보려고 한다. TokenAuthentication Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. 이렇게 나와있어서 내가 하려는 것과 일치해서 이걸로 결정 ~ 솔직히 처음 로그인을 구현하려고 하면 도대체 그 과정이 어떻게 되는지 모를 수 도 있다. 나는 쉽게 정리하면 아래와 같은 과정이라고 생각한다. 로그인 로그아웃...

(주)레터플라이 채용 정보: 프로그래밍을 생각하면 가슴이 뛰는 개발자...

(주)레터플라이 채용 정보: 프로그래밍을 생각하면 가슴이 뛰는 개발자... Angular.js, Python, MySQL 중 한 가지 언어에 뛰어나신 분도 좋고 개발 업무 전반적으로 센스가 있으신 분도 환영합니다. 맡은 업무를 성실하게 수행해 나갈 수 있는 책임감과 태도를 갖고계신 분, 그리고 항상 새로운 방법론에 도전하고 포기를 모르는 분일수록 저희와 더욱 잘 맞을 것 같습니다. Angular.js, Python, MySQL 중 한 가지 언어에 뛰어나신 분도 좋고 개발 업무 전반적으로 센스가 있으신 분도 환영합니다. 팀 내 뛰어난 풀스택 개발자분들이 Angular.js, Python, MySQL 모두 작업 가능하시니 오셔서 함께 배우며 즐겁게 작업하시면 됩니다. 맡은 업무를 성실하게 수행해 나갈 수 있는 책임감과 태도를 갖고계신 분, 그리고 항상 새로운 방법론에 도전하고 포기를 모르는 분일수록 저희와 더욱 잘 맞을 것 같습니다. 개발 업무: 레터플라이의 핵심 기능인 편지, 사진을 제작하는 레터에디터, 포토에디터 개발. 이 기능들은 "모바일 웹을 통한 출력제품 생산 자동화 기술"(특허 출원 준비중)로서 레터플라이에서 자체개발했습니다. 근무 지역: 광화문역 5번출구 바로 앞 근무 환경: 책임과 존중을 중요시하는 수평적인 분위기, 도전적이며 서로에게 배우는 문화 근무 시간: 10-19시, 출근시간 자유 지정. 급여: 연봉/스톡옵션 협의 지원 방법: 팀 지원하기 더 많은 내용은 더 많은 내용은 더팀스 에서 확인하세요! from http://theteams.tistory.com/721 by ccl(A) rewrite - 2020-03-20 09:20:18

jqxGrid 정렬, 필터 메뉴 숨기기

jqxGrid 정렬, 필터 메뉴 숨기기 How I can remove filter to particular grid column - Angular, Vue, React, Web Components, Javascript, HTML5 Widgets Hi, I tried that it's working. I set properties to those columns as sortable: false, filterable: false. but when I clicked on the column one drop down is appearing with options "sort ascending", "sort descending", "remove sort" and those are all in disable www.jqwidgets.com from http://devesim.tistory.com/90 by ccl(A) rewrite - 2020-03-11 04:20:29