FrontEnd Develop 77

Github 이해하기 #1. 두 사람의 브랜치 병합 협업

이번 글에서는 Git 협업에서 자주 마주하게 되는 브랜치 병합 과정을, 두 명의 개발자 Jessica와 John의 사례를 통해 단계별로 설명합니다. 이 글은 Git의 기본 구조를 이해하고자 하는 분에게 적합합니다.상황 가정John과 Jessica는 동일한 원격 저장소(origin)에서 각각 작업을 진행합니다.둘 다 master 브랜치를 기준으로 작업을 시작했으며, 각자의 로컬에서 feature를 개발한 후, 이를 다시 master로 병합하려고 합니다.1. 원격 저장소를 클론두 사람은 각각 다음과 같이 원격 저장소를 클론하여 작업을 시작합니다:$ git clone git@host:simplegit.git이때 로컬에는 다음과 같은 브랜치가 생성됩니다:master (로컬 작업 브랜치)origin/master..

FrontEnd Develop 2025.05.19

UseState 그냥 쓰지말고 알고쓰자!

UseState DeepDiveINTRO. 상태값 변경시 리렌더링 발생useState에서 반환된 배열의 두번째 값인 setter 함수를 호출하면 상태 값을 변경할 수 있고, 상태 값이 변경되면 해당 컴포넌트는 다시 렌더링됩니다.=> 컴포넌트가 마운트되었을 때는, 기본적으로 useState(초기값)에서 인자로 전달된 값을 상태의 초기값으로 사용합니다. 하지만 이후 setter 함수에 의해 상태의 값이 변경되었다면, 다음 렌더링에서는 그 상태를 유지합니다.setState 호출 => 상태 변경 => 리렌더링(변경된 상태값 사용)THEME #1. setState는 비동기로 동작한다. (정확히 비동기함수다 X)useState의 setter 함수를 호출한 이후 바로 다음 줄에서 해당 state값을 참조하면 아직 바..

FrontEnd Develop 2025.05.07

STT 라우팅과 비동기 처리 분리하기: 실전 리팩토링 사례

