시작하기에 앞서

원래는 구현하는 것과 동기화해서 글을 작성하는 것을 목표로 하였지만, 시간을 지체할 수 없었습니다. 지금 글을 작성하는 시점에서는 클론코딩 과제를 제출하였고 데모사이트 배포가 된 상황입니다. 실제 개발하면서 경험했던 상황을 재현하기 위해 개발자도구를 통해 제어를 해서 재현을 했는데요... 이 부분에서 양해를 부탁드립니다 ㅜㅜ

  • 데모 사이트
    https://zesty-custard-249c6c.netlify.app/
  • 검색 버튼 클릭시 검색 컴포넌트(요소) 활성화, 영어와 한글 변환 기능, 모바일 반응형 디자인을 제외한 나머지를 구현했습니다. 공유기능은 실제 API를 사용해야 되서 이번 과제에서는 구현하지 못했습니다.

main title 영역

제가 생각했을 때 main 영역내부에서 실제 카드요소로 이루어진 콘텐츠에 진입하기 직전에 보여지는 영역이기 때문에 main title영역이라고 구분지어봤습니다.
처음에 달력의 애니메이션을 보고 "직접 애니메이션 처리를 해줘야 되나?" 하고 난감했었는데요...

다행히도, 해당 달력 요소를 만들기 위해 네트워크 통신으로 gif파일을 받아서 처리하는 것을 확인할 수 있었고, 이를 통해 비교적 손쉽게 구현을 할 수 있었습니다.
주소 양식에서 유추할 수 있듯이 ~/ico_date{해당 일자}.gif로 요청하면 해당 일자에 대한 gif파일을 응답으로 가져올 수 있습니다.
(e.g. ~/ico_date30.gif로 요청하면 30일에 해당하는 gif 파일을 응답으로 받을 수 있습니다)

<img src="https://www.kakaocorp.com/page/calendar/light/ico_date2.gif" alt="day" />

위와 같이 html에서는 img태그를 통해 구현가능 합니다.

card 분석

sticky

css의 position:sticky 를 활용하여 좀 더 인터렉티브한 콘텐츠를 만들 수 있습니다. 스크롤 되는 요소가 특정위치에 도달하면 sticky가 적용된 요소는 스크롤이 끝나기 전까지 끈끈하게 달라붙어서 고정되어있습니다.

이게 어떤 차이인지는 실제 눈으로 보면 체감이 되실 것 같기 때문에, 개발자 도구에서 sticky 속성을 제거한 것(미적용)과 제거하지 않은 것(적용)한 것에 대한 차이를 보여드리겠습니다.

sticky가 사용되지 않은 경우

position:sticky가 적용되지 않은 상태에서 스크롤을 내리면 아무 효과 없이 일반적인 스크롤처럼 동작합니다. 그런데, 무언가 밋밋한 느낌이 들지 않나요? 사용자를 사로잡을 인터렉티브한 요소가 없어 보입니다.

sticky가 사용된 경우

이번에는 position:sticky를 적용한 화면입니다. sticky가 없던 화면과 다르게 스크롤 될 때 일정위치가 되면 메인뉴스에 해당하는 요소는 그 위치에서 움직이지 않고 고정되어있으며, 메인 카드 서브 요소들의 스크롤이 끝나면 고정되지 않고 정상적인 스크롤 방식으로 동작합니다.

이와 같이 인터렉티브한 요소가 있다면 전과는 다르게 스크롤할 때 콘텐츠에 집중해서 보고 싶은 욕구가 들지 않으시나요? (저만 그럴 수도 있습니다...)

호환성


역시 IE는 지원하지 않네요 (Internet Explorer를 삭제하여 그동안 수고한 Internet Explorer에게 조의를 표합시다...)

그러나, 대부분의 모던 브라우저에서는 지원해주기 때문에 호환성이 괜찮다고 할 수 있습니다. 예전에 js로 스크롤 위치를 계산해주고 position:fixed 를 활용하여 복잡하게 구현했던 것을 조금 더 간편하게 구현할 수 있도록 도와주는 css 표준 속성이라고 할 수 있습니다. 지원하지 않는 브라우저에도 지원해야 될 경우에는 번거롭지만, 직접 js로 구현이 필요해보이는군요...

sticky를 사용하기 위한 구조

제 생각으로 카카오에서는 자동으로 적용될 수 있도록 아래와 같은 방법을 사용했을 것이라고 추측됩니다.

  • 서버사이드 프레임워크인 Nuxt를 사용하고, 요청URL의 뉴스데이터에 카드 타입이 명시되있다.
  • 인라인 스타일로 css가 작성되어 있다.
    =>
  1. 타입에 따른 카드요소들의 높이는 정해져 있기 때문에, 통신을 통해 가져온 뉴스 데이터를 활용해서 높이를 계산
  2. js를 이용하여 계산된 수치값을 wrapper요소.style을 통해 인라인 스타일로 작성

다만, 저는 레이아웃을 직접 클론코딩해야 되기 때문에 각각 개별적으로 수치를 확인하고 적용했습니다.

height: calc(100vh - px)

sticky를 처음에 적용해서 확인했을 때 카카오 사이트와 달라서 어떻게 구현해야되는지 고민을 하게 되었습니다. 이미 사이트에 정답이 있고 그 것을 통해 배울수 있다는 클론코딩의 장점을 활용해서 구현을 하긴 했는데요... 제가 미숙해서 시간이 소요되었습니다. 혹시라도 저처럼 동일한 문제에 처해계신 분들을 위해 공유하고자 합니다. 일단 어떤 차이점이 있는지 아래를 통해 확인해봅시다.

