사고쳤어요
[React / ts] 모바일 대응하기 본문
웹 페이지를 제작할 때 화면 크기가 변경되었을 때 화면이 잘 출력되도록 대응하는 것은 매우 중요하다.
화면 크기에 맞춰 잘 보여지도록 개발을 하더라도 화면 크기에 따라 의도하지 않은 화면이 보여질 수 있다.

예를 들어 위의 페이지에서는 화면이 정상적으로 잘 보여진다.


그러나 모바일 환경 또는 화면 크기를 줄이면 의도하지 않은대로 화면이 깨지는 것을 볼 수 있다.
이런 일이 발생하지 않도록 화면 크기에 대응하여 보여지도록 해보자.
미디어 쿼리(@media)
const BooksListStyle = styled.div<BooksListStyleProps>`
display: grid;
grid-template-columns: ${({ view }) =>
view === "grid" ? "repeat(4, 1fr)" : "repeat(1, 1fr)"};
gap: 24px;
@media (max-width: 768px) {
grid-template-columns: ${({ view }) =>
view === "grid" ? "repeat(2, 1fr)" : "repeat(1, 1fr)"};
}
`;
미디어 쿼리를 사용하면 화면 크기에 따라 다른 스타일을 적용할 수 있다.
위 코드에서는 @media (max-width: 768px)를 통해 가로가 0~768px일 때 스타일을 지정해주었고
grid-template-columns를 2로 설정함으로써 가로 공간을 확보하고 스타일이 깨지지 않도록 하였다.

또는 hook을 사용하여 현재 화면이 모바일인지 여부를 간단하게 확인할 수도 있다.
// useMediaQuery.ts
import { useEffect, useState } from "react";
export const useIsMobile = () => {
const [isMobile, setIsMobile] = useState(
window.matchMedia("(max-width: 768px").matches
);
useEffect(() => {
const mediaQuery = window.matchMedia(`(max-width: ${768}px)`);
const handleChange = (e: MediaQueryListEvent) => {
console.log(e.matches);
setIsMobile(e.matches);
};
// 초기 값 설정
setIsMobile(mediaQuery.matches);
// 이벤트 리스너 등록
mediaQuery.addEventListener("change", handleChange);
// 정리(clean up)
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);
return { isMobile };
};
// BooksList.tsx
interface BooksListProps {
books: Book[];
}
const BooksList: React.FC<BooksListProps> = ({ books }) => {
const [view, setView] = useState<ViewMode>("grid");
const location = useLocation();
const { isMobile } = useIsMobile();
useEffect(() => {
const params = new URLSearchParams(location.search);
if (params.get(QUERYSTRING.VIEW)) {
setView(params.get(QUERYSTRING.VIEW) as ViewMode);
}
}, [location.search]);
return (
<BooksListStyle view={view} isMobile={isMobile}>
{books.map((book) => (
<BookItem key={book.id} book={book} view={view} />
))}
</BooksListStyle>
);
};
interface BooksListStyleProps {
view: ViewMode;
isMobile: boolean;
}
const BooksListStyle = styled.div<BooksListStyleProps>`
display: grid;
grid-template-columns: ${({ view, isMobile }) =>
view === "grid"
? isMobile
? "repeat(2, 1fr)"
: "repeat(4, 1fr)"
: "repeat(1, 1fr)"};
gap: 24px;
@media (max-width: 768px) {
grid-template-columns: ${({ view }) =>
view === "grid" ? "repeat(2, 1fr)" : "repeat(1, 1fr)"};
}
`;
export default BooksList;
useMediaQuery.ts에서 useEffect를 통해 화면 크기가 변경되어 768px 미만 / 이상일 때마다 isMobile값을 업데이트한다.
BooksList.ts에서는 이를 활용하여 isMobile일때는 repeat(2, 1fr), 아닐 때는 repeat(4, 1fr)로 설정하였다.

'웹 풀스택' 카테고리의 다른 글
| 쿠버네티스 사용해보기 (0) | 2025.05.14 |
|---|---|
| Docker Engine 사용하기 (0) | 2025.05.13 |
| [React / ts] MSW로 백엔드 구현 없이 API 테스트해보기 (0) | 2025.05.01 |
| [React / ts] 스니펫 사용하기 (0) | 2025.04.29 |
| [React / ts] Craco로 절대 경로(allias) 사용하기 (0) | 2025.04.29 |