아키텍처 : 웹 애플리케이션의 전체 구조를 나타내는 디자인 패턴이다. 전체 애플리케이션의 구성, 데이터 흐름, 컴포넌트 간의 관계 등을 다룬다.
렌더링 방식 : 사용자에게 UI를 표시하는 방법을 나타낸다. 사용자가 데이터를 받아오고 화면에 표시되는 기술적인 접근 방식을 다룬다.
SPA (Single Page Application) : 웹 애플리케이션이 단일 페이지로 이루어진 아키텍처로, 페이지 간 전환 시 전체 페이지를 다시 로드하지 않고 필요한 부분만 업데이트하는 방식이다. (visible/invisible 이용하여 한가지의 html만 보이도록 한다.) 주로 클라이언트 측에서 렌더링되며, JavaScript를 사용하여 동적으로 콘텐츠를 업데이트한다. 초기 로딩 이후에는 서버와의 통신을 통해 데이터를 주고받아 화면을 갱신한다.SSG(Static Site Generation) : 페이지를 사전에 생성하여 정적 파일로 저장한 후 클라이언트 요청시 해당 정적 파일을 제공하는 방식이다. 별도의 동작 서버가 필요하지 않고 클라이언트 측에서는 간단한 정적 파일을 받아 렌더링하는 방식이기 때문에 복잡한 아키텍처가 필요없다.CSR(Client-Side Rendering): 웹 페이지 초기 로딩 시 클라이언트 측에서 필요한 HTML, CSS, JavaScript 파일을 다운로드하고 JavaScript를 실행하여 페이지를 렌더링한다. 이후에 클라이언트에서 API 등을 통해 데이터를 받아와서 동적으로 업데이트한다.
장점 : 다운로드 이후에는 필요한 데이터를 비동기적으로 받아와 동적으로 페이지를 업데이트할 수 있어 빠르다.
단점 : 초기 로딩 속도 느리고, 검색 엔진 최적화 어려움이 있다.
1. 사용자가 웹 페이지에 접속하면 클라이언트는 해당 페이지를 서버에 요청한다.
2. 받아온 HTML파일은 HTML과 CSS로 이루어진 최소한의 레이아웃과 디자인을 가지며 데이터는 포함되어있지 않은 기본적인 페이지 구조로 이루어져 있다.
3. JS 파일을 로딩/실행하여 서버에 데이터를 요청(API 호출)하여 가져온다.
4. 가져온 데이터를 사용해서 클라이언트측에서 동적으로 웹 페이지를 렌더링한다.
5. 상호작용에 따라 필요한 부분을 JS를 통해 업데이트한다.
SSR (Server-Side Rendering): 서버에서 초기 HTML, CSS, JavaScript, 데이터를 렌더링한 후 클라이언트에 전송하며 이후 상호작용은 클라이언트에서 처리된다. 초기 로딩 시에는 서버에서 페이지를 완성하여 제공하며 이후에는 클라이언트에서 동적으로 데이터를 처리한다.SGR (Server-Generated Rendering): 서버에서 정적 페이지를 미리 생성하고 클라이언트에게 전송한 후, 클라이언트는 초기에 받은 정적 페이지를 기반으로 JavaScript나 플레이스홀더를 사용하여 동적 데이터를 비동기적으로 가져와서 페이지를 업데이트한다.1. 사용자가 웹 페이지에 접속하면 클라이언트는 해당 페이지를 서버에 요청한다.
2. 서버는 해당 페이지에 필요한 데이터를 수집하고 CSS, 데이터, 플레이스홀더가 포함된 HTML을 생성하여 클라이언트에게 응답으로 보낸다.(플레이스홀더 : 나중에 클라이언트측에서 JS를 사용하여 동적으로 채워질 데이터를 가리키는 일종의 마커)
3. 클라이언트가 HTML을 받으면 JS 파일이 함께 로딩되고 JS 파일은 플레이스홀더에 해당하는 데이터를 서버에 비동기적으로 요청하고 받아와서 페이지를 렌더링한다. 이로써 플레이스홀더에 있던 부분이 실제 데이터로 채워져서 화면에 나타난다.
4. 클라이언트가 렌더링된 페이지와 상호작용하면서 데이터가 추가로 필요한 경우 AJAX, Fetch를 사용하여 서버에 데이터를 요청하고 동적으로 페이지를 업데이트한다.
SEO(Search Engine Optimization) : 검색 엔진 최적화. 웹사이트나 웹 페이지가 검색 결과에 노출되기 위해 수행하는 최적화 작업
초기 로딩 시에 서버에서 완성된 HTML을 제공함으로써 검색 엔진은 페이지를 빠르게 이해하고 색인화할 수 있어서 검색 결과에서 해당 페이지를 더 잘 노출시킬 수 있다.
<!--index.html(빈 쉘)-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSR Example</title>
</head>
<body>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>
// app.js
// 기본적인 페이지 구조
const shell = document.getElementById('app');
// 서버로부터 데이터를 받아오는 함수 (가정)
async function fetchDataFromServer() {
// 실제로는 서버 API를 호출하거나 다른 방식으로 데이터를 가져옴
return new Promise((resolve) => {
setTimeout(() => {
resolve({ title: 'CSR Example', content: 'This is dynamic content fetched from the server.' });
}, 1000);
});
}
// 데이터를 받아와서 페이지 렌더링하는 함수
async function renderPage() {
// 서버로부터 데이터를 받아옴
const data = await fetchDataFromServer();
// 받아온 데이터를 사용하여 페이지 동적으로 렌더링
shell.innerHTML = `
<h1>${data.title}</h1>
<p>${data.content}</p>
`;
}
// 페이지 로드 후 초기 렌더링 수행
renderPage();