# 1.External Store

## 관심사의 분리

관심사 분리는 시스템의 다양한 측면 또는 책임의 구성 및 격리를 강조하는 소프트웨어 개발 원칙이다. React의 맥락에서 관심사 분리는 사용자 인터페이스 구성 요소, 데이터 가져오기, 상태 관리 및 비즈니스 로직과 같은 다양한 관심사를 별개의 모듈식 부분으로 분리하는 방식으로 애플리케이션을 구조화하는 것을 의미한다.

관심사를 분리하였을 때 얻는 이점

1. 모듈성(Modularity): 애플리케이션을 더 작은 자체 포함 구성 요소로 나누면 유지 관리와 재사용이 더 쉬워진다. 각 구성 요소는 특정 책임에 중점을 두어 개별적으로 더 쉽게 이해하고 수정할 수 있도록 한다.
2. 코드 재사용성(Code reusability): 관심사를 분리하면 애플리케이션의 다른 부분이나 다른 프로젝트에서도 구성 요소를 재사용할 수 있다. 이렇게 하면 개발 시간과 노력을 절약할 수 있다.
3. 협업(Collaboration): 여러 개발자가 한 프로젝트에서 작업할 때 관심사를 분리하면 서로의 코드를 방해하지 않고 동시에 작업할 수 있다. 각 개발자는 다른 사람의 발을 밟을 염려 없이 할당된 관심사에 집중할 수 있다.

React관점에서 다양한 기술과 패턴을 사용하여 관심사를 분리가 가능하다.

1. 구성 요소 기반 아키텍처(Component-based architecture): React는 재사용 가능한 구성 요소의 구성으로 애플리케이션을 구축하도록 권장한다. 각 구성 요소는 고유한 논리와 프레젠테이션을 캡슐화하여 문제를 명확하게 분리할 수 있다. 구성 요소를 함께 구성하여 복잡한 사용자 인터페이스를 구축할 수 있다.
2. SRP(Single Responsibility Principle): SRP에 따라 각 구성 요소는 단일 책임 또는 관심사를 가져야 한다. 예를 들어 데이터 렌더링, 사용자 입력 처리 및 상태 관리를 위한 별도의 구성 요소가 있을 수 있다.
3. 컨테이너 및 프레젠테이션 구성 요소(Container and Presentational Components): 스마트 컴포넌트와 덤 컴포넌트라고도 하는 컨테이너와 프레젠테이션 컴포넌트의 개념은 이러한 문제를 구분하는 데 도움이 된다. 컨테이너 컴포넌트는 로직과 데이터 불러오기를 처리하는 반면 프레젠테이션 컴포넌트는 제공된 소품을 기반으로 UI를 렌더링하는 데 중점을 둔다.
4. 상태 관리 라이브러리(State management libraries): React는 useState 및 useReducer라는 자체 상태 관리 시스템을 제공한다. 그러나 보다 복잡한 애플리케이션의 경우 Redux 또는 MobX와 같은 외부 상태 관리 라이브러리를 사용하도록 선택할 수 있다. 이러한 라이브러리는 상태 관리와 관련된 문제를 분리하는 데 도움이 되며 애플리케이션 수준 상태를 처리하는 중앙 집중식 접근 방식을 제공한다.
5. 별도의 데이터 가져오기(Separate data fetching): React 애플리케이션에서는 API 또는 기타 소스에서 데이터를 가져오는 것이 일반적이다. 데이터 가져오기 논리를 별도의 파일 또는 후크로 분리하면 문제를 독립적으로 격리하고 테스트할 수 있다.

## Layered Architecture

시스템의 구성 요소를 개별 계층으로 구성하는 소프트웨어 아키텍처 패턴이다. 여기서 각 계층은 특정 책임을 가지며 잘 정의된 방식으로 인접한 계층과 상호 작용한다. 계층화된 아키텍처는 관심사의 분리, 모듈식 설계 및 시스템의 유지 관리 가능성을 촉진한다.

Layered Architecture에서 각 계층은 관련 기능의 논리적 그룹을 나타내며 특정 작업 집합을 담당하며 가장 일반적인 계층은 다음과 같다.

