kakasoo

[HTTP] 14. 네트워크 기초 상식 (Server, client, HTTP, method란 뭐지?) 본문

프로그래밍/HTTP

[HTTP] 14. 네트워크 기초 상식 (Server, client, HTTP, method란 뭐지?)

카카수(kakasoo) 2020. 11. 1. 13:51
반응형

여기서는 네트워크, 서버, Express.js 등을 공부하면서 내가 경험한 착각들에 대해서 설명하고자 한다. 사실, 이 대부분의 문제들은 내 안에서 이미 해소가 된 것들이다.

그러나 다른 사람들, 동기나 후배들이 과제를 하는 모습을 보면서, 다른 사람들도 내 패턴을 그대로 답습할 수 있다는 것을 느끼고, 나와 같은 실수나 착각을 반복하지 않기를 바라는 마음에서 글을 쓴다.

잘하는 사람도 있겠지만 아예 새로 시작하는 사람들도 있을 것이고, 이 문제들을 직면하고 좌절할 사람들도 있을 것이기 때문에, 작성하는 글인 만큼, 이미 안다면 넘어가도 좋을, 그저 그런 글이다.

일단 처음에 공부를 하면서 겪은 문제들은 아래와 같다. 당연히 설명할 순서도 아래와 같다.

 

  1. 서버라는 게 뭐지? → 서버라는 개념을 너무 거창하게 생각해서 시작할 엄두를 내지 못한다.
  2. 클라이언트라는 게 뭐지? → 이미 우리가 쓰고 있는 게 클라이언트, 에이전트라는 사실을 몰라서 발생한다.
  3. HTTP라는 게 뭐지? → 어려운 개념은 맞다, 하지만 시작이 어려운 개념은 절대 아니다, 당장 필요한 몇 가지 기초 지식만 가지고 있다면 이후 학습에 더 도움이 될 수 있을 것이다.
    1. Method 라는 게 뭐지? → 메서드! 이름만 들어도 어렵지만, 사실 의미가 있든 없든 중요하지 않을 수 있다.
      • GET
      • POST
      • DELETE
      • PUT
        • PATCH는 PUT이랑 뭐가 달라? → 3-1의 내용을 염두하고 바라본다면 더욱 쉽게 이해할 수 있을 것이다. 굳이 할 필요 없는 설명인 거 같아서 생략한다.
    2. Transaction 이라는 게 뭐지? → Request와 Response
      • Request
      • Response

 

나와 같이 네트워크나 서버를 중점으로 공부하는 사람이 아니고, 데이터 분석을 위해서 배우는 수준으로 이해할 수 있게 최대한 간략한 설명을 하고자 한다. 그럼 시작하자.

 

서버, 클라이언트란 무엇일까?

컴퓨터를 공부하면서 배우는 모든 것들을 이렇게 정리해보자. 이론과 알고리즘, 그리고 실무라고. 그렇다면 서버는 당연 실무에 해당할 것이다.

대학에서 공부하는 것은 당연히 이론일 것이고, 취업을 하기 위해서는 알고리즘, 즉 로직을 짜는 것을 공부하는데, 막상 개발에 들어가게 되면 배운 적 없는 것들이 가득하니 당황할 수 밖에 없다.

그래서 서버만 설명할 게 아니라, 이 상관 관계를 설명할 필요성을 느낀다.

우선 서버 라는 게 뭘까?

사실 서버라는 것은, 어떠한 요청이 들어왔을 때 응답해주는 것을 기기를 의미한다. 그 응답이라는 것은 간단한 text 문서가 될 수도 있고, html나 img가 될 수도 있다. 때로는 아무것도 안주기도 한다.

하드웨어적인 의미로도, 또 소프트웨어적인 의미로도 서버가 있을 수 있다, 그렇지만 어렵게 생각하지 말고, 그저 서버를 24시간 편의점 정도로 생각해보는 것은 어떨까?

우리 노트북도 서버의 역할을 훌륭하게 수행할 수 있다. 하지만 노트북을 24시간 동안 돌아가게 하는 사람은 없을 것이다. 그렇기 때문에 우리 노트북은, 슈퍼마켓 정도일 것이다.

