diff --git a/front/package-lock.json b/front/package-lock.json
index 6824131..71ae8f0 100644
--- a/front/package-lock.json
+++ b/front/package-lock.json
@@ -10,6 +10,8 @@
"dependencies": {
"@react-three/drei": "^9.88.11",
"@react-three/fiber": "^8.15.10",
+ "@sentry/react": "^7.86.0",
+ "@sentry/tracing": "^7.86.0",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.29",
"@types/three": "^0.158.1",
@@ -884,6 +886,121 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@sentry-internal/feedback": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.86.0.tgz",
+ "integrity": "sha512-6rl0JYjmAKnhm4/fuFaROh4Ht8oi9f6ZeIcViCuGJcrGICZJJY0s+R77XJI78rNa82PYFrSCcnWXcGji4T8E7g==",
+ "dependencies": {
+ "@sentry/core": "7.86.0",
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sentry-internal/tracing": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.86.0.tgz",
+ "integrity": "sha512-b4dUsNWlPWRwakGwR7bhOkqiFlqQszH1hhVFwrm/8s3kqEBZ+E4CeIfCvuHBHQ1cM/fx55xpXX/BU163cy+3iQ==",
+ "dependencies": {
+ "@sentry/core": "7.86.0",
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/browser": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.86.0.tgz",
+ "integrity": "sha512-nfYWpVOmug+W7KJO7/xhA1JScMZcYHcoOVHLsUFm4znx51U4qZEk+zZDM11Q2Nw6MuDyEYg6bsH1QCwaoC6nLw==",
+ "dependencies": {
+ "@sentry-internal/feedback": "7.86.0",
+ "@sentry-internal/tracing": "7.86.0",
+ "@sentry/core": "7.86.0",
+ "@sentry/replay": "7.86.0",
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/core": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.86.0.tgz",
+ "integrity": "sha512-SbLvqd1bRYzhDS42u7GMnmbDMfth/zRiLElQWbLK/shmuZzTcfQSwNNdF4Yj+VfjOkqPFgGmICHSHVUc9dh01g==",
+ "dependencies": {
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/react": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.86.0.tgz",
+ "integrity": "sha512-2bHi+YcG4cT+4xHXXzv+AZpU3pdPUlDBorSgHOpa9At4yxr17UWW2f8bP9wPYRgj+NEIM3YhDgR46FlBu9GSKg==",
+ "dependencies": {
+ "@sentry/browser": "7.86.0",
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0",
+ "hoist-non-react-statics": "^3.3.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": "15.x || 16.x || 17.x || 18.x"
+ }
+ },
+ "node_modules/@sentry/replay": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.86.0.tgz",
+ "integrity": "sha512-YYZO8bfQSx1H87Te/zzyHPLHvExWiYwUfMWW68yGX+PPZIIzxaM81/iCQHkoucxlvuPCOtxCgf7RSMbsnqEa8g==",
+ "dependencies": {
+ "@sentry-internal/tracing": "7.86.0",
+ "@sentry/core": "7.86.0",
+ "@sentry/types": "7.86.0",
+ "@sentry/utils": "7.86.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sentry/tracing": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.86.0.tgz",
+ "integrity": "sha512-WPqgmbLm6ntpIoTZd1L/RHIVEDMmvVjIDxKeXGiJeXHZG2VMtgwoxuZAFluVFaD0Sr20Nhj+ZS7HvKOWTxrjjA==",
+ "dependencies": {
+ "@sentry-internal/tracing": "7.86.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/types": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.86.0.tgz",
+ "integrity": "sha512-pGAt0+bMfWgo0KG2epthfNV4Wae03tURpoxNjGo5Fr4cXxvLTSijSAQ6rmmO4bXBJ7+rErEjX30g30o/eEdP9g==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/utils": {
+ "version": "7.86.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.86.0.tgz",
+ "integrity": "sha512-6PejFtw9VTFFy5vu0ks+U7Ozkqz+eMt+HN8AZKBKErYzX5/xs0kpkOcSRpu3ETdTYcZf8VAmLVgFgE2BE+3WuQ==",
+ "dependencies": {
+ "@sentry/types": "7.86.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@swc/core": {
"version": "1.3.96",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.96.tgz",
diff --git a/front/package.json b/front/package.json
index c1dd327..82ad52d 100644
--- a/front/package.json
+++ b/front/package.json
@@ -12,6 +12,7 @@
"dependencies": {
"@react-three/drei": "^9.88.11",
"@react-three/fiber": "^8.15.10",
+ "@sentry/react": "^7.86.0",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.29",
"@types/three": "^0.158.1",
diff --git a/front/src/App.tsx b/front/src/App.tsx
index 7447212..f9cd2c7 100644
--- a/front/src/App.tsx
+++ b/front/src/App.tsx
@@ -9,6 +9,7 @@ import { SnowBallProvider } from '@pages/Visit/SnowBallProvider';
import { MessageProvider } from '@pages/Visit/MessageProvider';
import { DecoProvider } from '@pages/Visit/Deco/DecoProvider';
import { MessageListProvider } from '@pages/Visit/MessageListProvider';
+import * as Sentry from '@sentry/react';
const Outer = styled.div`
position: relative;
@@ -21,75 +22,75 @@ const Outer = styled.div`
width: ${theme.size['--desktop-width']};
}
`;
-
const App = () => {
return (
<>
-
-
-
-
-
-
-
-
-
- }
- />
+
+
+
+
+
+
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+ }
+ >
+ } />
+ } />
+
+
+
+
+
+
+
+ }
+ >
+ } />
+ } />
+
-
+
-
+
-
- }
- >
- } />
- } />
-
-
-
-
-
-
-
- }
- >
- } />
- } />
-
-
-
-
-
-
-
-
-
- }
- />
-
- } />
-
-
-
-
+ }
+ />
+ } />
+
+
+
+
+
>
);
};
diff --git a/front/src/components/Modal/Modal.tsx b/front/src/components/Modal/Modal.tsx
index fbbd205..13de5ba 100644
--- a/front/src/components/Modal/Modal.tsx
+++ b/front/src/components/Modal/Modal.tsx
@@ -1,7 +1,7 @@
import { useState, useRef, useEffect, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { createPortal } from 'react-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { theme } from '@utils';
import {
@@ -157,8 +157,7 @@ const DeleteModal = (props: DeleteModalProps) => {
setMessageList(messageList);
setUserData(userData);
})
- .catch(e => {
- console.error(e);
+ .catch(() => {
navigate('*');
});
})
diff --git a/front/src/index.tsx b/front/src/index.tsx
index 8b2e56b..22ba625 100644
--- a/front/src/index.tsx
+++ b/front/src/index.tsx
@@ -1,5 +1,19 @@
import ReactDOM from 'react-dom/client';
import App from './App';
+import * as Sentry from '@sentry/react';
+
+Sentry.init({
+ dsn: import.meta.env.VITE_APP_SENTRY_DSN,
+ integrations: [
+ new Sentry.BrowserTracing({
+ tracePropagationTargets: ['localhost', /^https:\/\/mysnowball\.kr\/api/]
+ }),
+ new Sentry.Replay()
+ ],
+ tracesSampleRate: 1.0,
+ replaysSessionSampleRate: 0.1,
+ replaysOnErrorSampleRate: 1.0
+});
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
diff --git a/front/src/pages/Main/ListMsgs.tsx b/front/src/pages/Main/ListMsgs.tsx
index f64c426..fbfb27c 100644
--- a/front/src/pages/Main/ListMsgs.tsx
+++ b/front/src/pages/Main/ListMsgs.tsx
@@ -1,6 +1,6 @@
import { useEffect, useState, useContext } from 'react';
import { createPortal } from 'react-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { useLogout } from '@hooks';
import { ListMsg, Prev } from '@components';
@@ -98,7 +98,7 @@ const ListMsgs = (props: ListMsgProps) => {
console.error(e);
logout();
});
- }, []);
+ }, [userData]);
return (
<>
diff --git a/front/src/pages/Main/Main.tsx b/front/src/pages/Main/Main.tsx
index e851a9f..3af801f 100644
--- a/front/src/pages/Main/Main.tsx
+++ b/front/src/pages/Main/Main.tsx
@@ -1,7 +1,7 @@
import { useEffect, useRef, useContext, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useCookies } from 'react-cookie';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { Loading } from '@utils';
import { useLogout } from '@hooks';
@@ -49,7 +49,7 @@ const moveSnowball = (
const nextSnowBallID =
userData.snowball_list[(nowSnowBallID + nextIdx) % userData.snowball_count];
- axios(`/api/snowball/${nextSnowBallID}`)
+ axios(`/api/snowball/${nextSnowBallID + 1000}`)
.then(res => {
setSnowBallData(res.data as SnowBallData);
setMessageListData(res.data.message_list as Array);
diff --git a/front/src/pages/Main/MainBody.tsx b/front/src/pages/Main/MainBody.tsx
index 2536e76..c29b00c 100644
--- a/front/src/pages/Main/MainBody.tsx
+++ b/front/src/pages/Main/MainBody.tsx
@@ -1,5 +1,5 @@
import { useContext, useEffect } from 'react';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { Msg } from '@components';
import { MessageListContext, Message } from '@pages/Visit/MessageListProvider';
diff --git a/front/src/pages/Make/Nickname/Nickname.tsx b/front/src/pages/Make/Nickname/Nickname.tsx
index 69f2c5f..a93f2eb 100644
--- a/front/src/pages/Make/Nickname/Nickname.tsx
+++ b/front/src/pages/Make/Nickname/Nickname.tsx
@@ -1,6 +1,6 @@
import { useState, useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { theme } from '@utils';
import { Button } from '@components';
diff --git a/front/src/pages/Make/Snowball/MainDeco/DecoEnroll.tsx b/front/src/pages/Make/Snowball/MainDeco/DecoEnroll.tsx
index 133d949..01d8830 100644
--- a/front/src/pages/Make/Snowball/MainDeco/DecoEnroll.tsx
+++ b/front/src/pages/Make/Snowball/MainDeco/DecoEnroll.tsx
@@ -1,6 +1,6 @@
import React, { useState, useRef } from 'react';
import { NavigateFunction, useNavigate } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { theme, BlurBody } from '@utils';
import { useLogout } from '@hooks';
diff --git a/front/src/pages/Make/Snowball/MainDeco/MakeButton.tsx b/front/src/pages/Make/Snowball/MainDeco/MakeButton.tsx
index 36b9be3..1b2defe 100644
--- a/front/src/pages/Make/Snowball/MainDeco/MakeButton.tsx
+++ b/front/src/pages/Make/Snowball/MainDeco/MakeButton.tsx
@@ -1,6 +1,6 @@
import { useState, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { LongButton } from '@utils';
import { DecoContext } from './DecoProvider';
diff --git a/front/src/pages/Make/Snowball/Snowball.tsx b/front/src/pages/Make/Snowball/Snowball.tsx
index 4de3d82..ab4801e 100644
--- a/front/src/pages/Make/Snowball/Snowball.tsx
+++ b/front/src/pages/Make/Snowball/Snowball.tsx
@@ -1,7 +1,7 @@
import { useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
-import axios from 'axios';
+import axios from '@utils/axios';
import { Loading, theme } from '@utils';
import { SnowGlobeCanvas, Button } from '@components';
import { MainDeco } from './MainDeco';
diff --git a/front/src/pages/Visit/Deco/PostButton.tsx b/front/src/pages/Visit/Deco/PostButton.tsx
index 4cec04e..20ac211 100644
--- a/front/src/pages/Visit/Deco/PostButton.tsx
+++ b/front/src/pages/Visit/Deco/PostButton.tsx
@@ -1,6 +1,6 @@
import { useContext, useState, useRef } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import styled from 'styled-components';
import { LongButton } from '@utils';
import { DecoContext } from './DecoProvider';
diff --git a/front/src/pages/Visit/SnowBallProvider.tsx b/front/src/pages/Visit/SnowBallProvider.tsx
index d734a16..453e468 100644
--- a/front/src/pages/Visit/SnowBallProvider.tsx
+++ b/front/src/pages/Visit/SnowBallProvider.tsx
@@ -1,5 +1,5 @@
import React, { useState, createContext } from 'react';
-import axios from 'axios';
+import axios from '@utils/axios';
import mockData from '@mock';
interface SnowBallData {
diff --git a/front/src/pages/Visit/Visit.tsx b/front/src/pages/Visit/Visit.tsx
index fc0da13..d924d64 100644
--- a/front/src/pages/Visit/Visit.tsx
+++ b/front/src/pages/Visit/Visit.tsx
@@ -1,6 +1,6 @@
import { useState, useContext, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
import { Loading } from '@utils';
import { SnowGlobeCanvas, UIContainer } from '@components';
import VisitHeader from './VisitHeader';
diff --git a/front/src/pages/Visit/VisitBody.tsx b/front/src/pages/Visit/VisitBody.tsx
index 0beb69d..74bf8e5 100644
--- a/front/src/pages/Visit/VisitBody.tsx
+++ b/front/src/pages/Visit/VisitBody.tsx
@@ -1,6 +1,6 @@
import { useContext, useRef } from 'react';
import styled from 'styled-components';
-import axios from 'axios';
+import axios from '@utils/axios';
import { Msg } from '@components';
import { MessageContext } from './MessageProvider';
import { SnowBallContext, SnowBallData, UserData } from './SnowBallProvider';
diff --git a/front/src/router/HasSnowballData.tsx b/front/src/router/HasSnowballData.tsx
index 4acb370..e547ce9 100644
--- a/front/src/router/HasSnowballData.tsx
+++ b/front/src/router/HasSnowballData.tsx
@@ -1,6 +1,6 @@
import React, { ReactNode, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
-import axios from 'axios';
+import axios from '@utils/axios';
// const saveCookie = () => {
// const cookieToken = import.meta.env.VITE_APP_COOKIE_TOKEN;
diff --git a/front/src/utils/axios.tsx b/front/src/utils/axios.tsx
new file mode 100644
index 0000000..b5e0843
--- /dev/null
+++ b/front/src/utils/axios.tsx
@@ -0,0 +1,17 @@
+import axios from 'axios';
+import * as Sentry from '@sentry/react';
+
+const instance = axios.create();
+
+instance.interceptors.response.use(
+ response => response, // 성공적인 응답 처리
+ error => {
+ // 오류 처리
+ if (error.response && error.response.status !== 409) {
+ Sentry.captureException(error);
+ }
+ return Promise.reject(error);
+ }
+);
+
+export default instance;