1. 프레젠테이션 계층(Presentation Layer): 사용자 인터페이스 계층이라고도 하는 이 계층은 시스템과 사용자 간의 상호 작용을 처리한다. 정보 표시 및 사용자 입력 캡처에 중점을 둔다. 프레젠테이션 계층에는 웹 페이지, 모바일 앱 화면 또는 데스크톱 애플리케이션 인터페이스와 같은 구성 요소가 포함될 수 있다.
2. 애플리케이션 계층(Application Layer): 비즈니스 로직 계층이라고도 하는 애플리케이션 계층에는 애플리케이션의 핵심 기능과 규칙이 포함되어 있다. 시스템에서 수행하는 실제 동작 및 작업을 나타냅니다. 프레젠테이션 계층에서 요청을 받아 처리하고 필요한 작업의 실행을 조정한다. 이 계층은 비즈니스 논리, 워크플로 및 유효성 검사 규칙 구현을 담당한다.
3. 도메인 계층(Domain Layer): 도메인 계층은 도메인별 논리를 캡슐화하고 문제 도메인과 관련된 개념 및 엔터티를 나타냅니다. 여기에는 애플리케이션의 동작을 제어하는 ​​비즈니스 개체, 엔터티 및 규칙이 포함된다. 도메인 계층은 특정 기술이나 프레임워크와 독립적이며 인프라 및 사용자 인터페이스의 세부 사항에 대해 독립적이어야 한다.
4. 데이터 액세스 계층(Data Access Layer): 지속성 계층이라고도 하는 데이터 액세스 계층은 데이터 저장 및 검색을 처리한다. 데이터베이스 또는 기타 데이터 소스와의 상호 작용을 추상화한다. 이 계층은 쿼리 실행, 데이터 액세스, 도메인 개체 저장 및 검색을 위한 인터페이스 제공을 담당한다. 데이터 저장 메커니즘의 복잡성으로부터 상위 계층을 보호하고 통합 데이터 액세스 인터페이스를 제공한다.
5. 인프라 계층(Infrastructure Layer): 인프라 계층은 애플리케이션 기능에 필요한 기본 서비스 및 유틸리티를 제공한다. 여기에는 외부 서비스 통합, 파일 시스템, 네트워크 통신, 로깅, 캐싱 및 보안과 같은 구성 요소가 포함된다. 인프라 계층은 상위 계층을 지원하고 상위 계층이 효과적으로 작업을 수행할 수 있도록 한다.

Layered Architecture의 주요 이점

1. 모듈화 및 관심사 분리(Modularity and separation of concerns): Layered Architecture는 관련 기능을 별개의 계층으로 그룹화하여 관심사를 명확하게 분리한다. 이를 통해 각 계층을 독립적으로 개발하고 테스트할 수 있으므로 시스템의 모듈식 개발 및 유지 관리가 가능한다.
2. 유연성 및 확장성(Flexibility and scalability): Layered Architecture는 전체 시스템에 영향을 주지 않고 개별 계층을 교체하거나 수정할 수 있는 유연성을 허용한다. 새로운 계층을 추가하거나 기존 계층을 제거하여 변화하는 요구 사항을 수용하거나 새로운 기술을 통합할 수 있다. 이러한 확장성은 시간이 지남에 따라 시스템이 성장하고 진화하는 데 도움이 된다.
3. 코드 재사용성(Code reusability): 시스템을 레이어로 구성하면 재사용 가능한 구성 요소를 식별하고 여러 레이어 또는 프로젝트에서 공유할 수 있다. 이를 통해 개발 효율성이 향상되고 코드 중복이 줄어듭니다.
4. 테스트 가능성(Testability): Layered Architecture는 테스트 프로세스를 용이하게 한다. 각 계층은 개별적으로 테스트할 수 있으므로 보다 집중적이고 대상이 지정된 테스트 시나리오가 가능한다. 단위 테스트, 통합 테스트 및 종단 간 테스트를 각 계층에서 수행하여 시스템이 전체적으로 올바르게 작동하는지 확인할 수 있다.

## Flux Architecture

Flux 아키텍처는 웹 애플리케이션에서 데이터 흐름을 관리하기 위한 패턴이다. Facebook에서 개발했으며 일반적으로 확장 가능하고 유지 관리 가능한 애플리케이션을 구축하기 위해 React와 함께 사용된다. Flux는 단방향 데이터 흐름을 따르므로 복잡한 상태 상호 작용을 관리하고 응용 프로그램을 더 쉽게 이해하고 디버그할 수 있다.

Flux 아키텍처는 다음 네 가지 주요 구성

