node.js

[Node.js] #3 http 모듈로 서버 만들기(1)

로춘남 2021. 11. 12. 15:50
728x90


1. 요청과 응답 이해하기

클라이언트와 서버의 관계

서버는 클라이언트가 있기에 동작하며, 클라이언트에서 서버로 요청(request)을 보내고, 서버에서는 요청의 내용을 읽고 처리한 뒤 클라이언트에 응답(response)을 보낸다. 요청과 응답을 바로 이벤트 방식이라고 표현한다. 클라이언트로부터 요청이 왔을 때 어떤 작업을 수행할지 이벤트 리스너를 미리 등록해야함.

 

아래는 가장 기본적인 서버의 요청과 응답

const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, { 'Content-Type' : 'text.html; charset=utf-8' });
    res.write('<h1>Hello Node!</h1>');
    res.end('<p>Hello Server!</p>');
})

    .listen(8081, () => { // 서버 연결
        console.log('8081번 포트에서 서버 대기중')
    });

위 코드를 실행하면, 서버는 8081포트에서 요청이 오기를 기다린다. res.writeHead는 응답에 대한 정보를 기록하는 메소드. 첫 번째 인수로 성공적인 요청임을 의미하는 200을. 두 번째 인수로는 응답에 대한 정보를 보내는데 콘텐츠 형식이 html이라는것을 표현하고 있다. 이러한 정보가 기록되는 부분을 바로 헤더(header)라고 부른다.

res.write 메서드의 첫 번째 인수는 클라이언트로 보낼 데이터이다. 예시는 html모양의 문자열을 보냈지만, 버퍼로도 보낼 수 있으며, 여러번 호출해서 데이터를 여러개 보낼 수 있다. 이러한 데이터가 기록되는 부분을 분문(Body)라고 부른다. res.end는 응답을 종료하는 메소드. 만약 인수가 있다면 그 데이터도 클라이언트로 보내고 응답을 종료할 것이다.

※ res.write와 res.end 에 일일이 HTML을 적는건 비효율이기때문에 HTML 파일을 따로 만들고 fs 모듈로 읽어서 전송하면 더 효율적일것 같음.

 

※ 포트 충돌이 일어나는 경우

코드에서 처음 8081이 아닌 8080으로 했을때 포트의 충돌이 일어났다. 아무래도 내가 개인적으로 하고있는 다른 작업이 8080으로 기본 설정이 되어있기때문에 그런것 같다. 다른 서비스가 이용하고 있는 포트를 사용 할 경우에는 Error: listen EADDRINUSE  :::포트번호 같은 에러가 나타난다. 이럴경우에는 해당 서비스를 종료하거나 노드의 포트를 다른 번호로 바꾸면 된다. 나같은 경우에는 8081로 변경했다. 만약 서비스가 종료되지 않는다면?

[윈도우 기준]
netstat -ano | findstr 포트
taskkill /pid 프로세스아이디 /f

로 작업을 죽여줄 수 있다. 이 작업은 아마 자바 공부를 하면서 한 번쯤은 겪었을 사람들이 많을것 같다. 개인적으로 나도 이런저런 프로젝트나 여러가지 공부 한꺼번에 할때 저렇게 taskkill로 죽여놨던듯...ㅋㅋ 잠깐 해석하자면,

netstat -ano | findstr 1234는 '누가 1234번 포트를 쓰고 있니?' 이런 뜻이다. 이 명령어를 입력했다면 명령크롬프트 우측에 포트번호와 함께 프로세스아이디가 나올것이다. 만약 프로세스 아이디가 67890이 나왔다면, taskkill /pid 667890 /f 를 입력해주면 해당 포트를 죽여버릴 수 있다.

 

※ HTTP 상태코드

• 2XX : 성공을 알리는 상태코드.  200(성공), 201(작성됨)

• 3XX : 리다이렉션(다른 페이지로 이동)을 알리는 상태코드. 어떤 주소를 입력했는데 다른 주소의 페이지로 넘어갈 때 이 코드가 사용. 301(영구 이동), 302(임시 이동), 304(수정되지 않음 → 요청의 응답으로 캐시 사용)

• 4XX : 요청 오류를 나타냄. 요청 자체에 오류가 있을 때 표시. 400(잘못된 요청), 401(권한없음), 403(금지됨), 404(찾을 수 없음)

• 5XX : 서버 오류를 나타냄. 요청은 제대로 왔지만 서버에 오류가 생겼을 때 발생. 이 오류가 뜨지 않게 주의하면서 프로그래밍을 해야한다. 이 오류를 res.writeHead로 클라이언트에 직접 보내는 경우는 거의 없고, 예기치 못한 에러 발생시 서버가 알아서 5XX대 코드를 보냄. 500(내부 서버 오류), 502(불량 게이트웨이), 503(서비스를 사용할 수 없음)

 

2. REST와 라우팅 사용하기

REST : REpresentational State Transfer. 서버의 자원을 정의하고 자원에 대한 주소를 지정하는 방법을 가리킴. 웹에 존재하는 모든 자원(이미지, 동영상, DB자원)에 고유한 URI를 부여해 활용하는것. 자원을 정의하고 자원에 대한 주소를 지정하는 방법을 의미하기도한다. 서버가 행할 수 있는 것들을 통틀어서 의미.

 

• HTTP 요청 메서드

- GET : 서버의 자원을 가져오고자 할 때 사용. 요청의 본문에 데이터를 넣지않으며, 데이터를 서버로 보내야 한다면 쿼리스트링을 사용.

- POST : 서버에 자원을 새로 등록하고자 할 때 사용. 요청의 본문에 새로 등록할 데이터를 넣어 보냄.

- PUT : 서버의 자원을 요청에 들어 있는 자원으로 치환하고자 할 때 사용. 요청의 본문에 치환할 데이터를 넣어보냄.

- PATCH : 서버 자원의 일부만 수정하고자 할 때 사용. 요청의 본문에 일부 수정할 데이터를 넣어보냄.

- DELETE : 서버의 자원을 삭제하고자 할 때 사용. 요청의 본문에 데이터를 넣지 않음.

- OPTIONS : 요청을 하기 전에 통신 옵션을 설명하기 위해 사용.

REST

HTTP통신을 사용할 경우 클라이언트가 누구든 상관없이 같은 방식으로 서버와 소통 할 수 있다. iOS, 안드로이드, 웹, 다른 서버 모두 같은 주소로 요청보내는것이 가능. → 서버와 클라이언트는 분리되어 있어 추후 서버를 확장 할 때 클라이언트에 구애를 받지 않는다.

 

코드를 구성하기전 대략적인 주소를 먼저 설계하면 좀 더 체계적으로 프로그래밍을 할 수 있다.

ex) REST에 기반한 서버 주소 구조

HTTP 메서드 주  소 역  할
GET / restFront.html 파일 제공
GET /about about.html 파일 제공
GET /users 사용자 목록 제공
GET 기타 기타 정적 파일 제공
POST /user 사용자 등록
PUT /user/사용자id 해당 id의 사용자 수정
DELETE /user/사용자id 해당 id의 사용자 제거

 

728x90