(네트워크) TCP/IP 쉽게, 더 쉽게 목차 리뷰 - 2장 네트워크 서비스와 애플리케이션 계층

오래전에 이 책을 추천받았으나 최근에 읽어보게 되었다.
백엔드 개발자로 일하면서 프론트 엔드 개발자와 의사소통을 원활히 하기 위해서는 서로 네트워크에 대한 기본 지식이 있어야하는 것 같다.
이 글은 빠르게 목차를 리뷰하며 백엔드에게 필요한 내용인지, 프론트에게 필요한 내용인지, 공통적으로 알아야하는 내용인지 개인적인 기준에서 분류해봤다.

들어가기에 앞서

내가 여태까지 봐왔던 네트워크 계층 설명글들은 대부분 OSI 7 Layer를 기준으로 설명을 풀어나가고 있다.
OSI 7 Layer는 각 계층이 하는 역할이 명확해서 설명하기가 명쾌하다.
하지만 이론과 현실 사이의 괴리감이랄까… OSI 7 Layer는 구현하기가 복잡하거나, 성능 등등의 이슈(굳이 여러 계층으로 쪼갤 필요 없이 하나의 장비가 여러 역할을 수행하는 게 더 나을 때도 있으므로)로 인해
실제 구현된 건 대부분 4계층으로 구성된 TCP/IP Stack으로 구현이 많이 돼있다.
이 책은 신기하게도 TCP/IP Stack에 기반해서 각 계층의 역할을 설명하고 있다.
따라서 진짜 구현된 모델에 대한 이해를 증진시키는 데는 좋은 것 같으나 당장 AWS나 다른 글들을 보면 L4니 L2니 L7이니 해서 OSI 7 Layer로 설명된 글들이 많아서
OSI 7 Layer와 책에 설명된 TCP/IP Stack을 매핑시켜 이해하기 위해 책 앞 부분을 많이 왔다갔다 해야하는 단점이 존재하는 것 같다.

또한 책이 TCP/IP Stack에 대한 전반적인 내용을 200페이지도 안 되는 분량으로 녹여내다보니 전반적인 흐름을 알기는 좋으나
각각의 계층에 대해 딥하게는 다루지 않고, 그림도 아기자기 잘 설명돼있어서(+풀컬러) 입문 서적으로 좋은 것 같다.
각 목차 뒤에 F(ront), B(ack)을 적어놨으니 자신의 직군에 맞춰 딥하게 볼지 그냥 흐름만 볼지, 아예 안 볼지 판단하길 바란다.

예를 들면 프론트는 클라이언트 측에 웹서비스를 제공해주는 일을 하는데 그 중에서 서버가 제공해주는 API로 통신을 해서 데이터를 땡겨와야 한다.
웹서비스를 제공하기 위해서는 HTTP(S) 프로토콜을 사용하고, 서버의 API와 통신할 때도 HTTP(S)로 통신을 한다.
HTTP 프로토콜은 정보 공유를 위해 만들어진 프로토콜이므로 엄청난 수의 클라이언트가 접속하게 된다.
통신을 위한 통로에 수십만명이 한 번에 들어오게 끔 하면 가능한지도 모르겠고, 매번 그 만큼의 사람이 들어오는 것도 아니고, 비용 낭비도 엄청날 것이다.
따라서 통신을 위한 통로를 독점하는 게 아니라 항상 연결을 맺고 끊어서 다른 사람들이 원활하게 접속을 하게 해준다.
예를 들면 이 통로를 통해서는 동시에 100명만 들어올 수 있게 만들고 나한테 볼 일이 끝난 애들은 다 연결을 끊는 것이다.(사실 이런 설정은 백엔드가 한다.)
이 때 연결을 위해 사용하는 프로토콜이 TCP 프로토콜이다. (UDP 프로토콜도 있지만 웹 서비스 내에서는 대부분 데이터를 손실없이 전달해주는 TCP 프로토콜을 사용한다.)
따라서 프론트 엔드 개발자라면 HTTP 프로토콜은 물론이고 TCP 프로토콜까지 알아야 어떻게 하면 통신을 최적화 할 수 있을지 생각할 수 있게 된다.

