목차

  • 네트워크를 알아야 하는 이유
  • 네트워크 거시적으로 살펴보기
  • 네트워크 미시적으로 살펴보기

1. 네트워크란 무엇인가?

네트워크란(Network), 두대 이상의 장치가 연결되어 서로 정보를 주고 받을 수 있는 통신망을 의미한다.

 

네트워크의 도식화

그렇다면, 우리는 네트워크 관련 지식들을 왜 알아야 할까? 사실 학부 수업이나 팀 프로젝트에서도 네트워크 관련된 부분을 도맡아 해 본적이 없다. 항상 가장 쉽게 느껴지는건 UI구축이였기 때문에, 백엔드로 넘어가는 순간 턱 막혀버리기 일수였다. 하지만 이번에 학부 연구에서 웹을 구축하고, 서버에 배포하는 과정들을 직접 손으로 해보면서 네트워크 지식이 없으면 나는 그저 GPT가 써주는 코드를 갖다 쓰는일 밖에는 할 수 없었다. 그래서 이번엔 네트워크를 좀 짚고 넘어가보자 한다!

 

네트워크는 우리 일상속에 아주 잘 스며들어 있다. 이 포스팅을 보고있는 당신 조차도 네트워크라는 복잡한 통신망 안에 있는것이다. 개발자가 처음에 가장 쉽게 눈으로 보며 접할 수 있는건 단연 웹 프로그래밍이다. 프레임워크나 라이브러리가 무수히 많고, 그냥 가져다 쓰면 웹을 뚝딱 만들 수 있어 처음에 비전공자도 코드를 좀 만지다 보면 "어? 뭐야 내가 항상 쓰던 웹 페이지가 이렇게 만들어지는거였어?" 라고 착각하기 쉽다. 나 또한 처음에 .html파일을 만들고, 그걸 친구에게 자랑하려고 그냥 localhost:3000번이 URL인줄 알고 보냈다가 친구가 접속을 하지 못해 당황했던 기억이 난다. 이렇게 또 다시 배우면서 네트워크는 어떻게 동작하는지 견문을 넓히면 좋을 것 같다.

 

2. 네트워크 거시적으로 살펴보기

 

네트워크 구조의 도식화

네트워크는 위의 그림과 같이 그래프의 형태를 가지고 있다. 자료구조를 한번쯤 공부 해 본 사람이라면, 노드와 간선으로 이루어진 그래프는 한번씩 접해 봤을것이다.

 

네트워크를 공부하다 보면, 호스트, 클라이언트 같은 단어를 수도 없이 듣게 될건데, 먼저 호스트가 무엇을 의미하는지 알아보자.

 

네트워크에서의 호스트를 설명한 그림

네트워크라는 그래프에서, 가장자리에 위치해 있으면서, 네트워크에 주고받을 정보를 맨 처음으로 보내거나, 네트워크에서 가장 마지막으로 정보를 받는 노드를 호스트 라고 한다. 카톡을 예로 한번 들어보자.