"2025년 5월 4일, 라우팅 흐름부터 API 처리까지, 실전 개발 중 맞닥뜨린 문제들과 그 해결 과정" ✨ 문제의 시작: 비동기 처리와 라우팅이 엉킨다처음엔 단순한 흐름이라고 생각했다. 기획자와 논의한 유저 플로우:사용자가 수업 영상 파일을 업로드하고 "다음" 버튼을 누른다.노트를 생성한다 (createNote).STT 변환을 시작한다 (createSTT).STT가 끝나면 다음 페이지로 router.push() 한다.다음 페이지에서 STT 결과를 기반으로 요약문을 생성한다.⚠️ 기존 코드 구조 (문제 있는 구조)const handleNoteNextBtn = async () => { const createdNote = await createNote(folderId, { title: noteName }..

타입스크립트(자바스크립트) 배열 반복(iteration) 메서드 정리

프론트엔드 개발에서 배열을 다룰 때 자주 사용하는 반복(iteration) 메서드들에 대해 정리해봅니다. map, filter, forEach, find, reduce 등은 모두 배열의 각 요소를 순회하며 무언가를 처리하는 함수형 도구입니다.✅ 1. map()배열의 각 요소를 **변형(transform)**하여 새로운 배열을 생성✅ 리턴값 필요: 각 요소를 어떻게 바꿀지 return 필수const numbers = [1, 2, 3];const doubled = numbers.map((n) => n * 2); // [2, 4, 6]원본 배열 유지됨JSX에서도 아주 자주 쓰임{todoList.map((todo) => ( {todo.text}))}✅ 2. filter()조건에 맞는 요소만 걸러내서 새 배열 ..

TypeScript의 객체 타입 지정에 편리한 내장 Record 유틸리티 타입

TypeScript에서는 객체의 타입을 명시할 때 보통 아래처럼 key-value 형태로 정의합니다:const user: { name: string; age: number } = { name: 'Alice', age: 30,};하지만 더 유연하고 깔끔하게 작성할 수 있는 유틸리티 타입이 있습니다. 그중 대표적인 것이 바로 **Record**입니다.Record란?"키가 K 타입이고, 값이 V 타입인 객체를 정의한다"는 의미입니다.Record 문자열 키와 문자열 값const colorMap: Record = { primary: 'blue', danger: 'red', success: 'green',}; 위는 아래와 동일한 의미를 가집니다.const colorMap: { [key: string]: s..

Tailwind 기반 버튼 컴포넌트 재활용하기

재활용을 왜하는가?React 프로젝트를 진행하다 보면 버튼과 같은 컴포넌트들을 반복해서 만들게 됩니다. 그때마다 className을 복붙하고 색깔을 바꾸다 보면 코드가 지저분해지고, 유지보수도 힘들어집니다. 이번 글에서는 Tailwind CSS + TypeScript 조합으로 깔끔하고 재사용 가능한 버튼 컴포넌트를 만들어보는 방법을 공유합니다.1. 기본 Button 컴포넌트 만들기먼저 가장 기본이 되는 버튼 컴포넌트를 Button.tsx로 만들겠습니다.import { ButtonHTMLAttributes } from 'react';interface ButtonProps extends ButtonHTMLAttributes { variant?: 'primary' | 'danger' | 'black'; f..

Zustand X Generic 심층분석.

Zustand create 완전 정복을 위하여..늘 context API로 전역상태 관리를 활용하던 내가 , zustand 공식문서를 읽어보며 zustand 활용법을 공부했다. zustand에는 Generic type으로 선언된 함수가 매우많아서 Generic 관련 내용 또한 매우 중요하다고 판단하여 같이 콜라보하여 공부했다.1. 제네릭이란 무엇인가?TypeScript에서 흔히 보이는 함수 형태는 제네릭(Generic) 문법입니다.function identity(value: T): T { return value;}identity('hello'); // ✉️ T = string → 매개변수도, 리턴값도 string즉, T라는 타입은 함수 선언부에서 고정하지 않고, 호출할 때 지정할 수 있는 타입 매개변수..

Props를 단순히 부모 - 자식 관계로만 치부할지말자.

중복된 여러 코드가 보기 싫다에서 탄생된 것이 props다.회원가입 form을 예시로, 아이디, 비밀번호, 뭐 등등 입력하는 칸거의 완전 똑같이 생겼는데 이걸 굳이 3줄 겹치는 내용을 적어야한다면 그것은 비효율적이겠다.import React, { useState } from 'react';export default function SignupForm() { const [id, setId] = useState(''); const [pw, setPw] = useState(''); return ( 아이디 setId(e.target.value)} className="border p-2 rounded" /> ..

useState는 여간 쉬운게 아니다.

React 상태 관리 제대로 이해하기React를 사용하다 보면 자주 마주치는 개념 중 하나가 상태(state)입니다. 하지만 상태의 작동 방식은 자칫 오해할 수 있는 비동기적 특성과 렌더링 사이클 덕분에 헷갈렸어서 시험기간 전 시간이 좀 남을때 글을 정리했습니다.1. 상태는 비동기적 특성을 지닌다.React에서 상태를 setState()로 변경하더라도, 즉시 반영되지 않습니다. 이는 React가 여러 상태 업데이트를 모아서 한 번에 처리하는 Batching 기법 때문입니다. 이 과정은 특정 렌더링 사이클 타이밍에 맞춰 일괄 처리됩니다. 따라서 변경되는 양상이 비동기적으로 보여서 상태는 정확히 비동기다. 라고도 오해할 수 있지만 그렇지는 않다고 합니다. 상태가 변경됨으로써, 리렌더링이 한번 이루어지고 나고..

Vite + React에서 이상적인 라우팅 구조 설계하기

Vite와 React로 프로젝트를 구성할 때, 라우팅 구조를 어떻게 설계하느냐는 유지보수성과 가독성에 큰 영향을 미친다고 생각한다. 이 글에서는 React Router v6 기준으로, router.tsx 파일을 별도로 구성하여 라우팅 책임을 명확히 분리하는 구조를 소개한다.기존 내가 했던 방식 (Vite)…App.tsx에 라우팅 책임을 맡겼다.import { BrowserRouter, Routes, Route } from 'react-router-dom';import Home from './pages/Home';import NotFound from './pages/NotFound';function App() { return ( } /> } /> );}Ap..