기본 콘텐츠로 건너뛰기

React 동시성 이해하기: 입력은 즉시 반응하고 무거운 렌더링은 뒤로 미루는 법

React 동시성 이해하기: 입력은 즉시 반응하고 무거운 렌더링은 뒤로 미루는 법 빠른 답 현재 기준으로는 Concurrent Mode 라는 전역 모드를 켜는 방식보다, createRoot 기반의 동시 렌더링과 transition API를 필요한 업데이트에 적용하는 방식으로 이해하는 편이 정확합니다. 입력창 값처럼 즉시 반영되어야 하는 상태는 transition 으로 감싸지 않고, 그 입력에 따라 바뀌는 무거운 결과 영역만 낮은 우선순위로 미룹니다. 상태 업데이트를 직접 호출하는 위치라면 useTransition 또는 startTransition 을, 이미 전달받은 값의 화면 반영만 늦추고 싶다면 useDeferredValue 를 고려합니다. 동시성 API는 느린 계산을 빠르게 만드는 도구가 아니라, 사용자가 먼저 체감하는 렌더링이 막히지 않도록 우선순위를 나누는 도구입니다. 목차 시간 흐름으로 이해하기 흐름으로 보기 Concurrent Mode라는 표현이 헷갈리는 이유 설정 기준 잡기 데이터 흐름과 상태 소유권 useTransition과 startTransition을 쓰는 위치 useDeferredValue가 어울리는 경우 흔한 안티패턴 현재 기준의 마이그레이션 포인트 시간 흐름으로 이해하기 검색창에 글자를 입력하고 그 결과로 큰 목록이 다시 렌더링되는 상황을 기준으로 보면 React 동시성은 다음 흐름으로 동작합니다. 입력 발생 사용자가 검색어를 입력합니다. → 긴급 업데이트 입력창의 text 상태는 즉시 반영됩니다. → 전환 예약 결과 목록을 바꾸는 query 업데이트는 낮은 우선순위로 표시됩니다. → 렌더링 조정 결과 렌더링 중 새 입력이 들어오면 React가 기존 작업을 중단하거나 최신 값 기준으로 다시 시작할 수 있습니다. → 화면 커밋 렌더링이 완료된 결과만 실제 DOM에 반영됩니다. 여기서 중요한 구분은 입력 상태와 결과 상태를 같은 속도의 일로 보지 않는 것입니다. 사용자는 키를 눌렀을 때 글자가 바로 찍히는지를 먼저 ...

공유 락과 배타 락의 차이: 읽기와 쓰기를 어떻게 막고 기다리게 할까

공유 락과 배타 락의 차이: 읽기와 쓰기를 어떻게 막고 기다리게 할까 빠른 답 공유 락은 읽은 행을 보호하는 락에 가깝고, 같은 행에 대한 다른 공유 락은 허용하지만 배타 락은 기다리게 합니다. 배타 락은 변경할 행을 독점하는 락에 가깝고, 같은 행에 대한 공유 락과 배타 락 요청을 모두 기다리게 합니다. 일반 SELECT 와 SELECT ... FOR SHARE , SELECT ... FOR UPDATE 는 다릅니다. InnoDB의 일반 조회는 보통 MVCC 스냅샷을 읽고 행 락을 잡지 않습니다. 데드락은 두 트랜잭션이 서로 필요한 락을 이미 상대가 쥐고 있을 때 발생하며, DB가 한쪽을 롤백할 수 있습니다. 목차 한눈에 비교 시간 흐름으로 이해하기 왜 공유 락과 배타 락이 헷갈리는가 예제 쿼리와 결과 해석 실행 계획과 인덱스가 락 범위를 바꾼다 대기 시간을 짧게 보고 실패 처리하기 데드락은 어떤 순서에서 발생하는가 락 대기와 데드락 출력 예시 해석하기 버전 기준과 오래된 설명 차이 한눈에 비교 목적 공유 락은 읽은 데이터가 트랜잭션 도중 바뀌지 않게 보호하는 쪽에 가깝고, 배타 락은 변경 대상 행을 독점하는 쪽에 가깝습니다. 호환성 공유 락끼리는 함께 잡을 수 있지만, 공유 락과 배타 락은 서로 충돌합니다. 배타 락끼리도 충돌합니다. 대표 문법 MySQL InnoDB에서는 SELECT ... FOR SHARE 가 공유 락 기반의 락킹 읽기이고, SELECT ... FOR UPDATE 가 배타 락 기반의 락킹 읽기에 가깝습니다. 일반 조회와의 차이 일반 SELECT 는 보통 consistent read로 처리되어 행 락을 잡지 않습니다. 락을 동반한 읽기가 필요할 때 FOR SHARE 나 FOR UPDATE 를 명시합니다. 인덱스 영향 락은 WHERE 조건 자체보다 실행 계획상 스캔한 인덱스 레코드와 범위에 더 가깝게 걸립니다. 장애 양상 단순 경합은 락 대기로 나타나고, 순환 대기는 데드락으로 감지되어 한쪽 트랜잭션이 실패할 수 있습니다. ...

