본문 바로가기

Project

[FE] 프론트 관련 내용 정리

TIL: React의 useEffect와 상태 관리 이해하기

  • 오늘 timer 의 시간이 0초가 되었을 때, 새로고침을 해야 모달이 뜨는 현상이 발생했습니다. 해당 내용을 학습하고자 useEffect와 상태관리를 공부하여, 0초가 되었을 때 새로고침 없이 modal 이 뜨도록 설정했습니다.

1. useEffect란 무엇인가?

useEffect는 React 훅(Hook)의 하나로, 컴포넌트에서 "부수 효과(side effect)"를 수행할 수 있게 해줍니다. 부수 효과란 데이터 가져오기, 타이머 설정, 이벤트 구독 같은 외부와의 상호작용을 말합니다.

useEffect(() => {
  // 실행할 코드
}, [의존성 배열]);

2. 의존성 배열의 역할

의존성 배열은 useEffect가 언제 실행될지 결정하는 중요한 요소입니다:

  • 빈 배열 []: 컴포넌트가 처음 화면에 나타날 때(마운트될 때)만 한 번 실행됩니다.

    useEffect(() => {
      console.log("컴포넌트가 화면에 나타났습니다!");
    }, []);
  • 의존성 있는 배열 [값1, 값2]: 컴포넌트가 마운트될 때와 배열 안의 값이 변경될 때마다 실행됩니다.

    useEffect(() => {
      console.log("count가 변경되었습니다:", count);
    }, [count]);
  • 의존성 배열 생략: 컴포넌트가 마운트될 때와 업데이트될 때마다 실행됩니다(거의 모든 렌더링마다).

    useEffect(() => {
      console.log("컴포넌트가 업데이트되었습니다!");
    });

3. 상태(State) 관리와 useState

useState는 컴포넌트에서 변경 가능한 상태를 관리하는 훅입니다:

const [timeLeft, setTimeLeft] = useState(600); // 초기값 600초
  • timeLeft: 현재 상태 값
  • setTimeLeft: 상태를 업데이트하는 함수

4. 함수형 업데이트와 prev

상태를 업데이트할 때 이전 상태 값을 기반으로 계산이 필요한 경우, 함수형 업데이트를 사용합니다:

// 일반 업데이트
setTimeLeft(timeLeft - 1);

// 함수형 업데이트 (더 안전한 방법)
setTimeLeft(prev => prev - 1);

여기서 prev는 현재 상태의 최신 값을 나타내는 매개변수입니다. 함수형 업데이트는 이전 상태에 의존하는 업데이트를 여러 번 할 때 더 안정적입니다.

5. 타이머 구현 예제 분석

문제 상황

타이머가 특정 시간(590초)에 도달했을 때 모달을 표시하려고 하는데, 새로고침을 해야만 모달이 나타나는 문제가 있었습니다.

원인

첫 번째 useEffect에서 조건을 확인했지만, 이 useEffect는 컴포넌트 마운트 시에만 실행되기 때문에 타이머가 실시간으로 변할 때 조건을 확인하지 못했습니다.

// 문제가 있던 코드
useEffect(() => {
  // 초기 설정 로직
  const remaining = 60 * 10 - elapsedSeconds;

  if (remaining <= 590) { // 이 조건은 마운트 시에만 확인됨!
    setShowTimeoutModal(true);
  } else {
    setTimeLeft(remaining);
  }
}, [isDemo]); // isDemo만 의존성으로 가짐

해결책

실시간으로 타이머 값을 확인하는 두 번째 useEffect 내부의 setTimeLeft 함수에서 조건을 확인하도록 변경했습니다:

// 해결된 코드
useEffect(() => {
  if (!isDemo || timeLeft <= 0) return;

  const interval = setInterval(() => {
    setTimeLeft(prev => {
      if (prev <= 590) { // 매초마다 이 조건이 확인됨!
        clearInterval(interval);
        setShowTimeoutModal(true);
        return prev;
      }
      return prev - 1;
    });
  }, 1000);

  return () => clearInterval(interval);
}, [isDemo, timeLeft]); // timeLeft 변화에 반응

6. useEffect 정리(Cleanup) 함수

useEffect는 정리 함수를 반환할 수 있습니다. 이 함수는 컴포넌트가 언마운트되거나 다음 이펙트가 실행되기 전에 호출됩니다:

useEffect(() => {
  const timer = setInterval(() => {
    // 타이머 로직
  }, 1000);

  // 정리 함수: 메모리 누수 방지
  return () => clearInterval(timer);
}, []);

정리 함수는 메모리 누수를 방지하는 데 중요합니다. 특히 타이머나 이벤트 리스너와 같은 리소스를 사용할 때 반드시 정리해주어야 합니다.

7. 핵심 요약

  1. useEffect 실행 시점은 의존성 배열에 의해 결정됩니다.
  2. 상태 업데이트는 즉시 일어나지만, 화면 갱신은 다음 렌더링에서 발생합니다.
  3. 함수형 업데이트(prev => {...})는 이전 상태에 의존하는 업데이트를 안전하게 처리합니다.
  4. 의존성 배열 설계는 컴포넌트의 올바른 동작과 성능에 중요합니다.
  5. 정리 함수로 타이머나 이벤트 리스너와 같은 리소스를 해제해야 합니다.