백엔드의 경우에는 HTTP(S), TCP 프로토콜만 안다고 해서 끝나는 게 아니다.
SSH 프로토콜을 이용해서 서버에 원격으로 붙어서 명령어를 날리기도 하고, FTP 프로토콜을 이용해서 파일 업로드/다운로드가 가능한 서버를 설계해야할 수도 있기 때문이다.
SSH 프로토콜을 사용하려면 여러 인증 방식 중에 키로 인증하는 방식이 있는데 그럼 공개키, 비공개키, 대칭키, 비대칭키 막 이런 내용이 나오는데 이런 보안적인 요소도 알아야한다.
이 내용은 HTTPS에 사용되는 TLS 인증서의 암호화 방식에도 적용된다.
또한 동영상 스트리밍 서버를 만든다고 하면 UDP 프로토콜을 사용한다.
기본적으로 TCP 프로토콜은 해주는 일이 많으므로(데이터 전송에 실패하면 재전송 처리 등등) 성능이 안 받쳐주는데
UDP 프로토콜(보내기만 할 뿐, 잘 받았는지 확인을 하지 않는다. 그래서 가끔 동영상이 깨져서 나오는 현상들이 나온다.
하지만 크리티컬한 이슈는 아니고 매번 똑같은 부분에서 동영상이 깨져나오는 게 아니고 네트워크 상황에 따라 달라지기 때문이다.)은 그거보다 성능이 낫기 때문이다.
또한 AWS를 사용하다보면 그 아랫단인 IP/Router/Subnet Mask 등등의 영역도 잘 알아야한다.
보안을 위해 외부에서 접근이 가능한 요소(다양한 요청을 분산해주는 로드 밸런서)와 내부에서만 접근이 가능한 요소(웹서버, DB 등등)을 구성해야하는데…
그러면 네트워크를 어떻게 구성해야할 것이며, 이 네트워크 안에 서버는 몇 대를 둘 것이며, 퍼블릭 요소들과 프라이빗 요소들은 어떻게 통신을 할 것이며
어떤 요청들을 받고 말지 네트워크부터 보안에 대한 요소들을 직접 다뤄야하는 경우가 오는데 이럴 때 이 내용들을 알고 있으면 정말 무릎을 탁 치게 되는 날이 온다.

더 아랫단이나 부가적인 요소들은 알면 +@, 몰라도 그만인 것 같은데 호기심이 충만하면 알고 싶을 것이다.
위에서 설명하지 않은 모뎀, 이더넷 카드, 랜선 등등은 사실 하드웨어 단으로 내려가는 거니 백엔드가 굳이 알 필요가 있나 싶다.(물론 알면 좋다.)
또한 데이터 전송에 실패했을 때 어떤 전략으로 재전송시킬 것인지(어플리케이션 단이 아닌 하드웨어 단에서 패킷을 처음부터 전송할 건지, 실패한 부분을 알아내서 그거부터 전송할 것인지)
이런 내용들은 내가 봤을 때는 굳이 알 필요가 있나 싶은데 분명 알아두면 어딘가는 써먹을 일이 있을테니 공부해둬야할 것 같긴 하다.

목차

  1. 컴퓨터 네트워크
  2. 네트워크 서비스와 애플리케이션 계층
  3. 트랜스포트 계층
  4. 라우팅과 인터넷 계층
  5. 하드웨어와 네트워크 인터페이스 계층
  6. 보안

2장, 네트워크 서비스와 애플리케이션 계층

애플리케이션 계층은 TCP/IP 스택의 최상단으로 사용자가 직접 체감을 느끼는 구간이고 프론트 개발자와 가장 밀접하다.
바로 HTTP(S) 프로토콜이 속해있으니 이 부분은 집중해서 봐야한다.
프론트가 알아야한다면 백엔드는 당연히 알아야한다.
OSI 7 Layer 기준으로는 L7(Application Layer), L6(Presentation Layer), L5(Session Layer)에 해당한다.

2-1. 애플리케이션 계층의 역할(F/B)

애플리케이션 계층의 패킷에는 다양한 내용들이 들어갈테지만 핵심적인 건 데이터(html 소스 코드 등등)이 여기서 실리게 된다.
어떤 데이터를 실어서 서버/클라이언트가 통신할지 여기서 결정되는 것이다.
HTTP 프로토콜 외에도 아래와 같은 애가 있다.

  • 파일의 전송을 위한 (S)FTP((Secure) File Transfer Protocol)
  • 원격지의 서버를 제어하는 SSH(Secure SHell)
  • 메일 서버 관련된 POP3, SMTP, IMAP 등등이 존재

시스템 내부적으로 사용하는 것 중에는 아래와 같은 것들이 있다.

  • ip ↔ domain(www.naver.com 같은 애) 역할을 하는 DNS(Domain Name System, 얘의 대표 포트가 53번 포트라 AWS에서 도메인 등록하는 서비스를 Route53이라고 지었다.)
  • ip를 할당해주는 DHCP(Dynamic Host Configuration Protocol)
  • 데이터를 암호화 할 때 쓰이는 SSL/TLS(Secure Sockets Layer/Transport Layer Security), HTTPS와 SFTP, SSH 프로토콜에서 데이터 암/복호화 할 때 사용된다.

