요즘IT
위시켓
최근 검색어
전체 삭제
최근 검색어가 없습니다.

HTML 레이아웃을 고민하게 된 이유

회원가입을 하면 원하는 문장을
저장할 수 있어요!

다음

회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!

확인

개발

UI 라이브러리 개발 일지: HTML 푸터 배치와 설계 원칙

년차,
어떤 스킬
,
어떤 직무
독자들이 봤을까요?
어떤 독자들이 봤는지 궁금하다면?
로그인

HTML 레이아웃을 고민하게 된 이유

 

최근 우리 팀에서는 UI 라이브러리를 직접 만들기로 결정했다. 지금까지는 웹 사이트를 만들면서 HTML 레이아웃을 깊이 고민해 본 적이 없던 것 같다. 어떤 것이 좋은 레이아웃인지 생각하기보다는, 요소의 의미와 속성만 찾아본 후 바로 사용했을 뿐 깊이 궁금해하지 않았다. 특히 UI 라이브러리를 사용하면서부터는 이미 만들어져 있는 UI 컴포넌트를 가져다 쓰는 데에 익숙했다. 그런데 이번 프로젝트를 통해 HTML 레이아웃에 관해 다시 생각하게 되었고, 오랜만에 HTML 요소를 하나씩 뜯어보기 시작했다.

 

그동안 HTML 요소를 완벽히 시맨틱하게 사용했다고 자부하지는 못해도, 적어도 기본적인 요소는 숙지 후 사용하고 있다고 생각했는데 그건 내 착각이었다. 무엇보다 당황스러웠던 요소는 푸터(footer)였다. 푸터는 메인 콘텐츠 하단에 배치하는 요소이기에, 당연히 position 속성을 absolute로 지정하여 위치를 고정시키는 배치 방법만 있는 줄 알았다. 그러나 이번에 푸터를 배치할 수 있는 방법이 한 가지가 아니라는 사실을 알게 되었다.

 

이러한 깨달음은 과연 우리 라이브러리를 쓰는 사용자는 어떤 배치를 주로 선호할지, 또한 일반적으로 권장하는 배치 방법이 있는지에 대한 고민으로 이어졌다. 하지만 열심히 이곳저곳을 찾아봐도 명확하게 답을 주는 곳은 없었다. 그래서 이 기회에 W3C 문서와 예시를 참고하여, 나만의 설계 원칙을 직접 세워보기로 했다. 이번 글에서는 스스로 정립해 본 푸터 컴포넌트의 배치와 설계 원칙에 관해 이야기해 보고자 한다.

 

<출처: tcpschool.com>

 

푸터 컴포넌트를 만들며 생긴 고민

UI 라이브러리를 만들면서 줄곧 고민한 지점은 바로 사용자의 자유도를 얼마나 보장해 주어야 하는지에 대한 부분이었다. 제약이 많으면 사용자는 제시한 대로 따르면 되지만, 원하는 커스터마이징을 할 수 없어서 불편을 느낄 수도 있다. 반면 제약을 걸지 않으면 사용자는 모든 옵션을 직접 지정해야 하고, 굳이 이 라이브러리를 사용할 필요성을 느끼지 못하게 될 것이다.

 

푸터 컴포넌트에선 position 옵션을 고정할지 말지가 바로 이 맥락의 고민이었다. 직관적으로 생각해 보면, 푸터는 뷰포트 하단에 배치되어야 하기에 position: absolute가 타당해 보인다. 하지만 스택 오버플로에서 ‘footer position’를 검색하면 의외로 fixed를 제안하는 답변이 많이 보인다.

 

position: absolute

푸터의 position을 absolute로 지정하면 마치 포토샵의 레이어처럼 부모 요소 위로 겹치게 되고, 푸터의 높이만큼 부모 요소를 가린다. 여기서 푸터에 bottom:0을 주면, 부모 요소의 아랫부분으로 위치는 내려가지만 여전히 부모 요소를 일부 가린다. 이를 해결하기 위한 여러 트릭이 있는데, 대표적으로 bottom 값으로 푸터의 높이만큼 마이너스 값을 지정하거나, 아니면 부모 요소에 그만큼의 padding-bottom을 지정하는 방법이 있다. 또는 DOM 트리가 Mount되는 시점을 고려해서 부모 요소의 아래쪽에 강제로 푸터 엘리먼트를 attach하는 방법도 있다.

 