슈퍼마켓을 편의점처럼 24시간 동작하게 할 수 있다면 훌륭한 상용 서버로 사용할 수 있을 것이다.

우리 개개인의 노트북은 클라이언트로써 서버에게 정보를 요구할 수 있을 것이다, 서버는 그 요청을 받으면 응답하는 노트북 (또는 그러한 기계 장치)일 뿐이다.

즉 클라이언트와 서버는 그저 개발자가 기기에 정해놓은 역할에 불과하다.

 


 

HTTP와 트랜잭션이란 뭘까?

여기까지만 들어도 서버에 대한 기초 지식은 쌓았다고 할 수 있겠다, 다음은 약간의 코드를 가미해서, 더 깊은 내용을 설명하고자 한다. 코드를 이해하지 못하더라도 흐름을 봐줬으면 한다.

이 코드는 자동으로 생성되는 코드 중에서 일부분을 떼온 것일 뿐이다.

 

const server = http.createServer(app);

server.listen(port, () => {
    server.on('error', onError);
    server.on('listening', onListening);
});

 

이 코드는 HTTP 라는 프로토콜 위에서 app을 올릴 것이고, 다른 요청이 들어올 수 있도록 입구(port)를 정해놓고 대기(listen) 상태로 만든다는 의미를 가지고 있다. 이미 이 자체로도 훌륭한 서버다.

다만 이렇게 말하고 시작해버리면, HTTP이 뭔지부터 다시 혼란이 찾아올 테니, 일단 정의부터 보도록 하자. Hyper Text Transfer Protocol, 즉 프로토콜이다. 여기서 프로토콜은 약속이다.

예를 들면 이렇게 설명할 수 있겠다.

우리가 카톡을 하면, 상대방이 응답을 할 거라는 보장이 없지만, HTTP 라는 프로토콜을 따른다는 것은 먼저 한 카톡에 대해서 반드시 답장하기 라는 규칙, 즉 심심이 프로토콜(...)이라고 할 수 있을까?

우리는 이 때, 먼저 한 카톡을 요청(Request), 그리고 나중에 한 카톡을 응답(Response)라는 용어로 부른다.

 

나   : 뭐하고 있어?
친구 : 답장.

 

물론, 당연하지만 이 정도 수준으로는 인간관계를 유지할 수 없을 것이고, 마찬가지로 이 정도 수준의 서버로는 사용자들을 만족시킬 수 없을 것이니, 우리는 더 좋은 서버를 만들 필요가 있는데,

여기서부터는 HTTP 프로토콜 위에 동작하는 app을 더 좋은 수준으로 개발할 필요가 있을 것이다.

서버 개발자들이 하는 일이란, 이 상호작용을 좀 더 그럴듯하게 만드는 일에 해당한다.

이는 마치 레코드 위에 음반을 돌리는 것과 유사한 것 같다.

레코드는 HTTP 프로토콜이고, 음반이 서버 개발자들이 코딩할 어플리케이션(Applycation)에 해당한다. (물론 HTTP나 Network 개발자들도 있다.)

 

HTTP 메서드란 뭘까?

import express from 'express';
import issuesController from '../controllers/issues.js';

const issuesRouter = express.Router();

issuesRouter
    .route('/')
    .get(issuesController.get)
    .post(issuesController.post)
    .put(issuesController.put)
    .delete(issuesController.delete);

export default issuesRouter;

위의 코드는 서버 중 일부이다. 자바스크립트 사용자라서 자바스크립트로 적은 것은 유감스러운 일이지만, 그래도 의미를 봐줬으면 한다.

issuesRouter 라는, 내가 직접 정의한 라우터는, get, post, put, delete 라는 메서드들에 내가 미리 만들어놓은 임의의 함수들을 라미터들에 넣어주고 있다. 이것 무슨 의미냐면,