2-2. 웹 페이지를 전송하는 HTTP(F/B)

웹 페이지가 표시되는 과정이나 HTTP 메시지가 어떤 식으로 구성돼있는지 설명하고 있다.
URL에 대한 설명과 HTTP 헤더, 바디, 요청과 응답, 그리고 status code에 대해서도 설명해주고 있다.

2-3. 웹 서비스와 웹 애플리케이션(F/B)

웹 서비스/어플리케이션이 뭐고 서로 어떻게 정보를 교환하는지 설명하고 있다.
사용성도 높여주고 서버의 부담을 줄여주는(html 전체를 내려주는 게 아니라 필요한 애만 내려주면 되니까) ajax에 대한 간단한 설명,
GET/POST 메소드의 차이에 대해 알려주고 있다.
학부 시절에 GET은 URL에 요청의 내용이 노출되니 보안에 민감하지 않은 정보인 검색이나 게시판 페이지 등등에 쓰이고 URL 길이에 제약이 있다고 배웠는데 면접에서 이렇게 답변하면 탈탈 털릴 것이다.
URL은 리소스의 경로를 나타내는 것이지 비밀번호, ID와 같은 정보는 리소스라고 보기에는 애매~한 것 같다.
따라서 로그인 같은 건 POST를 사용한다.
또한 POST라고 보안에 좋은 게 아니다.(패킷 캡쳐하면 다 보인다.)
POST는 리퀘스트에 Body(json이나 파일 전송에 쓰이는 multipart/form-data 등등)을 실어 보낼 때 쓰기도 하고,
GET은 URL 입력만으로 요청이 전송되기 때문에 혹시나 유저가 실수로 URL을 입력할 수도 있으므로 데이터의 변경이 일어나는 작업은 웬만해서는(조회수를 늘리는 경우 등등 빼고) GET으로 하면 안 된다.
또한 GET과 POST를 설명하려면 다른 HTTP Method인 PUT, DELETE, FETCH, OPTION 등등과 REST(FUL) API를 접목시켜서 설명해야하는데 책에서는 딱히 설명하고 있진 않다.

2-4. 세션을 유지하기 위한 쿠키(F/B)

세션은 뭘까?
일반적으로 세션은 허용된 유저가 리소스 사용하는 걸 허락하게 해주는 기간이라고 보면 된다.
세션은 API 마냥 어디에서 쓰이느냐에 따라 아주 다양한 의미를 가지지만 HTTP 프로토콜 내에서 위에 설명한 세션을 접목시켜보자면

  1. 유저가 로그인을 한다.
  2. 서버에서는 로그인에 성공하면 세션(A라는 유저는 2099년 1월 30일까지 로그인을 해야하만 하는 리소스에 접근이 가능하다는 정보를 담고 있는 파일)을 서버에 저장한다.

여기까지가 세션이 생성되는 과정이다.
하지만 HTTP 프로토콜은 무상태 프로토콜(Stateless protocol)이라서 세션에 대한 정보를 통신에 실어 보내지 않는다.

그렇다면 무상태 프로토콜은 무엇이며 왜 쓸까?
동일한 유저가 보낸 이전 요청과 다음 요청에 대한 상태(세션)을 가지지 않는 프로토콜을 말한다.
즉 세션이 없기 때문에 요놈이 로그인 한 상태인지 아닌지 모르게 된다는 말이다.
장점으로는 서버의 설계가 단순해진다고 한다. (여기서 말하는 서버가 백엔드가 개발하는 서버를 말하는 건지 다른 서버를 말하는 건지 모르겠다. 아마 내부적으로 알아서들 처리해주기 때문에 내가 잘 모르는 거일 수도 있다.)

그럼 HTTP 프로토콜에서는 세션을 어떻게 유지할까?(로그인 상태를 어떻게 유지할까?)
바로 쿠키라는 것을 통해서 유지한다.
쿠키에다가 세션에 대한 ID를 보내주고 매번 통신할 때마다 클라이언트는 서버로 쿠키를 보낸다.
서버는 해당 쿠키로 유저를 식별하므로 쿠키가 탈취당하면 해킹을 당했다고 보면 된다. (이걸 보완한 방법도 있는데 아직 이건 공부를 안 했다.)
또한 로그인이 필요치 않은 단순 이미지 파일 요청에 대해서도 요청에 쿠키를 실어 보내기 때문에 쿠키는 세션 유지에 필요한 최소한의 정보만 담고 있는 게 좋은 것 같다.

