[Coddit] createAsyncThunk를 이용한 비동기 데이터 처리

헤이즐·2023년 2월 26일
0

Coddit 프로젝트

목록 보기
1/2
post-thumbnail

🤔왜 비동기 데이터 처리여야 했나?

Reddit 클론 프로젝트를 구현하는 데에 있어서 중요했던 것 중 하나는 동기식 및 비동기식 데이터 처리에 익숙해지는 것이었다.

동기적 데이터 처리는 직관적이고 간단하며 프로그램이 선형 흐름을 따르기 때문에 실행 경로를 추적하고 발생할 수 있는 모든 오류를 정확하게 파악하는 것이 쉽다. 또한, 데이터 처리량이 상대적으로 적고 속도가 크게 중요하지 않은 소규모 응용 프로그램에 적합하다.

그러나 동기식 데이터 처리에는 여러 가지 단점도 있는데, 가장 큰 단점 중 하나는 대량의 데이터를 처리할 때 느리고 비효율적일 수 있다는 것이다. 프로그램이 각 작업이 완료될 때까지 기다리기 때문에, 일련의 작업을 완료하는 데 시간이 오래 걸릴 수 있다. 이로 인해 사용자 경험에 부정적인 영향을 미칠 수 있기 때문에, 나는 더 나은 사용자 경험을 위해 이해하기 불편하고 어려워 보였던 비동기적 데이터 처리라는 불구덩이에 뛰어들기로 했다(...🔥😇)

그리하여 내가 시도한 것은 Redux ToolkitcreateAsyncThunk 함수를 사용하여 비동기 데이터를 처리하는 방식이었다.createAsyncThunk를 사용한 예시 중 하나는 사용자가 본 게시물에 대한 데이터를 가져오는 것이다.

예시 코드 1

해당 함수는 액션 유형을 나타내는 문자열과 데이터를 반환하는 비동기 함수 두 가지 인수를 취한다.

const getCurrentPost = createAsyncThunk(
  "currentPost/getCurrentPost",
  async (postid) => {
    const resp = await axios.get("/api/currpost", {
      params: { postid: postid },
    });
    return resp.data;
  }
);

const currentPost = createSlice({
  name: "currentPost",
  initialState: {
    list: [],
  },
  extraReducers: (builder) => {
    builder.addCase(getCurrentPost.pending, (state, action) => {
    });
    builder.addCase(getCurrentPost.fulfilled, (state, action) => {
      state.list = action.payload;
    });
    builder.addCase(getCurrentPost.rejected, (state, action) => {
    });
  },
});

getCurrentPost 함수는 createAsyncThunk 를 사용하여 생성되며, postid를 매개변수로 사용하는 dispatch 메서드를 가지고 있다. 함수는 axios 라이브러리를 사용하여 postid 매개변수에 해당하는 서버 측 라우트에 대한 비동기 GET 요청을 수행합니다. 응답이 수신되면 함수는 데이터를 반환한다.

그 다음, getCurrentPost 함수를 사용하여 currentPost라는 상태 슬라이스를 만든다. extraReducers 속성을 사용하여 대기 중(pending), 완료(fulfilled) 및 거부(rejected)와 같은 비동기 호출의 다양한 상태를 처리했다. 대기 중(pending) 상태가 트리거되면 상태에 아무 작업도 수행하지 않고, 완료(fulfilled) 상태가 트리거되면 액션 페이로드(action.payload)인 비동기 호출의 응답 데이터를 상태의 list 속성으로 설정했다.

예시 코드 2

개별 게시물 데이터를 가져오는 것 외에도, 사이드메뉴에서 토픽 및 서브토픽 데이터를 검색하는 기능도 구현해야 했는데, 게시물과 마찬가지로 extraReducers 속성을 사용하여 비동기 호출의 다른 상태를 처리했다. 아래 코드가 해당 구현 코드다.

const asyncTopic = createAsyncThunk("communitySlice/asyncTopic", async () => {
  const resp = await axios.get("/api/topic");
  return resp.data;
});

const topicSlice = createSlice({
  name: "topicSlice",
  initialState: {
    list: [],
  },
  extraReducers: (builder) => {
    builder.addCase(asyncTopic.pending, (state, action) => {
      // console.log("pending");
    });
    builder.addCase(asyncTopic.fulfilled, (state, action) => {
      state.list = action.payload;
      // console.log("fulfilled");
    });
    builder.addCase(asyncTopic.rejected, (state, action) => {
      // console.log("rejected");
    });
  },
});

const asyncSub = createAsyncThunk("subSlice/asyncSub", async () => {
  const resp = await axios.get("/api/sub");
  return resp.data;
});

const subSlice = createSlice({
  name: "subSlice",
  initialState: {
    list: [],
  },
  extraReducers: (builder) => {
    builder.addCase(asyncSub.pending, (state, action) => {
      // console.log("pending");
    });
    builder.addCase(asyncSub.fulfilled, (state, action) => {
      state.list = action.payload;
      // console.log("fulfilled");
    });
    builder.addCase(asyncSub.rejected, (state, action) => {
      // console.log("rejected");
    });
  },
});

Redux ToolkitcreateAsyncThunk 함수를 사용하면 비동기 데이터 처리 과정을 단순화할 수 있다. 여러 상태에 대한 복수의 리듀서를 작성하지 않고도 비동기 작업을 생성할 수 있기 때문이다.

해당 기능을 구현하느라 씨름을 해야했지만, 비동기 데이터를 처리하는 좋은 방법에 대해 배우고 익힐 수 있었다는 점에서 만족스러운 경험이었다. 또한 비동기와 동기, 두가지 데이터 처리 방식에 대해 알아보고, 또 장단점과 차이점, 어느 곳에 적합한지 연구하며 개발자로서 더 나은 사용자 경험에 대해 생각해볼 수 있는 시간이었다.

profile
개발자를 꿈꾸며 하루하루 고군분투 중!

0개의 댓글