본문 바로가기

개발관련 지식들

Front, Back 분리시 동작 원리, 배포, 개발, 내가 궁금했던 것들(웹 서비스 구조)

#배포 #분리하여개발 #서버 #프론트엔드 서버 #백엔드 서버

 

(아래가 정리된 내용으로 출처 말고 아래서 보기를 권함)

출처: https://it-eldorado.tistory.com/85

좋은글 출처: https://iborymagic.tistory.com/94

도움이 되는 채팅: https://okky.kr/questions/874573

https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html :  Web server와 WAS의 차이와 웹 서비스 구조에 대해 설명한 매우 유익한 글

1. 일반적인 웹 어플리케이션의 동작 원리 : 풀 스택 (Full Stack)

프론트 엔드와 백 엔드가 구분되지 않는 일반적인 웹 어플리케이션의 동작 원리는 어떠할까? 파이썬 기반의 장고(Django), 자바 기반의 스프링(Spring) 등이 대표적인 웹 어플리케이션이라고 볼 수 있다. 이러한 웹 어플리케이션의 동작 원리는 아주 단순하다. 클라이언트가 요청(Request)을 보내면 서버에 존재하는 웹 어플리케이션이 데이터베이스 서버와 통신하여 필요한 데이터들을 전부 가져오고, 이것들을 가지고 완전한 HTML, CSS, JavaScript 파일들을 만들어서 클라이언트에게 제공한다. 그러면 클라이언트는 그렇게 전달받은 파일들을 그대로 브라우저에서 사용하기만 하면 된다. 이와 같은 방식으로 웹을 개발하는 사람들을 통상 풀 스택 개발자(Full Stack Developer)라고 부른다. 그러나 최근에는 프론트 엔드와 백 엔드가 분리되는 경향이 짙어지면서 프론트 엔드 개발자와 백 엔드 개발자가 나뉘었고, 이때 분리된 프론트 엔드와 백 엔드를 둘 다 개발하는 사람들도 마찬가지로 풀 스택 개발자라고 부른다.

※ 일반적인(벡엔드 서버만 존재하는) 웹 어플리케이션: 주문을 하면 요리까지 전부 직접 다 해서 제공해주는 식당에 비유할 수 있다.

2. 프론트 엔드의 분리 : SPA (Single Page Application)

왼쪽부터 순서대로 React, Angular, Vue

 

React, Vue, Angular 등은 JavaScript 라이브러리 혹은 프레임워크이다. 즉, 이것들은 클라이언트의 브라우저 단에서 실행되는 JavaScript를 멋지게 코딩할 수 있도록 도와주는 수단일 뿐이다. 특히 React나 Vue의 경우 JavaScript 코드를 작성할 때 필요한 만큼만 적재적소에 사용할 수 있기 때문에 이것들을 사용한다고 해서 프론트 엔드와 백 엔드가 구분되는 것은 절대 아니다. 다만 이것들을 활용하면 프론트 엔드와 백 엔드를 완전히 구분하여 두 기능을 독립적으로 개발할 수 있게 된다. 그렇다면 그것이 어떻게 가능한 것인지, 그 동작 원리를 한 번 살펴보도록 하자.

(위에서 말하는 것처럼 React는 멋지게 JS를 코딩할 수 있도록 도와주는 수단일 뿐이다. 스프링처럼 코드로 프로그램을 구현한다고 해서 서버가 되는게 아니라는 말이다. 그냥 JS코딩을 도와주는 수단일 뿐인 것이다.)

보통 우리가 말하는 웹서버(Web Server)가 이 프론트엔드 서버이다. 그리고 백엔드 서버는 보통 API서버라고 한다. 우리가 만든 웹 페이지를 '배포' 하면 해당 파일들은 프론트 서버에 올라가게 되고, 주소창에 URL을 입력하면 프론트 서버에 저장된 파일들을 전송받아서 웹페이지를 불러오게 되는 것. 이 때, 렌더링 방식에 따라 클라이언트(브라우저)와 서버 간의 소통 구조가 달라진다.

