Kyounghwan01 / blog

꾸준히 기록하는 개발 블로그!
https://kyounghwan01.github.io/blog/
MIT License
306 stars 9 forks source link

email in html #67

Open Kyounghwan01 opened 9 months ago

Kyounghwan01 commented 9 months ago

email을 등록하는 서비스 마다 다른지 모르겠지만

svg안먹고 display flex도 안먹고, onclick이벤트는 쥐메일이나 네이버메일에서 읽지도 않아서 다 a태그로 감아야하고 고난의 연속

Kyounghwan01 commented 6 months ago
        setUser({ id: customerNumber || '', username: name || '' });
Kyounghwan01 commented 6 months ago
Sentry.init({
    dsn: `${process.env.NEXT_PUBLIC_SENTRY_DSN}`,
    release: process.env.CONFIG_BUILD_ID,
    autoSessionTracking: true,
    integrations: [
        httpClientIntegration({
            failedRequestStatusCodes: [[500, 599]],
        }),
        new Sentry.BrowserTracing(),
        new Sentry.Replay({
            maskAllText: false,
            maskAllInputs: true,
        }),
    ],
    tracesSampleRate: 1.0,
    replaysSessionSampleRate: 0.5,
    replaysOnErrorSampleRate: 1.0,
    allowUrls: [/https?:\/\/((www|ad|dev|tst|predev-www|local)\.)?carrotins\.com/],
    ignoreErrors: [
        'Failed to fetch',
        "Can't find variable: kakaoPixel",
        'Cancel rendering route',
        'ResizeObserver loop limit exceeded',
        "Cannot read property 'Client' of undefined", // Vestpin
        "Cannot read properties of undefined (reading 'Client')", // Vestpin
        "undefined is not an object (evaluating 'new yt.vestPIN.Client')", // Vestpin
        'getDCAScroll is not defined',
        'Installations: Firebase Installation is not registered. (installations/not-registered).', // Firebase
        'Installations: Could not process request. Application offline. (installations/app-offline).', // Firebase
        'Background Sync is disabled.', // show get
        'PAPP_MENU_TYPE', // 네이트판(nate_pansection_cpa)
        'TLT is not defined', // LP_APP(PA00403)
        "undefined is not an object (evaluating 'window.carrotWebBridge.resultApp')", // Carrot iOS Eli 확인불가
        'Network request failed', // Carrot iOS 네트워크 끊김
        "Cannot read properties of undefined (reading 'exec')", // ibk 앱
        "undefined is not an object (evaluating 'window.karrotPixel.track')", // 당근마켓 앱
    ],
    beforeSend: (event, hint) => {
        const device = checkUserAgentForMobile();
        // sentry 에러 제외시킬 앱 user-agent
        if (['ocb', 'syrup', 'tworld', 'paybooc', 'ionebank', 'googlebot', 'naverbot'].includes(device)) {
            return null;
        }
        if ((!event || !event.contexts) && (!hint || !hint.originalException || hint.syntheticException)) {
            return null;
        }
        // 메세지처리
        try {
            const error = hint.originalException || hint.syntheticException;
            let errorMessage: string | undefined;
            if (typeof error === 'string') {
                errorMessage = error;
            } else if (error instanceof Error) {
                errorMessage = error.message;
            }

            const domain = location.protocol + '//' + location.host;
            const pathname = location.pathname;
            const search = location.search;
            let channel = '#error-etc'; // 기타

            // 정리 필요한 url
            if (pathname.match(/members-auto/)) channel = '#error-legacy'; // 멤버스오토 서비스(구)
            if (pathname.match(/calculation\/car/)) channel = '#error-legacy'; // 자동차 산출(구)
            if (pathname.match(/contract\/car/)) channel = '#error-legacy'; // 자동차 계약(구)
            if (pathname.match(/reward\/accident/)) channel = '#error-legacy'; // 자동차 보상(구)
            if (pathname.match(/calculation\/general/)) channel = '#error-legacy'; // 일반 산출(구)
            if (pathname.match(/contract\/general/)) channel = '#error-legacy'; // 일반 계약(구)
            if (pathname.match(/reward\/claim/)) channel = '#error-legacy'; // 일반 보상(구)

            // 정리된 url (desktop,mobile 빠지고 소스정리 error-service, error-insurance)
            if (pathname.match(/my-information/)) channel = '#error-service'; // 서비스
            if (pathname.match(/my-insurance/)) channel = '#error-insurance'; // 내 보험
            if (pathname.match(/tarot/)) channel = '#error-service'; // 타로 서비스
            if (pathname.match(/fortune/)) channel = '#error-service'; // 운세 서비스
            if (pathname.match(/point/)) channel = '#error-service'; // 포인트 서비스
            if (pathname.match(/carrot-drive/)) channel = '#error-service'; // 캐롯고-드라이브 서비스
            if (pathname.match(/go-walk/)) channel = '#error-service'; // 캐롯고-워크 서비스
            if (pathname.match(/one-pass/)) channel = '#error-service'; // 원패스 서비스
            if (pathname.match(/product/)) channel = '#error-product'; // 상품
            if (pathname.match(/product\/partner/)) channel = '#error-product'; // 제휴 상품
            if (pathname.match(/tool\/t/)) channel = '#error-etc'; // 기타

            // 한번 정리된 소스만 에러 확인
            if (['#error-service', '#error-product', '#error-insurance'].includes(channel)) {
                const error_text = `\n:rotating_light:Error:rotating_light: ${errorMessage}\n
            >>> url: ${domain}${pathname}${search}\n
            >>> event: https://femon.carrotins.com/organizations/carrot-insurance/issues/39/?project=2&query=id%3A${event.event_id}&referrer=issue-list&statsPeriod=14d\n
            >>> ua: ${navigator.userAgent}\n\n`;
                fetch('https://hooks.slack.com/services/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', {
                    method: 'post',
                    headers: {
                        Accept: 'application/json, text/plain, */*',
                        'Content-type': 'application/x-www-form-urlencoded',
                    },
                    body: JSON.stringify({ channel: channel, text: error_text, username: '에러봇', icon_emoji: ':ghost:' }),
                });
            }
        } catch (e) {
            console.log('error bot send error');
            return null;
        }

        return event;
    },
});
Kyounghwan01 commented 5 months ago