React 리렌더링을 줄이는 실전 기준: memo, useMemo, useCallback은 언제 써야 할까

React 리렌더링을 줄이는 실전 기준: memo, useMemo, useCallback은 언제 써야 할까 빠른 답 리렌더링은 React의 정상 동작입니다. 먼저 React DevTools Profiler나 Profiler API로 느린 컴포넌트와 상호작용을 확인하는 편이 좋습니다. memo 는 부모가 자주 렌더링되지만 자식의 props 가 자주 같게 유지되는 경우에 효과가 있습니다. useMemo 는 비싼 계산 결과를 캐시할 때, useCallback 은 함수 참조 변화가 자식 리렌더링이나 Effect 재실행으로 이어질 때 씁니다. 메모이제이션에도 비교 비용, 메모리 비용, 의존성 관리 비용이 있으므로 모든 값과 함수에 붙이는 방식은 대체로 이득이 작습니다. 목차 선택 기준 매트릭스 React 리렌더링 흐름 문제가 되는 리렌더링 현재 기준과 오래된 설명의 차이 상태 소유권부터 정리하기 자식 컴포넌트 리렌더링 줄이기 린트와 구성 기준 Profiler로 병목 확인하기 흔한 오해와 주의사항 선택 기준 매트릭스 상황 부모만 자주 바뀌고 자식 props 는 그대로라면 memo 로 자식 렌더링을 건너뛸 수 있습니다. 상황 큰 배열 필터링, 정렬, 집계처럼 렌더 중 계산이 무겁다면 useMemo 로 계산 결과를 재사용합니다. 상황 memo 로 감싼 자식에게 콜백을 넘기는데 함수 참조가 매번 바뀐다면 useCallback 을 고려합니다. 조건 객체, 배열, 함수가 매 렌더마다 새로 만들어진다면 props 형태를 줄이거나 참조를 안정화해야 memo 가 의미를 가집니다. 조건 입력값, hover, 모달 열림 같은 일시적 UI 상태가 너무 위에 있다면 메모이제이션보다 상태 위치 조정과 컴포넌트 분리가 먼저입니다. 상황 React Compiler를 도입한 환경이라면 수동 메모이제이션 필요성이 줄 수 있지만, 빌드 설정과 지원 범위를 먼저 확인해야 합니다. React 리렌더링 흐름 React 컴포넌트는 state , props , context 가 바뀌면 다시...

CORS를 제대로 이해하기: 브라우저가 막는 것과 서버가 허용하는 것

CORS를 제대로 이해하기: 브라우저가 막는 것과 서버가 허용하는 것 빠른 답 CORS 오류는 서버 요청 자체가 실패했다기보다, 브라우저가 응답을 JavaScript에 노출하지 않았다는 뜻인 경우가 많습니다. Access-Control-Allow-Origin 은 클라이언트가 요청에 붙여 해결하는 헤더가 아니라 서버가 응답으로 내려줘야 하는 헤더입니다. 쿠키나 인증 정보를 포함하는 요청은 Access-Control-Allow-Origin: * 와 함께 쓸 수 없고, 클라이언트와 서버의 credentials 설정이 함께 맞아야 합니다. 디버깅할 때는 콘솔 메시지뿐 아니라 OPTIONS preflight 응답과 실제 요청의 응답 헤더를 나눠서 확인해야 합니다. 목차 흐름으로 보기 CORS가 필요한 배경 실제로 막히는 지점 서버 CORS 기준선 요청 코드에서 확인할 부분 디버깅과 운영 검증 품질 기준으로 보는 점검 순서 CORS와 CSRF의 차이 흐름으로 보기 흐름 다이어그램 브라우저에서 요청이 발생하면, 브라우저는 현재 페이지의 출처와 요청 대상의 출처를 비교합니다. 출처는 프로토콜, 호스트, 포트의 조합입니다. https://app.example.com 과 https://api.example.com 은 호스트가 다르므로 다른 출처이고, http://localhost:3000 과 http://localhost:8080 은 포트가 다르므로 다른 출처입니다. 출처가 다르면 브라우저는 동일 출처 정책을 기준으로 응답을 JavaScript에 보여줘도 되는지 판단합니다. 요청 자체가 서버까지 도달할 수는 있지만, 서버 응답에 올바른 CORS 헤더가 없으면 브라우저가 응답 본문과 일부 헤더를 코드에 숨깁니다. 요청 메서드나 헤더가 단순 요청 범위를 벗어나면 실제 요청 전에 OPTIONS preflight 요청이 먼저 나갑니다. 예를 들어 Content-Type: application/json 으로 POST 를 보내거나 Authorization 헤더를...