Web 17

영화 검색 사이트 + 성능 최적화 (useCallback, useMemo, React.memo)

TMDB API를 활용해 영화 검색 앱을 만들면서 검색 기능, 상세 모달, 언어 선택 기능을 구현하고, 불필요한 리렌더링을 줄이기 위해 useCallback, useMemo, React.memo를 직접 적용해보았다. 최종 실행 화면부터 보여주자면 아래와 같다. 구현 처음 앱에 진입했을 때 검색 결과가 비어 있으면 화면이 어색하게 느껴질 수 있다.따라서 기본적으로 인기 영화를 자동으로 불러오도록 구현했다.이를 위해 useEffect 안에서 TMDB의 /movie/popular 엔드포인트를 호출했다.useEffect(() => { const fetchPopular = async () => { setIsLoading(true); const params = new URLSearchParams({ ..

Web 2026.06.05

Redux Toolkit에서 Zustand로 리팩토링하기

저번 실습에선 Redux Toolkit을 사용해서 플레이리스트 장바구니와 모달 상태를 관리했다. 이번엔 기능은 그대로 유지하되 상태 관리 방식을 Redux Toolkit에서 Zustand로 리팩토링하였다. 이번 미션의 핵심은 단순히 라이브러리를 바꾸는 것이 아닌, Redux에서 사용하던 전역 상태 관리 흐름을 Zustand 방식으로 다시 설계해보는 것이다. 이번 실습에서 진행한 작업은 다음과 같다. Zudstand 설치Redux Toolkit, React Redux 제거Redux Provider 제거cartSlice, modalSlice 제거장바구니 상태와 모달 상태를 하나의 Zustand Store로 통합기존 기능과 화면 동작은 그대로 유지 1. Zustand Store 생성 Redux Toolki..

Web 2026.05.31

Modal Slice 활용하여, 모달 기능 추가

저번 실습에서는 장바구니 데이터를 Redux Toolkit으로 관리했다. 여기서 한 단계 더 나아가, 장바구니 데이터뿐만 아니라 모달의 열림/닫힘 상태도 Redux Toolkit으로 관리하도록 기능을 추가했다. 1. Modal Slice 생성먼저 features/modal/modalSlice.ts 파일을 새로 만들었다.모달 상태는 단순하게 isOpen 값 하나로 관리했다. interface ModalState { isOpen: boolean}const initialState: ModalState = { isOpen: false,} const modalSlice = createSlice({ name: 'modal', initialState, reducers: { openModal: (st..

Web 2026.05.30

Redux Toolkit으로 Play List 장바구니 생성

이번엔 Redux Toolkit, TypeScript, Tailwind CSS를 활용해서 전역 상태로 관리되는 플레이리스트 장바구니 화면을 구현했다. 이번 실습의 목표는 아래와 같았다.음반 Mock Data 분리Redux Store 생성cartSlice 설계수량 증가, 감소, 삭제, 전체 삭제 기능 구현총 수량과 총 금액 자동 계산React 컴포넌트와 Redux 상태 연결Tailwind CSS로 UI 구성1. 음반 Mock Data 분리먼저 음반 정보를 constants/cartItems.ts 파일로 분리한다.각 음반 데이터는 id, title, singer, price, img, amount 값을 가진다.export interface CartItem { id: string title: string ..

Web 2026.05.29

TanStack Query 실습

1. 개요내용: 이번 프로젝트의 목적과 주요 기능(인증, 데이터 조회, 반응형 UI)을 간단히 소개한다 2. 기술 스택 및 초기 설정내용: Vite, React, TypeScript, TanStack Query, Axios를 사용코드: 8000번 포트의 백엔드 서버와 통신하기 위한 베이스 URL 설정import axios from 'axios';const axiosInstance = axios.create({ baseURL: 'http://localhost:8000/v1', headers: { 'Content-Type': 'application/json', },});axiosInstance.interceptors.request.use((config) => { const token = loc..

Web 2026.05.09

OAuth 로그인 구현 (Google)

이번엔 로그인 보안의 핵심, OAuth 2.0을 활용해 구글 소셜 로그인을 구현했다.1. Google API Console 설정 (환경 설정)먼저 구글로부터 앱 사용 허가를 받아야 합니다. Google Cloud Console에서 다음 작업을 수행해야 한다.OAuth 동의 화면 구성: 앱 이름과 이메일 등 필수 정보를 입력OAuth 클라이언트 ID 발급: '웹 애플리케이션' 유형으로 생성.리디렉션 URI 설정: 백엔드 서버 주소인 http://localhost:8000/v1/auth/google/callback을 정확히 등록. 이 주소가 틀리면 인증 후 데이터를 돌려받을 수 없음2. 백엔드 서버 환경변수 연동발급받은 Client ID와 Client Secret을 서버 코드에 심어줍니다.위치: 서버의 .e..

Web 2026.05.01

Refresh 토큰을 활용한 끊김 없는 로그인 유지하기

웹 서비스를 개발할 때 가장 중요한 것 중 하나는 보안과 사용자 경험이다. 이번 포스팅에서는 로그인이 필요한 페이지를 보호하고, 토큰이 만료되어도 사용자가 모르게 자동으로 로그인을 연장하는 기능을 구현한 과정을 기록하고자 한다. 1. API 권한 확인자물쇠가 있는 API: 가장 먼저 백엔드 Swagger 문서를 확인했다. Swagger 문서를 보면 오른쪽에 회색 자물쇠 아이콘이 있는 것들이 있다.이는 요청 헤더에 유효한 토큰이 반드시 포함되어야 함을 의미한다. 즉, 로그인한 사용자만 사용 가능 2. 로그인 상태 관리와 UI 대응로그인에 성공한 화면이다. 로그인을 하면 서버에서 받은 accessToken을 localStorage에 저장한다. 동시에 Navbar의 UI도 토큰 유무에 따라 '로그인/회원가입..

Web 2026.04.30

사용자 인증 Token : Access vs Refresh

1. Access Token역할: API 요청 시 사용자 인증/인가 "확인" 용도로 사용수명: 짧음 (보통 15~30분)이유: 만약 토큰 탈취 당하면 위험하므로 빨리 만료되도록 설계저장위치: 메모리2. Refresh Token역할: AccessToken 만료 되었을 시 새로운 AccessToken 발급 받기 위해 사용수명: 길다 (보통 7일 ~ 30일)이유: 평소 통신할 때는 사용하지 않고 오직 토큰 갱신할 때만 서버에 보냄저장위치: HttpOnly 쿠키3. 사용자 인증 흐름도로그인 성공: 서버가 Access(30분짜리)와 Refresh(2주 짜리) token을 둘 다 제공평상시: 클라이언트는 Access token만 헤더에 실어서 요청만료: 30분이 지나 Access Token이 죽으면, 서버에 "유효..

Web 2026.04.06

영화 웹사이트 - 3단계 ( 상세 페이지 구현 )

구조 기존의 영화 목록 중심 구조에서 상세 페이지로 들어갈 수 있는 동적 라우팅 구현 src/pages/MovieDetailPage.tsx : 영화 ID를 파라미터로 받아서 상세 정보를 렌더링src/types/movie.ts : 영화 상세 정보와 출연진에 대한 인터페이스를 새롭게 정의src/api/axios.ts : 기존에 설정한 Axios 인스턴스 활용해서 상세 정보, 출연진 둘 다 호출 구현 내용1. 동적 라우팅 설정URL의 특정 부분을 변수처럼 사용하는 동적 라우팅 설정해서 하나의 컴포넌트로 많은 영화 페이지 호출 가능적용 코드 ( src/main.tsx )흐름: 사용자가 영화를 클릭하면 MovieCard 내부의 Link 컴포넌트가 동작해서 /movie/12345와 같은 주소로 이동 { path:..

Web 2026.04.03

영화 웹사이트 - 2단계 (Router, Pagination)

구조 수정1단계에서 만든 구조를 벗어나 관심사 분리를 위해 구조 재설계src/pages/ : 각 메뉴(인기, 상영 중 등)에 맞는 페이지 컴포넌트 배치src/components/ : 공통 레이아웃(Layout), 네비게이션(Navbar), 로딩 상태(LoadingsPinner) 등을 재사용 가능한 컴포넌트 단위로 분리src/api/ : Axios인스턴스 통해 API통신 모듈화 구현 내용 1. React Router 이용하여 멀티 페이지 구현 적용코드: src/main.tsx흐름: 사용자가 상단에 있는 메뉴 클릭 > URL 변경 > Layout 컴포넌트 내부의 자리에 해당 페이지 컴포넌트가 동적으로 변함const router = createBrowserRouter([ { path: '/', ..

Web 2026.04.03