클라이언트가 요청을 보낼 때 저기서 해당하는 함수를 동작시킨다는 의미이다. 예컨대 issuesController.get, post, put, delete를 그 때 그 때의 요청 때마다 보내준다는 의미이다.

즉, Method는 클라이언트와 서버끼리의 약속이다.

물론 이후 logic을 구현하는 것은, 서버의 자율이긴 하다. 약속을 한다고 무조건 지켜지는 것은 아니지만, 최소한 서버는 이런 표준을 지키고자 노력이라도 해야 할 것이다.

 

클라이언트 : 내가 GET 요청 보내면 뭐 줄거야? (GET Method인 시점에서, 일단 무언가를 받을 거라는 것은 대전제이다.)
서버 : 그냥 전부 다 줄게!

클라이언트 : 내가 POST 요청을 보내면 어떤 일이 생겨? (POST Method인 시점에서, 일단 무언가 생성된다고 예측할 수 있다.)
서버 : 데이터가 생기지!

클라이언트 : 내가 DELETE 요청을 보내면 어떤 일이 생겨? (DELETE Method인 시점에서, 일단 무언가가 삭제된다고 예측할 수 있다.)
서버 : 데이터가 사라지지!

클라이언트 : 내가 PUT 요청을 보내면 어떤 일이 생겨? (PUT Method인 시점에서, 일단 무언가가 수정된다고 예측할 수 있다.)
서버 : 데이터가 수정되지!

 

브라우저를 보자, 이 글을 보고 있다면 IE든 Chrome이든 또는 firefox나 네이버의 웨일 같이 브라우저를 사용하고 있을 것이다, 자신이 사용하고 있는 브라우저의 주소창을 한 번 보자.

그 주소창에 특정 주소를 입력하고 enter를 누르게 된다면 해당하는 page를 찾아서 화면에 띄워준다. 이 때의 요청이 GET 요청이다. (브라우저의 모든 주소 입력은 GET 요청이다.)

서버에서 GET 요청에 대한 logic을 짠다는 것은, 클라이언트가 GET 요청을 보냈을 때 동작시킬 내용을 준비한다는 것과 같다는 것을 알 수 있다.

POST나 PUT, DELETE도 마찬가지다. 만약 파라미터로 전달할 logic들을 아래와 같이 고쳐보자.

 

import express from 'express';
import issuesController from '../controllers/issues.js';

const issuesRouter = express.Router();

issuesRouter
    .route('/')
    .get(issuesController.get)
    .post(issuesController.get)
    .put(issuesController.get)
    .delete(issuesController.get);

export default issuesRouter;

 

이제 서버는 어떤 요청을 받든지 간에 무조건, GET 요청처럼 처리하게 될 것이다.

클라이언트가 GET 요청이 아니라 POST, PUT, DELETE 요청을 보내도 GET의 logic대로 동작하여 응답을 보내줄 것이라는 의미를 담고 있다. 즉, 약속을 잘못(?) 따르고 있는 설계라고 할 수 있겠다.

이런 설계를 지키면 어떤 점이 좋을까?

 

RESTful API

API (Application Programming Interface), 어플리케이션 프로그래밍 인터페이스는, 쉽게 말하면 기능을 사용하기 위한 인터페이스라고 할 수 있겠다, 이게 무슨 의미냐면 자판기의 버튼 정도가 될까?

API는 Server에서만 쓰이는 말은 아니다, 모바일에서 화면을 터치해서 사용하는 버튼들도, 예전 스마트폰에 있던 홈 버튼도, 사용자가 직관적으로 사용할 수 있는 모든 인터페이스를 일컫는 말이기도 하다.

아마 웹 환경도, Server가 모든 것을 예측하고 logic을 짜는 것은 무척이나 곤혹스러운 일이었기에, 이러한 설계 패턴이 생겨나지 않았나 싶다.

자조하는 것으로도, 또는 농담으로도 서버 개발자들은 API 자판기라는 표현을 쓰곤 하는데, 상대방이 자판기의 원리를 이해하지 않아도 일단 버튼을 누르면 (GET, POST, DELETE, PUT) 원하는 게 나오는 것.

