Fake JSON API 를 통한 더미 데이터 응답값 생성하기

msung99·2023년 2월 19일
2
post-thumbnail

시작에 앞서

현재 진행중인 해커톤 프로젝트에서 더미데이터를 축적해야할 상황이 발생했습니다. 이들을 데이터베이스에 쌓아두고 일반적인 RestAPI 를 호출하여 데이터들을 조회해도 되겠지만, 이번에는 조금 더 효율적인 방법으로 데이터를 리턴받고자 학습을 진행하게 되었습니다.


Fake JSON API 란?

Fake JSON API 란 임의로 개발한 API 에 대해 고정된 응답값을 보내주는 테스트용 API를 의미합니다.
이때 저희는 "고정된 응답값" 을 보내준다는 특성을 살려볼겁니다. DB에 데이터를 저장해두지 않고 JSON 파일를 별도로 생성하고, JSON 의 특정 필드를 파싱하여 원하는 컬럼(필드) 값들을 추출해내는 방식으로 API 를 개발해봅시다.

즉, 고정값인 Response 로 보내줄 데이터들을 JSON 파일에 더미데이터로써 저장해두고, 개발해놓은 Fake JSON API 로 해당 파일을 읽어서 원하는 더미 데이터를 추출해내는 방식입니다.


json 파일 더미데이터 생성

Fake API 를 개발하기 전에, 우선 더미데이터를 저장할 json 파일을 생성해봅시다. 다음과 같이 resources 파일 아래에 dummy.json 파일을 생성해줍시다.

그리고 더미데이터를 생성해줍시다. 저희가 파싱할 JSON 의 key 값으로는 "infoDummyList" 라는 명칭을 부여해봤습니다.

{
  "infoDummyList" : [
    {
      "infoNumber" : 100,
      "imageUrl" : "https://bucket-test.s3.ap-northeast-2.amazonaws.com/test.png",
      "name" : "myName1"
    },
    {
      "infoNumber" : 101,
      "imageUrl" : "myImageUrl2",
      "name" : "myName2"
    },
    {
      "infoNumber" : 102,
      "imageUrl" : "myImageUrl3",
      "name" : "myName3"
    }
  ]
}

이때 유의해야 할점은 하나의 JSON 파일에 여러개의 JSON 단위가 들어갈 수 없습니다. 쉽게말해, 아래처럼 구성하지는 못한다는 것이죠.

{
  "infoNumber" : 100,
  "imageUrl" : "https://bucket-test.s3.ap-northeast-2.amazonaws.com/test.png",
  "name" : "myName1"
},
{
  "infoNumber" : 101,
  "imageUrl" : "myImageUrl2",
  "name" : "myName2"
},
{
  "infoNumber" : 102,
  "imageUrl" : "myImageUrl3",
  "name" : "myName3"
}

json.simple 의존성 추가

implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'

또 본격적인 API 구성전에 사전준비물이 하나 있습니다. json.simple 에 대한 의존성을 추가해주는 것이죠. Json 라이브러리중 가장 보편적인 json-simple 입니다.


Controller 정의

이제 본격적으로 컨트롤러부터 시작해서 API 를 개발해봅시다. 컨트롤러를 어떻게 구성했는지는 자세한 내용은 생략하고, 핵심적인 부분만 살펴봅시다.

아래처럼 infoService 로부터 더미데이터를 얻어와서, Object 를 리턴하면 JSON 형식으로 리턴이 되도록 구성해습니다. 이어서 설명드릴 Service 단을 보시면 이해하시겠지만, JSON 파일을 파싱한 내용은 Object 타입으로 리턴되죠.

    @ResponseBody
    @GetMapping("/getAllInfo")
    @Operation(summary = "모든 디폴트 더미 데이터 조회", description = "infoNumber, imageUrl, name 필드를 조회합니다. / 스웨거에서 'execute' 버튼 누르면 모든 값들 싹다 조회됩니다!")
    public BaseResponse<Object> getDummyListInJsonFile(){
        try{
            Object object = infoService.getDummy();
            return new BaseResponse(object);
        } catch (BaseException baseException) {
            return new BaseResponse(baseException.getStatus());
        }
    }

Service : 잘못된 파일경로 탐색방식