2-5. 이메일(B)

사실 메일 서비스를 구현해보지 않고 항상 써드파티들을 이용하다보니 크게 ~ 와닿지는 않았다.
하지만 메일을 보내는 프로토콜(SMTP, Simple Mail Transfer Protocol)과 메일을 받는 프로토콜(POP, Post Office Protocol)이 따로 있다는 사실은 신기했다.

2-6. PC끼리 파일 공유하기

이거는 사실 뭐 웹개발 할 때는 필요없고 사내에서 그냥 파일 공유할 때 알아두면(사실 뭐 몰라도 사용하는 데는 문제 없지만) 좋은 것 같다.
여기서 말하는 파일 공유는 같은 네트워크 상에 존재하는 PC끼리 파일 공유를 하는 P2P(Peer to Peer) 방식이기 때문에 중앙에서 관리해주는 서버가 없는 방식이다.
따라서 새로 연결되는 컴퓨터는 브로드캐스팅(네트워크에 연결된 모든 PC에 데이터를 보냄)을 통해 입주 신고를 한다.
그럼 원래부터 네트워크에 있던 모든 PC들이 파일 공유에 필요한 정보들을 새로 입주한 PC에게 주면 파일 공유 준비는 끝나게 된다.
또한 OS 별로 파일 공유를 위한 프로토콜이 다르다. (윈도우는 SMB, 맥은 SMB, AFP, 리눅스는 SMB, NFS)
예전에는 그래서 다른 OS간 파일 공유가 안 됐었는데 요새는 SMB로 대동단결 된 것인지 뭐 어떻게든 공유를 할 수 있는 모양이다.

2-7. 파일을 전송하는 FTP(B)

파일 전송을 위한 프로토콜인데 보안에 취약해서 SSH 프로토콜을 이용하는 SFTP(SSH FTP 또는 Secure FTP)를 사용한다.
그래서인지 대표 포트가 SSH와 똑같은 22번 포트를 사용한다.
파일 전송만을 하는 SCP(Secure CoPy) 프로토콜(얘도 22번 포트를 사용한다)과는 달리 SFTP는 원격지의 파일의 제어를 어느정도 허용한다.

FTP는 파일을 주고받기 위해서도 쓰이지만(이 때 데이터 커넥션이라는 접속 모드를 사용)
명령어를 보내기 위해서도 사용한다.(이 때 컨트롤 커넥션이라는 접속 모드를 사용, 디렉토리/파일의 생성/이동/삭제/수정 등등)
또한 HTTP 프로토콜과는 달리 허용된 유저만 접근을 허락하는 목적으로 설계된 프로토콜이라 요청과 응답이 끝났다고 해서 바로 연결을 끊는 게 아니다.
기본적으로 HTTP 보다는 동접이 많지 않을 것이므로 바로 연결을 끊을 이유가 없다.
또한 상태를 가지는 프로토콜이기 때문에 HTTP 처럼 매번 쿠키와 같이 접속에 대한 정보를 계속해서 보내줄 필요도 없다.

또 액티브 모드와 패시브 모드란 게 있는데
액티브 모드를 사용하면 ftp 서버의 방화벽 중에 아웃바운드 트래픽에 걸려서 응답을 못 받는 경우가 존재한다.
이럴 때 패시브 모드를 사용해서 서버에서 클라이언트로 데이터 커넥션을 만드는 게 아니라 역으로 클라이언트에서 서버로 데이터 커넥션을 만들어서 통신하면 된다.

2-8. 원격지의 컴퓨터 제어하기(B)

원격지의 컴퓨터를 제어할 때는 GUI(Graphic User Interface) 방식으로 직접 마우스를 움직여서 컨트롤 하는 방법이 있지만,
일반적인 컴퓨터와 달리 서버의 경우에는 CLI(Command Line Interface) 방식으로 마우스를 쓸 수 없는 환경의 OS를 사용하는 게 대부분이다.
서버의 역할을 수행하는데 GUI를 쓸 필요가 없기도 하고 CLI로 간단하게 명령어만 날리면 되기 때문이다.
이런 CLI OS(뭐 GUI도 마찬가지고)를 원격지에서 제어하기 위한 프로토콜로 SSH를 많이 쓴다. (과거에는 Telnet을 많이 썼지만 보안 상 이슈로 대부분 SSH로 통신한다.)
사용해보면 마치 내 컴퓨터에서 명령어 내리는 거 마냥 신기하게 바로바로 명령어들을 수행할 수 있다.
이걸 사용해서 서버의 설정을 바꾸고 배포하고 지지고 볶고 다 할 수 있다. (하지만 서버가 한 두대도 아니고, 짜치는 건 다 자동화하는 추세라서 직접 접속할 필요가 없기도 하다.)

