GitHub
©-2 kd02109 All rights reserved.

카카오 인앱 브라우저 대응하기

  • project
  • react
  • mbtmi
  • javascript
December 10, 2023

문제 배경

해당 채팅 리스트 창에서 대화 창을 클릭하게 되면, 상세 대화 창으로 접속이 이루어지게 됩니다.

윈도우 환경에서 shareAPI를 실행했을 때채팅 리스트
윈도우 환경에서 shareAPI를 실행했을 때상세 대화창

이때 상세 대화 창에 접속하게 되면, 자동으로 스크롤을 대화창 하단으로 이동 되도록 설정을 했습니다. 이는 사용자의 편의성을 위해서 위의 대화가 많다면, 바로 최신 대화를 확인할 수 있도록 하기 위함입니다. 해당 기능을 구현하기 위해서 useEffect와 DOM API를 활용했습니다.

DOM API를 활용한 스크롤 통제하기

  1. **scrollTop** , **scrollHeight** 활용하기

    • **scrollTop** Element.scrollTop 속성은 element의 콘텐츠가 세로로 스크롤되는 픽셀 수를 가져오거나 설정합니다. element의 scrollTop 값은 element의 상단에서 가장 위에 표시되는 콘텐츠까지의 거리를 측정한 값입니다. element의 콘텐츠가 세로 스크롤바를 생성하지 않는 경우 해당 element의 scrollTop 값은 0입니다. scroll이 생성될 경우, scroll을 아래로 움직인 만큼 scrollTop 값이 증가하게 됩니다.
    • **scrollHeight** Element.scrollHeight 읽기 전용 속성은 element 콘텐츠의 총 높이를 나타내며, 바깥으로 넘쳐서 보이지 않는 콘텐츠도 포함합니다. 즉 element의 overflow:hidden을 포함한 총 높이 값을 정수로 반환하게 됩니다.

    해당 두 요소를 활용해서 특정 element의 제일 하단으로 이동시킬 수 있습니다.

    useEffect(() => {
      if (chatDivRef.current) {
        chatDivRef.current.scrollTop = chatDivRef.current.scrollHeight;
      }
    }, [answers]);
  2. scrollTo

    scrollTo는 위의 방법 보다 더 범용적으로 사용할 수 있습니다. **scrollTo()** 메서드의 목적 자체가 문서의 지정된 위치로 스크롤하기 위함입니다.

    window.scrollTo(x_좌표, y_좌표);
    // x 좌표는 문서의 왼쪽 상단부터 시작하는 픽셀 단위로 가로축
    // y 좌표는 문서의 왼족 상단부터 시작하는 픽셀 단위로 세로
    • Option
    window.scroll({
      top: 100, // 창 또는 element를 스크롤할 Y축을 따라 픽셀 수를 지정합니다.
      left: 100, // 창 또는 element를 스크롤할 X축을 따라 픽셀 수를 지정합니다.
      behavior: 'smooth', // "smooth" | "instant" | "auto"
    });
    • 사용 예시
    useEffect(() => {
      if (chatDivRef.current) {
        chatDivRef.current.scrollTo(0, chatDivRef.current.scrollHeight);
      }
    }, [answers]);

인앱 브라우저에서 스크롤이 되지 않는 현상

해당 코드를 통해서 상세 대화창에 대화를 입력할 때 마다, 가장 최근에 입력된 대화를 바로 유저에게 보이도록 했습니다. 해당 기능을 휴대폰으로 테스트 했을 때, 크롬 브라우저에서는 정상적으로 동작을 했지만, 카카오 인앱 브라우저, 네이버 인앱 브라우저 환경에서는 정상적인 동작을 하지 않았습니다.

inapp카카오 인앱 환경
chrome크롬 브라우저 환경

왼쪽의 화면의 경우 카카오 인앱 브라우저입니다. 오른쪽의 경우 크롬 웹브라우저 입니다.

카카오 인앱의 경우 웹 화면 자체를 줄이게 됩니다. 따라서 헤더가 고정이 되고 대화창의 크기 자체가 줄어들게 됩니다. 해당 현상으로 resize가 발생하게 되어 화면이 리렌더링 되면서 기존의 스크롤 기능이 정상적으로 동작하지 않게 되었습니다.

반면에 크롬 웨브라우저의 경우 모바일에서 키보드가 올라오게 될 때, 웹 화면 전체를 위로 올려 보냅니다. 따라서 화면 자체의 크기를 재조정하지 않습니다. 따라서 스크롤 환경에 어떠한 영향을 끼치지 않게 됩니다.

카카오 인앱 브라우저에 대응하기 위해서는 웹 브라우저의 전체 크기가 변경 될 경우 스크롤을 다시 채팅 하단으로 이동시키도록 강제할 필요가 있었습니다. 이를 위해서 window의 가로 크기, 높이 크기를 측정하고 해당 크기에 변화가 있을 시에, 스크롤을 통해 채팅창 하단으로 이동 시키도록 했습니다. 이를 위해서 **resize 이벤트를 활용해서 window 화면에 변화를 감지하고 변화가 있을 경우 스크롤이 발생**하도록 했습니다.

'use client';
import { useState, useEffect, useRef } from 'react';
export default function useResize(answers: string[]) {
  // jsx에 활용할 ref를 설정합니다.
  const chatDivRef = useRef<HTMLDivElement>(null);
 
  // window 크기를 감지하기 위한 state를 지정합니다.
  const [windowSize, setWindowSize] = useState({
    width: 0,
    height: 0,
  });
 
  // effect를 활용해서 DOM에 접근하고 window에 event를 달아서 해결합니다.
  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };
 
    window.addEventListener('resize', handleResize);
 
    return () => window.removeEventListener('resize', handleResize);
  }, []);
 
  // windowSize가 변경될시 ref에 연결된 element의 제일 하단으로 스크롤 합니다.
  useEffect(() => {
    if (chatDivRef.current) {
      chatDivRef.current.scrollTop = chatDivRef.current.scrollHeight;
    }
  }, [windowSize]);
 
  // 처음 화면 진입시 window 제일 하단으로 스크롤 발생
  useEffect(() => {
    window.scrollTo(0, document.body.scrollHeight);
  }, []);
 
  // 이후 답변이 생성 될 시에 scroll을 통해 제일 최근에 단 답변기
  useEffect(() => {
    if (chatDivRef.current) {
      chatDivRef.current.scrollTo(0, chatDivRef.current.scrollHeight);
    }
  }, [answers]);
 
  return chatDivRef;
}
Content Table
  • 문제 배경
  • DOM API를 활용한 스크롤 통제하기
  • 인앱 브라우저에서 스크롤이 되지 않는 현상

Mbtmi

2023.12.10
11 / 12