[Java]json encoding 하기 + 좋은 코드에 대한 짧막한 글

봄도둑·2022년 7월 15일
0

Spring 개인 노트

목록 보기
4/17

고객의 요구 사항 중 팜플릿을 출력할 때 백엔드에서 내려주는 파일의 인코딩 버전을 CP949(MS949)로 바꿔달라는 요청이 들어왔습니다. 아주 간단한 수정이었지만 수정 후 사수분이 다른 방법도 있다며 2가지 관점에서 코드를 바라보는 방법을 알려주셨기 때문에 짧지만 내용을 좀 남겨보고자 합니다.

1. json 타입 인코딩 방법(1)

public ResponseEntity<byte[]> printPamphlet(long deliveryNo) {
	//...	

	String pamphletJsonText = new Gson().toJson(resultJson);
	
	//...

	return ResponseEntity.ok()
                  .contentType(MediaType.APPLICATION_OCTET_STREAM)
                  .header("Content-Disposition", "attachment;filename=" + targetName)
                  .body(pamphletJsonText.getBytes("MS949")); 

}

아주 간단합니다. service 내 ResponseEntity의 제네릭을 byte[]로 지정 후 응답할 json body에서 응답할 json strting을 getBytes에 변환할 인코딩 타입을 넣으면 됩니다. 여기 있는 첫번째 방법은 사수님이 제안한 방법입니다.

2. json 타입 인코딩 방법(2)

@PostMapping(value = "{deliveryNo}/pamphlet", produces = "application/json; charset=cp949")
public Callable<ResponseEntity<String>> printPamphlet(@PathVariable("deliveryNo") long deliveryNo) {
    return () -> printService.printPamphlet(deliveryNo);
}

먼저 컨트롤러의 mapping 어노테이션에 produces란 property를 추가하고 다음과 같은 값을 입력 "application/json; charset=cp949" 합니다.

@Transactional
public ResponseEntity<byte[]> printPamphlet(long deliveryNo) {
//...

return ResponseEntity.ok()
//            .contentType(MediaType.APPLICATION_OCTET_STREAM)
              .header("Content-Disposition", "attachment;filename=" + targetName)
              .body(pamphletJsonText);
}

다음, RestonseEntity의 제네릭을 byte[]로 지정한 후 body는 결과로 내보낼 string을 값 그대로 내보냅니다. 이 때, contentType(APPLICATION_OCTET_STREAM) 이 들어가면 utf-8로 계속 인코딩이 되어서 주석 처리를 하고 진행했습니다. 이럴 경우 아래의 코드처럼 string을 MS949로 인코딩 해주지 않아도 만들어진 json 파일이 열릴 때 MS949로 인코딩되어서 열리게 됩니다.

//cp 949 인코딩해주는 코드
byte cp949Byte[] = pamphletJsonText.getBytes("MS949");
String convertCp949Json = new String(cp949Byte, "MS949");

3. 정리하자면

사수님이 저에게 알려주고 싶었던 것은 각자 다른 기준으로 코드를 본다는 것이었습니다. 단순한 인코딩을 처리하는 코드를 모든 사람이 제각각 코딩한다는 것입니다. 그동안 사수님이 지켜본 저의 모습은 좋은 코드라는 하나의 정답만을 찾아가는 것처럼 보였다고 합니다.

좋은 코드라는 평소 제 질문에 대해 좋은 인사이트를 주고 싶다고 하셨습니다. 누군가에겐 결과를 return에서 정해주는 것 그리고 결과값에 대한 인코딩이 return에 명시되어 있어서 가독성이 좋은 코드라고 볼 수 있고, 다른 누군가에게는 최종적으로 데이터가 전달되는 시점에 인코딩을 명시해 결과만 잘 만들어주는 printPamphlet()이라는 메소드를 모듈화 시킬 수 있고, 처음 코드를 보는 사람이 controller 레벨에서 바로 알 수 있도록 하는 것이 좋은 코드일 수 있다라는 것입니다.

코딩에 대한 정답은 없지만 다양한 관점의 코드를 보면서 좋은 코드를 찾아갔으면 하는 마음에 알려주셨다고 하는 사수님.

굉장히 단순한 동작이지만 개발자로서 커리어를 쌓을 때 중요한 가르침을 하나 배웠고 잊지 말자는 의미에서 소소하게나마 블로그 글로 정리해서 올려봅니다.

profile
배워서 내일을 위해 쓰자

0개의 댓글