티스토리 뷰

지금까지 페이지를 반응형으로 만들기 위해서는 '미디어 쿼리'를 사용해야 하는 줄 알았다.

아니, 정확히 말하면 '미디어 쿼리'만 있는 줄 알았다.

 

미디어 쿼리를 제외한다면 뷰포트 크기를 조절하기 위해 `rem`, `vw`, `vh` 단위 또는 `flex`, `grid`만 사용해야 하는 줄 알았다. 그러나, 이와 관련된 번역된 글을 보고 나서 '미디어 쿼리'가 아닌 다른 방법에 대해 알게 되었다.

 

 

[번역] CSS 미디어 쿼리, 그 너머로

어떤 방식으로 반응형 웹을 구축하고 있나요? 우리에게 가장 친숙한 방법은 CSS 미디어 쿼리일 것입니다. 이 글에서는 미디어 쿼리는 여러 도구 중 하나일 뿐이고, 반응성을 높이는 다른 좋은 선

velog.io

 

위의 글을 간략하게 요약하자면, 미디어 쿼리가 실용적인 것은 맞지만 여러가지 문제가 있다.

 

미디어 쿼리의 문제점

뷰포트만 고려

레이아웃의 기준인 미디어 쿼리 중단점을 작성할 때, `width`나 `orientation`과 같은 뷰포트 속성에만 접근할 수 있다.

→ 폰트 크기만 조정하면 되는 경우에는 효율적이지만, 대부분의 경우에는 컨텍스트가 중요해 문제가 발생한다.

 

어려운 관리

요즘은 컴포넌트 중심이다. 컴포넌트는 다른 컴포넌트와 공간을 공유하고 변화하는 콘텐츠를 가져온다. 미디어 쿼리는 컴포넌트를 둘러싼 컨텍스트를 전혀 알지 못해 개발자가 모든 경우에 맞는 최적의 지점을 찾아야 한다.

→ CSS 중첩 기능으로 약간의 개선이 이루어졌지만, 모든 컴포넌트마다 해당 작업을 수행해야 하기 때문에 문제는 여전히 존재한다.

 

생각과 다른 반응형

요소의 크기가 화면에 따라 유동적으로 조정되길 바라는 마음과 달리, 특정 중단점에서 컴포넌트가 깨지는 경우가 발생한다. 이 때마다, 미디어 쿼리를 새로 작성하고 관리해야 한다.

(예. 960px에서 970px 사이일 때, 컴포넌트 요소 크기에 문제가 있다면 새로운 스타일 집합을 또 작성해야 하는 문제)

→ 반응형이지만, 반응형이 아닌 문제로 매우 구체적인 상황에만 곶어된 수치를 기반으로 하는 적응형에 가깝다.

 

크기 조정을 위해서 미디어 쿼리만 답이 아니다

미디어 쿼리만 존재했던 과거와 달리, 지금은 많은 선택지들이 생겼다.

`Flexbox`, `Grid`, `반응형 단위`, `수학 함수` 등이 대표적이다.

 

나도 위의 선택지들 중 `Flexbox`, `반응형 단위`를 활용해 페이지를 반응형으로 구현했었다. 그러나, 많은 부분에 있어서 미디어 쿼리를 사용해야 하는 경우가 많았다. 예를 들자면, 브라우저 크기(뷰포트 크기)에 따라 여백을 다르게 준다던지, 크기를 조절해야 한다든지 말이다. 

 

그렇게 미디어 쿼리를 작성하다보니 코드가 지저분해지는 경우가 종종 발생했다. "이를 어떻게 개선할 수 있을까?" 고민하던 중 위의 글을 읽게 되었다. 위의 글은 다음과 같은 방법들을 추천했다.

 

  • Flexbox
    • 뷰포트 중심
    • 재사용과 관리가 어려움
    • 낮은 반응성
    • → 미디어 쿼리를 사용하지 않고, `flex-flow`, `flex`를 활용하자
  • Grid
    • `grid-template-columns` → `auto-fit`, `minmax` 등
  • 수학 함수와 반응형 단위
    • min()
    • max()
    • clamp()
  • 컨테이너 쿼리 (호환성 문제 존재)

 

나는 여러가지 방법 중 `수학 단위`를 활용하기로 결정했다. `min()`, `max()`, `clamp()` 등 여러가지 수학 단위를 활용해 많은 미디어 쿼리 코드를 줄이고자 하였다.

 

수학 단위를 사용하기 전에는 미디어 쿼리를 사용해 뷰포트 크기마다 높이 값을 다르게 했었다.

 

export const SlideCard = styled.article`
    position: relative;
    width: 100%;
    height: 40vh;
    border-radius: 4px;
    overflow: hidden;
    padding: 0 4px;
    margin: 0 20px;
    
    @media (max-width: 1440px) {
        height: 30vh;
    }
    @media (max-width: 1024px) {
        height: 26vh;
    }
    @media (max-width: 768px) {
        height: 22vh;
    }
    @media (max-width: 425px) {
        height: 18vh;
    }
    @media (max-width: 375px) {
        height: 16vh;
    }
    @media (max-width: 320px) {
        height: 14vh;
    }
`

 

수학 단위가 아닌 다른 방법도 사용해 봤는데, 반응형으로 움직이기는 하지만, 내가 원하는 크기가 아니었다.

나는 내가 원하는 크기로 만들기 위해서는 `수학 단위`가 맞다고 판단하고, `수학 단위`로 수정하기로 결정했다.

 

export const SlideCard = styled.article`
    position: relative;
    width: 100%;
    height: clamp(20vh, 10vw, 40vh);
    border-radius: 4px;
    overflow: hidden;
    padding: 0 4px;
    margin: 0 20px;
`

 

나는 `clamp()` 단위를 사용했다.

clamp(최소 크기, 뷰포트 크기에 따라 변경될 크기, 최대 크기)

 

처음에 `clamp()` 단위를 사용할 때, 가운데에 넣는 값이 어떤 것을 의미하는 지 몰랐다.

적용하고 난 뒤, 화면에서 뷰포트 크기에 따라 반응하는 것을 보고 나서 알게 되었다. 가운데 값에 따라 크기가 달라진다는 것을 말이다.

 

그래서 최소 크기와 최대 크기에 상관없이 가운데 값에 따라 같은 뷰포트 크기라도 다르게 나타낸다는 것을 알게 된 후에 어떻게 값을 넣는 게 좋을 지 고민이 많았다. 나는 여러가지 값을 넣어보고 가장 적당한 값인 `10vw`를 적용하기로 결정했다.

 

위 코드만 봐도 미디어 쿼리를 사용했던 것보다 훨씬 간단해졌다. 미디어 쿼리를 사용해서 나타내는 것과 비교해서도 큰 차이가 없었다.

 

높이 값 외에 폰트 크기, 여백 등 다양한 요소에 `clamp()` 단위를 사용해 처리하니 코드가 훨씬 간단해졌고, 반응형으로 잘 나타낼 수 있었다.

 

이렇게 새로운 지식을 활용하니, 미디어 쿼리만을 사용해 처리했던 때에서 시야가 더 넓어진 기분이었다. 번역 글을 작성해주신 블로그 주인분 덕분에 기존 코드를 개선시킬 수 있었다.

(감사함을 표합니다)

 

물론, 더 좋은 방법이 있을 수 있으니 본인에게 더 적합한 방법을 찾아 미디어 쿼리 대신 활용해 코드를 개선해보기를 바란다.