-
[원티드 프리온보딩 인턴십-프론트엔드] 2주차 회고록회고록 2023. 9. 4. 00:26
2주차 회고록
2주차는 1주차와 동일한 방식으로 4일동안 주어진 과제를 각자 만들어 팀원들과 회의를 통해서 Best Practice를 선정하는 것이다.
2주차는 1주차와 다르게 약간의 라이브러리의 자유도와 난이도가 조금 더 올라갔다고 생각한다.팀프로젝트를 진행하면서
2주차는 원티드 인턴십에 대해서 약간의 실망감이 드는 주간이였다.
원티드 인턴십은 프로젝트를 구현할 수 있는 지식을 갖고 있는 사람들과 함께 4주간 팀프로젝트를 진행한다고 소개하고 있다.
그리고 합격하면 약 5~6명 정도로 팀이 구성되고 이 팀원들과 프로젝트를 진행하게 된다.근대 이렇게 팀원들 만들고 난 후에 불참을 하는 사람들도 존재하고, 회사에 합격해서 빠지게 되는 사람들도 존재하게 된다.
그래서 구성된 팀보다 적은 인원으로 진행되기도 한다. 하지만 이는 크게 문제가 되지 않는다.문제가 되는 것은 이런 저런 핑계를 대면서 팀프로젝트에 참여를 하지 않거나, 실력이 부족해 주어진 문제를 구현하지도 못하는 팀원들도 있다.
나는 팀원들을 배려해 원하는 기술 스택까지 양보하면서 처음 사용해보는 라이브러리도 있어서 자는 시간까지 줄여가면서 프로젝트를 만들어 회의에 참여를 하였지만, 아예 시작도 못한 팀원, 기능이 동작하지도 않는 팀원, 시간이 없어서 못했다는 팀원등 제대로 진행한 사람이 없었다.
best practice를 뽑기 위해서는 서로의 코드를 바탕으로 회의가 진행되어야 하는데, 회의가 진행될 정도의 코드도 구현되어 있지 않아서 어쩔수없이 내 코드를 바탕으로 리팩토링하는 시간을 가졌다.
하지만 실력이 부족해서 코드를 못짜는 건 이해가 가지만 기분이 언짢은 것은 리팩토링 기간에는 이런 저런 핑계를 대면서 참여하지 않다가 마지막날에 문서 작업에만 참여하는 사람때문에 2주차는 좋지 않는 시간이였다.
배운점
2주차때 라이브러리의 자유가 주어졌기에 팀원들과 회의를 통해서 전역 상태 관리 라이브러리로 리덕스 툴킷을 정하게 되었으며, 해당 기술에 대해서 여러 지식을 배우게 되었다.
리덕스 툴킷
리덕스에 대해서는 어느정도 알고 있었고, 주로(??) 리덕스 사가를 바탕으로 프로젝트를 진행했다.
그 이유는 사가에 제공되는 이팩트로 인해서 비동기 작업이 편했으며, 툴킷의 경우에는 스타트업 혹은 소규모 프로젝트에는 사용이 용이하지만 기업에서는 아직까지 사용하는 단계는 아니라고 알고 있었기에 툴킷을 제대로 공부해본 적이 없었다.
하지만 이번 기회를 바탕으로 공부를 해보았고 그중에서도 사가 이펙트와 같은 효과를 내는 미들웨어에 대해서 작성해보고자 한다.
https://redux-toolkit.js.org/api/createListenerMiddleware%5D
이전까지 툴킷에서 사가 이펙트 라이브러리를 다운받아서 사용한다고 알고 있었는데, 이렇게 사용할 경우에는 호환성이 그닥 좋지 않다고 알고 있었다.
하지만 리덕스 툴킷에서 최근에 사가 이펙트와 같은 효과를 제공하는 createListenerMiddleware라는 미들웨어를 제공한다는 소식을 제로초님의 인프런 답변을 통해서 접하게 되었다.
As of v0.5.0, the middleware does include several async workflow primitives that are sufficient to write equivalents to many Redux-Saga effects operators like takeLatest, takeLeading, and debounce.
출처: Redux-toolkit툴킷에 미들웨어를 연결하는 방법은 문서에 자세히 나와있으니 해당 과정은 생략하고, 미들웨어에 대해서 작성해보고자 한다.
import { configureStore, createListenerMiddleware } from '@reduxjs/toolkit' import todosReducer, { todoAdded, todoToggled, todoDeleted, } from '../features/todos/todosSlice' const listenerMiddleware = createListenerMiddleware() // async thunk 로직도 작성할 수 있으며, 일반적인 동기 로직도 작성할 수 있다. listenerMiddleware.startListening({ actionCreator: todoAdded, effect: async (action, listenerApi) => { // todoAdded 액션을 감지해서 해당 액션이 동작하면 effect 내부의 코드가 동작한다. }, }) const store = configureStore({ reducer: { todos: todosReducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware().prepend(listenerMiddleware.middleware), })
createListenerMiddleware()
를 통해 미들웨어를 생성해주자. 그리고 해당 미들웨어에 포함되어져 있는 리스너 중에서 우리가 특정한 액션을 실행할 때를 감지하는 startListening를 호출해주자.이때 actionCreator에는 우리가 감지할 액션을 작성하는데 무조건 한개 이상의 액션을 작성해야만 한다.
이후에 해당 액션이 실행되면 effect 내부의 코드가 실행되게 된다.
그럼 effect 내부에서
listenerApi
와action
을 통해서 우리가 의도한 코드를 작성하면 된다.여기서
listenerApi
는 여러 비동기 로직과dispatch
,state
등을 제공하며 사가 이팩트를 바탕으로 생성된 워크플로우도 제공된다.test('debounce / takeLatest', async () => { // Repeated calls cancel previous ones, no work performed // until the specified delay elapses without another call // NOTE: This is also basically identical to `takeLatest`. // Ref: https://redux-saga.js.org/docs/api#debouncems-pattern-saga-args // Ref: https://redux-saga.js.org/docs/api#takelatestpattern-saga-args listenerMiddleware.startListening({ actionCreator: increment, effect: async (action, listenerApi) => { // Cancel any in-progress instances of this listener listenerApi.cancelActiveListeners() // Delay before starting actual work await listenerApi.delay(15) // do work here }, }) } test('takeLeading', async () => { // Starts listener on first action, ignores others until task completes // Ref: https://redux-saga.js.org/docs/api#takeleadingpattern-saga-args listenerMiddleware.startListening({ actionCreator: increment, effect: async (action, listenerApi) => { listenerCalls++ // Stop listening for this action listenerApi.unsubscribe() // Pretend we're doing expensive work // Re-enable the listener listenerApi.subscribe() }, }) }) test('canceled', async () => { // canceled allows checking if the current task was canceled // Ref: https://redux-saga.js.org/docs/api#cancelled let canceledAndCaught = false let canceledCheck = false // Example of canceling prior instances conditionally and checking cancelation listenerMiddleware.startListening({ matcher: isAnyOf(increment, decrement, incrementByAmount), effect: async (action, listenerApi) => { if (increment.match(action)) { // Have this branch wait around to be canceled by the other try { await listenerApi.delay(10) } catch (err) { // Can check cancelation based on the exception and its reason if (err instanceof TaskAbortError) { canceledAndCaught = true } } } else if (incrementByAmount.match(action)) { // do a non-cancelation-aware wait await delay(15) if (listenerApi.signal.aborted) { canceledCheck = true } } else if (decrement.match(action)) { listenerApi.cancelActiveListeners() } }, }) })
사가 이펙트를 한번이라도 사용해본 사람이라면 위의 코드를 보자마자 직관적으로 너무 잘 설명하고 있다는 것을 느낄것이다.
만약 위의 코드를 보면서 takeLatest가 뭐지? 사가 이펙트는 뭐야 라고 생각이 든다면 몰라도 괜찮다.
그럴줄 알고 리덕스 툴킷에서 주석으로 해당 코드가 어떤 목적으로 동작하는지를 작성해 놓았기 때문에 이를 통해서 아 해당 코드가 이렇게 동작하는구나 알기만 한다면 코드를 사용하는데 지장이 없다.
그리고 위의 코드가 이해가 된다면 주석으로 링크된 리덕스 사가 문서를 읽어보며 해당 코드와 사가 이펙트를 비교해가면서 아 사가에서 해당 이팩트가 툴킷에서는 이런 방식으로 작성되었구나 라는 생각을 하게 될 것이다.
'회고록' 카테고리의 다른 글
[원티드 프리온보딩 인턴십-프론트엔드] 4주차 회고록 (0) 2023.09.16 [원티드 프리온보딩 인턴십-프론트엔드] 3주차 회고록 (0) 2023.09.09 [원티드 프리온보딩 인턴십-프론트엔드] 1주차 회고록 (0) 2023.08.26 [원티드 프리온보딩 인턴십-프론트엔드] 온보딩을 시작하기 전에 (0) 2023.08.26 우아한 테크 코스 5기 - 프리코스를 마치며 (0) 2022.11.23