2-9. Voice over IP와 영상 스트리밍(B)

유선 통화와 핸드폰으로 통화 할 때 3G까지는 회선 교환 방식으로 통신이 일어났는데
아마 4G인 LTE(Long Term Evolution)부터는 패킷 교환 방식 중에 데이터 그램 방식을 사용하고, VoIP 프로토콜을 사용하는 모양이다.
데이터 그램 방식 중에도 UDP 방식(음성 일부가 지지직 대는 현상을 느꼈을텐데 아마 UDP 방식으로 통신을 하기 때문인 듯…?)을 사용하는 것 같다.
왜냐하면 음성 중 일부가 유실 되어도 그렇게 크리티컬한 상황은 아니고 실시간성이 보장돼야하기 때문에 안정성 보다는 성능이 보장돼야하기 때문에 TCP 보다는 UDP 방식을 택한 것 같다.

동영상 스트리밍 같은 경우에도 위와 마찬가지의 이유로 UDP 프로토콜을 사용하는데 아직 동영상 프로토콜이 보편화 된 것이 아니라 일부 네트워크 환경에서 차단 될 가능성이 있다고 한다.
따라서 HTTP 프로토콜에 동영상 데이터를 싣는데 일반적인 TCP + HTTP의 조합이 아닌 실시간 성이 어느정도 보장되는 UDP + HTTP의 조합으로 가는 거 같다.

2-10. 크롬 개발 도구로 HTTP 메시지 살펴보기(F/B)

엄청 엄청 중요하다.
백엔드가 응답 잘 내려주고 있다는데 뻥치고 있을 수도 있으므로 응답을 어떻게 주는지 봐야한다.
마찬가지로 프론트가 요청 잘 보내고 있다고 뻥치고 있을지도 모르므로 요청을 어떻게 주는지 봐야한다.
이럴 때 실제 동작하는 코드 위에서 어떻게 데이터를 주고받는지 제일 간단하게 확인하는 방법은 크롬 개발자 도구의 네트워크 탭을 보는 것이다.
아마 AJAX를 사용해서 API를 호출하는 경우가 가장 많으므로 XHR(AJAX로 통신하기 위해서는 XMLHttpRequest로 통신하기 때문에, XHR이라고 줄여 부르는 듯, Fetch API를 쓰는 경우에도 여기 뜸)
탭을 눌러서 확인해보면 된다.
그럼 메소드, URL, 헤더, 바디에 뭘 실어서 보내고 응답받는지 다 확인할 수 있다.

MIME(Multipurpose Internet Mail Extensions)(F/B)

원래는 이메일을 위해서 나온 애이다.
컴퓨터는 서구권에서 만들어져서 원래 영어 +@로 영미권에서만 사용하는 문자들의 집합인 ASCII 코드로 표현할 수 있는 데이터만 실어 보낼 수 있었다.
하지만 첨부파일을 보내고 싶은데 이거는 텍스트가 아니라 보낼 수 없어서 텍스트 외의 데이터를 실어 보내기 위해서 MIME이 나왔다.
한글의 경우에도 ASCII 코드에 해당하지 않기 때문에 MIME을 활용해서 이메일을 보내고 있다.

하지만 이걸 뛰어넘어서 이메일이 아닌 HTTP로 통신하는 경우에도 MIME을 활용하고 있다.
내가 서버로 JSON 데이터를 보내고 싶으면 HTTP Body에 JSON을 실어보낸다고 끝이 아니다.
이 정보가 JSON이니까 그거에 맞게 해석해야한다 라는 정보를 HTTP Request 어딘가에 실어야한다.
그 정보를 HTTP Headers안에 Content-Type이라는 키(key) 안에 application/json 이라는 값(value)로 실어서 보낸다.
저 application/json 이라는 문자를 MIME이라고 부르며 MIME Type이라고 부르기도 한다.
MIME Tpye은 type/subtype으로 구성된다.

가끔 이미지 확장자를 jpg만 받는 사이트가 있으면 확장자만 png 같은 확장자를 jpg로 바꿔서 올리는 경우도 있다.
하지만 실제로 파일을 까보면 헤더에 image/png라는 정보가 있어서 서버나 클라이언트에서 마임타입으로 체크를 하면 업로드에 실패할 것이다.