출처: https://iborymagic.tistory.com/94  (정말 도움되는 글)

개발자가 React 라이브러리를 활용하여 클라이언트에게 제공할 JavaScript 파일들을 ES6 + JSX 문법으로 코딩하면, Babel 등의 컴파일러가 그것들을 모든 브라우저에서 호환이 가능한 문법(ES5)의 코드로 변환해준다. 또한 Webpack 등의 모듈 번들러가 HTML, CSS, JavaScript 파일들을 효율적인 방식으로 적절히 번들링 하여 준비해둔다. create-react-app으로 생성한 React 프로젝트의 개발 환경에서는 "npm start"로 실행되는 개발 서버(webpack-dev-server)가 파일이 수정될 때마다 이러한 변환 작업들을 자동으로 수행해준다. 그리고 실제 배포 시에는 번들링 한 파일들을 프론트 엔드 서버의 다큐먼트 루트에 미리 준비해두고 웹 서버가 그 파일들을 제공할 수 있도록 설정해야 한다.

 

이후 클라이언트가 요청을 보내면 프론트 엔드 서버는 미리 준비해둔 HTML, CSS, JavaScript 파일들을 클라이언트에게 제공한다. 그러면 클라이언트의 브라우저는 전달받은 JavaScript 파일을 실행하여 페이지에 렌더링을 시작한다. 즉 앞서 React 라이브러리를 활용하여 코딩했던 JavaScript 코드는 동적으로 DOM에 렌더링을 해주기 위한 코드였던 것이다. 만약 렌더링 과정에서 DB 데이터가 필요한 경우에는 백 엔드 서버에게 API 요청을 보내서 필요한 데이터를 요청한다. 이러한 맥락에서 백 엔드 서버를 API 서버라고 부르기도 한다. 필요한 데이터를 전달해주는 역할만 수행할 뿐, 페이지 렌더링에 필요한 정적 리소스들(HTML, CSS, JavaScript)을 제공해주는 것이 아니기 때문이다. (하지만 프론트서버가 존재하지 않고 벡엔드 서버만 존재하면 벡엔드서버에서 정적 리소스도 당연히 제공하는 것이다)

 

이후, 페이지를 리로드 하지 않고 부분적으로만 리렌더링이 필요해지는 경우에는 사용자의 버튼 클릭과 같은 액션을 감지하여 JavaScript가 마찬가지 방식으로 백 엔드 서버에게 API 요청을 보내게 된다. 이때는 딱 해당 부분의렌더링에 필요한 데이터만 요청하게 된다. 그러면 JavaScript가 그 응답 데이터를 가지고 필요한 부분만 리렌더링을 해주게 된다. 이것 또한 개발자가 React 라이브러리를 활용하여 미리 코딩해둔 JavaScript 코드의 역할인 것이다.

 

이러한 맥락에서 React, Vue, Angular 등을 SPA(Single Page Application)라고 부른다. 기본적인 HTML, CSS, JavaScript 파일들만 제공받은 다음에 렌더링이 필요한 부분에 대해서만 직접 백 엔드 서버에게 API 요청을 보내서 리렌더링을 하는 방식이기 때문이다. 한 번 받은 페이지를 깜빡 거리는 일 없이 동적으로 제어가 가능해진다.

 

※ 주문을 하면 각종 재료와 불판만 제공해주고 요리는 알아서 해 먹으라는 식당에 비유할 수 있다. (백엔드 서버와 프론트엔드 서버의 기능이 각각존재 하는 경우가 여기서 말하는 재료만 준비해주고 요리는 알아서 해먹으라는 식당이다. 여기서 주의 할점이 백엔드, 프론트엔드의 기능을 각각 따로 맡아서 한다는 것을 다 개의 서버가 다른 서버에 있다는 것을 의미하는 것은 아니다. 아래의 말처럼 말이다)