1. Dispatcher: Dispatcher는 애플리케이션의 중앙 허브 역할을 한다. 응용 프로그램의 다른 부분에서 작업을 수신하고 적절한 저장소로 발송한다. 작업이 순차적이고 결정적인 방식으로 처리되도록 한다. Dispatcher는 등록된 콜백 목록을 유지 관리하고 작업이 발송될 때 이를 알리는 역할을 한다.
2. Actions: Actions은 애플리케이션 내에서 발생하는 이벤트 또는 사용자 상호 작용을 나타냅니다. "사용자가 버튼을 클릭했다." 또는 "서버에서 데이터를 가져왔다."와 같이 발생한 상황을 설명하는 일반 JavaScript 개체이다. 액션은 액션 객체 생성을 담당하는 헬퍼 함수인 액션 생성자에 의해 생성된다. 작업이 생성되면 Dispatcher로 발송된다.
3. Stores: Stores에는 애플리케이션 상태 및 비즈니스 로직이 포함된다. 발송된 작업에 응답하고 그에 따라 내부 상태를 업데이트한다. Stores는 애플리케이션의 뷰(구성 요소)에 대한 데이터 관리 및 노출을 담당한다. 작업을 수신하고 적절하게 처리하기 위해 Dispatcher에 등록한다. Stores의 상태가 변경되면 뷰에 알리기 위해 변경 이벤트를 내보냅니다.
4. Views: 종종 React 구성 요소로 표시되는 Views는 Stores에서 제공하는 데이터를 기반으로 사용자 인터페이스를 렌더링하는 역할을 한다. 관심 있는 매장을 구독하고 변경 이벤트를 수신한다. Stores가 변경 이벤트를 내보내면 뷰는 Stores에서 업데이트된 데이터를 검색하고 스스로를 다시 렌더링한다.

Flux 아키텍처의 데이터 흐름은 엄격한 단방향 패턴을 따른다.

1. 사용자 상호 작용 또는 시스템 이벤트는 Dispatcher로 발송되는 작업을 트리거한다.
2. Dispatcher는 조치를 수신하여 적절한 상점으로 보냅니다.
3. Stores는 작업을 처리하고 그에 따라 상태를 업데이트한다.
4. Stores가 상태를 업데이트하면 변경 이벤트가 발생한다.
5. Views(구성 요소)는 이러한 변경 이벤트를 수신하고 저장소에서 업데이트된 데이터를 검색한다.
6. Views는 사용자 인터페이스의 변경 사항을 반영하여 새 데이터를 기반으로 스스로를 다시 렌더링한다.

Flux 아키텍처 사용의 이점

1. 예측 가능한 데이터 흐름(Predictable data flow): Flux의 단방향 데이터 흐름을 통해 데이터가 응용 프로그램을 통해 어떻게 변경되고 흐르는지 더 쉽게 이해할 수 있다. 이 예측 가능성은 디버깅을 단순화하고 상태 변경의 원인을 식별하는 데 도움이 된다.
2. 중앙화된 상태 관리(Centralized state management): Flux Stores는 중앙화된 방식으로 애플리케이션 상태를 포함한다. 이렇게 하면 특히 복잡한 데이터 종속성이 있는 대규모 애플리케이션에서 상태를 더 쉽게 관리하고 추론할 수 있다.
3. 유지 보수성(Maintainability): Flux의 관심사 분리를 통해 더 나은 코드 구성 및 모듈화가 가능한다. 각 구성 요소(Dispatcher, Actions, Stores, Views)에는 특정 책임이 있으므로 코드베이스를 보다 쉽게 ​​유지 관리하고 수정할 수 있다.
4. 확장성(Scalability): Flux는 많은 양의 데이터 및 상태 상호 작용이 있는 복잡한 애플리케이션을 처리하기 위한 확장 가능한 아키텍처를 제공한다. 단방향 흐름 및 중앙 집중식 상태 관리는 애플리케이션이 성장함에 따라 확장하는 데 도움이 된다.

## useReducer

React에서 useReducer 후크는 복잡한 상태 및 상태 전환을 보다 제어되고 예측 가능한 방식으로 관리할 수 있는 내장 함수이다. 이것은 useState 후크의 대안이며 여러 값이 포함된 상태를 처리하거나 상태 전환이 이전 상태를 기반으로 할 때 특히 유용한다.

useReducer 후크는 리듀서 함수와 초기 상태라는 두 가지 인수를 사용한다. reducer function은 다른 작업에 대한 응답으로 상태를 업데이트하는 방법을 지정하는 역할을 한다. 초기 상태 인수는 상태의 초기 값을 설정한다.

