S3Template 의 store() 를 이용하여 객체를 저장하는 기능을 구현하였다. 사용자의 프로필을 저장하는 기능이므로 객체는 MultipartFile 이었고, 테스트에서 확인하는 중이었기 때문에 실제 객체는 MockMultipartFile 이다.

@Override
public ResourceResponse save(final MultipartFile resource, final String path, final String resourceName) {
    final String resourceKey = concatResourceKey(path, resourceName);
		final ByteArrayInputStream serializedResource = serialize(resource);
    final S3Resource savedResource = s3Template.store(s3Provider.bucket(), resourceKey, serializedResource);
    return createResourceResponse(resourceKey, savedResource);
}

그런데 다음과 같은 에러가 발생하였다.

Failed to serialize object to JSON
io.awspring.cloud.s3.S3Exception: Failed to serialize object to JSON
	at app//io.awspring.cloud.s3.Jackson2JsonS3ObjectConverter.write(Jackson2JsonS3ObjectConverter.java:46)
	at app//io.awspring.cloud.s3.S3Template.store(S3Template.java:96)
	at app//com.dobugs.yologaauthenticationapi.support.resource.S3Connector.save(S3Connector.java:32)
	at app//com.dobugs.yologaauthenticationapi.support.resource.S3ConnectorTestTest$save.success(S3ConnectorTestTest.java:42)

입력한 객체를 직렬화할 수 없다는 에러였다. 에러가 발생한 가장 마지막 위치를 디버깅해보았다.

Jackson2JsonS3ObjectConverter.java

Untitled

S3 에서 저장하려는 리소스를 직렬화하기 위해 별도의 Converter 객체가 있었고, 내부에서는 ObjectMapper 를 사용한다. 내가 작성한 객체인 S3Connector 에서도 ObjectMapper#writeValueAsBytes 를 실행해보니 동일한 오류가 발생하여, MultipartFile 이 ObjectMapper 로 직렬화할 수 없는 객체라고 판단하였다.

JsonProcessingException 의 에러 메시지를 읽어보면 다음과 같이 설명되어 있다.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

MulfipartFile 은 필드가 없는 객체이고, 객체에 필드가 없으면 직렬화를 할 수 없다. 이 에러를 피하고 싶으면 SerializationFeature.FAIL_ON_EMPTY_BEANS 을 비활성화 시켜라

입력한 객체가 내가 커스텀한 객체였다면 직렬화할 수 있는 조건(ex. 기본 생성자, getter 등) 들을 맞추었을텐데 내가 생성한 객체가 아니다보니 설정값을 바꾸는 방향으로 찾아보았다.

SerializationFeature.java

Untitled

먼저 FAIL_ON_EMPTY_BEANS 는 비어있는 객체, 즉 필드가 없는 객체에 대해서 직렬화를 시도할 경우 fail 이 되도록 설정하는 값이었다. 기본값이 true 이므로 MultipartFile 같은 경우는 직렬화를 할 수 없었다. 따라서 이 설정값을 false 로 변경하여 문제를 해결하였다.

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false