일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- React
- e.preventDefault()
- route53
- liunx
- GlobalStyle
- typeorm
- requests
- Object.freeze()
- 배포
- code-server
- ACM
- CloudFront
- 리액트
- 카카오 로그인
- ci/cd
- Recoil
- riotapi
- 롤
- Github Actions
- mysqlclient
- styled-component
- Python
- docker
- s3
- e.stopPropagation()
- nestjs
- 전역스타일
- 자바스크립트
- AWS
- Django
- Today
- Total
군붕이의 메모장
[Nest.js] euc-kr 인코딩 변환하기 본문
● Nest.js의 body-parser
Nest.js의 경우 기본적으로 bodyparser 라이브러리를 사용해서 json 데이터를 변환한다.
nest new [name]을 통해서 nestjs 프로젝트를 생성하면 아래 사진처럼 node_modules 내부에 bodyparser가 설치되어있다.
자바스크립트는 기본적으로 UTF 인코딩을 지원하기때문에 실제 bodyparser 내부를 들여다보면 UTF를 제외한 인코딩 방식은 에러로 처리하는것을 확인할 수 있다.
body-parser/lib/types/json.js
// assert charset per RFC 7159 sec 8.1
var charset = getCharset(req) || 'utf-8'
if (charset.slice(0, 4) !== 'utf-') {
debug('invalid charset')
next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
charset: charset,
type: 'charset.unsupported'
}))
return
}
실제로 Nest.js의 동작방식으론 HTTP 요청에 대해서 라우터에 도달하기전에 JSON 데이터를 파싱하게된다.
하지만 euc-kr등 다른 캐릭터셋으로 요청을 하게되면 body-parser에 의해서 아래처럼 에러가 발생한다.
● 에러가 안나도록 데이터 받기
간단하게 생각하면 간단하다.
데이터를 받을때 body-parser를 통해서 받지말고 그냥 직접 받으면 된다.
Nest.js는 8번대 버전과 9번대 이상 버전의 처리방식이 다르다.
● Nest.js 8.X 버전 해결방법
9점대 버전에는 rawBody 옵션을 통해서 편하게 처리가 가능하다.
하지만 8점대 버전에는 해당 옵션이 존재하지 않으므로 미들웨어를 통해서 직접 처리해줘야 한다.
1. body-parser 비활성화
body-parser가 기본적으로 활성화 되있어서 비활성화 하지 않으면 위 사진처럼 HTTP 415 에러가 발생한다.
// main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
bodyParser: false
});
await app.listen(3000);
}
bootstrap();
2. 데이터 처리용 미들웨어 생성
API에 따라서 어떻게 JSON 데이터를 처리할지 정하기 위해서 미들웨어를 사용한다.
// raw-body.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
@Injectable()
export class RawBodyMiddleware implements NestMiddleware {
public constructor() {}
public use(req: Request, res: Response<any>, next: () => any): any {
bodyParser.raw({ type: '*/*' })(req as any, res as any, next);
}
}
content-type과 관계없이 body에 대해서 전부 raw 형식으로 처리한다는 의미이다.
// json-body.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
@Injectable()
export class JsonBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.json()(req as any, res as any, next);
}
}
UTF-8 요청의 경우 body-parser의 일반 json 메소드를 통해서 처리한다.
3. 미들웨어 등록
// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { RawBodyMiddleware } from './middlewares/raw-body.middleware';
import { JsonBodyMiddleware } from './middlewares/json-body.middleware';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(RawBodyMiddleware).forRoutes('create/euc-kr');
consumer.apply(JsonBodyMiddleware).forRoutes('create/utf-8');
}
}
각 API의 URI에 따라서 특정 미들웨어를 적용시켜준다.
4. 컨트롤러 설정
import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Post('create/euc-kr')
createEuckr(@Body() raw: Buffer) {
console.log('EUC-KR 데이터 : ', raw.toString());
}
@Post('create/utf-8')
createUtf8(@Body() body: any) {
console.log('UTF-8 데이터 : ', body);
}
}
@Body()를 사용해서 데이터를 받게되면 Buffer <aa bb cc...> 형식의 데이터를 받게된다.
해당 버퍼 데이터를 toString()을 통해서 변환해주면 정상적으로 euc-kr 데이터를 받을 수 있다.
● Nest.js 9.X 이상 버전 해결방법
우선 8점대 버전과 다른점은 rawBody를 사용할 수 있다는 점이다.
8점대 버전처럼 굳이 미들웨어를 생성하지 않아도되서 매우 편리하다
상세 내용은 공식문서를 참고하면 좋다.
https://docs.nestjs.com/faq/raw-body
1. rawBody 활성화
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
rawBody: true
});
await app.listen(3000);
}
bootstrap();
rawBody를 활성화하면 body를 raw 형식으로 받을 수 있다.
2. 컨트롤러 설정
// app.controller.ts
import { Controller, Post, Body, RawBodyRequest, Req } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Post('create/euc-kr')
createEuckr(@Req() req: RawBodyRequest<Request>) {
const raw = req.rawBody;
console.log('EUC-KR 데이터 : ', raw.toString());
}
@Post('create/utf-8')
createUtf8(@Body() body: any) {
console.log('UTF-8 데이터 : ', body);
}
}
8점대 버전과 다른점은 req 객체 내부에 rawBody라는 데이터가 들어온다는 점이다.
RawBodyRequest<Request>를 req 타입에 할당해야 타입에러 없이 접근이 가능하다.
● 코드
https://github.com/imkdw/nestjs-euckr
'웹 개발 > 백엔드' 카테고리의 다른 글
[Nest.js] AWS Parameter Store를 통해 환경변수 관리하기 (1) | 2023.07.08 |
---|---|
[Nest.js] Swagger API 문서에 로그인 설정하기 (0) | 2023.05.26 |
[Nest.js] Nest.js에서 사용자 인증 처리하기 with Passport (0) | 2023.03.12 |
Node.js AWS S3 이미지 업로드하기 feat. AWS-SDK v3 (0) | 2023.02.27 |
[Django] Ubuntu 18.04 에서 mysqlclient 설치오류 해결방법 (0) | 2021.07.18 |