다음으로 Service 단입니다. 이름은 infoService 라고 부여해줬구요.
우선 Service 단의 메소드 구성방식에 있어 아래와 같은 2가지 방식을 소개드려볼까 합니다.

  • 로컬에서 실행할때는 문제없으나, jar 파일을 배포시 파일탐색 에러가 발생하는 방식
  • 로컬과 배포서버에서 모두 문제없이 돌아가는 방식

먼저 로컬에서만 실행했을때 문제없는 메소드 구성방식에 대해 알아봅시다.

public Object getDummy() throws BaseException{
  try{
        Object jsonVO = new InfoInputReq();
        JSONParser jsonParser = new JSONParser();
        File path = new File("");
        JSONObject jsonObject = (JSONObject) jsonParser.parse(new FileReader(path.getAbsolutePath() + "/src/main/resources/dummy.json"));
        jsonVO = jsonObject.get("infoDummyList");
        return jsonVO;
     } catch (Exception exception){
            throw new BaseException(BaseResponseStatus.SERVER_ERROR);
     }
}

위 방식은 로컬에서는 문제없이 dummy.json 파일 경로를 잘 읽어올거비니다. 그러나 배포한 .jar 파일에서는 해당 파일이 존재하지 않는다는 FileNotFoundException 에러가 발생하게되죠.
저의 경우에도 진행중인 프로젝트 개발서버를 도커에 jar 파일로 이미지화 시켜서 띄웠을때 파일 경로를 읽어오는 과정에서 문제가 발생했었습니다.

jar파일은 class file, resource와 nested jar들로 구성되어 있는데 여기서 resource의 URL은 상단 .jar 루트 경로를 참고해보면 jar://로 시작하는 주소를 가지게 됩니다.

로컬로 실행했을 땐 실제 resource 파일인 file:// 프로토콜을 사용하기 때문에 File 객체를 생성해 줄 수 있어 해당 경로를 찾아올 수 있었고, .jar 파일은 해당 경로를 찾아올 수 없었던 것입니다.


Service : 파일경로 탐색 개선

다음으로 배포 서버에서도 파일 경로를 올바르게 찾을 수 있도록한 코드 개선 내용입니다. 앞선 방식처럼 Jar로 Boot을 구동시 ResourceUtils를 사용시 File Not Found Exception이 발생하죠. 이렇게 ClassPathResource 를 사용해야만 환경에 구애받지 않고 올바르게 탐색이 가능해집니다.

public Object getDummy() throws BaseException{
        try{
            String data = "";
            ClassPathResource cpr = new ClassPathResource("/dummy.json");
            byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
            data = new String(bdata, StandardCharsets.UTF_8);
            JSONParser jsonParser = new JSONParser();
            Object object = jsonParser.parse(data);
            return object;
            
        } catch (Exception exception){
            throw new BaseException(BaseResponseStatus.SERVER_ERROR);
        }
    }

응답 결과

위 API 를 통해 얻어내는 Response 값을 확인해보면 다음과 같습니다. Object 타입으로 리턴했을때 아래와 같이 정상적으로 json 파일의 특정 필드를 파싱한 결과를 도출할 수 있게 되었습니다.

{
  "message": "요청에 성공했습니다.",
  "result": {
    "infoDummyList": [
      {
        "infoNumber": 100,
        "imageUrl": "https://bucket-test.s3.ap-northeast-2.amazonaws.com/test.png",
        "name": "myName1"
      },
      {
        "infoNumber": 101,
        "imageUrl": "myImageUrl2",
        "name": "myName2"
      },
      {
        "infoNumber": 102,
        "imageUrl": "myImageUrl3",
        "name": "myName3"
      }
    ]
  }
}

마치며

이렇게 JSON 파일을 파싱하여, 그 안에 저장해놓은 더미데이터를 응답값으로 보내주는 Fake JSON API 를 알아봤습니다. 꼭 더미데이터뿐만 아니라 다양한 테스트 용도로도 활용되는 방식이니, 큰 도움이 되시길 바랍니다 😉


참고

JSON 파일 파싱 스프링 JAVA VO저장
JAVA - json simple 설치하기
📗 [Spring Boot] .jar 배포 후 resources 파일 경로 찾기
여러개의 @RequestBody의 사용? (Multiple @RequestBody)
Spring | 더미 데이터

profile
https://haon.blog

0개의 댓글