MPA? SPA? 톺아보기

김상민·2023년 8월 4일
0

Web

목록 보기
1/4

원티드 7월 프론트엔드 챌린지의 내용이 좋아서 조금 더 찾아보며 공부해보았다.

🥊 SPA와 MPA의 역사

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

MPA를 사용해온 방식을 form 태그를 통해 자세히 알아보자.

Typescript를 통해 form 태그의 attribute를 살펴보면, method가 존재한다.
get과 post 두가지 method가 있고 mdn 설명은 다음과 같다.

  • POST: The POST method; form data sent as the request body.
  • GET (default): The GET; form data appended to the action URL with a ? separator. Use this method when the form has no side effects.

즉, form 태그를 이용해서 데이터 전송을 할 수 있는 것이다.

🤔 event.preventDefault

이렇게 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의 통신 과정

MPA의 통신 구조를 염두에 두고 통신 상황에서 실제로 어떤 일이 일어나는지 따져보자.

  1. 유저가 서버에 GET 요청을 보내 blog.html을 받는다.
  2. 유저는 브라우저에서 blog.html 을 열어 웹 사이트를 이용합니다.
  3. blog.html 페이지 내에 form 태그가 있고, 해당 form 태그는 input에 유저의 정보를 담아 서버로 POST 요청을 보낸다.
    유저는 해당 정보가 업데이트 된 이후의 화면을 봐야 합니다.
  4. 서버는 새로운 blog.html 을 만든다. 유저가 가지고 있는 blog.html 에서는 이것을 알지 못한다.
  5. 유저는 화면을 새로고침 하여 서버에 새로운 blog.html 을 받아와 이용한다.

따라서 화면을 새로고침 하는 이유는 새로운 HTML 페이지를 보기 위함이다.
그래서 옛날 웹 사이트는 다음 페이지로 이동하면 HTML 페이지를 다운로드 받아올 때 화면이 깜박일 수 밖에 없었다.

📄 SPA

SPA는 말 그대로 한 개(Single)의 Page로 구성된 Application을 말한다.
사용자가 웹사이트를 처음 방문하면 HTML/JS를 모두 다운받아 화면을 그리고, 이후에는 새로고침 없이 변화하는 부분만 리렌더링하는 방식으로 작동한다.

최근 웹 프로그래밍의 가장 흔한 방법이라고 할 수 있다.
React를 통해 SPA방식을 자세히 살펴보자.

🤓 React의 SPA(with CSR)

React가 대표적으로 SPA방식을 따른다. React에서는 React-router라는 라이브러리를 활용해서 손쉽게 SPA를 만들 수 있다.

  1. 브라우저에서 서버로 웹 페이지를 조회하고 싶다는 요청을 보낸다.

  2. 서버는 브라우저로부터 날아온 요청 경로를 확인(/)하고 index.html 을 서버 내 자원으로부터 찾아 응답으로 돌려준다. 이 때 index.html의 body 태그 내부는 비어있는 상태다.

  3. 브라우저는 HTML 파일에서 head 태그를 읽으며 추가로 필요한 자원(index.js, index.css 등)을 서버로 다시 요청한다.

  4. 엔트리 역할을 하는 자바스크립트 파일이 다운로드 → 로딩 → 실행되고, 자바스크립트 앱은 미리 프로그래밍 된 로직에 따라 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>
  5. 초기 로딩 이외의 변경이 필요할 때는 서버 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를 제공한다.

🪧 Reference

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월 프론트엔드 챌린지

profile
성장하는 웹 프론트엔드 개발자 입니다.

2개의 댓글

comment-user-thumbnail
2023년 8월 4일

좋은 글이네요. 공유해주셔서 감사합니다.

1개의 답글