Redux-saga 소스 리펙토링

IT쿠키·2023년 3월 19일
0

[뉴비쿠키 React]

목록 보기
9/12
post-thumbnail

redux-saga 소스 리펙토링

특정 데이터를 api를 call 하는 제네레이터를 사용하여 데이터를 불러오는 작업을 진행하는 데 요청사항으로 특정 url들을 base64로 인코딩을 해줘야 한다.
하지만 여기서 해당 이미지들의 url들이 우리 서버에 위치하지 않기 때문에 api를 활용하여 수정하는 작업을 진행했다.

기존 product data call 코드

//** 액션 타입을 지정**
export const FETCH_PRODUCTS = "blog/FETCH_PRODUCTS";
export const FETCH_PRODUCTS_SUCESS = "blog/FETCH_PRODUCTS_SUCESS";
export const FETCH_PRODUCTS_FAIL = "blog/FETCH_PRODUCTS_FAIL";

// **액션 생성 후 반환값 지정(타입스크립트)**
export const fetchProducts = createAsyncAction(
  FETCH_PRODUCTS,
  FETCH_PRODUCTS_SUCESS,
  FETCH_PRODUCTS_FAIL
)<ProductRequest, { products: ProductsResponse }, APIError>(); //순서대로 "입력받는타입", "반환되는타입", "에러타입"

// 제네레이터 생성 
function* fetchBlogSaga(action: ReturnType<typeof fetchProducts.request>) {
  try {
    const { data }: AxiosResponse<ProductsResponse> = yield callWrapperSaga(
      blogService.getProducts,
      action.payload
    );
    데이터를 action.payload로 받아온 후에 비구조화 할당 후 데이터 할당
    yield put(fetchProducts.success({ products: data }));
  } catch ({ response }) {
    const { data, status } = response as AxiosResponse;
    yield put(fetchProducts.failure({ data, status }));
  }
}

image url 변경 코드

// PRODUCTS
export const FETCH_PRODUCTS = "blog/FETCH_PRODUCTS";
export const FETCH_PRODUCTS_SUCESS = "blog/FETCH_PRODUCTS_SUCESS";
export const FETCH_PRODUCTS_FAIL = "blog/FETCH_PRODUCTS_FAIL";

export const fetchProducts = createAsyncAction(
  FETCH_PRODUCTS,
  FETCH_PRODUCTS_SUCESS,
  FETCH_PRODUCTS_FAIL
)<ProductRequest, { products: ProductsResponse }, APIError>(); //순서대로 "입력받는타입", "반환되는타입", "에러타입"

function* fetchBlogSaga(action: ReturnType<typeof fetchProducts.request>) {
  try {
    const { data }: AxiosResponse<ProductsResponse> = yield callWrapperSaga(
      blogService.getProducts,
      action.payload
    );
    
    const dataBase64: AxiosResponse<ProductsResponse> = yield callWrapperSaga(
      blogService02.getTransImageUrlLists,
      data.list.map((el) => el.itemImage)
    );
    
    data.list.map((el, index: number) => {
      return (el.itemImage = `data:image/*;base64,${dataBase64.data.list[index]}`);
    });
    

    yield put(fetchProducts.success({ products: data }));
    
  } catch ({ response }) {
    const { data, status } = response as AxiosResponse;
    yield put(fetchProducts.failure({ data, status }));
  }
}
  1. 첫 번째 요소는 put dispatch 를 하기 전에 해당 data의 특정 image url들을 api를 전송함으로서 재가공 해줘야함
  2. data를 다시 yield call 하여 데이터를 넘겨줘야함 여기서 call 부분은 커스텀하여 callWrapperSaga로 만들어줌
  3. 그 이후 data를 map 메서드를 활용하여 dataBase64에 index를 할당 해주면서 base64로 인코딩 해준 데이터를 새로 만들어 준다.
  4. yield put 디스패치를 활용하여 data를 할당 해준다.

itemSegInfo data 소스 최적화

// itemSegInfo
export const FETCH_ITEMSEG = "blogV2/FFETCH_ITEMSEG";
export const FETCH_ITEMSEG_SUCESS = "blogV2/FETCH_ITEMSEG_SUCESS";
export const FETCH_ITEMSEG_FAIL = "blogV2/FETCH_ITEMSEG_FAIL";

export const fetchItemSegInfo = createAsyncAction(
  FETCH_ITEMSEG,
  FETCH_ITEMSEG_SUCESS,
  FETCH_ITEMSEG_FAIL
)<ProductRequest, ItemSegInfoResponse, APIError>();

// segBest
export const FETCH_SEGBEST = "blogV2/FFETCH_SEGBEST";
export const FETCH_SEGBEST_SUCESS = "blogV2/FETCH_SEGBEST_SUCESS";
export const FETCH_SEGBEST_FAIL = "blogV2/FETCH_SEGBEST_FAIL";

export const fetchSegBest = createAsyncAction(
  FETCH_SEGBEST,
  FETCH_SEGBEST_SUCESS,
  FETCH_SEGBEST_FAIL
)<SegBestItemsRequest, SegBestResponse, APIError>();

// similarSeg
export const FETCH_SIMILAR = "blogV2/FFETCH_SIMILAR";
export const FETCH_SIMILAR_SUCESS = "blogV2/FETCH_SIMILAR_SUCESS";
export const FETCH_SIMILAR_FAIL = "blogV2/FETCH_SIMILAR_FAIL";