오늘 배운 내용을 통해 React에서 타이머 같은 부수 효과를 다룰 때 useEffect와 상태 관리의 중요성을 이해할 수 있었습니다. 의존성 배열을 올바르게 설정하고 함수형 업데이트를 활용하면 더 안정적인 React 애플리케이션을 구축할 수 있습니다.

TIL: 듀티메이트 자동 생성 구독 시스템 구현

오늘 듀티메이트 앱에 자동 생성 구독 시스템을 구현했습니다. 이 과정에서 여러 기술적인 내용과 React 컴포넌트 설계에 대해 배웠습니다. 또한 Patch, Put 메서드의 차이를 알아보고 결정하였습니다.

배운 내용

1. React 모달 구현 패턴

  • 여러 모달을 순차적으로 표시하기 위한 상태 관리 방법
  • 부모 컴포넌트에서 모달 상태를 관리하고 자식 컴포넌트에 props로 전달하는 패턴
  • 모달 닫기 및 다음 모달 열기 로직 설계

2. API 호출 관리

  • 서비스 레이어를 통한 API 호출 분리
  • API 오류 처리 및 예외 상황 대응
  • 개발 환경에서 API 호출 실패 시 대체 로직 구현 (임시 데이터 사용)

3. CORS 이슈 해결

  • PATCH 요청시 preflighted request로 인한 CORS 문제 발생
  • 단순 요청(GET)과 preflighted 요청의 차이점
  • 백엔드 측에서 Access-Control-Allow-Methods 설정 필요성

4. Put vs Patch

PUT

  • 정의: 대상 리소스의 상태를 요청에 포함된 표현으로 대체하는 메서드
  • 특징:
    • 클라이언트가 리소스의 정확한 URI를 알아야 함 (예: /payments/1)
    • 멱등함 (같은 요청을 여러 번 보내도 결과가 동일)
    • 리소스 전체를 업데이트해야 함 (모든 필드 데이터 필요)

PATCH

  • 정의: 요청에 설명된 변경사항을 특정 리소스에 적용하는 메서드
  • 특징:
    • 특정 리소스 URI를 정확히 알아야 함
    • 부분 업데이트 가능 (변경이 필요한 필드만 요청 본문에 포함)
    • 일반적으로 멱등하지 않음 (동시 호출 시 데이터 손실 가능)

비교 요약표

메서드 설명 요청 URI 멱등성
PUT 리소스 생성 및 전체 업데이트 특정 리소스 URI O
PATCH 리소스 부분 업데이트 특정 리소스 URI X

채널톡 SPA 환경에 적용하기 - React 프로젝트 적용 TIL

오늘 React 프로젝트에 채널톡을 적용하는 과정을 진행했습니다. 채널톡은 고객 소통 및 지원 플랫폼으로, 웹사이트에 채팅 기능을 쉽게 추가할 수 있게 해주는 서비스입니다.

학습 내용

1. SPA vs MPA의 차이점

  • MPA(Multi-Page Application): 각 페이지를 요청할 때마다 새로운 정적 리소스를 로드하는 방식
  • SPA(Single Page Application): 최초 한 번만 페이지를 로드하고, 이후에는 필요한 데이터만 서버에서 가져와 동적으로 페이지를 갱신하는 방식
  • React는 SPA 프레임워크이기 때문에 MPA와는 다른 방식으로 채널톡을 설치해야 함

2. 채널톡 서비스 클래스 생성

  • SPA 환경에서 채널톡을 사용하기 위해 별도의 서비스 클래스를 생성
  • TypeScript 사용 시 인터페이스도 함께 정의됨

3. 채널톡 초기화 과정

  • loadScript(): 채널톡 스크립트를 로드하는 함수
  • boot(): 채널톡 서비스를 초기화하는 함수, 사용자 정보와 함께 호출 가능

4. 컴포넌트 분리를 통한 구조화

  • App.tsx에 직접 채널톡 코드를 작성하는 대신, 별도의 컴포넌트(ChannelTalkLoader)를 생성하여 관심사 분리
  • 이를 통해 코드 가독성과 유지보수성 향상

5. 사용자 인증 정보 연동

  • Zustand 상태 관리 라이브러리를 사용해 관리되는 사용자 인증 정보를 채널톡에 연동
  • 로그인 상태에 따라 익명 사용자 또는 인증된 사용자로 채널톡 초기화
  • isAuthenticateduserInfo 상태에 따라 조건부 초기화 설정

6. 의존성 배열과 useEffect

  • useEffect의 의존성 배열에 isAuthenticateduserInfo를 추가하여 로그인 상태 변화에 따라 채널톡이 재초기화되도록 설정

결론

react 프로젝트에 서드파티 프로그램을 이식하는 과정을 처음 겪어 보았고, 해당 과정에서 서드파티 프로그램과 데이터를 주고받는 방식에 대한 이해도를 높일 수 있었습니다.