이제 UI 라이브러리의 푸터 컴포넌트가 position에 absolute를 가지고 있다고 가정해 보자. 사용자는 푸터 컴포넌트를 배치하자마자 푸터 컴포넌트가 부모 요소를 가리는 것을 목격할 것이고, 푸터를 아래쪽으로 보낼 방법을 고민해야 할 것이다. 그러나 사용자가 너무 귀찮을 수 있으니, 푸터 컴포넌트에 아예 앞서 언급한 트릭 로직까지 넣어두면 좋을 것 같다. 이제 사용자는 푸터 컴포넌트를 간단하게 배치할 수 있게 됐다.

 

position: fixed

그런데 스택 오버플로에서 확인했듯이 푸터의 position을 fixed로 지정하고 싶어 하는 사용자들도 있다. fixed 속성을 통해 위치가 고정된 엘리먼트는 뷰포트 기준으로 위치가 고정되므로, 부모 요소의 내용이 길어져 스크롤이 발생하더라도 무시하고 자기 위치를 고수한다. 개인적으로는 좀 이상하다고 느끼는 UI다. 푸터는 HTML 레이아웃상 아래쪽, 즉 콘텐츠의 맨 끝에 위치해야 자연스럽다고 생각하기 때문이다. 다만 사용자의 요구사항이 더 우선이기 때문에, 우리의 푸터 컴포넌트는 이 요구사항도 충족시켜 주어야 한다.

 

그러면 앞서 position: absolute를 지정했던 설계에 수정이 필요하다. 푸터 컴포넌트의 옵션으로 position을 제공하면 어떨까? 만약 그런 옵션이 있다면 값을 absolute와 fixed로 제한하는 것보다는 CSS의 기본 position을 모두 허용하는 것이 더 자연스럽다. 이쯤에서 궁금한 것은 사용자의 요구사항이다. 다른 position을 지정하고 싶은 사용자도 있지 않을까?

 

position: relative(flexbox)

푸터 배치에 관해 좀 더 공부해 본 결과, position은 relative로 두고 flexbox를 이용할 수 있다는 점을 알게 되었다. 실제로 자주 이용하는 웹사이트를 살펴본 결과, 의외로 푸터 position이 relative로 지정되어 있는 경우가 많았다. 아래 이미지를 보면, 모두 우측 하단 Styles 탭에 position:relative 속성이 포함되어있는 것을 볼 수 있다.

 

<출처: nuxt>

 

<출처: Vuetify>

 

<출처: Vite>

 

<출처: Apple>

 

이에 고민이 꼬리에 꼬리를 물고 이어졌다.

 

  • position을 absolute 또는 fixed로 고정할 것인가?
  • 아니면 relative로 고정하고, 푸터가 추가되는 순간 부모 컴포넌트에 자동으로 display:flex 속성을 부여할 것인가?
  • 그럴 거면 애초에 CSS position 선택지를 모두 주는 게 자연스럽지 않을까?
  • 만약 그렇게 한다면 각각의 position 속성에 대해 별도의 CSS 대응을 해두어야 하지 않을까?

 

고민 끝에 결국 position을 지정하지 않기로 했다. 이제 대략적인 윤곽이 잡혔으니 컴포넌트 설계 원칙을 세우기로 했다. 그래야 작업하면서 똑같은 고민의 굴레에 갇히는 일이 없을 것 같았다.

 

 

내가 세운 좋은 푸터 컴포넌트의 원칙

본격적인 작업에 앞서 UI 라이브러리 관점에서 좋은 푸터 컴포넌트란 이렇게 만들어져야 한다는 기준을 세웠고, 그 내용은 다음과 같다.

 

1) 푸터 컴포넌트는 고정된 높이 없이 콘텐츠에 의해 높이가 정해져야 한다.

<출처: 작가>

 

2) 메인 영역의 아래쪽 영역은 전부 푸터가 차지할 수 있어야 한다.

<출처: 작가>

 

만약 메인 영역의 콘텐츠가 너무 짧다면 메인 영역의 아래쪽을 padding-bottom으로 채우거나, 메인 영역의 높이를 충분히 크게 지정해서 메인 영역의 크기를 키울 수 있을 것이다. 그러나 이에 대해 푸터가 일부러 margin-top을 갖는 등 관여해서는 안 된다. 이를 위해 푸터의 flex속성을 ‘1 1 auto’로 지정한다. (이는 부모 컴포넌트를 flexbox로 지정하는 경우 적용되는 속성이다.)

 

<출처: 작가>

 

3) 만약 메인 콘텐츠가 매우 짧고 푸터의 높이를 고정값으로 지정하는 경우, 푸터 아래쪽에 여백이 남을 수 있다.

<출처: 작가>

 