- 내가 친구에게 카톡으로 메시지를 보낸다(여기서 맨 처음 네트워크를 통해 친구에게 "메시지"라는 정보를 전달함으로(네트워크를 통해 전달받은 정보를 최초로 발신), 여기서 나의 스마트폰은 "호스트" 이고, 그 메시지를 받은 친구의 스마트폰도 "호스트"이다(네트워크를 통해 전달받은 정보를 최종적으로 수신).

 

그렇다면 오늘날 가장 많이 쓰이는 네트워크는 어떻게 정보를 주고 받을까?

패킷 교환 네트워크는 페이로드 +  헤더(어디서, 또 어디로 정보를 전송할지 정보를 담은 객체) + 트레일러를 포함하여 정보를 주고 받는다.

즉, 보내고자 하는 메시지를 패킷이라고 하는 단위로 쪼개어 보내는 방식을 의미한다. 그리고 그 하나의 패킷은 보내고자 하는 실질적인 데이터를 의미하는 "페이로드",  패킷에 대한 부가정보 또는 제어 정보인 "헤더", 또는 "트레일러" 라는 부분으로 구성이 되어있다.

 

3. 네트워크를 미시적으로 살펴보기

- 두개의 네트워크 기기가 네트워크를 통해 정보를 주고받는 상황에서 어떤 일이 일어나는지 살펴보자.

 

일단 기본적으로 알아야 할 세가지 개념들이 있다.

  • 프로토콜(네트워크 세상의 언어 라고도 한다)
  • 네트워크 참조 모델
  • 캡슐화와 역캡슐화

자 그럼, 네트워크를 공부하다 보면 항상 등장하는 "프로토콜" 이란 무엇일까?

위의 패킷 전달 방식을 예시로 들어 보자.

 

더보기

내가 친구 A에게 택배를 보내고자 한다. 먼저, 나는 택배 상자 안에 친구에게 보낼 내용물을 담고(페이로드), 그 다음, 상자에다가 운송장을 출력하여 붙여준다. 이 운송장에는 누가 보내는지, 누가 이 택배를 받는지 등등 부가 정보가 담겨있다(헤더). 그렇지만, 이 택배는 내가 친구에게 직접 전달하는것이 아니라, 내가 편의점 택배를 부치면, 택배 기사님께서 택배를 픽업하고, 택배를 보내는 방식이다. 하지만, 내가 친구에게 보낸 페이로드와 헤더의 언어는 Java로 되어있다고 가정했을때, 택배 기사님이 갖고있는 프로그래밍 언어가 Python이면 어떤 상황이 벌어질까? 택배 기사님은 택배를 어디로 어떻게 보내야 할지 절대 이해할 수 없을것이고, 내 친구 또한 Python만 알고있다면, 설령 택배를 받았다고 한들 안에있는 페이로드가 무슨 내용인지 이해하지 못할 것이다.

이처럼, 네트워크를 통해 통신할때에는 서로간의 정해진 규칙이 있어야 한다. 이러한 규칙을 알고 있어야 네트워크 기기에서 네트워크 중간 노드(라우터, 스위치)에서도 내가 전송한 데이터의 형식을 확인하고, 최종 목적지까지 안전하게 보낼 수 있다. 이렇듯, 네트워크에서의 프로토콜은 한마디로 말해 정해진 "통신 규칙" 이다.

 

우리가 많이 들어본 프로토콜은 HTTP, HTTPS, TCP, UDP등등이 있을 것이다. 항상 기억해 두자. 각각의 프로토콜은 사용 목적과 특징이 다르다. 예를들어, HTTPS는 HTTP보다 보안성이 뛰어나다는 특징을 갖고 있다.

 

출처 : 조코딩 Youtube

이번에는 React를 사용한 웹 애플리케이션에서 페이지간의 라우팅을 어떻게 하는지 정말 간단히 짚고 넘어가겠다.

 

이번 프로젝트에서 요구하는 사이트를 예로 들어보자. 이번 페이지의 규모는 그렇게 큰 규모가 아니기 때문에(아직까지는) 일단은 2개의 페이지만 있다. 로그인페이지, 피드백 페이지.

 

로그인 구현은 아직 하지 못했기 때문에 이번에는 간단히 로그인 버튼을 누르면 피드백 페이지로 이동하도록 라우팅을 설정 하도록 하겠다.

 

리액트에서 라우팅이란, 

단일 페이지 애플리케이션(Single Page Application, SPA) 내에서 사용자가 다양한 페이지를 탐색할 수 있도록 하는 메커니즘을 말한다. 전통적인 웹 애플리케이션에서 페이지 간의 이동은 새로운 페이지 요청을 서버에 보내고, 서버는 새로운 페이지를 클라이언트에 전송하는 방식으로 이루어진다. 이 과정에서 페이지 전체가 새로고침되며, 사용자는 그동안 딜레이를 겪게 된다.

그러나 리액트와 같은 SPA 프레임워크나 라이브러리에서는 클라이언트 사이드에서 라우팅을 처리한다. 즉, 사용자가 링크를 클릭할 때마다 서버에 새 페이지를 요청하는 대신, 리액트가 미리 로드해둔 컴포넌트를 화면에 렌더링하여 페이지를 변경한다. 이 과정에서 실제 페이지 전환은 발생하지 않으며, URL만 변경됨으로써 사용자에게 여러 페이지가 있는 것처럼 느껴지게 한다.

 

리액트 라우팅의 장점:

1. 속도: 모든 리소스가 처음에 한 번만 로드되고, 필요한 컴포넌트만 선택적으로 업데이트되므로 페이지 전환 시 새로고침이 필요 없어 속도가 매우 빠르다.
2. UX: 페이지를 새로고침하지 않기 때문에 훨씬 향상된 UX를 가진다. 사용자는 끊김 없는 화면이동과 즉각적인 페이지 전환을 경험할 수 있다.
3. 효율적인 자원 사용: 필요한 컴포넌트만 로드하고 렌더링하기 때문에, 네트워크 사용량과 서버 부하가 감소한다.
4. 검색 엔진 최적화(SEO)**: 리액트 라우팅 라이브러리 중 일부는 서버 사이드 렌더링(SSR)이나 정적 사이트 생성을 지원하여 SEO 문제를 해결한다.

새로고침 여부:
리액트 라우팅을 사용하면, 사용자가 애플리케이션 내에서 페이지 간에 이동할 때 웹 페이지의 새로고침 없이 뷰가 변경된다. URL은 변경되지만, 이는 브라우저의 History API를 통해 관리되며, 실제로 페이지를 새로 불러오는 것이 아니라 애플리케이션 상태의 변경을 반영한다.

예제 설명:

예를 들어, 로그인 페이지에서 피드백 페이지로의 이동을 구현하려면, 리액트의 `react-router-dom` 라이브러리를 사용하여 라우팅을 설정한다. 로그인 버튼을 누르면, `useNavigate` 훅을 사용하여 피드백 페이지로의 경로를 지정할 수 있다. 이러한 방식으로, 리액트 애플리케이션에서는 사용자의 액션에 따라 끊김 없는 페이지 전환을 구현할 수 있다.


 

자 그럼, 이번 프로젝트에서의 예시를 한번 보자.

 

먼저, 올바른 디렉토리에서 npm install react-router-dom 를 입력해 router-dom을 설치해준다. 여기서 잘 확인해야 할 것은, 현재 설치된 react와 router-dom의 버전에서 불일치가 발생하지 않도록 해야한다.(나도 단지 이것때문에 30분동안 스택오버플로우를 뒤졌다...)

 

설치가 되었으면, package.json으로 이동해 dependencies안에 제대로 설치가 되었는지 확인한다.

 

  "name": "feedback_collection_web_app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "again": "^0.0.1",
    "axios": "^1.6.7",
    "bootstrap": "^5.3.2",
    "react": "^18.2.0",
    "react-bootstrap": "^2.10.0",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.51.2",
    "react-modal": "^3.16.1",
    "react-router-dom": "^6.22.3",
    "react-scripts": "5.0.1",
    "react-toastify": "^10.0.4",
    "web-vitals": "^2.1.4"
  },

 

