1. SPA(Single Page Application) = 단일 페이지 모던 웹 애플리케이션
SPA는 웹 애플리케이션이 하나의 HTML 페이지에서 동적으로 콘텐츠를 변경하며 동작하는 방식의 애플리케이션이다.
즉, 페이지 전체를 새로고침하지 않고 필요한 부분만 동적으로 변경하는 방식이다.
대표적으로 SPA 프레임워크와 라이브러리에는 React.js, Vue.js, Angular 등이 있다.
초기에 필요한 모든 JS와 CSS를 가져와서 로딩이 길지만 이후에는 빠른 속도로 이용이 가능하고 새로운 페이지 요청 없이 동작이 가능하다.
React는 하나의 index.html만을 사용하며 페이지를 새로고침하지 않고도 컴포넌트들을 동적으로 변경할 수 있다.
이를 가능하게 하는 핵심 요소는 Virtual DOM과 React Router다.
1) Virtual DOM
기존 HTML을 직접 수정하는 대신 메모리에서 변경 사항을 먼저 계산한 후 실제 DOM을 최소한으로 업데이트 하는데 이를 통해 빠른 렌더링 성능을 제공한다.
2) React Router
브라우저의 URL이 변경되더라도 새로운 HTML 파일을 요청하는 것이 아니라 JS가 동적으로 렌더링한다.
다른 페이지로 이동해도 실제로는 같은 index.html을 사용하며 필요한 컴포넌트만 변경된다.
2. HOOK이란?
React Hooks는 함수형 컴포넌트에서 상태 관리와 생명주기 기능을 사용할 수 있도록 해주는 기능이다.
원래는 클래스 컴포넌트에서만 사용 가능했던 기능(setState, componentDidMount)을 함수 컴포넌트에서도 사용할 수 있게 도와준다.
Hooks를 사용하면 간결한 함수형 컴포넌트로 변환이 가능하고 상태 및 로직을 더 쉽게 관리할 수 있다.
1) useState(상태관리)
컴포넌트 내에서 상태(state)를 관리하는 Hook이다.
예시는 아래와 같다. 원래는 클래스 컴포넌트에서 this.state.count 뭐 이렇게 설정했던걸 간단하게 사용할 수 있다.
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;
2) useEffect (생명주기 관리)
컴포넌트가 렌더링될 때 실행되는 코드로 componentDidMount, componentDidUpdate, componentWillUnmount를 대체한다.
예시는 아래와 같은데 useEffect 안에서 타이머를 설정해서 컴포넌트가 사라질 때 정리할 수 있다.
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <p>Elapsed time: {seconds} seconds</p>;
}
export default Timer;
3) useRef
렌더링 없이 값을 유지하거나 DOM 요소에 접근할 때 사용한다.
useRef를 사용해서 input 요소에 직접 접근이 가능한데 state와 달리 값이 변경되어도 컴포넌트가 다시 그려지지 않는다.
import React, { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}
export default FocusInput;
4) useContext (전역 상태 관리)
전역 데이터를 쉽게 공유할 떄 사용한다. Redux 대체가 가능하다고 하는데 Redux를 사용할 거긴 하다.
import React, { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function ThemeComponent() {
const theme = useContext(ThemeContext);
return <p>Current Theme: {theme}</p>;
}
export default function App() {
return (
<ThemeContext.Provider value="dark">
<ThemeComponent />
</ThemeContext.Provider>
);
}
useContext(ThemeContext)를 사용해서 전역 상태를 쉽게 가져온다.
부모에서 Provider를 통해서 데이터를 제공하는데 useContext로 하위 컴포넌트에서 바로 사용이 가능하다.
결론: Hooks는 React를 더 쉽게 만들어준다
3. Redux (상태 관리 라이브러리)
Redux는 React에서 전역 상태를 효율적으로 관리하기 위해 만들어진 상태 관리 라이브러리다.
React에서 상태를 다룰 때 컴포넌트 간 상태 공유가 어려운 문제를 해결하기 위해 등장했다.
기존에는 한 컴포넌트에서 useState로 관리하는 값을 다른 컴포넌트에서 사용하려면 부모-자식 간 props로 계속 내려줘야했는데 컴포넌트가 많아지면 코드가 지저분해지고 유지보수가 어려운 문제점이 있었다.
특히 로그인 정보나 사용자 설정 같은 전역 상태를 관리할 때 되게 불편하게 느껴졌다고 한다.
function Parent() {
const [user, setUser] = useState("John");
return <Child user={user} />;
}
function Child({ user }) {
return <GrandChild user={user} />;
}
function GrandChild({ user }) {
return <p>사용자: {user}</p>;
}
그리고 useState는 상태가 변경될 때 그 컴포넌트와 하위 컴포넌트가 모두 다시 렌더링 되어서 불필요한 렌더링이 많아지면 성능 저하로 이어질 수 있었다.
그래서 Redux가 등장했다.
Redux는 하나의 중앙 저장소(Store)를 사용하여 모든 컴포넌트가 동일한 상태를 공유할 수 있도록 하는 전역 상태 관리 라이브러리다.
Redux 동작원리
1) 사용자가 액션(dispatch)을 발생시킨다
2) Reducer가 Action을 받아 상태를 변경한다
3) Store가 변경된 상태를 모든 컴포넌트에 전달한다
즉, 중앙에서 모든 상태가 관리되고 컴포넌트 간 props 없이도 쉽게 공유가 가능하다.
그럼 Redux랑 hook 뭐가 달라? 둘 다 상태관리하는데?
둘 다 상태(state)를 관리하는 기능이지만, 사용 목적과 방식이 다르다.
Redux는 "전역 상태 관리"를 위한 라이브러리, Hook(useState, useContext)는 "로컬 상태 관리"를 위한 기능이다.


