• JPEG vs. PNG: 적절한 이미지 포맷 선택하기 (2) - PNG편

    2021. 1. 27.

    by. 나나 (nykim)

     

     

    프롤로그

    지난 글에서는 JPEG의 특징에 대해 살펴보았으니, 이번엔 PNG에 대해 알아봅니다!

     

    이 시리즈의 이전 글: JPEG vs. PNG: 적절한 이미지 포맷 선택하기 (1) - JPEG편

     

     


     

    PNG를 소개합니다

     

    PNG 역시 웹에서 널리 사용되는 이미지 포맷 중 하나입니다.
    JPEG와 마찬가지로 픽셀로 이루어진 비트맵 그래픽이기도 하고요.

     

     


    이름은 Portable Network Graphics의 약자로, 말그대로 ‘인터넷’에서 표현될 이미지를 염두에 두고 개발되었습니다.
    따라서 RGB가 아닌 색 공간(CMYK 등)은 지원하지 않습니다.

     

     

    PNG 역시 24비트 이상의 색상, 곧 트루 컬러를 지원합니다.
    그런데 JPEG랑 다르게 8비트 알파채널을 지원하기 때문에 다양한 투명도를 표현할 수 있습니다.
    box-shadow 등의 CSS 속성을 쓸 때 투명도 조절을 위해 rgba(0,0,0,0.1)처럼 쓸 때가 있는데, 여기서 ‘a’가 바로 알파 채널입니다.

     

    알파채널은 일종의 마스크 영역으로 이 채널을 조절해 RGB 색상채널에 효과를 적용할 수 있습니다.
    이 알파채널은 색상 정보를 갖지 않으므로 32비트 PNG라 할지라도 표현되는 색의 수는 여전히 16,777,216 색 입니다.
    (PNG는 일반적으론 24비트로 저장하지만 8비트 이미지로 저장하는 경우 최대 256색까지 표현됩니다.)

     

     

    읽을 때는 '핑'이라고 읽는 게 공식이라고 합니다. (하지만 얘도 그냥 피-엔-지일 뿐)

     

     

     

     

     

    PNG의 등장배경

    PNG는 원래 'GIF'라는 포맷을 대체하고자 나타난 포맷입니다. 얘도 많이 들어본 이름이죠!
    GIF는 특허 관계가 좀 난잡했던(?!) 포맷이었기 때문에 그런 GIF랑 헤어지기 위해 만들어졌다고 합니다.
    사실 PNG란 이름의 원래 뜻이 ’PNG’s Not Gif!’ 라는 얘기도 있어요 ;)

     

     

     

     

     


    GIF는 누구시죠?

    고양이.gif ⤴

    GIF(Graphics Interchange Format)는 이름부터 올드한 느낌이 팍팍 나죠?! 옛날 포맷답게 한정된 색만 표현할 수 있습니다.
    24비트 이미지가 아니며 픽셀당 8비트(2^8)밖에 저장하지 못하므로 256색밖에 쓸 수 없어요.
    이 256색 크레파스 세트는 '인덱스 컬러'라고 부릅니다. (아까 살짝 언급했던 PNG-8도 인덱스 컬러죠!)


    사실 GIF도 원래는 'BMP'란 포맷을 대체하고자 나온 포맷입니다.
    BMP는 비트맵 그래픽 중에서도 구조가 가장 단순하고 원시적인 압축 알고리즘을 갖고 있어 용량이 크다는 특징이 있습니다.
    그래서 LZW라는 무손실 압축 알고리즘을 사용한 GIF라는 포맷을 만들어내게 됐죠.
    BMP와 비교해 품질은 유지하고 용량은 줄인 GIF는 웹 상에서 금세 인기를 끌었습니다.

     

     

     

     

     


    GIF를 넘어서다


    하지만 GIF에도 한계는 있었습니다.
    표현할 수 있는 색상 수가 적기도 했고, 무엇보다 GIF의 압축 기술(LZW)에는 특허가 걸려있었습니다.
    특허권을 가진 유니시스 사는 LZW 기술을 쓰려면 특허료를 내야한다고 주장했기 때문에 기업과 사용자들은 GIF 사용을 꺼리기 시작했습니다.
    특히, 1999년에는 프리웨어를 쓸 때도 특허료를 받기로 하면서 반발이 커졌고, 이를 대체하기 위해 나온 PNG의 위상은 점점 커져갑니다.

     

    GIF처럼 무손실압축을 하면서도 더 많은 색을 표현할 수 있는데 PNG가 예뻐 보이지 않을 수가 없죠! 😻
    또, GIF는 단색 투명층인데 반해 PNG는 8비트 알파채널을 지원하므로 가변 투명도를 설정할 수 있다는 것도 장점이었습니다.

     

     

     


    GIF의 특허는 2004년 이후로 만료됐으나 이미지 포맷의 대세는 JPEG와 PNG로 넘어간 뒤였고, 남겨진 GIF는 쓸쓸하게 움짤 담당이 됩니다.
    그래도 한때 잘나가던 이미지 포맷이며, 하나의 파일에 여러 이미지를 저장할 수 있다는 특징 덕분에 아직까지도 쓰이고 있습니다.
    하지만 이마저도 video가 치고 올라오고 있기 때문에, GIF는 과연 무사히 일자리를 지킬 수 있을지...?!

    다만, IE6 이하에선 PNG의 알파값을 나몰라라 하는 이슈가 있으므로 투명 이미지가 필요한 경우 GIF를 사용해야 합니다.
    (근데 IE6은 2001년에 나왔는데... 설마 이거 쓰시는 분 있나요.....)

     

    참고

     

     

     

     


     

     



    무손실 압축: 용량보다 품질 우선

    지난 글에서 JPEG는 품질보다 용량을 택한 손실 압축을 택한다고 했는데요,
    반면에 PNG는 DEFLATE라는 무손실 압축 알고리즘을 통해 고품질을 유지합니다.

     

     


    GIF와는 다르게 특허가 걸린 기술을 사용하지 않고 있기 때문에 이는 PNG 파일 포맷의 대중화에도 영향을 주었습니다.
    이 알고리즘은 LZ77 알고리즘을 통해 데이터를 압축한 뒤, 허프만 부호화를 통해 한 번 더 압축합니다.

     

     

    1) LZ77

    LZ77 알고리즘은 사전(Dictionary) 방식의 압축 알고리즘으로 현재 압축하려는 데이터가 이전에 존재했는지 파악해 반복여부를 표시합니다.
    부호화 도중에 새로 나타나는 심볼열을 책(사전)에 기록하고 그 내용을 다음 부호화에 사용하는 형태입니다.

    예를 들면 아래 이미지를 압축하게 되면...

    출처: Compress-or-Die


    위와 같이 메모리를 사용하게 됩니다.

    진한 파란색 영역은 메모리를 거의 차지하지 않고, 빨간색은 많은 메모리를 차지합니다.
    처음으로 색이 다른 공이 나오면 저장 공간을 쓰지만, 그 다음으로 나올 땐 사용하지 않은 게 보입니다.
    (다만 세번째 빨간 공은 꽤 많은 메모리를 차지하는데 이는 반복되는 거리가 멀기 때문입니다.)

     



    2) 허프만 부호화

    허프만 부호화는 아까 JPEG 압축에도 쓰였던 엔트로피 부호화입니다.
    이 방식은 데이터 문자가 얼마나 자주 출현하는지 빈도를 파악해 빈도수가 높은 기호에 짧은 접두어 코드를 부여합니다. 많이 사용되는 게 작을수록 공간이 절약되겠죠?!

     

    예를 들어, aaabbaabcd라는 문자열이 있습니다.
    가장 많이 쓰인 건 a(5번), 그 다음은 b(3번), 적게 쓰인 건 c(1번)와 d(1번)입니다.

    이제 이 순서대로 짧은 코드를 부여합니다. a=0, b=01, c=011, d=111 이런 식으로요.
    그럼 00001010001011111 으로 압축할 수 있겠죠! 

    압축 전의 문자열은 80비트지만, 부호화 후에는 17비트로 줄어들게 되므로 21%나 압축한 셈이 됩니다 WOW

     

     

    허프만 코딩에 대한 자세한 내용은 여기를 참고하시면 좋을 것 같아요.

     

    PNG 압축 및 다른 포맷과의 비교는 위키피디아에서도 상세히 다루고 있습니다!

     

     




    여기서 우리에게 중요한 점은,
    문자, 선, 패턴 등이 있는 이미지라면 반복되는 영역이 많으므로 압축 효과가 훨씬 클 거라는 뜻입니다.
    여기서부터 저기까지 다 같은 색이라면 퉁치기 편하잖아요ㅎㅎ


    게다가 단순 텍스트나 아이콘인 경우 사용되는 색의 수가 한정적입니다.
    그렇다면 1677...어쩌구 색상을 다 쓸 필요가 없으니 256색을 사용하는 8비트 이미지로 저장하면 용량을 더욱 낮출 수 있겠네요.

     

     

    아래의 이미지는 PNG 파일의 픽셀당 비트 비용을 나타냅니다.
    단순한 유형일 수록 싸게싸게 먹히고 있네요. 특히, Banana 문자 부분은 거의 파란색인 걸 볼 수 있습니다.

     

    출처: Wikipedia

     

     

     

     


    이미지 최적화 (마지막까지 압축하기!)

    MozJPEG, Guetzli 등 이미지를 마지막까지 꾹꾹 압축시켜주는 도구들이 있습니다.
    이러한 이미지 최적화 도구들은 브라우저나 이미지 처리 앱과의 호환성은 유지하면서도 더 작은 이미지 파일을 만들어 줍니다.


    웹에서 쓸 수 있도록 인터페이스를 제공하는 압축 도구 몇 개를 정리했습니다.

    저는 주로 TinyPng를 쓰는데 이유는 판다가 귀엽기 때문입니다 🐼
    압축할 이미지를 업로드하면 아래와 같이 용량을 줄여줍니다.

     

     


    물론 친애하는 이미지 편집 도구(aka 포토샵)에서 적절한 설정을 조절해 용량을 줄이는 것도 좋은 방법이죠 (•̀ᴗ•́)

     

     

     

     

     


     

     

     

     

    실제로 비교해보기

     

    그럼 정말로 이미지 유형에 따라 용량이 달라지는지 확인해 봅시다.

     

     

    여기 멋진 일러스트가 있습니다. (출처: People vector created by pikisuperstar - www.freepik.com)
    지금껏 살펴본 바에 따르면 이 이미지에 어울리는 포맷은? 당연히 PNG겠죠!

     

    출처: freepik

     

     

    이걸 포토샵으로 가져와서 JPEG와 PNG로 각각 저장해보면...

     

     

    JPEG(163K)보다 PNG(76K)의 용량이 훨씬 적게 저장되는 걸 볼 수 있어요.

     

     

     

    JPEG의 품질을 낮춰서 용량을 줄일 수는 있지만, 예상하던 바와 같이 양자화로 인해 글자 부분이 화질구지🦜가 됩니다.

     

     

     

    갑자기 궁금한 점!
    GIF랑 PNG 중에 뭐가 더 용량이 적을까요?

    왠지 GIF의 크기가 더 작을 것 같지만... 사실은 PNG가 최신 기술이라 일을 더 잘해요!
    똑같이 256색을 쓴다고 하면 PNG의 압축률이 더 높습니다.

     

     

    이 일러스트에서는 사용된 색상 수가 그리 많지 않으니까, 인덱스 컬러를 쓰는 8비트 이미지로 저장해도 될 것 같습니다.

    125색상을 쓰는 PNG-8과 GIF로 저장했을 때 용량은 어떻게 나올까요?

     

     

    용량이 작은 순대로 나열하면 PNG-8 > GIF > PNG-24 > JPEG이 됩니다.
    게다가 GIF는 뭔지 모를 손상이 일어나고 있고요 :P

     

    결국 이 이미지는 PNG-8로 저장하는 게 제일 적절해 보입니다.

     

     

     

    출처: Unsplash

    이번엔 사진을 갖고 왔습니다. (출처: Photo by Lauren Mancke on Unsplash)
    이건 JPEG로 저장하는 게 가장 좋을 것 같아요.

     

     

    고해상도 사진이라 용량이 큰 걸 감안해도... JPEG의 압승이네요!

     

     

     

    다른 포맷과 비교해봤습니다.
    JPEG(50품질, 서브샘플링 적용) > JPEG(100품질) > PNG-8 > PNG-24 순대로 용량이 작습니다.

     

    이걸로 사진은 역시 JPEG 포맷이 어울린다는 걸 알았네요.
    엄청난 고해상도 사진이 필요한 게 아니라면, 서브샘플링 같은 눈속이기 기법(?)을 통해 용량 절약도 가능하니까요.

     

     

     

    정리하면

     

    먼 길을 돈 것 같은데, 결국 우리가 알게 된 내용은 프롤로그에서 언급했던 것과 동일합니다ㅎㅎ

     

    추천하는 이미지 포맷

    • JPEG → 복잡한 이미지나 사진

    • PNG → 단순한 이미지, 투명 표현이 필요한 이미지

    • (GIF → 간단한 애니메이션 이미지)

     

    하지만 적어도 이제는 그 이유가 왜인지 알게 됐습니다! 👏👏

     

     

     

     


     



    에필로그

     

    처음엔 '같은 이미지인데 왜 JPEG랑 PNG로 저장할 때 용량이 다르지?' 싶어서 검색을 시작한 거였는데......
    JPEG는 양자화를 한다고? 그게 뭔데? 고주파? 이미지에서 주파수는 뭔 뜻인데? PNG는 GIF를 대체한다고? 그럼 GIF가 대체 어땠길래?
    하다보니 글이 길어졌네요 흐흐흫


    지금껏 너무 당연하게 (생각없이) 이미지를 써왔는데, 이런 내용들을 알게 되면서 리소스를 바라보는 시야가 더 넓어진 느낌이 듭니다. 그리고 저런 거 개발하시는 분들 완전 멋져... 😎

     

     

     

     

     

    댓글 5

    • 프로필사진
      누룽대디 2021.02.01 09:56

      안녕하세요.
      유익한 정보가 많은 블로그 잘 보고 있습니다.
      나나님의 포트폴리오를 통해 이 곳 까지 오게 되었는데요. 궁금한 점이 있어서요.
      저도 나나님의 포트폴리오처럼 제 홈페이지에 제 블로그 최신글 리스트를 보여주고 싶은데
      크로스 도메인 문제로 블로그 RSS 직접 불러오기가 안되더라고요.
      나나님은 포트폴리오 계정에 블로그 RSS를 올려놓고 불러오시는것 같던데
      블로그를 업데이트 하실 때마다 포트폴리오 계정에 수동으로 RSS를 업데이트 하시는건지 아니면 자동화 하신건지
      어떤 방법을 어떻게 사용하시는지 궁금합니다.

      • 프로필사진
        나나 (nykim) 2021.02.03 23:20 신고

        안녕하세요, 댓글 감사합니다~
        저도 티스토리 RSS를 바로 보여주고 싶어서 여러모로 찾아봤는데 결국 웹서버에서 크로스 도메인 설정을 해줘야 하더라구요!
        저는 웹서버를 직접 다루지 않아서, 서버를 관리해 주시는 개발자분께 부탁드려 CORS 설정을 변경했습니다.

      • 프로필사진
        yeon 2021.02.04 00:14

        안녕하세요. 언급된 개발자입니다.
        CORS가 정석이긴 한데, 이건 A 도메인에서 요청을 해서 B 도메인이 응답할 때 B 도메인 가진 서버에서 붙여서 보내줘야 합니다.
        하지만 티스토리에 그런 옵션이 있을 리 없으니, A 도메인인 포트폴리오측 서버에 추가로 서버 경로를 설정해서, 이쪽에서 티스토리쪽으로 대신 요청을 보내게 만들었습니다.
        아시다시피, CORS는 브라우저가 검증하는 보안 체계이기 때문에 브라우저에게 이런 과정이 보이지 않는 게 핵심이죠.

        리버스 프록시라고 nginx 서버에서는 proxy_pass라는 설정으로 가능합니다.
        rewrite 설정으로 URL의 필요한 부분만 제대로 티스토리 서버에 도달하는지 잘 설정을 해줘야 합니다.

        이렇게 하면 같은 도메인이니 CORS 설정이 없어도 문제 없이 요청을 가져올 수 있었습니다.
        포트폴리오를 올리는 서버도 순수 웹호스팅이면 이런 설정이 어렵겠지만, Apache나 nginx로 서버를 설치했다면 덤으로 설정만 추가하면 되는 간편한 방법입니다.
        웹호스팅은 갑작스럽게 방문자가 늘면 트래픽이 초과되고, 그렇다고 평소에 비싼 플랜을 쓸 순 없다보니 VPS 위에 설정하게 되었고, 덕분에 유연하게 여러 기능을 추가할 수 있었습니다.

      • 프로필사진
        나나 (nykim) 2021.02.04 00:20 신고

        대댓글 남겨주셨네요! 상세한 설명 감사합니다 :)

      • 프로필사진
        누룽대디 2021.02.04 09:14

        상세한 답변 감사합니다.
        개발자가 아니다보니 서버 설정 부분은 아무래도 좀 어렵군요ㅠㅠ
        제 홈페이지 서버도 웹호스팅 업체에서 제공하는 일반형이다 보니 어려운 부분이 있을 것 같네요.
        많이 배우고 갑니다!