이렇게  "react-router-dom": "^6.22.3" 설치가 된것이 보이면, router는 제대로 설치가 된 것이다. 먼저, login page에서 login이라는 버튼을 누르면 feedback page로 이동 할 수 있도록 코드를 살펴보자.

 

먼저, loginpage.js로 이동해 아래처럼 import를 해 준다.

import { useNavigate } from 'react-router-dom';

 

 

React Router v5까지는 페이지 이동을 위해 useHistory 훅을 사용했었다. 그러나 v6부터는 useNavigate로 대체되어, 라우팅 및 페이지 이동 관련 기능을 좀 더 직관적이고 간결하게 사용할 수 있게 되었다. useNavigate 훅은 라우터의 history 스택에 직접적으로 접근하지 않고도 페이지 이동이나 뒤로 가기 등의 작업을 수행할 수 있게 해준다.

 

 

 

자 그럼, 우리는 login버튼 하나만 가지고 있으므로, 그 버튼에 대한 핸들러 함수를 추가한다. 단, 핸들러를 추가 하기 전, navigation을 담당 할 상수를 선언 해 준다.

const navigate = useNavigate();

 

그 다음 핸들러 함수를 작성 해 준다.

 

    const handleLogin = (event) => {
        event.preventDefault();
        toast.info('Navigating to VT CAS login page...');
        // login stuff going on
        setTimeout(() => {
          navigate('/FeedbackForm');
        }, 2000)
    };