ios androiid보다 codepush가 빨리도니까 문제가 발생하네, 네이티브가 먼저 완료되면 . 그이후에 codepush 발동되도록 해야함

Kyounghwan01 commented 3 months ago

어쩔때는 앱이 터져도 걍 심사 허용해즘, 대부분 권한이 추가될때 해당권한을 사용하는 것을 명시적으로 말하지 않아서 허가가 안됨

Kyounghwan01 commented 2 months ago

dynamic meta nextjs 신버전으로 패치

Kyounghwan01 commented 1 month ago
  1. ScrollView ScrollView는 자식 컴포넌트를 스크롤할 수 있는 컨테이너입니다. 모든 자식 요소들을 메모리에 한 번에 로드하고 렌더링하기 때문에, 비교적 적은 양의 데이터를 스크롤하는 경우에 적합합니다.

사용하는 경우:

리스트나 컨텐츠의 크기가 작아서 모두 한 번에 렌더링해도 성능에 문제가 없는 경우 리스트가 고정된 크기나 길이를 가지고 있어 동적으로 확장될 가능성이 없는 경우 성능 측면: ScrollView는 모든 데이터를 한 번에 메모리에 로드하기 때문에, 데이터 양이 많아지면 메모리 사용량이 증가하고, 이는 성능 저하로 이어질 수 있습니다. 따라서, 데이터가 많지 않을 때 사용해야 성능적으로 유리합니다.

  1. FlatList FlatList는 대량의 데이터를 효율적으로 렌더링할 수 있는 리스트 컴포넌트입니다. 내부적으로 가상화(Virtualization) 기법을 사용하여 현재 화면에 보이는 아이템들만 렌더링하고, 스크롤에 따라 필요한 아이템들만 추가로 렌더링합니다.

사용하는 경우:

많은 양의 리스트 데이터를 렌더링할 때 동적인 리스트 데이터를 렌더링할 때 (예: 서버로부터 데이터를 받아온 경우) 각 리스트 아이템이 동일한 구조를 가질 때 성능 측면: FlatList는 가상화를 통해 메모리 사용량을 줄이고 성능을 최적화합니다. 데이터가 많을 때는 ScrollView보다 FlatList를 사용하는 것이 성능적으로 훨씬 유리합니다.

  1. SectionList SectionList는 FlatList와 유사하지만, 섹션 단위로 그룹화된 데이터를 렌더링할 수 있는 기능이 추가된 컴포넌트입니다. 각각의 섹션에는 헤더가 있을 수 있으며, 각 섹션 내에서 리스트가 독립적으로 존재합니다.

사용하는 경우:

그룹화된 리스트 데이터를 렌더링할 때 (예: 카테고리별 상품 리스트, 날짜별 일정 등) 각 섹션별로 다른 구조나 스타일을 적용해야 할 때 성능 측면: SectionList는 FlatList와 마찬가지로 가상화를 지원하기 때문에, 데이터 양이 많더라도 성능 저하가 적습니다. 섹션별로 데이터를 나누어야 할 필요가 있을 때는 FlatList보다 SectionList를 사용하는 것이 더 적합하고 성능적 이점이 있습니다.

요약: ScrollView: 적은 양의 데이터, 단일 스크롤 뷰를 사용하는 간단한 경우에 적합. FlatList: 많은 양의 리스트 데이터를 렌더링할 때 적합, 가상화로 성능 최적화. SectionList: 섹션별로 그룹화된 많은 양의 데이터를 효율적으로 렌더링할 때 적합. 데이터의 양, 구조, 그리고 필요한 기능에 따라 적절한 컴포넌트를 선택하여 사용하는 것이 성능 최적화에 도움이 됩니다.