깜놀하는 해므찌로

NGX Anuglar Store 이론 및 활용 예시 본문

IT

NGX Anuglar Store 이론 및 활용 예시

agnusdei1207 2023. 7. 21. 19:23
반응형
SMALL

화살표는 http 요청을 나타냅니다.

1. 위 이미지는 단순히 ngx store 구현 시 http 요청의 횟수가 확연히 줄어든다는 것을 나타내기 위한 그림입니다.

 

 

ngx store 구조

2. 이 부분이 핵심입니다. 

3. store 는 데이터를 저장하는 공간이며 여러번 서버에 http 요청을 보내지 않고 페이지가 열리는 첫 순간에 미리 데이터를 받아올 때 활용됩니다.

 

 

서버 요청 예시

4. 우측 상단에 서버가 보입니다. 사용자가 많을 경우 store 는 더욱 빛을 발합니다. 예를 들어 한 명의 고객이 정보를 수정했는데, 해당 정보를 다른 모든 고객에게 보여줘야 하는 상황이 발생한다면? 고객들은 각각 페이지 새로고침 및 서버 요청이 필요합니다. 하지만, store 경우 수정이 발생했을 때 변화를 감지하여 서버에 새로운 데이터 목록을 요청할 수도 있으며, 자동으로 클라이언트들 또는 컴포넌트에 데이터 갱신을 할 수 있습니다. 이론 설명은 여기까지 하고 실전으로 넘어갑시다.

 

 

yarn add @ngrx/store

0. store 설치 cli ( 저는 yarn 을 사용합니다. npm 이나 다른 거 사용하시는 분들은 그거에 맞는 설치 cli로 변경해서 쓰세요)

 

스토어 폴더 및 파일 생성

1. 경로는 보통 app/store 에 생성합니다.

2. 주로 상태 관리라고 하기에 파일 이름에는 state 를 넣습니다. 저는 타입스크립트를 사용하므로 ts 파일로 생성

import { Injectable } from '@angular/core'; // Angular의 핵심 모듈 중 하나로, @Injectable 데코레이터를 사용하기 위해 필요합니다.
import { DTO } from '@DTO/interface'; // 사용자 정의 DTO
import { Action, NgxsOnInit, Selector, State, StateContext } from '@ngxs/store'; // Ngxs 라이브러리의 상태 관리를 위한 데코레이터와 인터페이스를 가져옵니다.
import { HttpService } from '../services/http.service'; // Http 통신을 위한 서비스를 가져옵니다.

export type ClientInformationStateModel = { // ClientState의 상태 모델을 정의합니다.
  client: DTO; // client 정보를 담을 DTO 타입의 객체입니다.
};

export class FetchClient {
  static readonly type = '[Client] Fetch Client'; // FetchClient 액션의 유형을 정의합니다.
}

@State({ // @State 데코레이터를 사용하여 상태 클래스를 정의합니다.
  name: 'client', // 상태의 이름을 설정합니다.
  defaults: { // 상태의 기본값을 설정합니다.
    client: null, // client 정보는 초기에는 null로 설정합니다.
  },
})
@Injectable() // 상태 클래스에 @Injectable 데코레이터를 사용하여 의존성 주입이 가능하도록 합니다.
export class ClientState implements NgxsOnInit { // NgxsOnInit 인터페이스를 구현합니다. 이는 상태 클래스의 초기화를 위한 라이프사이클 후크를 제공합니다.

  constructor(private readonly httpService: HttpService) {} // HttpService를 주입합니다.

  // NgxsOnInit 인터페이스의 메서드를 구현합니다.
  ngxsOnInit(ctx: StateContext<ClientInformationStateModel>): void {
    this.httpService
      .get<DTO>(`client-info/${process.env['NX_PROJECT_ID']}`) // HTTP GET 요청을 보냅니다.
      .subscribe({
        next: (client) => {
          // HTTP 요청의 결과값인 client 정보를 상태에 업데이트합니다.
          ctx.setState({ client });
        },
      });
  }

  // 수동으로 FetchClient 액션을 호출할 때 사용되는 메서드입니다.
  @Action(FetchClient)
  async fetchClient(ctx: StateContext<ClientInformationStateModel>) {
    this.httpService
      .get<DTO>(`client-info/${process.env['NX_PROJECT_ID']}`) // HTTP GET 요청을 보냅니다.
      .subscribe({
        next: (client) => {
          // HTTP 요청의 결과값인 client 정보를 상태에 업데이트합니다.
          ctx.setState({ client });
        },
      });
  }

  @Selector() // Selector 데코레이터를 사용하여 상태의 일부를 선택할 수 있는 선택자 함수를 정의합니다.
  static client(state: ClientInformationStateModel) {
    return state.client; // 상태 모델에서 client 정보를 선택하여 반환합니다.
    
// static 키워드를 사용하는 이유는 선택자 메서드를 정적(static)으로 선언하여 
// 외부에서 인스턴스화하지 않고도 호출할 수 있도록 하기 위함입니다. 
// 정적 메서드는 클래스 자체에 속하며 클래스의 인스턴스를 생성하지 않고도 호출할 수 있습니다. 
// 이렇게 하면 선택자 메서드를 간편하게 사용할 수 있고, 상태 클래스 외부에서도 접근할 수 있습니다.
// 따라서, static 키워드를 사용하여 선택자 메서드를 정적으로 선언한 이유는 
// 선택자를 상태 클래스 외부에서 사용하기 쉽고 편리하게 하기 위해서입니다.

	}
}

3. store 내부입니다. 상세한 설명은 주석을 참고해주세요.

4. 이제 작성한 스토어를 기반으로 다른 컴포넌트에서 호출하여 사용해봅시다.

 

 

 

port class test {
	@Select(ClientState.client) information!: Observable<DTO>;
 }

5. @Select(ClientState.client): ClientState 상태 클래스의 client 속성을 선택하는 선택자 함수입니다.

6. 스토어에서 작성한 대로 해당 정보를 리턴 받아 곧바로 할당합니다.

7. 주의할 점은 반드시 옵저버블 타입이어야 합니다.

 

 

import { Store } from '@ngxs/store';
import { FetchClient } from '../../store/client-information.state';

constructor(private store: Store) {} // store 의존성 주입

this.store.dispatch(new FetchClient()); // @Action 사용 예시 -> 수동 호출

8. @Action 사용 예시입니다. 

9. 액션의 경우 의존성 주입이 필요합니다.

10. 스토어에서 작성한 대로 리턴 받은 값을 바로 할당합니다.

11. 이렇게 구현할 경우 유지보수도 용이할 뿐더러 http 요청을 줄여 성능 향상에 도움이 됩니다.

 

 

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import {
  provideRouter,
  withEnabledBlockingInitialNavigation,
  RouteReuseStrategy,
} from '@angular/router';
import { appRoutes } from './app.routes';
import { BrowserModule } from '@angular/platform-browser';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';

// Animation
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

// HTTP
import { HttpClientModule } from '@angular/common/http';
import { NgxsModule } from '@ngxs/store'; // store
import { ClientState } from './store/client-information.state'; //store

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(appRoutes, withEnabledBlockingInitialNavigation()),
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    importProvidersFrom(
      BrowserModule,
      IonicModule.forRoot(),
      BrowserAnimationsModule,
      HttpClientModule,
      NgxsModule.forRoot([ClientState]) //store
    ),
  ],
};

12. 해당 프로젝트 app.config 에 store 를 추가하면 됩니다

반응형
LIST