Express를 다루다 보면 res.send()와 res.json()을 혼용해서 사용하는 경우가 많다.
대강 res.json()은 JSON 데이터를 보낼 때 사용한다고 알고 넘어갔는데,
사실 res.send()로도 JSON 데이터가 넘어간다는 사실!
엥?
그럼 둘의 차이가 도대체 뭐지?
res.json() VS res.send()
익스프레스 어플리케이션 서버는 HTTP 요청을 받으면, 서버는 흔히 res라고 불리는 객체를 응답으로 전송한다.
res 객체는 기본적으로 API 콜의 보내지는 응답의 한 부분이라고 생각하면 된다.
res.send()는 content type을 "text/Html"로 설정해 클라이언트가 그것을 텍스트로 다루게끔 한다.
반면, res.json()은 content type "application/JSON"으로 설정해 클라이언트에서 응답을 JSON 객체로 다루게끔 한다는 차이가 있다.

근데 위에서는 .send()도 JSON을 보낸다며?
이부분은 .json()과 .send()의 소스코드를 살펴보면 간단하게 이해가 되는데, 코드 길이가 꽤 되니 아래에 공유하니 궁금하신 분들은 찾아보시길...
아래 코드를 보면 알겠지만 .json()도 결국에 리턴할 때는 res.send()를 리턴한다.
즉 .json()을 사용하면 여러 가지 json을 보내기 위한 세팅을 마친 뒤 res.send()로 그 데이터를 보내는 방식이다.
res.send의 소스코드에는 (필자도 길어서 다 읽어보진 않았다) 인자로 넘겨지는 body의 데이터 타입을 검사하는 코드가 들어가 있다. 여기서 만약에 데이터 타입이 object이면 res.json()을 호출한다. (코드 중간쯤에 나온 듯하다)
사실 이렇게만 놓고보면 .send()와 .json()을 따로 분리한 이유가 있나...? 싶지만 다른 개발자의 글을 읽어보니,
.json()은 JSON 데이터를 보낸다는 의미를 명확히 표시를 하니 JSON을 보낼 때는 .json()을 사용한다고 한다.
res.send()
res.send = function send(body) {
var chunk = body;
var encoding;
var req = this.req;
var type;
// settings
var app = this.app;
// allow status / body
if (arguments.length === 2) {
// res.send(body, status) backwards compat
if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') {
deprecate('res.send(body, status): Use res.status(status).send(body) instead');
this.statusCode = arguments[1];
} else {
deprecate('res.send(status, body): Use res.status(status).send(body) instead');
this.statusCode = arguments[0];
chunk = arguments[1];
}
}
// disambiguate res.send(status) and res.send(status, num)
if (typeof chunk === 'number' && arguments.length === 1) {
// res.send(status) will set status message as text string
if (!this.get('Content-Type')) {
this.type('txt');
}
deprecate('res.send(status): Use res.sendStatus(status) instead');
this.statusCode = chunk;
chunk = statuses[chunk]
}
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;
}
// write strings in utf-8
if (typeof chunk === 'string') {
encoding = 'utf8';
type = this.get('Content-Type');
// reflect this in content-type
if (typeof type === 'string') {
this.set('Content-Type', setCharset(type, 'utf-8'));
}
}
// determine if ETag should be generated
var etagFn = app.get('etag fn')
var generateETag = !this.get('ETag') && typeof etagFn === 'function'
// populate Content-Length
var len
if (chunk !== undefined) {
if (Buffer.isBuffer(chunk)) {
// get length of Buffer
len = chunk.length
} else if (!generateETag && chunk.length < 1000) {
// just calculate length when no ETag + small chunk
len = Buffer.byteLength(chunk, encoding)
} else {
// convert chunk to Buffer and calculate
chunk = Buffer.from(chunk, encoding)
encoding = undefined;
len = chunk.length
}
this.set('Content-Length', len);
}
// populate ETag
var etag;
if (generateETag && len !== undefined) {
if ((etag = etagFn(chunk, encoding))) {
this.set('ETag', etag);
}
}
// freshness
if (req.fresh) this.statusCode = 304;
// strip irrelevant headers
if (204 === this.statusCode || 304 === this.statusCode) {
this.removeHeader('Content-Type');
this.removeHeader('Content-Length');
this.removeHeader('Transfer-Encoding');
chunk = '';
}
if (req.method === 'HEAD') {
// skip body for HEAD
this.end();
} else {
// respond
this.end(chunk, encoding);
}
return this;
};
res.json()
res.json = function json(obj) {
var val = obj;
// allow status / body
if (arguments.length === 2) {
// res.json(body, status) backwards compat
if (typeof arguments[1] === 'number') {
deprecate('res.json(obj, status): Use res.status(status).json(obj) instead');
this.statusCode = arguments[1];
} else {
deprecate('res.json(status, obj): Use res.status(status).json(obj) instead');
this.statusCode = arguments[0];
val = arguments[1];
}
}
// settings
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)
// content-type
if (!this.get('Content-Type')) {
this.set('Content-Type', 'application/json');
}
return this.send(body);
};
'Back-End > Express' 카테고리의 다른 글
[Express] json()과 urlencoded() 메소드에 관하여 (0) | 2022.01.06 |
---|---|
[Express] CORS Configuration Options (0) | 2021.12.27 |