4) 만약 사용자가 원한다면 푸터 스타일을 직접 수정할 수 있어야 한다.
이러한 기준에 따라서 최종적으로 결정된 스타일시트는 다음과 같다.

.vs-footer {
    background-color: var(--vs-footer-backgroundColor, var(--vs-comp-backgroundColor));
    bottom: var(--vs-footer-bottom, auto);
    color: var(--vs-footer-color, var(--vs-comp-color));
    display: var(--vs-footer-display, flex);
    flex: var(--vs-footer-flex, 1 1 auto);
    height: var(--vs-footer-height, auto);
    left: var(--vs-footer-left, auto);
    padding: var(--vs-footer-padding);
    position: var(--vs-footer-position, static);
    right: var(--vs-footer-right, auto);
    top: var(--vs-footer-top, auto);
    width: var(--vs-footer-width, auto);

    &.primary {
        background-color: var(--vs-footer-backgroundColor, var(--vs-comp-backgroundColor-primary));
        color: var(--vs-footer-color, var(--vs-comp-color-primary));
    }

    .vs-footer-content {
        text-align: var(--vs-footer-textAlign, inherit);
        width: 100%;
    }
}

<출처: Vlossom>

 

위 SCSS 파일에서 사용된 var 함수는 CSS 파일에서 특정 값을 변수로 추상화하고 싶을 때 사용할 수 있는 함수다. 별도 파일에 미리  –vs-footer로 시작하는 변수들을 선언해 놓고, 필요한 곳에서 var 함수로 호출하여 사용했다. –vs-footer는 prefix로, 사용자가 직접 지정한 스타일 속성 앞에 자동으로 붙도록 해두었다. 그래서 var 함수의 첫 번째 인자는 사용자가 커스터마이징한 값들이고, 두 번째 인수는 대체 값이다. 사용자가 아무런 값을 지정하지 않으면 디폴트로 대체 값이 지정되는 방식이다. 물론 사용자가 원한다면 class를 붙여 스타일을 수정할 수도 있다.

 

 

UI 라이브러리를 만들며 깨달은 것

UI 라이브러리를 개발할 때 무엇보다 중요한 것은 사용성이다. 베스트 케이스를 만드는 것도 중요하지만, 컴포넌트가 활용될 수 있는 다양한 방식을 함께 고려해야 한다는 점을 깨달았다. 물론 가장 나은 방식을 베스트 케이스로 두고 컴포넌트를 만들고, 그 방식을 따르게 하면 디자인에 대한 사용자의 고민을 덜어줄 수 있다. 그 자체로 사용하기 편한 라이브러리가 될 수 있을 것이다. 그러나 사용하기 쉽다는 이유만으로 여러 제약을 둔다면 오히려 사용성을 해칠 수도 있다. 만약 사용자가 추구하는 방향이 있다면, 그 역시 가능하게 해야 한다.

 

이번에 푸터 컴포넌트를 개발하면서 사용자가 과연 어떤 것을 원할지 깊이 고민해 보았고, 그 과정에서 다양한 푸터 배치 방식을 알게 되었다. 특히 position 속성의 경우 하나로 제한하지 않았지만, 또 다른 경우 다소 마이너한 취향의 사용법은 제한하는 것이 다수의 사용자에게 편리할 수도 있다.

 

현재 우리 팀은 계속해서 다양한 UI 컴포넌트를 오픈소스로 개발하고 있다. 누구나 사용하기 편리한 UI 라이브러리를 만든다는 목표하에, 나 또한 사용자 관점에서 한 번 더 고민하며 한층 더 성장하게 된 것 같다. 앞으로도 나만의 컴포넌트 원칙을 세워 더 나은 개발자가 되는 일에 집중해 보고자 한다.

 

요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.

좋아요

댓글

공유

공유

댓글 0
프론트엔드 엔지니어
138
명 알림 받는 중

작가 홈

프론트엔드 엔지니어
138
명 알림 받는 중
2년차 프론트엔드 개발자입니다. 리액트와 자바스크립트를 좋아합니다.

좋아요

댓글

스크랩

공유

공유

지금 회원가입하고,
요즘IT가 PICK한 뉴스레터를 받아보세요!

회원가입하기
요즘IT의 멤버가 되어주세요! 요즘IT의 멤버가 되어주세요!
요즘IT의 멤버가 되어주세요!
모든 콘텐츠를 편하게 보고 스크랩해요.
모든 콘텐츠를 편하게 보고 스크랩 하기
매주 PICK한 콘텐츠를 뉴스레터로 받아요.
매주 PICK한 콘텐츠를 뉴스레터로 받기
로그인하고 무료로 사용하기