---
# System prepended metadata

title: Sentry

---

# Sentry

### Why Sentry?
- **에러 탐지**에 특화되어있음
- 프리티어만 사용하더라도 어떤 에러가 어느 코드에서 발생하는지 추적 가능(sourcemap upload 필요)
- 하지만 성능개선을 위한 지표도 제공
- 성능개선은 개발자가 다양한 기법을 적용하며 유도할 수 있음
    - Throttle
        - 수행할 콜백을 덮어씌울것인가 말것인가(Origin)
            ```typescript
            const getThrottle = () => {
              let waiting = false;
              let willExecuteCallback: () => void;
              return (callback: () => void, time: number) => {
                willExecuteCallback = () => callback();
                if (!waiting) {
                  waiting = true;
                  setTimeout(() => {
                    willExecuteCallback();
                    waiting = false;
                  }, time);
                }
              };
            };

            const getOriginThrottle = () => {
              let waiting = false;
              return (callback: () => void, time: number) => {
                if (!waiting) {
                  waiting = true;
                  setTimeout(() => {
                    callback();
                    waiting = false;
                  }, time);
                }
              };
            };
            ```
    - Debounce
      ```typescript
      const getDebounce = () => {
        let timeoutId: NodeJS.Timeout | undefined = undefined;
        return (callback: () => void, time: number) => {
          if (timeoutId !== undefined) {
            clearTimeout(timeoutId);
          }
          timeoutId = setTimeout(callback, time);
        };
      };
      ```
    - setTimeout/setInterval => [requestAnimationFrame](https://developer.mozilla.org/ko/docs/Web/API/window/requestAnimationFrame)
        - 무한스크롤에도 적용 할 수 있어요 ㅎㅎ
        - https://tech.kakaoenterprise.com/149
    - etc...


### 적용 방법
***아래를 적용하기 전에 우선적으로 도커에 띄워서 테스트해보아야 한다는 점을 참고해주세요. 에러를 일부러 내보고 다음처럼 Issues 탭에 항목이 떠야합니다. `throw new Error('센트리 에러 테스트')`***
![](https://i.imgur.com/JkenNWy.jpg)

1. [Sentry 홈페이지](https://sentry.io/welcome/)에서 회사 계정으로 회원가입
2. 로그인 후 sentry 홈페이지에 접속하면 Organization 만들라는 페이지로 이동하게 될텐데 적절한 name(lighthouse or todaycare)을 적은 후 create합니다.
3. [새 Project 만들기](https://docs.sentry.io/product/sentry-basics/integrate-frontend/create-new-project/) 링크에서 Step1만 따라해주세요. [리액트 설정](https://docs.sentry.io/platforms/javascript/guides/react/) 링크에서 Configure 참고하시면 되며 코드를 보시면 `dsn: "(화살표 아래방향)https://123!#@!#!@#"` 이런식으로 나올 텐데 클릭하셔서 자신이 만든 프로젝트를 선택해주시고 해당 DSN은 복사해두세요. 위 링크에서 설치하라는 패키지 외에 아래 패키지를 추가적으로 설치합니다.
```bash
npm install @sentry/integrations
npm install -D @sentry/webpack-plugin
```
최종적으로 아래와 같은 코드를 설정해주시면 되어요
```typescript
// index.tsx or App.tsx
// redux 설정 코드가 들어가는 그 파일입니다
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { Offline as OfflineIntegration } from '@sentry/integrations';
// OfflineIntegration은 사용자가 Offline일 때 에러가 발생하면
// 브라우저의 IndexDB에 저장해두었다가
// 온라인이 되었을 때 쏴주는 아이입니다

if (process.env.NODE_ENV === 'production') {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    integrations: [new BrowserTracing(), new OfflineIntegration({ maxStoredEvents: 60 })],
    tracesSampleRate: 1.0,
    environment: process.env.NODE_ENV,
    release: 'head',
  });
}
```
4. 웹팩도 설정해야합니다. production webpack만 설정해주세요
```javascript
const SentryWebpackPlugin = require('@sentry/webpack-plugin');

module.exports = {
    ...,
    devtool: 'source-map',
    // 여기서 나온 sourcemap은 Sentry에 업로드 하며
    // 배포되어서는 아니되는 파일입니다
    ...,
    plugins: [
        new SentryWebpackPlugin({
          authToken: process.env.SENTRY_AUTH_TOKEN,
          org: 'lighthouse-km', // organization 이름
          ignore: ['node_modules', 'webpack.dev.js', 'webpack.prod.js'],
          project: 'carehouse-production', // 프로젝트명
          include: './build', // 빌드폴더 명
          release: 'head',
          urlPrefix: '~/', // 배포되었을 때 static file(배포 결과물)들이 위치하는 url prefix
        }),
    ]
}
```

5. ErrorBoundary가 Router를 감싸주어야 합니다. 하단 코드를 참고해주세요
```typescript
// SentryErrorBoundary.tsx
import { ErrorBoundary } from '@sentry/react';
import ErrorBoundaryFallback from '~/pages/ErrorBoundaryFallback';

interface Props {
  children: React.ReactNode;
}

export default function SentryErrorBoundary({ children }: Props) {
  return (
    <ErrorBoundary fallback={({ resetError }) => <ErrorBoundaryFallback resetError={resetError} />}>{children}</ErrorBoundary>
  );
}
```
```typescript
// ErrorBoundaryFallback.tsx
interface Props {
  resetError: () => void;
}

const ErrorBoundaryFallback: React.FC<Props> = ({ resetError }) => {
  const globalState = useSelector((state: RootState) => state.globalReducer);

  return (
    <S.Container>
      <Logo
        to={globalState[KEY.GLOBAL.USER.TYPE] === UserType.INSTITUTE ? PATH.INSTITUTE_HOME : PATH.GUARDIAN_HOME}
        business={globalState[KEY.GLOBAL.USER.TYPE] === UserType.INSTITUTE}
        onClick={() => resetError()}
      />
      <br />
      <S.Description>
        오류가 발생하였습니다.
        <br />
        불편을 드려 죄송합니다.
        <br />
        해당 화면이 반복될 경우
        <br />
        오른쪽 하단 채널톡으로 문의주시기 바랍니다.
      </S.Description>
      <br />
      <Button
        width={200}
        height={48}
        color={'primary'}
        borderradius={6}
        btnLinkinize
        to={globalState[KEY.GLOBAL.USER.TYPE] === UserType.INSTITUTE ? PATH.INSTITUTE_HOME : PATH.GUARDIAN_HOME}
        onClick={() => resetError()}>
        홈으로 이동
      </Button>
    </S.Container>
  );
};

export default ErrorBoundaryFallback;
```
```typescript
// router.tsx
<Router>
    <Switch>
        <SentryErrorBoundary>
            // ...
            <Route path={PATH.GUARDIAN_HOME} exact component={GuardianHomePage} />
            // ...
        </SentryErrorBoundary>
    </Switch>
</Router>
```

6. 아까 복사해둔 DSN 주소는 env파일에 SENTRY_DSN으로 넣어두시구요

7. 다음 위치에서 Auth Tokens를 발급 & 복사해주세요
![](https://i.imgur.com/iBeU6pt.png)

8. 신영님께 배포 스크립트 수정을 요청하며 다음과 같이 전달합니다. 환경변수 하나만 설정해달라고 요청(`SENTRY_AUTH_TOKEN`에다가 방금 복사해둔 Auth Tokens를 넣어달라 요청) + .js.map으로 끝나는 빌드 결과물은 배포하면 안됩니다. 또는 테스트중이라면 빌드 스크립트에서 넣어주면 됩니다.

9. 이제 npm run build시에 빌드 결과물이 떨어지면서 동시에 sentry에 sourcemap이 업로드 됩니다.

10. 일부러 에러를 내보고 테스트 및 production에 적용!
