액션
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
Redux FAQ: 액션
type은 왜 문자열이어야 하나요? 액션 타입을 상수로 정의해야 하는 이유는 무엇인가요?
상태와 마찬가지로 직렬화 가능한 액션은 시간 여행 디버깅, 액션 기록 및 재실행과 같은 Redux의 핵심 기능을 가능하게 합니다. type 값으로 Symbol을 사용하거나 액션 자체에 instanceof 검사를 적용하면 이러한 기능이 동작하지 않습니다. 문자열은 직렬화가 가능하고 자체 설명적이므로 더 나은 선택입니다. 단, 미들웨어에서 사용하기 위한 액션의 경우 Symbol, Promise 또는 기타 비직렬화 가능한 값을 사용해도 괜찮다는 점에 유의하세요. 액션은 실제로 스토어에 도달하여 리듀서로 전달될 때만 직렬화 가능하면 됩니다.
성능상의 이유로 직렬화 가능한 액션을 강제할 수 없기 때문에 Redux는 모든 액션이 일반 객체인지와 type이 문자열인지만 확인합니다. 나머지는 사용자에게 달려 있지만, 모든 요소를 직렬화 가능하게 유지하면 문제 디버깅과 재현에 도움이 될 수 있습니다.
일반적으로 사용되는 코드 조각을 캡슐화하고 중앙 집중화하는 것은 프로그래밍의 핵심 개념입니다. 모든 곳에서 수동으로 액션 객체를 생성하고 각 type 값을 직접 작성하는 것도 가능하지만, 재사용 가능한 상수를 정의하면 코드 유지 관리가 쉬워집니다. 상수를 별도의 파일에 두면 오타 방지를 위해 import 문을 확인할 수 있어 실수로 잘못된 문자열을 사용하는 것을 방지할 수 있습니다.
추가 정보
문서
토론
리듀서와 액션 사이에는 항상 일대일 매핑이 존재하나요?
아닙니다. 독립적인 작은 리듀서 함수들을 작성하여 각각 상태의 특정 부분을 담당하도록 하는 "리듀서 컴포지션" 패턴을 권장합니다. 특정 액션은 모든 리듀서, 일부 리듀서 또는 아무 리듀서에도 의해 처리될 수 있습니다. 이렇게 하면 컴포넌트가 실제 데이터 변경과 분리되어 유지됩니다. 하나의 액션이 상태 트리의 여러 부분에 영향을 미칠 수 있으며, 컴포넌트가 이를 알 필요가 없기 때문입니다. 일부 사용자는 "ducks" 파일 구조처럼 더 긴밀하게 바인딩하기도 하지만, 기본적으로 일대일 매핑은 존재하지 않으며, 하나의 액션을 여러 리듀서에서 처리해야 할 때는 항상 이러한 패러다임에서 벗어나야 합니다.
추가 정보
문서
토론
AJAX 호출 같은 "사이드 이펙트"는 어떻게 표현하나요? 비동기 동작을 위해 "액션 생성자", "썽크", "미들웨어"가 필요한 이유는 무엇인가요?
이는 복잡하고 다양한 의견이 존재하는 주제로, 코드를 어떻게 구성하고 어떤 접근 방식을 사용할지에 대해 광범위한 논의가 있습니다.
의미 있는 웹 애플리케이션은 일반적으로 AJAX 요청과 같은 비동기 작업을 포함한 복잡한 로직을 실행해야 합니다. 이러한 코드는 순수히 입력값에 의존하는 함수가 아니며, 외부 세계와의 상호작용을 사이드 이펙트라고 부릅니다.
Redux는 함수형 프로그래밍에서 영감을 받았으며 기본적으로 사이드 이펙트 실행을 위한 장치를 제공하지 않습니다. 특히 리듀서 함수는 반드시 (state, action) => newState 형식의 순수 함수여야 합니다. 그러나 Redux의 미들웨어는 디스패치된 액션을 가로채고 그 주변에 사이드 이펙트를 포함한 추가적인 복잡한 동작을 가능하게 합니다.
일반적으로 Redux는 사이드 이펙트가 있는 코드가 액션 생성 과정의 일부가 되어야 한다고 제안합니다. 이러한 로직은 UI 컴포넌트 내부에서 수행될 수 있지만, 여러 장소에서 동일한 로직을 호출할 수 있도록 재사용 가능한 함수로 추출하는 것이 합리적입니다. 즉, 액션 생성자 함수를 의미합니다.
가장 간단하고 일반적인 방법은 Redux Thunk 미들웨어를 추가하여 더 복잡하고 비동기적인 로직을 가진 액션 생성자를 작성하는 것입니다. 널리 사용되는 또 다른 방법은 제너레이터를 사용해 동기적으로 보이는 코드를 작성할 수 있게 해주는 Redux Saga로, Redux 앱에서 "백그라운드 스레드"나 "데몬"처럼 동작합니다. 또 다른 접근법으로는 리듀서가 상태 변경에 반응해 사이드 이펙트를 선언하고 별도로 실행할 수 있게 하는 Redux Loop가 있습니다. 이 외에도 커뮤니티에서 개발한 수많은 라이브러리와 아이디어들이 각기 다른 방식으로 사이드 이펙트를 관리합니다.
추가 정보
문서
아티클
토론
어떤 비동기 미들웨어를 사용해야 하나요? Thunk, 사가, 옵저버블 등을 어떻게 선택하나요?
다양한 비동기/사이드 이펙트 미들웨어가 존재하지만, 가장 널리 사용되는 것은 redux-thunk, redux-saga, redux-observable입니다. 각기 다른 강점과 약점, 사용 사례를 가진 도구들입니다.
일반적인 선택 기준은 다음과 같습니다:
-
Thunk: 복잡한 동기 로직(특히 전체 Redux 스토어 상태 접근이 필요한 경우)과 단순한 비동기 로직(기본 AJAX 호출 등)에 최적화되어 있습니다.
async/await사용 시 프로미스 기반 복잡 로직에도 적합할 수 있습니다. -
사가: 복잡한 비동기 로직과 디스패치된 액션 리스닝이 필요한 경우(Thunk로 불가능)에 적합합니다. 제네레이터 함수와
redux-saga의 "이펙트" 연산자 숙지가 필요합니다. -
옵저버블: 사가와 동일한 문제를 해결하지만 RxJS를 활용합니다. RxJS API에 대한 이해가 필요합니다.
대부분의 사용자는 Thunk로 시작하고, 복잡한 비동기 로직 처리 필요 시 사가나 옵저버블을 추가하는 것을 권장합니다.
사가와 옵저버블은 동일한 사용 사례이므로 일반적으로 둘 중 하나만 사용합니다. 단, Thunk와 사가/옵저버블을 함께 사용하는 것도 문제없습니다. 서로 다른 문제를 해결하기 때문입니다.
아티클
토론
하나의 액션 생성자에서 여러 액션을 연속으로 디스패치해야 할까요?
액션 구조화에 대한 명확한 규칙은 없습니다. Redux Thunk 같은 비동기 미들웨어를 사용하면 연속적으로 서로 다르지만 관련된 여러 액션을 디스패치하거나, AJAX 요청 진행 상황을 나타내는 액션을 디스패치하거나, 상태에 따라 조건부로 액션을 디스패치하거나, 액션 디스패치 후 즉시 업데이트된 상태를 확인하는 시나리오가 가능해집니다.
일반적으로 이 액션들이 서로 관련되어 있지만 독립적인지, 아니면 실제로 하나의 액션으로 표현되어야 하는지 고민해보세요. 각 상황에 맞는 방법을 선택하되, 리듀서 가독성과 액션 로그 가독성 사이의 균형을 유지하세요. 예를 들어 전체 새 상태 트리를 포함하는 액션은 리듀서를 한 줄로 만들 수 있지만, 변경이 발생한 이유에 대한 기록이 없어 디버깅이 매우 어려워집니다. 반면 과도하게 세분화된 액션을 루프에서 발생시키는 것은 다른 방식으로 처리되는 새로운 액션 유형이 필요하다는 신호일 수 있습니다.
성능이 중요한 상황에서는 동기적으로 여러 번 연속 디스패치하는 것을 피하세요. 디스패치를 일괄 처리하는 다양한 애드온과 기법들이 존재합니다.
추가 정보
문서
아티클
토론