Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

카카오커머스를 지탱하는 Angular

johnny.m(김민형) / 카카오커머스
3년간 카카오커머스에서 Angular v2부터 사용하며 겪었던 경험들을 토대로 프레임웍의 특징과 장단점, 그리고 서비스를 안정적으로 운영하기 위한 Best Practice를 공유합니다.

  • Als Erste(r) kommentieren

카카오커머스를 지탱하는 Angular

  1. 1. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ProductComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); } console.log(form.value); /* { name: " " } */
  2. 2. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ProductComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); } console.log(form.value); /* { name: " " } */
  3. 3. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ProductComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); } if (form.valid) { this.http.post( '/api/product', form.value ).subscribe(res => { alert(' !'); }); }
  4. 4. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <div formGroupName="discount"> <input type="text" formControlName="price" /> <input type="text" formControlName="period" /> </div> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl('', Validators.required), discount: new FormGroup({ price: new FormControl(''), period: new FormControl(''), }) }); }
  5. 5. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <div formGroupName="discount"> <input type="text" formControlName="price" /> <input type="text" formControlName="period" /> </div> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl('', Validators.required), discount: new FormGroup({ price: new FormControl(''), period: new FormControl(''), }) }); }
  6. 6. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <app-discount formControlName="discount" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl(''), discount: new FormControl(), }); } @Component({ selector: 'app-discount', template: ` <form [formGroup]="discount"> <!-- ... --> </div> `}) class DiscountComponent { discount = new FormGroup({ price: new FormControl(''), period: new FormControl(''), }); }
  7. 7. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <app-discount formControlName="discount" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl(''), discount: new FormControl(), }); } @Component({ selector: 'app-discount', template: ` <form [formGroup]="discount"> <!-- ... --> </div> `}) class DiscountComponent { discount = new FormGroup({ price: new FormControl(''), period: new FormControl(''), }); }
  8. 8. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <app-discount formControlName="discount" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl(''), discount: new FormControl(), }); } @Component({ selector: 'app-discount', template: ` <form [formGroup]="discount"> <!-- ... --> </div> `}) class DiscountComponent { discount = new FormGroup({ price: new FormControl(''), period: new FormControl(''), }); }
  9. 9. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <app-discount formControlName="discount" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl(''), discount: new FormControl(), }); } @Component({ selector: 'app-discount', template: ` <form [formGroup]="discount"> <!-- ... --> </div> `}) class DiscountComponent { discount = new FormGroup({ price: new FormControl(''), period: new FormControl(''), }); }
  10. 10. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <span *ngIf="form.get('name')?.errors?.required"> </span> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); }
  11. 11. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <span *ngIf="form.get('name')?.errors?.required"> </span> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); }
  12. 12. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <span *ngIf="form.get('name')?.errors?.required"> </span> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); } function required(ctrl) { if (!ctrl.value) { return {required: true}; } return null; }
  13. 13. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> <span *ngIf="form.get('name')?.errors?.required"> </span> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', Validators.required ), }); } function required(ctrl) { if (!ctrl.value) { return {required: true}; } return null; }
  14. 14. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', ctrl => '' === ctrl.value ? {required: true} : null, ), }, form => isEmpty(form.value) ? {error: true} : null ); }
  15. 15. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', ctrl => '' === ctrl.value ? {required: true} : null, ), }, form => isEmpty(form.value) ? {error: true} : null ); }
  16. 16. @Component({ template: ` <form [formGroup]="form"> <input type="text" formControlName="name" /> </form>`}) class ExampleComponent { form = new FormGroup({ name: new FormControl( '', ctrl => '' === ctrl.value ? {required: true} : null, ), }, form => isEmpty(form.value) ? {error: true} : null ); }
  17. 17. // POST: /product/8022881030 // Response 400 { error_code: -10003, validations: { "name": [" "], "discountA.period": [" 0 "] } } <form [formGroup]="form"> <input type="text" formControlName="name" /> <input type="text" formControlName="price" /> <div formGroupName="discountA"> <input type="text" formControlName="period" /> </div> </form>
  18. 18. // POST: /product/8022881030 // Response 400 { error_code: -10003, validations: { "name": [" "], "discountA.period": [" 0 "] } } <form [formGroup]="form"> <input type="text" formControlName="name" /> <input type="text" formControlName="price" /> <div formGroupName="discountA"> <input type="text" formControlName="period" /> </div> </form>
  19. 19. // POST: /product/8022881030 // Response 400 { error_code: -10003, validations: { "name": [" "], "discountA.period": [" 0 "] } } <form [formGroup]="form"> <input type="text" formControlName="name" /> <input type="text" formControlName="price" /> <div formGroupName="discountA"> <input type="text" formControlName="period" /> </div> </form> <app-error> </app-error>
  20. 20. // POST: /product/8022881030 // Response 400 { error_code: -10003, validations: { "name": [" "], "discountA.period": [" 0 "] } } <form [formGroup]="form"> <input type="text" formControlName="name" /> <input type="text" formControlName="price" /> <div formGroupName="discountA"> <input type="text" formControlName="period" /> </div> </form> <app-error> </app-error>
  21. 21. // POST: /product/8022881030 // Response 400 { error_code: -10003, validations: { "name": [" "], "discountA.period": [" 0 "] } } <form [formGroup]="form"> <input type="text" formControlName="name" /> <input type="text" formControlName="price" /> <div formGroupName="discountA"> <input type="text" formControlName="period" /> </div> </form> <app-error> </app-error> <app-error> ...</app-error>
  22. 22. <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger"> <div *ngIf="name.errors.required"> . </div> <div *ngIf="name.errors.minlength"> 4 . </div> <div *ngIf="name.errors.forbiddenName"> . </div> </div> <input id="name" class="form-control" formControlName="name" />
  23. 23. <input id="name" class="form-control" formControlName="name" />
  24. 24. import { Component } from "@angular/core"; import { FormGroup, FormControl, Validators } from "@angular/forms"; @Component({ selector: "my-app", template: ` <form [formGroup]="form"> <input formControlName="name" /> </form> <pre><code>{{form.value | json}}</code></pre> ` }) export class AppComponent { form = new FormGroup({ name: new FormControl("", Validators.required) }); }
  25. 25. import { Component } from "@angular/core"; import { FormGroup, FormControl, Validators } from "@angular/forms"; @Component({ selector: "my-app", template: ` <form [formGroup]="form"> <input formControlName="name" /> </form> <pre><code>{{form.value | json}}</code></pre> ` }) export class AppComponent { form = new FormGroup({ name: new FormControl("", Validators.required) }); }
  26. 26. @Component({ selector: 'app-product-list', template: ` <div> click count: {{count}} <button type="button" (click)="onClick()">click</button> </div> ` }) export class ProductListComponent { count = 0; onClick() { this.count += 1; } }
  27. 27. @Component({ selector: 'app-product-list', template: ` <div> click count: {{count}} <button type="button" (click)="onClick()">click</button> </div> ` }) export class ProductListComponent { count = 0; onClick() { this.count += 1; } }
  28. 28. const origin = window.setTimeout; window.setTimeout = function(...args) { origin(...args); ngZone.runChangeDetection(); } // window.clearTimeout // ...
  29. 29. @NgModule({ imports: [ RouterModule.forRoot([ { path: '/product', loadChildren: () => import('./product/product.module') .then(mod => mod.ProductModule) }, { path: '/delivery', loadChildren: () => import('./delivery/delivery.module') .then(mod => mod.DeliveryModule) } ]) ] }) class EntryModule {}
  30. 30. @NgModule({ imports: [ RouterModule.forRoot([ { path: '/product', loadChildren: () => import('./product/product.module') .then(mod => mod.ProductModule) }, { path: '/delivery', loadChildren: () => import('./delivery/delivery.module') .then(mod => mod.DeliveryModule) } ], {preloadingStrategy: PreloadAllModules}) ] }) class EntryModule {}
  31. 31. @NgModule({ imports: [ RouterModule.forRoot([ { path: '/product', loadChildren: () => import('./product/product.module') .then(mod => mod.ProductModule) }, { path: '/delivery', loadChildren: () => import('./delivery/delivery.module') .then(mod => mod.DeliveryModule) } ], {preloadingStrategy: PreloadAllModules}) ] }) class EntryModule {}
  32. 32. @NgModule({ providers: [{ provide: HTTP_INTERCEPTORS, useClass: ApiPrefixInterceptorService, multi: true, }, { provide: HTTP_INTERCEPTORS, useClass: HttpErrorHandlerInterceptor, multi: true, }, { provide: HTTP_INTERCEPTORS, useClass: DistinctRequest, multi: true, }] }) export class AppModule {}
  33. 33. router.events .pipe( filter(e => e instanceof NavigationEnd) ) .subscribe(e => { console.log(e); // NavigationEnd ('/product') });
  34. 34. router.events .pipe( filter(e => e instanceof NavigationEnd), pairwise() ) .subscribe(e => { console.log(e); // NavigationEnd ('/product') });
  35. 35. router.events .pipe( filter(e => e instanceof NavigationEnd), pairwise() ) .subscribe(e => { console.log(e); // NavigationEnd ('/product') });
  36. 36. const subscription = activatedRoute.queryParams.pipe( switchMap(queryParams => httpClient.get('/api/product', queryParams) ).subscribe();
  37. 37. curl -F 'data=@path/to/local/a.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/b.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/c.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/d.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/e.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/f.js' UPLOAD_ADDRESS # ...
  38. 38. curl -F 'data=@path/to/local/a.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/b.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/c.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/d.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/e.js' UPLOAD_ADDRESS curl -F 'data=@path/to/local/f.js' UPLOAD_ADDRESS # ... import {uploadFilesToKakaoCDN} from '@commerce-ui/deploy-toolkit' (async () => { const cdnUrl = await uploadFilesToKakaoCDN({ path: 'dist/' }); })();

    Als Erste(r) kommentieren

    Loggen Sie sich ein, um Kommentare anzuzeigen.

  • ChunJongSong

    Nov. 30, 2019
  • yich

    Dec. 3, 2019
  • lovetodeath

    Jan. 3, 2020

johnny.m(김민형) / 카카오커머스 3년간 카카오커머스에서 Angular v2부터 사용하며 겪었던 경험들을 토대로 프레임웍의 특징과 장단점, 그리고 서비스를 안정적으로 운영하기 위한 Best Practice를 공유합니다.

Aufrufe

Aufrufe insgesamt

15.282

Auf Slideshare

0

Aus Einbettungen

0

Anzahl der Einbettungen

13.876

Befehle

Downloads

26

Geteilt

0

Kommentare

0

Likes

3

×