개인공부/TIL(Today I Learned)

TIL 85일차_Express res.json과 res.send

soon327 2021. 4. 13. 21:05

Express를 통해서 JSON 응답을 보낼 때,
Express의 res.json 함수를 쓰기도 하고, res.send 함수를 쓰기도 하는데
이 둘의 차이가 궁금해졌다.

res.json을 써도, res.send를 써도 JSON 응답을 보낼 수 있는데,
둘의 차이는 뭘까???
둘의 함수 내부 코드를 살펴본 글이 있어서 감사히 잘 알 수 있었다.

res.json

res.json 소스코드의 일부는 다음과 같다.

res.json = function json(obj) {
  var val = obj;

  // 생략...

  var app = this.app;
  var escape = app.get('json escape')
  var replacer = app.get('json replacer');
  var spaces = app.get('json spaces');
  var body = stringify(val, replacer, spaces, escape)

  if (!this.get('Content-Type')) {
    this.set('Content-Type', 'application/json');
  }

  return this.send(body);
};

살펴보면,

  1. obj가 JSON 문자열로 변환되서 body에 저장되고,
  2. Content-Type 헤더가 세팅되지 않았을 경우,
    this(res객체)에 Content-Type으로 application/json을 세팅한다.
  3. 마지막으로 res.send(body)를 실행하면서 그 결과를 반환한다.

결국 res.json은 내부적으로 res.send를 호출하고 있다.

res.send

res.send 소스코드의 일부는 다음과 같다.

res.send = function send(body) {
    var chunk = body;

    // 생략....

    switch (typeof chunk) {
        // string defaulting to html
        case 'string':
            if (!this.get('Content-Type')) {
                this.type('html');
            }
            break;
        case 'boolean':
        case 'number':
        case 'object':
            if (chunk === null) {
                chunk = '';
            } else if (Buffer.isBuffer(chunk)) {
                if (!this.get('Content-Type')) {
                    this.type('bin');
                }
            } else {
                return this.json(chunk);
            }
            break;
    }

    // 생략..

    return this;
}

인자로 들어온 body는 chuck로 할당되고, chunk에 대한 타입검사가 시작된다.
여기서 chunk가 objec이면 res.json을 호출한다.

그러면 res.jsonres.send이 서로를 호출하는 건데 콜스택이 무사할까?
살펴보면,
res.json에서 res.send를 호출할 때는, body로 문자열을 넘겨주기때문에,
두번째 실행되는 res.send의 chunk타입은 string이다.
chunk가 string일 경우에는 object일 때와 다른 분기를 타게되서
res.json을 호출하지 않기 때문에, 계속해서 서로를 호출하는 일은 없게된다.

정리

이 두개의 함수를 각각 사용했을 때의 차이점을 정리해보자.

res.send(object)를 실행했을 때, 함수의 호출 순서는 다음과 같다.

  1. res.send(object)
  2. res.json(object)
  3. res.send(string)

res.json(object)를 실행했을 때, 함수의 호출 순서는 다음과 같다.

  1. res.json(object)
  2. res.send(string)

object를 인자res.send를 호출하면 res.json을 호출했을 때보다,
불필요한 호출이 한 번 더 발생한다.
또한 소스를 읽을 때도, res.json이 JSON 데이터를 보낸다는 의도가 더 명확하게 드러나기때문에,
JSON으로 응답을 할때는 res.json을 쓰는게 적절한 방법일 것 같다.


Reference

https://haeguri.github.io/2018/12/30/compare-response-json-send-func