카카오 메인 랜딩페이지 sticky

  • 일반

  • 뷰포트 높이가 줄어듬

네... 역시 카카오답게 매우 자연스러운 sticky 동작을 확인할 수 있습니다. (클론코딩할 때 레이아웃보다 이런 세세한 애니메이션을 구현해야 되는 것에 시간이 더 소요되었다는 사실이...?! ㅠㅠ)

calc(100vh - px) 미적용

  • 일반

  • 뷰포트 높이가 줄어듬

이 화면을 처음봤을 때 당황했습니다. sticky 기본적인 내용만 알고 있는 상태이여서 해결방안이 생각이 나지 않아 그랬던 것 같습니다. 처음에는 배우는 입장이고, 시간이 지체될 것 같아서 그냥 넘어갈까도 싶었지만... 꺾이지 않는 마음을 가지고 개발자 도구 형님의 도움을 받아보기로 합니다.

vhviewport height 뷰포트 높이에 대한 단위이며 100vh의 의미는 실제 보여지는 브라우저 영역 높이의 전체입니다. 이것이 유동적으로 높이가 줄어들어 일정한 비율로 보여지게 되는 원리입니다. 카드 컴포넌트의 높이를 100vh에서 하단 여백으로 설정하고 싶은 높이를 빼주면 됩니다. 여기에서, max-height를 통해 최대 높이를 설정해주지 않을 경우 레이아웃을 해칠수 있기 때문에 700px로 설정해서 하단 콘텐츠들의 레이아웃에 영향이 없도록 한 것을 확인할 수 있습니다.

inline 특성vertical-align: baseline으로 인한 img 하단의 공백을 제거하기 위해 display: block을 설정한 것으로 보입니다. (vertical-align: top을 이용해서도 제거할 수 있습니다. 그래서 inline-block으로 설정한 요소의 css에 vertical-align:top속성이 적용되는 것도 같은 이유라고 할 수 있습니다.)

이미지는 넘칠 경우 잘려져서 보이게 되며, 카드 컴포넌트의 높이는 보여지는 뷰포트의 높이에 따라 줄어들고 늘어납니다. 결과적으로 스크롤하였을 때 유동적으로 일정비율을 유지하며 고정되있는 효과와 스크롤 했을 때 이미지가 같이 스크롤 되는 것 같은 효과를 얻을 수 있습니다.

relative wrapper

section_home의 두번째 자식요소의 wrap_item이 메인 카드 옆에 있는 서브카드들의 wrapper입니다. 여기에서 height를 충분히 주는 것을 통해 스크롤이 되서 sticky가 화면상에서 정상적으로 적용되도록 할 수 있습니다. height 값을 늘이고 줄여보면 어떤 의미인지 체감할 수 있습니다.

flex-direction: row-reverse

처음 카드 섹션이 끝나고 밑으로 더 스크롤이 되면 동일한 구조의 카드 컴포넌트 구조가 확인됩니다. 다만, 여기에서는 서로 방향이 반대로 되어있네요. 반대로 구현하기 위해서 다시 구조를 만들고 스타일을 생성해야 될까요...?

다행히도 card containerflex container요소이며 현재 flex의 direction은 기본 값인 row입니다. 즉, 가로방향을 따라 정렬되어있습니다. 동일한 html 구조와 class 스타일을 적용한 뒤, flex containercard container요소에 flex-direction: row-reverse 를 적용하면 순서가 거꾸로 되서 가로로 정렬되기 때문에 비교적 손쉽게 동일한 레이아웃을 만들 수 있습니다.

이미지 스프라이트

culture 영역의 아이콘에 사용되는 이미지들은 이미지 스프라이트라는 기법을 통해 적용이 됩니다. 그럼 카카오만 이 기술을 적용하고 있을까요?


네이버도 동일한 기술을 사용하고 있습니다.

그럼 이 기술을 왜 사용하는 걸까요?
동일한 100MB의 용량이 있고 1MB로 100개를 받는 것과 100MB로 1개를 받는다고 가정해봅시다. 여기에서는 서버에서의 비용이라는 개념을 생각해야 되는데, 서버 입장에서는 여러개로 분할해서 받는 것 보다 최대한 1번에 받는 것이 비용이 저렴합니다. 이런 이유로, 여러 이미지들이 모여져 있는 이미지 1개를 받고, background-position 속성으로 위치를 조정하여 해당하는 아이콘의 이미지를 삽입하는 구조입니다.

이미지 스프라이트에 대해 궁금하신 분들은 아래의 사이트를 참고하셔도 좋을 것 같습니다.

https://velog.io/@untiring_dev/HTMLCSS-Day31.-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%8A%A4%ED%94%84%EB%9D%BC%EC%9D%B4%ED%8A%B8-%EA%B8%B0%EB%B2%95

처음에는 레이아웃 클론코딩으로 시작하였지만 하게 되면서 애니메이션 구현에 대한 배움도 있는 것 같고 다양한 기법들에 대해 학습할 수 있어서 유익한 과정이 되는 것 같습니다. 이외의 내용들은 다음 포스트에서 다룰 수 있도록 하겠습니다.

profile
$ npm run dev:ryan

0개의 댓글