reducer 함수는 state와 action 두 가지 인수를 받는다. action type을 확인하고 그에 따라 필요한 상태 업데이트를 수행한다. reducer 함수는 상태가 변경되지 않더라도 항상 새로운 상태 객체를 반환해야 한다.

```js
import React, { useReducer } from 'react';

// Reducer function
const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    case 'RESET':
      return { count: 0 };
    default:
      return state;
  }
};

// Component using useReducer
const Counter = () => {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  const increment = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const decrement = () => {
    dispatch({ type: 'DECREMENT' });
  };

  const reset = () => {
    dispatch({ type: 'RESET' });
  };

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
};

```

useReducer를 사용 시 이점

1. 복잡한 상태 관리(Complex state management): useReducer는 여러 값 또는 복잡한 데이터 구조와 관련된 상태를 관리하는 데 적합하다. 이를 통해 보다 복잡한 상태 전환 및 논리를 중앙 집중식으로 처리할 수 있다.
2. 예측 가능한 업데이트(Predictable updates): 상태 전환은 특정 패턴을 따르는 리듀서 함수에 의해 결정되므로 상태에 대한 업데이트를 더 예측 가능하고 추적할 수 있다.
3. 최적화(Optimization): useReducer는 이전 상태에 의존하는 상태 업데이트를 처리할 때 성능을 최적화할 수 있다. 이는 상태 전환이 가장 최신 상태를 기반으로 하고 잠재적 경합 상태를 방지하도록 한다.
4. 상태 로직 공유(Sharing state logic): 리듀서 기능은 여러 구성 요소에서 재사용할 수 있으므로 코드 공유가 가능하고 중복이 줄어듭니다.

useReducer는 useState와 같은 간단한 상태 관리 솔루션에 비해 추가적인 복잡성을 유발할 수 있다는 점에 유의하는 것이 중요하다. 일반적으로 상태 로직이 더 복잡해지고 상태 전환에 대한 예측 가능하고 제어된 접근 방식이 필요한 경우 'useReducer'를 사용하는 것이 좋다.

## useCallback

React에서 useCallback 후크는 콜백 함수 생성을 메모하고 최적화하는 데 사용된다. 렌더링 성능 최적화 또는 불필요한 다시 렌더링 방지와 같이 참조 동등성에 의존하는 자식 구성 요소에 콜백 함수를 전달하는 시나리오에서 주로 유용하다.

구성 요소 내에서 콜백 함수를 정의할 때 해당 함수의 새 인스턴스가 각 렌더링에서 생성된다. 이로 인해 함수 로직이 동일하게 유지되더라도 이러한 콜백에 의존하는 자식 구성 요소가 불필요하게 다시 렌더링될 수 있다. useCallback은 종속 항목이 변경되는 경우에만 변경되는 메모화된 버전의 콜백 함수를 반환하여 이 문제를 완화하는 데 도움이 된다.

useCallback 후크는 콜백 함수와 종속성 배열이라는 두 가지 인수를 사용한다. 종속성은 메모화된 콜백을 업데이트해야 하는 시기를 결정하는 데 사용된다.

```js
import React, { useState, useCallback } from 'react';

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <ChildComponent onClick={handleClick} />
    </div>
  );
};

const ChildComponent = ({ onClick }) => {
  // Child component logic using the onClick callback
  // ...
};
```

useCallback 사용 시 이점

1. 최적화된 성능(Optimized performance): useCallback은 콜백 함수를 메모하여 자식 구성 요소의 불필요한 재렌더링을 방지하는 데 도움이 된다. 종속성이 변경될 때만 콜백이 다시 생성되도록 한다.
2. 불필요한 함수 재생성 방지(Avoiding unnecessary function recreation): 콜백을 하위 구성 요소에 소품으로 전달할 때 useCallback은 각 렌더링에서 콜백 인스턴스 재생성을 방지하여 잠재적인 성능 최적화로 이어질 수 있다.
3. 안정된 참조(Stable references): useCallback은 콜백 함수에 대한 안정적인 참조를 제공한다. 이는 컴포넌트 메모를 위해 'React.memo'를 사용하거나 이벤트 리스너에 콜백을 전달하는 것과 같이 참조를 비교하는 시나리오에서 중요할 수 있다.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jin-11.gitbook.io/jin-devnote/week6/external-store.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
