diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index eb0b615f2..bf29ada12 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,4 +1,4 @@
-import { lazy, Suspense } from 'react';
+import { lazy } from 'react';
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider } from 'styled-components';
@@ -15,7 +15,9 @@ import ApplicationFormPage from './pages/ApplicationFormPage/ApplicationFormPage
import ClubUnionPage from './pages/ClubUnionPage/ClubUnionPage';
import IntroducePage from './pages/IntroducePage/IntroducePage';
import 'swiper/css';
+import { GlobalBoundary } from './components/common/ErrorBoundary';
import LegacyClubDetailPage from './pages/ClubDetailPage/LegacyClubDetailPage';
+import ErrorTestPage from './pages/ErrorTestPage/ErrorTestPage';
const queryClient = new QueryClient({
defaultOptions: {
@@ -33,70 +35,51 @@ const AdminRoutes = lazy(() => import('@/pages/AdminPage/AdminRoutes'));
const App = () => {
return (
-
-
-
-
-
-
-
-
-
-
- }
- />
- {/*기존 웹 & 안드로이드 url (android: v1.1.0)*/}
-
-
-
- }
- />
- {/*웹 유저에게 신규 상세페이지 보유주기 위한 임시 url*/}
-
-
-
- }
- />
- {/*새로 빌드해서 배포할 앱 주소 url*/}
-
-
-
- }
- />
- } />
- } />
-
-
-
-
-
- }
- />
- }
- />
- } />
- } />
-
-
-
-
+
+
+
+
+
+
+
+
+ } />
+ {/*기존 웹 & 안드로이드 url (android: v1.1.0)*/}
+ } />
+ {/*웹 유저에게 신규 상세페이지 보유주기 위한 임시 url*/}
+ } />
+ {/*새로 빌드해서 배포할 앱 주소 url*/}
+ }
+ />
+ } />
+ } />
+
+
+
+
+
+ }
+ />
+ }
+ />
+ } />
+ {/* 개발 환경에서만 사용 가능한 에러 테스트 페이지 */}
+ {import.meta.env.DEV && (
+ } />
+ )}
+ } />
+
+
+
+
+
);
};
diff --git a/frontend/src/components/common/ErrorBoundary/GlobalBoundary.tsx b/frontend/src/components/common/ErrorBoundary/GlobalBoundary.tsx
new file mode 100644
index 000000000..6bf44c5b6
--- /dev/null
+++ b/frontend/src/components/common/ErrorBoundary/GlobalBoundary.tsx
@@ -0,0 +1,25 @@
+import { ReactNode, Suspense } from 'react';
+import * as Sentry from '@sentry/react';
+import Spinner from '../Spinner/Spinner';
+import GlobalErrorFallback from './GlobalErrorFallback';
+
+interface GlobalBoundaryProps {
+ children: ReactNode;
+}
+
+const GlobalBoundary = ({ children }: GlobalBoundaryProps) => {
+ return (
+ (
+
+ )}
+ >
+ }>{children}
+
+ );
+};
+
+export default GlobalBoundary;
diff --git a/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.styles.ts b/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.styles.ts
new file mode 100644
index 000000000..2845c4618
--- /dev/null
+++ b/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.styles.ts
@@ -0,0 +1,129 @@
+import styled from 'styled-components';
+
+export const Container = styled.div`
+ min-height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+ background: linear-gradient(135deg, #fff5f0 0%, #ffffff 100%);
+`;
+
+export const Content = styled.div`
+ max-width: 600px;
+ width: 100%;
+ text-align: center;
+ background: white;
+ border-radius: 16px;
+ padding: 48px 32px;
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
+`;
+
+export const IconWrapper = styled.div`
+ margin-bottom: 24px;
+ color: #ff5414;
+ display: flex;
+ justify-content: center;
+
+ svg {
+ width: 64px;
+ height: 64px;
+ }
+`;
+
+export const Title = styled.h1`
+ font-size: 24px;
+ font-weight: 700;
+ color: #111111;
+ margin-bottom: 16px;
+ line-height: 1.4;
+`;
+
+export const Message = styled.p`
+ font-size: 16px;
+ font-weight: 500;
+ color: #787878;
+ line-height: 1.6;
+ margin-bottom: 32px;
+`;
+
+export const ErrorDetails = styled.div`
+ background: #f5f5f5;
+ border: 1px solid #ebebeb;
+ border-radius: 8px;
+ padding: 16px;
+ margin-bottom: 32px;
+ text-align: left;
+ max-height: 300px;
+ overflow-y: auto;
+`;
+
+export const ErrorDetailsTitle = styled.div`
+ font-size: 12px;
+ font-weight: 600;
+ color: #989898;
+ margin-bottom: 12px;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+`;
+
+export const ErrorMessage = styled.div`
+ font-size: 14px;
+ font-weight: 600;
+ color: #ff5414;
+ margin-bottom: 12px;
+ word-break: break-word;
+`;
+
+export const StackTrace = styled.pre`
+ font-size: 12px;
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
+ color: #4b4b4b;
+ white-space: pre-wrap;
+ word-break: break-all;
+ line-height: 1.5;
+`;
+
+export const ButtonGroup = styled.div`
+ display: flex;
+ gap: 12px;
+ justify-content: center;
+ flex-wrap: wrap;
+`;
+
+const BaseButton = styled.button`
+ padding: 14px 32px;
+ font-size: 16px;
+ font-weight: 600;
+ border-radius: 8px;
+ border: none;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ min-width: 140px;
+ font-family: 'Pretendard', sans-serif;
+
+ &:active {
+ transform: scale(0.98);
+ }
+`;
+
+export const PrimaryButton = styled(BaseButton)`
+ background: #ff5414;
+ color: white;
+
+ &:hover {
+ background: #ff7543;
+ box-shadow: 0 4px 12px rgba(255, 84, 20, 0.3);
+ }
+`;
+
+export const SecondaryButton = styled(BaseButton)`
+ background: white;
+ color: #4b4b4b;
+ border: 1px solid #dcdcdc;
+
+ &:hover {
+ background: #f5f5f5;
+ border-color: #c5c5c5;
+ }
+`;
diff --git a/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.tsx b/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.tsx
new file mode 100644
index 000000000..0fb33b525
--- /dev/null
+++ b/frontend/src/components/common/ErrorBoundary/GlobalErrorFallback.tsx
@@ -0,0 +1,74 @@
+import * as Styled from './GlobalErrorFallback.styles';
+
+interface ErrorFallbackProps {
+ error: Error;
+ resetError: () => void;
+}
+
+const WarningIcon = () => (
+
+);
+
+const GlobalErrorFallback = ({ error, resetError }: ErrorFallbackProps) => {
+ const isDev = import.meta.env.DEV;
+
+ const handleReload = () => {
+ window.location.href = '/';
+ };
+
+ const handleReset = () => {
+ resetError();
+ };
+
+ return (
+
+
+
+
+
+
+ 서비스 이용에 불편을 드려 죄송합니다
+
+ 예상치 못한 오류가 발생하여 페이지를 표시할 수 없습니다.
+
+ 잠시 후 다시 시도해 주세요.
+
+
+ {isDev && error && (
+
+
+ 개발자 정보 (프로덕션에서는 표시되지 않습니다)
+
+ {error.message}
+ {error.stack && (
+ {error.stack}
+ )}
+
+ )}
+
+
+
+ 다시 시도
+
+
+ 홈으로 이동
+
+
+
+
+ );
+};
+
+export default GlobalErrorFallback;
diff --git a/frontend/src/components/common/ErrorBoundary/index.ts b/frontend/src/components/common/ErrorBoundary/index.ts
new file mode 100644
index 000000000..f7da0a3ed
--- /dev/null
+++ b/frontend/src/components/common/ErrorBoundary/index.ts
@@ -0,0 +1,2 @@
+export * from './GlobalErrorFallback';
+export { default as GlobalBoundary } from './GlobalBoundary';
diff --git a/frontend/src/components/common/Header/Header.styles.ts b/frontend/src/components/common/Header/Header.styles.ts
index 066141931..8eaac12ab 100644
--- a/frontend/src/components/common/Header/Header.styles.ts
+++ b/frontend/src/components/common/Header/Header.styles.ts
@@ -8,8 +8,7 @@ export const Header = styled.header<{ isScrolled: boolean }>`
left: 0;
right: 0;
width: 100%;
- height: 62px;
- padding: 10px 20px;
+ padding: 18px 0;
background-color: white;
z-index: ${Z_INDEX.header};
@@ -21,6 +20,10 @@ export const Header = styled.header<{ isScrolled: boolean }>`
height: 56px;
padding: 10px 20px;
}
+
+ ${media.mobile} {
+ padding: 8px 20px;
+ }
`;
export const Container = styled.div`
diff --git a/frontend/src/components/common/SearchField/SearchField.styles.ts b/frontend/src/components/common/SearchField/SearchField.styles.ts
index 205dad827..ad8c7a678 100644
--- a/frontend/src/components/common/SearchField/SearchField.styles.ts
+++ b/frontend/src/components/common/SearchField/SearchField.styles.ts
@@ -6,7 +6,7 @@ export const SearchBoxContainer = styled.form<{ $isFocused: boolean }>`
align-items: center;
justify-content: center;
width: 345px;
- height: 36px;
+ height: 40px;
padding: 3px 20px;
border: 1px solid transparent;
border-radius: 41px;
diff --git a/frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts b/frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts
index 655515ca5..a6de3a841 100644
--- a/frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts
+++ b/frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts
@@ -45,6 +45,7 @@ export const TextContainer = styled.div`
padding: 20px;
gap: 8px;
background-color: ${colors.gray[100]};
+ line-height: 160%;
${media.mobile} {
padding: 16px;
diff --git a/frontend/src/pages/ErrorTestPage/ErrorTestPage.styles.ts b/frontend/src/pages/ErrorTestPage/ErrorTestPage.styles.ts
new file mode 100644
index 000000000..8f89d8839
--- /dev/null
+++ b/frontend/src/pages/ErrorTestPage/ErrorTestPage.styles.ts
@@ -0,0 +1,173 @@
+import styled from 'styled-components';
+
+export const Container = styled.div`
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 40px 20px;
+ min-height: 100vh;
+`;
+
+export const Header = styled.div`
+ text-align: center;
+ margin-bottom: 48px;
+ padding-bottom: 24px;
+ border-bottom: 2px solid ${({ theme }) => theme.colors.gray[300]};
+`;
+
+export const Title = styled.h1`
+ font-size: ${({ theme }) => theme.typography.title.title1.size};
+ font-weight: ${({ theme }) => theme.typography.title.title1.weight};
+ color: ${({ theme }) => theme.colors.base.black};
+ margin-bottom: 12px;
+`;
+
+export const Subtitle = styled.p`
+ font-size: ${({ theme }) => theme.typography.paragraph.p3.size};
+ color: ${({ theme }) => theme.colors.gray[700]};
+ line-height: 1.6;
+`;
+
+export const Section = styled.div`
+ background: white;
+ border: 1px solid ${({ theme }) => theme.colors.gray[300]};
+ border-radius: 12px;
+ padding: 24px;
+ margin-bottom: 24px;
+ transition: all 0.2s ease;
+
+ &:hover {
+ border-color: ${({ theme }) => theme.colors.gray[400]};
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+ }
+`;
+
+export const SectionTitle = styled.h3`
+ font-size: ${({ theme }) => theme.typography.title.title5.size};
+ font-weight: ${({ theme }) => theme.typography.title.title5.weight};
+ color: ${({ theme }) => theme.colors.base.black};
+ margin-bottom: 8px;
+`;
+
+export const Description = styled.p`
+ font-size: ${({ theme }) => theme.typography.paragraph.p5.size};
+ color: ${({ theme }) => theme.colors.gray[600]};
+ line-height: 1.5;
+ margin-bottom: 16px;
+`;
+
+interface TestButtonProps {
+ $variant: 'danger' | 'warning' | 'info';
+}
+
+export const TestButton = styled.button`
+ width: 100%;
+ padding: 16px 24px;
+ font-size: ${({ theme }) => theme.typography.paragraph.p3.size};
+ font-weight: 600;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+
+ ${({ $variant, theme }) => {
+ switch ($variant) {
+ case 'danger':
+ return `
+ background: ${theme.colors.primary[900]};
+ color: white;
+ &:hover {
+ background: ${theme.colors.primary[800]};
+ box-shadow: 0 4px 12px rgba(255, 84, 20, 0.3);
+ }
+ `;
+ case 'warning':
+ return `
+ background: ${theme.colors.secondary[2].main};
+ color: ${theme.colors.gray[900]};
+ &:hover {
+ background: ${theme.colors.secondary[5].main};
+ box-shadow: 0 4px 12px rgba(255, 160, 77, 0.3);
+ }
+ `;
+ case 'info':
+ return `
+ background: ${theme.colors.secondary[4].main};
+ color: white;
+ &:hover {
+ background: ${theme.colors.accent[1][900]};
+ box-shadow: 0 4px 12px rgba(61, 187, 255, 0.3);
+ }
+ `;
+ }
+ }}
+
+ &:active {
+ transform: scale(0.98);
+ }
+`;
+
+export const InfoBox = styled.div`
+ background: ${({ theme }) => theme.colors.accent[1][600]};
+ border: 1px solid ${({ theme }) => theme.colors.accent[1][700]};
+ border-radius: 12px;
+ padding: 24px;
+ margin-top: 32px;
+`;
+
+export const InfoTitle = styled.h4`
+ font-size: ${({ theme }) => theme.typography.paragraph.p1.size};
+ font-weight: 600;
+ color: ${({ theme }) => theme.colors.base.black};
+ margin-bottom: 12px;
+`;
+
+export const InfoList = styled.ul`
+ list-style: none;
+ padding: 0;
+ margin: 0;
+
+ li {
+ font-size: ${({ theme }) => theme.typography.paragraph.p5.size};
+ color: ${({ theme }) => theme.colors.gray[800]};
+ line-height: 1.6;
+ margin-bottom: 8px;
+ padding-left: 20px;
+ position: relative;
+
+ &:before {
+ content: '•';
+ position: absolute;
+ left: 8px;
+ color: ${({ theme }) => theme.colors.primary[900]};
+ font-weight: bold;
+ }
+
+ strong {
+ color: ${({ theme }) => theme.colors.base.black};
+ font-weight: 600;
+ }
+ }
+`;
+
+export const BackButton = styled.button`
+ display: block;
+ margin: 32px auto 0;
+ padding: 12px 24px;
+ font-size: ${({ theme }) => theme.typography.paragraph.p3.size};
+ font-weight: 500;
+ color: ${({ theme }) => theme.colors.gray[700]};
+ background: transparent;
+ border: 1px solid ${({ theme }) => theme.colors.gray[400]};
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+
+ &:hover {
+ background: ${({ theme }) => theme.colors.gray[100]};
+ border-color: ${({ theme }) => theme.colors.gray[500]};
+ }
+
+ &:active {
+ transform: scale(0.98);
+ }
+`;
diff --git a/frontend/src/pages/ErrorTestPage/ErrorTestPage.tsx b/frontend/src/pages/ErrorTestPage/ErrorTestPage.tsx
new file mode 100644
index 000000000..9c1616349
--- /dev/null
+++ b/frontend/src/pages/ErrorTestPage/ErrorTestPage.tsx
@@ -0,0 +1,148 @@
+import { useState } from 'react';
+import { useQuery } from '@tanstack/react-query';
+import * as Styled from './ErrorTestPage.styles';
+
+/**
+ * 에러바운더리 테스트용 페이지
+ * 개발 환경에서만 사용
+ */
+const ErrorTestPage = () => {
+ const [shouldThrow, setShouldThrow] = useState(false);
+
+ // 1. 동기 런타임 에러 테스트
+ const throwSyncError = () => {
+ setShouldThrow(true);
+ };
+
+ // 2. 비동기 에러 테스트
+ const throwAsyncError = async () => {
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ throw new Error('비동기 에러 테스트: Promise 내부에서 에러 발생');
+ };
+
+ // 3. API 에러 테스트 (React Query)
+ const { refetch: triggerQueryError } = useQuery({
+ queryKey: ['error-test'],
+ queryFn: async () => {
+ throw new Error('React Query 에러 테스트: API 호출 실패');
+ },
+ enabled: false,
+ throwOnError: true,
+ });
+
+ // 4. 타입 에러 시뮬레이션
+ const throwTypeError = () => {
+ // @ts-ignore
+ const obj = null;
+ // @ts-ignore
+ console.log(obj.property.nested);
+ };
+
+ // 5. 이벤트 핸들러 에러
+ const throwEventError = () => {
+ throw new Error('이벤트 핸들러 에러 테스트');
+ };
+
+ if (shouldThrow) {
+ throw new Error('동기 런타임 에러 테스트: 렌더링 중 에러 발생');
+ }
+
+ return (
+
+
+ 🧪 에러바운더리 테스트 페이지
+
+ 개발 환경에서만 사용 가능합니다. 각 버튼을 클릭하여 에러바운더리
+ 동작을 테스트하세요.
+
+
+
+
+
+ 🔥 동기 에러 (ErrorBoundary 캐치)
+
+
+ 컴포넌트 렌더링 중 발생하는 에러입니다. ErrorBoundary가 캐치합니다.
+
+
+ 동기 런타임 에러 발생
+
+
+
+
+
+ ⚡ 이벤트 핸들러 에러 (콘솔 에러)
+
+
+ 이벤트 핸들러 내부 에러는 ErrorBoundary가 캐치하지 않습니다. 콘솔에
+ 에러가 기록됩니다.
+
+
+ 이벤트 핸들러 에러 발생
+
+
+
+
+
+ 🌐 React Query 에러 (ErrorBoundary 캐치)
+
+
+ throwOnError: true 설정 시 ErrorBoundary가 캐치합니다.
+
+ triggerQueryError()}
+ $variant='danger'
+ >
+ React Query 에러 발생
+
+
+
+
+ ⏱️ 비동기 에러 (콘솔 에러)
+
+ Promise 내부 에러는 ErrorBoundary가 캐치하지 않습니다. try-catch나
+ .catch()로 처리해야 합니다.
+
+
+ 비동기 에러 발생
+
+
+
+
+
+ 💥 타입 에러 (ErrorBoundary 캐치)
+
+
+ null/undefined 접근 에러입니다. 렌더링 중 발생하면 캐치됩니다.
+
+
+ 타입 에러 발생
+
+
+
+
+ ℹ️ 테스트 가이드
+
+
+ ErrorBoundary 캐치: 빨간색 버튼 - 에러 폴백 UI가
+ 표시됩니다
+
+
+ 콘솔 에러: 노란색 버튼 - 콘솔에 에러가 기록되지만
+ 앱은 정상 동작합니다
+
+
+ Sentry 전송: 모든 에러는 Sentry 대시보드에
+ 기록됩니다
+
+
+
+
+ (window.location.href = '/')}>
+ ← 메인 페이지로 돌아가기
+
+
+ );
+};
+
+export default ErrorTestPage;
diff --git a/frontend/src/pages/MainPage/MainPage.styles.ts b/frontend/src/pages/MainPage/MainPage.styles.ts
index b8a1a9c1f..5156dfc57 100644
--- a/frontend/src/pages/MainPage/MainPage.styles.ts
+++ b/frontend/src/pages/MainPage/MainPage.styles.ts
@@ -27,10 +27,10 @@ export const SectionBar = styled.div`
display: flex;
align-items: flex-end;
justify-content: space-between;
- margin: 60px 0px 24px 8px;
+ margin: 24px 0px 16px 8px;
${media.mobile} {
- margin: 32px 4px 16px;
+ margin: 12px 4px 12px;
}
`;
@@ -43,15 +43,16 @@ export const SectionTabs = styled.nav`
}
`;
+// 현재는 중앙동아리 상태만 유지
+// 과동아리 또는 가동아리 확장성을 위해 active 속성 유지
export const Tab = styled.button<{ $active?: boolean }>`
display: flex;
position: relative;
- font-size: 24px;
- font-weight: bold;
+ font-size: 20px;
+ font-weight: 700;
color: ${({ $active }) => ($active ? '#787878' : '#DCDCDC')};
border: none;
background: none;
- cursor: pointer;
&::after {
content: '';
@@ -119,3 +120,30 @@ export const EmptyResult = styled.div`
font-size: 0.95rem;
}
`;
+
+export const RetryButton = styled.button`
+ margin-top: 24px;
+ padding: 12px 32px;
+ font-size: 16px;
+ font-weight: 600;
+ color: white;
+ background: ${({ theme }) => theme.colors.primary[900]};
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+
+ &:hover {
+ background: ${({ theme }) => theme.colors.primary[800]};
+ box-shadow: 0 4px 12px rgba(255, 84, 20, 0.3);
+ }
+
+ &:active {
+ transform: scale(0.98);
+ }
+
+ ${media.mobile} {
+ padding: 10px 24px;
+ font-size: 14px;
+ }
+`;
diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx
index 7b88f6f7a..f09224ce6 100644
--- a/frontend/src/pages/MainPage/MainPage.tsx
+++ b/frontend/src/pages/MainPage/MainPage.tsx
@@ -28,7 +28,7 @@ const MainPage = () => {
const [active, setActive] =
useState<(typeof tabs)[number]>('부경대학교 중앙동아리');
- const { data, error, isLoading } = useGetCardList({
+ const { data, error, isLoading, refetch } = useGetCardList({
keyword,
recruitmentStatus,
category: searchCategory,
@@ -46,10 +46,6 @@ const MainPage = () => {
return clubs.map((club: Club) => );
}, [clubs, hasData]);
- if (error) {
- return 에러가 발생했습니다.
;
- }
-
return (
<>
@@ -75,10 +71,17 @@ const MainPage = () => {
{`전체 ${isLoading ? 0 : totalCount}개의 동아리`}
-
{isLoading ? (
+ ) : error ? (
+
+ 동아리 목록을 불러오는 중 문제가 발생했습니다.
+
+ refetch()}>
+ 다시 시도
+
+
) : isEmpty ? (
앗, 조건에 맞는 동아리가 없어요.
diff --git a/frontend/src/pages/MainPage/components/Banner/Banner.styles.ts b/frontend/src/pages/MainPage/components/Banner/Banner.styles.ts
index 9e4fa1c7d..af38a27ed 100644
--- a/frontend/src/pages/MainPage/components/Banner/Banner.styles.ts
+++ b/frontend/src/pages/MainPage/components/Banner/Banner.styles.ts
@@ -8,7 +8,7 @@ export const BannerContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
- margin-top: 90px;
+ margin-top: 88px;
position: relative;
${media.laptop} {
diff --git a/frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts b/frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts
index 627354b10..152e8c800 100644
--- a/frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts
+++ b/frontend/src/pages/MainPage/components/CategoryButtonList/CategoryButtonList.styles.ts
@@ -5,7 +5,7 @@ export const CategoryButtonContainer = styled.div`
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
- margin-top: 32px;
+ margin-top: 24px;
${media.mobile} {
background-color: white;
@@ -14,7 +14,7 @@ export const CategoryButtonContainer = styled.div`
z-index: 1;
margin: 0px -20px;
- padding: 6px 20px 12px;
+ padding: 16px 20px;
}
${media.mini_mobile} {
@@ -73,6 +73,7 @@ export const CategoryButton = styled.button`
font-size: 12px;
margin-top: 4px;
line-height: normal;
+ font-weight: 600;
}
${media.mini_mobile} {
diff --git a/frontend/src/styles/Global.styles.ts b/frontend/src/styles/Global.styles.ts
index 7427302a4..a6999b4a1 100644
--- a/frontend/src/styles/Global.styles.ts
+++ b/frontend/src/styles/Global.styles.ts
@@ -6,6 +6,9 @@ const GlobalStyles = createGlobalStyle`
padding: 0;
box-sizing: border-box;
}
+ html {
+ overscroll-behavior-y: none;
+ }
textarea, button, input, select {
font-family: 'Pretendard', sans-serif;
}
diff --git a/frontend/src/utils/initSDK.ts b/frontend/src/utils/initSDK.ts
index 4478e1c6c..2f0d113e2 100644
--- a/frontend/src/utils/initSDK.ts
+++ b/frontend/src/utils/initSDK.ts
@@ -51,6 +51,7 @@ export function initializeSentry() {
sendDefaultPii: false,
release: import.meta.env.VITE_SENTRY_RELEASE,
tracesSampleRate: 0.1,
+ integrations: [Sentry.browserTracingIntegration()],
});
}