(내생각에 아랫글은 SSR(Server Side Rendering)과 CSR(Client Side Rendering)을 설명한 것과 관련된 글이다. 둘의 차이점은 Rendering에 필요한 데이터들이 Server측에 모두 있는가에 있는 것같다. Server측에 모든 데이터가 있으면 SSR이고 그렇지 않고 백엔드 서버까지 또 거쳐서 데이터를 얻어내는 것이 CSR인 것 같다.

이와는 다르게 백 엔드 서버의 기능과 프론트 엔드 서버의 기능을 하나의 서버에서 서비스하도록 할 수도 있다. 즉 웹 서버, 웹 어플리케이션 서버, 웹 어플리케이션을 하나의 서버에 두는 것이다. 이 경우, 웹 서버가 웹 어플리케이션 서버에 대한 프록시 서버로 동작하도록 함으로써 API 요청을 처리할 수 있다. 그러나 이는 해당 서버가 마비되면 백 엔드 서버의 기능과 프론트 엔드 서버의 기능이 모두 마비된다는 문제점 때문에 사용되지 않는 경우도 많은 것 같다.

→ 참고 : https://fractalideas.com/blog/making-react-and-django-play-well-together/

 

※ CORS 및 쿠키 문제

백 엔드 서버와 프론트 엔드 서버가 서로 다른 도메인을 가지는 경우, 다음과 같은 두 가지 문제점이 발생한다. 첫째, 기본적인 CORS 정책은 다른 오리진의 자원에 접근하는 것을 막는다는 문제이다. 따라서 백 엔드 서버에게 API 요청을 보내면 CORS 정책에 의해 요청이 거부당할 것이다. 이를 해결하려면 백 엔드 서버 쪽에서 CORS를 허용하기 위한 별도의 설정을 해줘야 한다. 다음으로, 다른 오리진에 대한 요청 시에는 쿠키를 전송 혹은 수신할 수 없다는 문제이다. 즉 백 엔드 서버에게 API 요청을 보내더라도 쿠키가 설정되지 않기 때문에 로그인 등의 기능을 구현하는 것이 어려워진다. 이를 해결하려면 백 엔드 서버에게 API 요청을 보낼 때 JavaScript 단에서 특정 설정(XMLHttpRequest.withCredentials 옵션을 true로 설정하거나, fetch API라면 credentials 옵션을 include로 설정)을 해줘야 하며, 백 엔드 서버 쪽에도 응답의 헤더에서 Access-Control-Allow-Credentials 옵션을 true로 설정해줘야 한다. (참고)

한편 이것과 별개로 쿠키의 SameSite 옵션에도 주의를 기울여야 하는데, 기본적으로 Lax로 설정이 되기 때문에 GET 요청과 같은 안전한 요청이 아닌 이상 동일한 도메인일 때만 쿠키가 전송될 수 있다. 여기서 말하는 동일한 도메인이란 1차 도메인과 2차 도메인까지만을 말한다. 즉, a.naver.com과 b.naver.com은 동일한 도메인으로 취급된다. (참고)

참고로, 도메인 및 서브 도메인 간의 쿠키 공유와 관련해서는 링크 1 또는 링크 2를 참고하기 바란다.

 

※ 오리진 (Origin)

프로토콜, 도메인, 포트
를 합친 부분이다. 예를 들어, URL이 https://www.naver.com:8000/users/123이면 오리진은 https://www.naver.com:8000이다. 참고로, 서브 도메인이 있는 오리진과 없는 오리진은 다른 오리진으로 취급된다.

========================================================================================

아랜는 단톡방에한 내 질문글

안녕하세요 선생님들 아랫글 보다가 궁금한 점이 생겨서 질문드립니다. 

https://it-eldorado.tistory.com/85

의문1. React를 사용하면 프론트엔드서버의 기능을 하는 프로그램과 벡엔드서버의 기능을 하는 프로그램을 따로 사용하는 것으로 알고 있습니다. 하지만 그렇다고 해서 백엔드서버와 프론트엔드 서버를 각각 다른 서버에 반드시 두어야 하는 것은 아닌 것으로 알고 있습니다. 그렇다면 React를 사용해서 프론트엔드 서버와 벡엔드 서버(Spring사용)를 각각 따로 프로그램으로 구현했을 때 보통의 경우(가장 일반적인 경우)는 Front와 Back의 서버를 각각 달리 배포하는 것이 가장 일반적인 경우인가요?(앞에서 언급하고 또한 인용글에서도 나와있듯이 React를 사용하여 프론트엔드서버를 백엔드 서버와 따로 구현하였어도 하나의 서버에서 서비스할 수 있다는 사실 때문에 질문드립니다). 

A. 그렇다. React 는 그냥 자바스크립트 라이브러리에 불과합니다. 

의문2. "React를 사용하면 좋은 이점이 뭘까?" 라는 이유를 Client-Server 관점에서만 보자면 페이지 전부를 Reload하는 것이 아닌 일부, 필요한 부분만 리렌더링 하는 것이기 때문에 페이지 깜빡이는일 없이, 즉 SPA(Single Page Application)의 구현이 가능해진다라고만 알고 있습니다. 제가 궁금한 것은 "React를 사용하면 좋은 이점을 Client-Server관점에서만 보았을때(오직 이 관점에서만 보았을때) 페이지 전체를 리로드 하는 것을 없애주기 때문이다. 다른 이점은 없다" 라고 생각해도 되나요? 다른 이점이 또 있다면 짧게라도 언급해 주시면 정말 감사하겠습니다. 

A.  JSX와 JSP+Thymeleaf만 비교해봐도 장점이 보임. React 의 좋은 점은 UI 를 상태 값의 함수형으로 표현하기 때문에 제어권의 측면에서 이점이 있습니다. 필요한 부분만 리렌더링 하고 VDOM 어쩌고 SPA 구현 어쩌고 이런건 다... 그냥 부가적인거구요. 결론적으론 React DOM 에 한정해서 보면 HTML 을 작성하지 않고 자바스크립트만으로 HTML 을 렌더링 할 수 있는 규격화 된 방법이고, 이것이 더욱 프로그래머에게 유연함을 제공하기 때문에 좋습니다. (DOM싸개)

의문3. 위의 글의 내용과 관련된 질문입니다. 위의글에서는 프론트엔드 서버없이 벡엔드 서버만 있을때를 "주문을 하면 요리까지 전부 직접 다~ 해서 제공해주는 식당" 에 비유를 하고 React를 사용하여 프론트엔드 서버를 따로 만드는 경우는 "주문을 하면 각종 재료와 불판만 제공해주고 요리는 손님이 직접 알아서 해 먹으라는 식당" 에 비유하고 있습니다. 이렇게 비교가 되는 이유가 벡엔드 서버만 있는 경우는 필요한 DB데이터들까지 한번에 제공을 해서 그 DB에 있는 내용들까지 포함된 HTML문서가 클라이언트로 전달되기 때문인거고 프론트엔드 서버까지 있는 경우에는 DB에 있는 데이터는 전송할 수 없으니 요리까지는 직접 해줄수 없기 때문에 위와 같은 비유를 한건가요? 음.. 좀 더 명확히 제 질문은 위와 같이 비유를 한 그 근거가, 둘의 차이점인 DB데이터의 유무만을 가지고 위와 같은 비유(완성이 된 음식을 내오는것 vs 필요한 모든 재료만 나오고 요리는 내가 알아서)가 가능한건가요? 위와 같은 비유가 맞는 비유가 되는 다른 이유가 있는지 궁금합니다.