서버 개발자들이 설계하는 것 역시 API를 설계한다고 할 수 있겠다.

여기에, 앞서 말한 약속들에 대해서, 개발자들은 이런 약속을 지키고자 노력(?)을 하는데, 이 때 약속을 충실히 이행한 설계를 우리는, RESTful API 라고 한다.

다시 묻자, 이런 설계를 지키면 어떤 점이 좋을까?

 

클라이언트 : 데이터 좀 줘
서버 : 어디다 쓸 건데?
클라이언트 : 아, 그냥 알아서 잘 쓸 거니까 좀 줘!

 

 

자녀 : 용돈 좀 줘
부모 : 어디다 쓸 건데?
자녀 : 아, 그냥 알아서 잘 쓸 거니까 좀 줘!

 

나는 RESTful한 API라는 것을 이러한 의미로 생각한다.

첫째로, 설계 내용물을 몰라도, 클라이언트가 어떠한 것을 돌려받을 거라는 믿음이 성사될 수 있다는 점이다.

결국엔 부모님이 줄 거란 믿음.

마치 자판기 버튼을 누르면 음료수가 나올 거라는 믿음과 같다.

당연한 것처럼 보이겠지만, 인터페이스가 분리되지 않았을 무렵, 또는 이러한 약속들이 없고 각 서버나 클라이언트마다 자체적인 패턴을 적용했을 무렵의 웹은 난장판이었다.

길거리 모르는 사람에게 용돈 달라고 하는 수준

RESTful API는, HTTP 표준을 따르는 사람이면 어떤 서버나 웹 사이트, 클라이언트 등 환경에 대한 걱정 없이 설계를 할 수 있게 만들어 준다. 개발자들의 수고를 덜어준 셈이다.

둘째로, 앞서 이미 말한 것과 같이 서버 개발자의 수고가 줄어든다. 즉 설계가 단순해진다. 요청에 따라 주기만 하면 된다. 정말로 위험한 거라면 그냥 안 주면 되는 거 아닌가?

 

자녀 : 통장 좀 줘
부모 : 그걸 왜 달라는 건데! (이런 과도한 부탁은 들어주지 않는다. 들어주는 부모가 있다면...)

 

클라이언트를 믿지 못하는 서버는, 클라이언트가 무언가를 달라고 할 때마다, 그것이 잘못 쓰일 경우를 대비한 온갖 예외와 오류를 대비할 수 있어야 한다. 그러나 RESTful한 API는 그런 고민이 없다.

정말로 위험한 것은 애초에 줄 생각이 없을 뿐더러, 주고 난 후의 일은 클라이언트의 책임으로 물으면 된다. 말하자면 정말로, 알아서 잘 쓸 것이라고 믿는 것이다.

 

부모 : 딴 데 쓰지 말고 잘 써야 한다!

 

다시 설명하면, 원론적인 설명으로 돌아가면, 이 글은 이론을 최대한 쉽게 풀어 쓴 글이라고 할 수 있겠다. 그리고 이 이론에 충실한 프로그램을 만드는 것들을 개발이라고 할 수 있을 것이고,

지금까지 우리가 배워 온 알고리즘은 특정 배열에서 어떠한 값을 찾아서 그 값을 가공하는 logic처럼, 이 개발의 효율성을 높이는 작업이라고 할 수 있겠다.

필자를 포함하여, 학생일 무렵의 모든 개발자들은 개발에 급급하기보다 이론과 알고리즘을 충실히 이해하는 것이 중요할 거라고 생각하여 이 글을 작성했다.

반응형

'프로그래밍 > HTTP' 카테고리의 다른 글

[HTTP] 16. 캐시(1)  (0) 2020.12.05
[HTTP] 15. 프락시  (0) 2020.11.30
[HTTP] 13. 웹 서버 (Web server)  (0) 2020.10.31
[HTTP] 12. 파이프라인과 커넥션 끊기  (0) 2020.10.24
[HTTP] 11. 병렬 커넥션과 지속 커넥션  (0) 2020.10.24