본문 바로가기
카테고리 없음

5단원 정리[2] Do It 리액트 모던 웹 개발 with 타입스크립트 (리액트) 공부

by ㅋ ㅅㅋ 2024. 12. 16.

리듀서 활용하기

리듀서 합치기

combineReducers() 함수는 여러 리듀서를 통합하여 새로운 리듀서를 만들어 줍니다. redux 패키지는 다음처럼 combineReducers() 함수를 제공합니다.

 

combineReducers 함수 임포트
import {combineReducers} from 'redux'

 

combineReducers() 함수는 다음처럼 ReducerMapObject 타입 객체를 입력 매개변수로 받는 함수 입ㅂ니다. 여기서 타입 변수 S는 상태를 의미하며 이절에서는 AppState가 이에 해당합니다.

combineReducers() 함수 선언문
export function combineReducers<S>(reducers: ReducerMapObject<S, any>): Reducer<CombinedState<S>>

 

combineReducers() 함수는 매개변수 reducers는 ReducersMapObject 타입 객체입니다. 이 객체의 선언문을 보면 상태 타입의 키에 설정되는 값은 Reducer<State[Key], Action>타입의 함수여야 한다는 것을 알 수있습니다.

ReducersMapObject 타입 선언문
export type ReducersMapObject<State = any, A extends Action = Action> = {
   [Key in keyof State]: Reducer<State[Key], A>
}

앱 상태를 구성하는 멤버 상태 구현하기

combineReducers() 함수를 실습해 보겠습니다. 

코드는 앱 수준 상태 AppState를 다시 clock, counter, remoteUser, cards라는 이름의 독립적으로 동작하는 멤버 상태로 구성한 것입니다.

코드에서는 AppState는 4개의 멤버 상태로 구성했으므로 이를 각각 처리하는 4개의 리듀서가 필요합니다. 그리고 앞서 만든 clock, count와 같은 디렉터리 안에는 컴파일 오류만 없는 최소한으로 구현한 리듀서가 이미 있습니다.

 

이제 src/store 디렉터리의 rootReducer.ts 파일을 다음처럼 구현합니다.

코드는 combineReducers()함수로 '상태이름: 해당_리듀서' 형태의 조합을 모두 결합하여 새로운 루트 리듀서를 만듭니다. 앞서 combineReducers()의 매개변수 reducers는 ReducersMapObject타입이 라고 했습니다. 이타입 선언문에서 [Key in keyof State]: Reducer<State[Key], A> 부분을 고려해 보면, clock, count 등의 멤버 상태는 모두 AppState의 키이므로, [Key in keyofState] 조건을 만족합니다. 또한 각 키 설정값의 타입은 Reducer<State[Key], A>, 즉 리듀서 함수여야 하므로 Clock.reducer를 설정해야 합니다.

 

 

 combineReducer() 함수는 리덕스 관련 코드를 어떤 기계적인 패턴으로 구현할 수 있게 해줍니다. 이제 clock부터 차례대로 AppState의 멤버 상태에 대응하느 ㄴ리덕스 기능을 구현해 가면서 이 기계적인 패턴의 코드를 어떻게 작성하는지 알아보겠습니다.

시계 만들기

먼저 AppState의 clock 멤버 상태에 대한 타입을 선언하겠습니다. 코드는 AppState.clock의 타입을 any가 아닌 Date로 변경합니다. 그리고 Action<'@clock/setClock'> 타입과 payload라는 속성이 있는 '이름 없는 타입 '의 교집합으로 액션을 선언합니다. 그런데 @clock/이나 payload라는 이름이 좀 생소합니다. 이 이름은 리덕스 커뮤니티에서 관행으로 사용하는 타입과 변수 이름입니다. 왜 이런 이름을 사용하는지 잠시후 알아보겠습니다.

이제 SetClockAction 타입의 액션 객체를 생성하는 setClock이란 '액션 생성기'를 만들어 보겠습니다.

참고로 코드에서 setClock 은 매개변수 payload의 타입을 설정할 수 있게 해주므로

{type: '@clock/setClock', payload} 형태의 코드에서 발생할 수 있는 타입 오류를 미연에 방지해주는 효과가 있습니다.

앞서 types.ts 파일의 State타입은 실제로는 Date이므로 다음 코드에서 Date 클래스의 인스턴스를 초깃값으로 설정하는 것은 당연합니다. 또한 action.payload의 타입인 State 또한 Date이므로 action의 payload값을 그대로 반환하는 것도 타당합니다.

 

이 코드 AppState의 clock속성값을 화면에 출력하므로 useSelector의 타입 변수들을 <AppState, C.State>로 설정합니다.