원티드 7월 프론트엔드 챌린지의 내용이 좋아서 조금 더 찾아보며 공부해보았다.
Single-Page Application 프레임워크들이 나타나기 이전에는 정적인 HTM*과 PHP, Java, Ruby, Python 같은 server-side 기술을 이용해서 만든 Multiple-Page Application이 지배적이었다.
MPA에서의 페이지 이동은 "a" 태그를 사용하여 새로운 HTML파일 하나를 서버에서 가져와 새로운 페이지를 만들어서 보여주는 방식을 사용했다.
이렇듯 클라이언트에서 서버에 여러개의 HTML파일을 요청하는 방식으로 작동하다보니, 웹사이트가 복잡해짐에 따라 서버에 대한 요구 사항도 증가했다.
AJAX의 도입으로 이 문제는 부분적으로 완화되었고 jQuery, Knockout.js, Backbone.js를 지나 Angular.js의 등장으로 우리가 알고있는 SPA 프레임워크가 탄생했다.
AJAX?
- Asynchronous JavaScript and XML
- 웹 페이지를 다시 로드하지 않고도 웹 페이지의 일부분만을 업데이트 할 수 있다.
MPA를 사용해온 방식을 form 태그를 통해 자세히 알아보자.
Typescript를 통해 form 태그의 attribute를 살펴보면, method가 존재한다.
get과 post 두가지 method가 있고 mdn 설명은 다음과 같다.
즉, form 태그를 이용해서 데이터 전송을 할 수 있는 것이다.
이렇게 form + input으로 이루어진 페이지를 html로 작성한다면 다음과 같을 것이다.
<div class="container">
<h1>Hello velog!</h1>
<form method="POST" action="action_page.php">
<label for="fname">이름</label>
<input type="text" id="fname" name="firstname" placeholder="Your name.." />
<label for="lname">성</label>
<input type="text" id="lname" name="lastname" placeholder="Your last name.." />
<label for="country">국적</label>
<select id="country" name="country">
<option value="australia">Korea</option>
<option value="canada">Canada</option>
<option value="usa">USA</option>
</select>
<label for="subject">메모</label>
<textarea id="subject" name="subject" placeholder="Write something.." style="height: 200px"></textarea>
<input type="submit" value="보내기" />
</form>
</div>
하지만 React를 사용하다보면, form 태그 내부에 있는 type=”submit”
input or button 태그에 onSubmit 이벤트가 일어나면 새로고침을 한다.
🤯 이 때문에 e.preventDefault()
를 꼭 써주었는데 form 태그는 왜 그럴까?
🤓 바로 화면을 업데이트 하기 위해서다.
MPA의 통신 구조를 염두에 두고 통신 상황에서 실제로 어떤 일이 일어나는지 따져보자.
blog.html
을 받는다.blog.html
을 열어 웹 사이트를 이용합니다.blog.html
페이지 내에 form 태그가 있고, 해당 form 태그는 input에 유저의 정보를 담아 서버로 POST 요청을 보낸다.blog.html
을 만든다. 유저가 가지고 있는 blog.html
에서는 이것을 알지 못한다.blog.html
을 받아와 이용한다.따라서 화면을 새로고침 하는 이유는 새로운 HTML 페이지를 보기 위함이다.
그래서 옛날 웹 사이트는 다음 페이지로 이동하면 HTML 페이지를 다운로드 받아올 때 화면이 깜박일 수 밖에 없었다.
SPA는 말 그대로 한 개(Single)의 Page로 구성된 Application을 말한다.
사용자가 웹사이트를 처음 방문하면 HTML/JS를 모두 다운받아 화면을 그리고, 이후에는 새로고침 없이 변화하는 부분만 리렌더링하는 방식으로 작동한다.
최근 웹 프로그래밍의 가장 흔한 방법이라고 할 수 있다.
React를 통해 SPA방식을 자세히 살펴보자.
React가 대표적으로 SPA방식을 따른다. React에서는 React-router라는 라이브러리를 활용해서 손쉽게 SPA를 만들 수 있다.
브라우저에서 서버로 웹 페이지를 조회하고 싶다는 요청을 보낸다.
서버는 브라우저로부터 날아온 요청 경로를 확인(/
)하고 index.html
을 서버 내 자원으로부터 찾아 응답으로 돌려준다. 이 때 index.html의 body 태그 내부는 비어있는 상태다.
브라우저는 HTML 파일에서 head 태그를 읽으며 추가로 필요한 자원(index.js
, index.css
등)을 서버로 다시 요청한다.
엔트리 역할을 하는 자바스크립트 파일이 다운로드 → 로딩 → 실행되고, 자바스크립트 앱은 미리 프로그래밍 된 로직에 따라 DOM API를 활용해 화면에 태그들을 그려넣는다.
<div id="root"></div>
<script>
const root = document.getElementById("root")
root.innerHTML = `
<div>
<h1>hello world!</h1>
<button type="button">get new posts</button>
</div>
`
</script>
초기 로딩 이외의 변경이 필요할 때는 서버 API에 요청하여 받아온 데이터로 새롭게 갈아 끼운다.
<div id="root"></div>
<script>
const root = document.getElementById("root")
root.innerHTML = `
<div id="root">
<h1>hello world!</h1>
<button type="button">get new posts</button>
</div>
`
const getPosts = function() {
return fetch("/posts").then(res => res.json()).then(
({ posts }) => {
const feed = document.createElement("ul")
feed.innerHTML = posts.map(post => `<li>${post.title}</li>`).join()
root.appendChild(feed)
}
)
}
</script>
SPA방식은 새로고침 없이 변경되는 부분만 새로운 데이터로 갈아끼우는 방식으로 구현되어있다.
이 경우 MPA 방식에 비해 페이지 전환이 부드러우며, 기존 방식에 비해 훨씬 동적인 UX를 제공한다.
https://www.scalablepath.com/front-end/single-page-applications
https://www.hestabit.com/blog/single-page-vs-multi-page-web-apps/
https://programmingpercy.tech/blog/how-to-implement-a-single-page-application-using-react-router/
원티드 7월 프론트엔드 챌린지
좋은 글이네요. 공유해주셔서 감사합니다.