export const fetchSimilarSeg = createAsyncAction(
  FETCH_SIMILAR,
  FETCH_SIMILAR_SUCESS,
  FETCH_SIMILAR_FAIL
)<SimilarSegItemsRequest, SimilarSegResponse, APIError>();

// associated
export const FETCH_ASSOCIATE = "blogV2/FFETCH_ASSOCIATE";
export const FETCH_ASSOCIATE_SUCESS = "blogV2/FETCH_ASSOCIATE_SUCESS";
export const FETCH_ASSOCIATE_FAIL = "blogV2/FETCH_ASSOCIATE_FAIL";

export const fetchAssociatedSeg = createAsyncAction(
  FETCH_ASSOCIATE,
  FETCH_ASSOCIATE_SUCESS,
  FETCH_ASSOCIATE_FAIL
)<SimilarSegItemsRequest, any, APIError>();

// seg item info의 요청값을 받은다음 segBest, similarSeg, associated 모두 요청
export const FETCH_SEGS = "blogV2/FFETCH_SEGS";
export const FETCH_SEGS_SUCESS = "blogV2/FETCH_SEGS_SUCESS";
export const FETCH_SEGS_FAIL = "blogV2/FETCH_SEGS_FAIL";

export const fetchSegs = createAsyncAction(
  FETCH_SEGS,
  FETCH_SEGS_SUCESS,
  FETCH_SEGS_FAIL
)<any, any, APIError>();

function* fetchSegsSaga(
  action: ReturnType<typeof fetchItemSegInfo.request>
): Generator<
  | AllEffect<any>
  | PutEffect<PayloadAction<"blogV2/FETCH_ITEMSEG_FAIL", APIError>>
  | PutEffect<PayloadAction<"blogV2/FETCH_SEGBEST_FAIL", APIError>>,
  void,
  [
    any,
    any,
    AxiosResponse<AssociatedSegResponse>,
    AxiosResponse<SegBestResponse>
  ]
> {
  try {
    const [itemSegInfoRes, similarSegRes, associatedSegRes] = yield all([
      callWrapperSaga(blogService02.getItemSegInfo, action.payload),
      callWrapperSaga(blogService02.getSimilarSegItems, action.payload),
      callWrapperSaga(blogService02.getAssociatedItems, action.payload),
    ]);
    const firstSeg = itemSegInfoRes.data.data.segData.filter(
      (el: { segRank: number }) => el.segRank === 1
    )[0];
    const [segBestRes] = yield all([
      callWrapperSaga(blogService02.getSegBestItems, {
        cuid: action.payload.cuid,
        date: action.payload.date,
        segId: firstSeg.segId,
      }),
    ]);
    const [iBase64, siBase64, assBase64] = yield all([
      callWrapperSaga(
        blogService02.getTransImageUrl,
        itemSegInfoRes.data.data.imageUrl
      ),
      callWrapperSaga(
        blogService02.getTransImageUrlLists,
        similarSegRes.data.list.map((el: { imageUrl: string }) => el.imageUrl)
      ),
      callWrapperSaga(
        blogService02.getTransImageUrlLists,
        associatedSegRes.data.list.map(
          (el: { imageUrl: string }) => el.imageUrl
        )
      ),
    ]);

    itemSegInfoRes.data.data.imageUrl = `data:image/*;base64,${iBase64.data.data}`;
    similarSegRes.data.list.map((el: { imageUrl: string }, index: number) => {
      return (el.imageUrl = `data:image/*;base64,${siBase64.data.list[index]}`);
    });
    associatedSegRes.data.list.map(
      (el: { imageUrl: string }, index: number) => {
        return (el.imageUrl = `data:image/*;base64,${assBase64.data.list[index]}`);
      }
    );

    yield all([
      itemSegInfoRes && put(fetchItemSegInfo.success(itemSegInfoRes.data)),
      put(fetchSimilarSeg.success(similarSegRes.data)),
      put(fetchAssociatedSeg.success(associatedSegRes.data)),
      put(fetchSegBest.success(segBestRes.data)),
    ]);
    // 대표세그를 받는다
    // yield put(fetchSegBest.success(segBestRes.data));
  } catch (error) {
    const { data, status } = error as AxiosResponse;
    yield put(fetchItemSegInfo.failure({ data, status }));
    yield put(fetchSegBest.failure({ data, status }));
  }
}
  1. product data를 했을 때 처럼 데이터를 동기 작업을 진행함
    문제점 발생
  2. 데이터를 동기적으로 불러오니 순차적으로 데이터를 불러옴 이 문제로 인해 데이터를 전부 불러오는 데 시간이 너무나 딜레이가됨!
  3. 이 부분을 해결하기 위해 기존 동기적으로 하던 작업비동기적으로 변경을 함 그 부분을 해결 하기 위해 yiled all 을 활용하여 작업 진행
  4. 제네레이터 생성 함수의 타입을 제대로 지정을 해줘야함 -> 기존 작업시 운영 반영 문제로 제대로 정하지 않은 문제가 있음 이후 차후 운영 배포 전에 반영해야함
profile
IT 삶을 사는 쿠키

0개의 댓글