Resolve 사용하기

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

이 게시물의 소스코드는 기본사이트 만들기 / Guard로 비로그인 접근제한 만들기에서 이어집니다.

angular-site.git 을 clone 한 적이 있는 경우: 터미널에서 해당 폴더로 이동 후 아래 명령어들을 붙여넣기합니다. 폴더 내 모든 코드가 이 게시물의 코드로 교체됩니다. 이를 원치 않으시면 이 방법을 선택하지 마세요.

git reset --hard
git pull
git reset --hard 4944e19
git reset --soft 73fd793
npm install
atom .

angular-site.git 을 clone 한 적이 없는 경우: 터미널에서 코드를 다운 받을 폴더로 이동한 후 아래 명령어들을 붙여넣기하여 angular-site.git 을 clone 합니다.

git clone https://github.com/a-mean-blogger/angular-site.git
cd angular-site
git reset --hard 4944e19
git reset --soft 73fd793
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/angular-site/tree/4944e19b08d26ac5db18dd4a515322e0e500284b


이전강의까지 만든 사이트에서 Users 메뉴를 클릭하면 아래와 같은 화면이 잠시 보였다가 user 리스트가 나타나게 됩니다. 이번 강의에서는 이 현상이 일어나는 이유와 해결법에 대해 알아보도록 하겠습니다.


현재 Users 메뉴를 눌렀을때 일어나는 일은 다음과 같습니다.

  1. AppRoutingModule에서 AuthGuard를 통해 해당 페이지로 접근이 가능한지 불가능한지 판단함
  2. 접근이 가능하면 UserIndexComponent로 route이 됨. 이때 사용자는 위 화면을 보게 됨
  3. UserIndexComponent에서 UserService의 Index함수로 user 목록을 요청
  4. user 목록을 받으면 페이지에 user 목록이가 업데이트됨

즉, 2번에서 위 화면이 보이고 4번에서 최종화면으로 업데이트가 되는 것입니다.

이 문제는 Resolve를 사용해서 해결할 수 있습니다.

Resolve

Angular2에서 resolve는 route 이동전에 해당 component에서 필요한 data를 미리 확보해서 해당 component는 그 data가 무조건 있다는 가정이 가능하게 해 줍니다. Resolve 클라스는 Resolve 인터페이스를 구현(implement), resolve라는 함수에 대상이 되는 data를 받아 리턴하는 코드를 넣게 됩니다. Routing module의 resolve 항목에 넣어서 해당 route의 component로 이동 전에 데이터를 미리 확보합니다.

폴더 구조


주황색은 변경된 파일, 녹색은 새로 생성된 파일, 회색은 변화가 없는 파일입니다.

Resolve는 ng 명령어로 만들 수 없습니다. users.resolve.ts를 직접 만들어 줍시다.

코드

users.resolve.ts를 살펴봅시다.

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { UserService } from './user.service';
import { User } from './user';

@Injectable()
export class UsersResolve implements Resolve<User[]> {

  constructor(
    private userService: UserService,
  ) {}

  resolve(route: ActivatedRouteSnapshot) {
    return this.userService.index().catch(response => null);
  }
}

Resolve 인터페이스를 구현(implement)하여 UsersResolve 클라스를 만들었고 route을 파라메터로 갖는 resolve함수를 만들었습니다.

UsersResolve는 user 목록을 확보하는 resolve로 UserService의 index함수를 통해 user list를 받게 됩니다. 위 코드에서는 만약 resolve에서 에러가 있어도 그냥 무시(.catch(response => null))하게 했지만 필요하다면 다른 에러페이지로 보내거나 등 할 일을 정해줘도 됩니다.

어렵지 않죠?

// src/app/app-routing.module.ts

//...생략

import { AuthGuard } from './auth.guard';
import { UsersResolve } from './users.resolve';

//...생략

const routes: Routes = [
  //...생략
  { path: 'users', canActivate: [AuthGuard],
    children: [
      { path: '',
        component: UserIndexComponent,
        resolve: { //1
          users: UsersResolve,
        }
      },
    ]
  },
  { path: '**', component: Error404Component },
];

//...생략

1. resolve 항목을 만들고 그 안에 'users'라는 이름과 UsersResolve를 넣었습니다. 해당 route에 접근시 먼저 resolve안의 항목들이 모두 준비되고 나서 해당 component(위 예제에서는 UserIndexComponent)로 이동할 수 있으며, 해당 component에서는 resolve된 data를 바로 사용할 수 있습니다.

// src/app/user-index/user-index.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { User } from '../user';

@Component({
  selector: 'app-user-index',
  templateUrl: './user-index.component.html',
  styleUrls: ['./user-index.component.css']
})
export class UserIndexComponent implements OnInit {
  users: User[];

  constructor(
    private route: ActivatedRoute,
  ) {
    this.users = this.route.snapshot.data['users']; //1
  }

  ngOnInit() {
  }

}

1. Resolve에 의해 준비된 데이터는 route.snapshot.data를 통해 접근할 수 있습니다.

// src/app/app.module.ts

//...생략
import { AuthGuard } from './auth.guard';
import { UsersResolve } from './users.resolve'; //1

@NgModule({
  //...생략
  providers: [
    //...생략
    UserService,
    UsersResolve, //1
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

 Resolve는 @Injectable() 이므로 providers에 넣습니다. 

실행 결과

Angular-CLI 명령어 사용해서 서버를 실행합시다. 

ng serve --open

로그인 후 Users 메뉴를 클릭하면 회원 목록이 바로 나옵니다.


마치며..

이제 Users를 누르면 일어나는 일은 다음과 같습니다.

  1. AppRoutingModule에서 AuthGuard를 통해 해당 페이지로 접근이 가능한지 불가능한지 판단함
  2. Resolve에 의해 UserService의 Index함수로 user 목록이 준비됨
  3. UserIndexComponent로 route이 되고 준비된 user 목록으로 page를 생성함.

여기서 또 한가지 의문을 가질 수 있는 부분! 페이지를 이동하기 전에 API call을 하는 데, 만약 API call이 시간이 오래걸리면? 뭔가 로딩 화면을 보여줘야 하겠죠. 다음 강의에서 알아봅시다.

댓글

댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP