본문 바로가기
개발 이야기/Springboot

Springboot 에서 Gzip으로 압축(with Kotlin)

by 농개 2024. 7. 6.
반응형

Gzip은 파일이나 데이터를 압축하기 위한 소프트웨어 기술을 의미합니다.

간혹 .tar.gz이란 포맷을 가진 파일을 볼 수 있는데 여기에 사용된 압축 기술도 Gzip입니다.

압축률이 준수하고, 속도도 빨라서 웹 환경에서도 자주 사용되곤 합니다.

 

이번 포스팅에서는 Springboot 프로젝트에서 Gzip을 사용한 압축/압축해제 하는 방법을 정리합니다.

 

목차

    1. 압축 하기

    아래와 같이 코드를 작성해줍니다.

    import java.io.BufferedReader
    import java.io.ByteArrayInputStream
    import java.io.ByteArrayOutputStream
    import java.io.InputStreamReader
    import java.util.*
    import java.util.zip.GZIPInputStream
    import java.util.zip.GZIPOutputStream
    
    object CommonUtil {
    
        fun compressGzip(input: String): ByteArray {
            val bos = ByteArrayOutputStream()
            val gzip = GZIPOutputStream(bos);
            gzip.write(input.toByteArray(Charsets.UTF_8))
            gzip.flush()
            gzip.close()
    
            return bos.toByteArray();
        }
    }

    gzip 압축 시에는 압축 대상이 되는 문자열

    ByteArray(java 에서는 byte[]) 형태로 압축하게 됩니다.

     

    2. 압축 해제 하기

    import java.io.BufferedReader
    import java.io.ByteArrayInputStream
    import java.io.ByteArrayOutputStream
    import java.io.InputStreamReader
    import java.util.*
    import java.util.zip.GZIPInputStream
    import java.util.zip.GZIPOutputStream
    
    object CommonUtil {
    
        // ..(중략)
        fun decompressGzip(input: ByteArray): String {
            val gzip = GZIPInputStream(ByteArrayInputStream(input))
            val brd = BufferedReader(InputStreamReader(gzip, Charsets.UTF_8))
            val sb = StringBuilder()
    
            var line: String?
            while (brd.readLine().also { line = it } != null) {
                sb.append(line)
            }
    
            return sb.toString()
        }
    }

    압축 해제 시에는 ByteArray 형태의 압축된 바이트배열을 원본 문자열로 리턴해줍니다.

     

    3. 테스트

    앞서 만든 CommonUtil의 두개 함수를 테스트해봅시다.

    (추가로 byte[] 출력을 위해서 toHexString() 이라는 확장함수를 만들었습니다.)

    import org.junit.jupiter.api.Assertions
    import org.junit.jupiter.api.Tag
    import org.junit.jupiter.api.Test
    
    class CommonUtilTest {
    
        private fun ByteArray.toHexString() = joinToString("") { it.toString(16).padStart(2, '0') }
        
        @Test
        fun `test gzip compress & decompress`() {
            val input =
                "abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!("
    
            val compressed = CommonUtil.compressGzip(input)
            println("compressed: ${compressed.toHexString()}")
    
            val decompressed = CommonUtil.decompressGzip(compressed)
            println("decompressed: $decompressed")
    
            Assertions.assertEquals(input, decompressed)
        }
    }

     

     

    위 테스트 코드를 실행 해봅시다.

    compressed: 1f-7508000000000000-14b4c4a4e312c342a374e35295274-30-305004-3e-3c01120300-64-4c-1e69-74000000
    decompressed: abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(abcd1q2w3e4r!@((!(!(

     

    위와 같이 출력되고 테스트가 통과됨을 확인 할 수 있습니다.

    반응형