...



          <Button onClick={handleLogin} style={{ backgroundColor: 'maroon', borderColor: 'maroon', 
          padding: '10px 20px', fontSize: '16px' }} type="submit">CAS Login</Button>

 

나는 핸들러 함수에 setTimeout함수를 추가해 toast로 유저들에게 로그인 페이지로 이동 중이라고 알려주었다. 저기서 위에서 선언한 상수 'navigate'에다가 ( 를 열고, import한 FeedbackForm이라는 컴포넌트를 넣어준다. 이렇게 하면 버튼이 클릭되었을때, navigation 상수가 알아서 페이지 간 전환을 담당 할 것이다. 이렇게 보니까 정말 간단하다.. 나는 의존성부터 시작해서 여러가지 애를 먹었지만 다음에는 이런 일이 없었으면 좋겠다.

 

이렇게 loginPage.js에서 라우팅을 담당하는 함수를 작성 한 후, React의 엔트리 포인트인 index.js에서 이제 페이지들을 어떻게 렌더링 할지 결정 해야한다.

 

현재 나의 index.js는

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
// Bootstrap CSS
import "bootstrap/dist/css/bootstrap.min.css";
// Bootstrap Bundle JS
import "bootstrap/dist/js/bootstrap.bundle.min";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

그냥 이렇게 <App /> 컴포넌트를 받아 렌더링을 하기 때문에 나는 App.js를 수정해야 한다.

import FeedBackForm from './pages/FeedBackForm';
import LoginPage from './pages/loginPage';
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';


function App() {
  return (
    <React.StrictMode>
    <BrowserRouter>
    <Routes>
      <Route path="/" element={<LoginPage />} />
      <Route path="/FeedbackForm" element={<FeedBackForm />} />
    </Routes>
    </BrowserRouter>
    </React.StrictMode>
  );
}

export default App;

 

보다시피 위에 BrowserRouter, Routes, Route를 import 한 후, 제일 상단을 <BrowserRouter>로 감싼다. 그 후, <Routes> 태그 안에는 우리가 이동하고싶은 페이지들의 경로를 <Route>태그 안에 넣어 준다. 여기서 짚고 넘어가야 할 것이 있다.

 

먼저, element = {<>}안에 들어 가야 할 내용은 우리가 import한 페이지 컴포넌트들을 넣어주면 된다.

 

그리고, 

위에서 보이는 <Route path ="/"는 루트 경로로 매핑 한다는 뜻이다. 즉, path에서 / 를 가진 컴포넌트가 웹을 실행할때 가장 먼저 렌더링 될 페이지이다. 보통의 웹 페이지라면 서비스를 이용하기 전에 로그인을 먼저 해야함으로 나는 login page를 루트 경로로 설정 해 줬다.(이걸 몰라서 화면에 아무것도 뜨지 않아 또 새벽 두시에 스오플을 뒤졌다...)

 

이렇게 모든 과정을 마친 후,

이렇게 페이지간 이동을 할 수 있게 되었다!

내가 처음 GUI수업을 들었을때가 생각난다. 처음 HTML로 못생긴 웹을 찍어내고, 그래도 내 딴엔 자료구조수업만 들었어서 처음으로 내 손으로 뭔가 웹사이트를 만든게 너무 신기했다. 그래서 이걸 동생한테 보여주려고 그냥 열려있는 html파일의 localhost:3000을 동생한테 복사해서 보내주며 내가 만든 웹사이트인데 어떻냐고 물어봤더니 동생은 열리지 않는다고 했다. 저땐 그냥 html로 웹만 찍어내면 모두가 그 웹에 접근해 소스를 볼 수 있는줄 알았다..... 

 

하지만, 우리가 진짜 웹을 개발하는 과정에 있어서 배포하는 과정도 엄청 중요하고, 절대 빼먹을 수 없는 것 중 하나이다.

 

자 그러면, 오늘은 웹 서비스 호스팅, 도메인 설정(이걸 통틀어서 전문용어로 Deploy라고 한다.)을 하는 과정을 짚고 넘어가 보자.

 

자 먼저, 외부에 공개를 하는 방법에는 크게 2가지가 존재한다.

 

  • 내 컴퓨터 서버로 공개하기
  • 외부 서버 빌리기

그러나 보통은 두번째 옵션 '외부 서버 빌리기' 를 많이 사용한다. 이게 훨씬 간편하고 직관적인 방법이기 때문이다. 위 내용을 간단하게 도식화 한 그림이다.

 

 

 

외부 서버를 이용해 웹을 공개하는 과정

위의 그림처럼 외부 서버에 내가 만든 웹 사이트를 올려놓고 클라이언트가 요청하면 언제든 가져다 주는것이 '배포'의 기본적인 원리이다.

 

클라우드 서비스가 등장하기 전에는, 서버가 필요한 곳마다 서버를 따로 설치해야 했다. 예를들어, 어떠한 기업에서 그 기업만의 독점적인 서버를 운용하려고 한다면, 그 기업은 서버실을 따로 만들어 서버 구축에 필요한 하드웨어들을 설치 해야 했었다. 하지만, 클라우드 서비스가 등장한 이후로는 물리적으로 서버를 설치하지 않고도, 가상의 서버를 이용료를 내고 이용 할 수 있게 되었다. 

 

우리가 많이 알고있는 서버 서비스를 제공하는 플랫폼은 대표적으로 AWS(Amazon Web Service), MS Azure, Google Clould등등이 있다.

 

오늘은 무료 클라우드 서비스중 하나인  netlify.com에서 실습을 해 보도록 하겠다.

https://www.netlify.com/?qgad=669861900644&qgterm=netlify&utm_source=google&utm_term=netlify&utm_campaign=GS_Connect:+Netlify+Brand&utm_medium=paid_search&hsa_acc=3888979506&hsa_cam=20355763121&hsa_grp=154990107550&hsa_ad=669861900644&hsa_src=g&hsa_tgt=kwd-309804753741&hsa_kw=netlify&hsa_mt=b&hsa_net=adwords&hsa_ver=3&gad_source=1&gclid=CjwKCAjw8diwBhAbEiwA7i_sJXT4YHSd_q7S5-hPk2dTrttK6jFJRhdIT6nd2FzCQhA53uRlmRaQoBoCuzwQAvD_BwE

 

Scale & Ship Faster with a Composable Web Architecture | Netlify

Realize the speed, agility and performance of a scalable, composable web architecture with Netlify. Explore the composable web platform now!

www.netlify.com

 

 

 

이 곳에 접속헤서 먼저 회원가입을 한다. 회원 가입을 마치고, 왼쪽에 'sites'탭으로 이동하면 아래와 같은 화면이 보일 것이다.

 

 

그러면 저기 보이는 'browse to upload'를 누르고, 원하는 index.html파일을 넣으면 이제 누구나 자동으로 생성된 URL을 가지고 그 웹에 접속 할 수 있다.

 

그럼 이렇게 정말 간단하게 웹을 배포하는법을 알아보았다. 다음에는 '학부연구' 카테고리에서 직접 학교 서버에 웹을 호스팅 하는것을 포스팅 해 보도록 하겠다!

'Cloud Computing' 카테고리의 다른 글

[Docker] Docker? 개념과 간단한 설명  (0) 2024.04.11

+ Recent posts