4. Axios & AJAX
1) AJAX (Asynchronous JavaScript and XML)
비동기(Asynchronous) 방식으로 서버와 데이터를 주고받는 기술을 의미한다.
자바스크립트에서 XMLHttpRequest 또는 fetch API를 사용하여 서버와 통신한다.
XML뿐만 아니라 JSON, HTML, 일반 텍스트도 주고받을 수 있다.
2) Axios
Axios는 AJAX 요청을 쉽게 처리하기 위한 JavaScript 라이브러리이다.
AJAX를 활용하는 라이브러리 중 하나로, fetch API보다 간편한 문법을 제공한다.
Promise 기반으로 동작하여 async/await을 지원한다.
JSON 데이터를 자동으로 변환하고 요청 및 응답을 쉽게 인터셉트할 수 있다.
정리하자면,
AJAX는 서버와 데이터를 비동기적으로 주고받는 "기술 개념"이고, Axios는 AJAX를 더 쉽게 사용할 수 있도록 도와주는 "라이브러리"이다.
Axios는 fetch API보다 간결한 문법, JSON 자동 변환, 요청 취소 기능을 제공하고 AJAX를 직접 쓰는 것보다 Axios를 쓰는 것이 대부분의 경우 더 편리하다.
5. Async/Await
Async/Await는 Javascript에서 비동기 코드를 보다 직관적으로 작성할 수 있도록 도와주는 문법이다.
기존의 Promise.then() 체인 방식보다 가독성이 뛰어나며 동기 코드처럼 보이지만 비동기적으로 실행된다.
서버에서 데이터를 가져오는 비동기 작업 처리 시, MySQL이나 MongoDB 등의 비동기 DB 요청 처리 시, 타이머/이벤트 헨들링 시 사용한다.
기존 Promise.then과 async/awiat를 비교해보자.
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data received");
}, 2000);
});
}
fetchData().then((data) => {
console.log(data); // "Data received"
}).catch((error) => {
console.error(error);
});
async function fetchDataAsync() {
try {
const data = await fetchData();
console.log(data); // "Data received"
} catch (error) {
console.error(error);
}
}
fetchDataAsync();
await fetchData는 fetchData가 완료될 때까지 기다린 후 값을 반환한다.
하지만 전체 실행이 블로킹 되지는 않아서 다른 비동기 작업들은 정상적으로 실행된다.
await는 async 함수 안에서만 사용할 수 있고 순차적으로 진행되므로 여러 개의 비동기 작업을 병렬로 실행해야 할 경우 Promise.all() 을 활용해야 하고 try ... catch를 사용하여 비동기 코드에서 발생할 수 있는 예외를 처리해야 한다.
6. localStorage, sessionStorage, cookie
이 세 가지는 클라이언트 측(브라우저)에 데이터를 저장하는 방법으로 각자의 목적과 특성이 다르다.
1) localStorage
브라우저에 데이터를 영구적으로 저장하는 공간
2) sessionStorage
현재 탭이 유지되는 동안만 데이터를 저장하는 공간
3) cookie
클라이언트와 서버 간의 데이터를 주고받기 위해 사용되는 작은 데이터 저장소
localStorage는 주로 JWT 토큰 저장이나 테마 설정 같은 장기간 유지해야 하는 데이터로 사용되고 JWT 토큰은 보안상 권장되지는 않는다.
sessionStorage는 일회성 데이터를 저장할 때 주로 사용하고 사용자가 현재 세션에서만 필요한 데이터용으로 사용한다.
cookie는 사용자 인증 정보를 저장할 때(세션ID나 JWT 토큰) 사용하고 서버와 데이터를 자동으로 동기화해야 할 때 사용한다.
나는 쿠키로 JWT 토큰을 저장하려고 한다.
'dev > 프로젝트' 카테고리의 다른 글
[프로젝트] S3 + CloudFront + Route53 (10) | 2025.02.09 |
---|---|
[프로젝트] 프론트엔드(React & Redux) 적용 (8) | 2025.02.07 |
[프로젝트] JWT + Redis 전환 (4) | 2025.02.06 |
[프로젝트] 테스트 코드 적용 (5) | 2025.01.30 |
[프로젝트] QueryDSL 적용 (2) | 2025.01.29 |