Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] 성능 개선 : 랜딩 페이지 이미지를 필요한 만큼만 불러오기 #774

Merged
merged 9 commits into from
Oct 23, 2024

Conversation

jinhokim98
Copy link
Contributor

issue

구현 의도

사용자에게 보이지 않는 이미지를 요청하느라 초기 요청 속도가 느려지는 현상이 있었습니다. 필요한 순간에 이미지를 불러올 수 있다면 초기 로딩 속도를 줄일 수 있을 것 같아서 도입했습니다.

현재 성능

네트워크 탭을 기준으로 작성했습니다.

이미지 필요할 때 부르기 전

총 20번의 request가 발생했고 5MB의 데이터 전송량, 7.3MB의 리소스 사용량, 모든 요소가 로드된 Finish time은 4.67초, DomContentLoaded는 631ms, Load는 632ms가 걸렸습니다.

랜딩페이지에 처음 접속했을 때 보이는 화면은 맨 처음 화면 뿐이지만 그 외 화면에 보이지 않는 이미지를 (feature1~5) 불러오는 요청으로 인해 로딩 속도가 지연되고 있습니다.

해결책 고민 점

단순히 img 태그에 loading lazy 속성값을 주게 되면 필요할 때 이미지를 요청할 수 있습니다. 하지만 우리 랜딩 페이지의 경우 이 속성 만을 주었을 때 첫 페이지를 로딩할 때 feature1 이미지까지 같이 불러오는 현상이 발생합니다.

이미지 필요할 때 부르기 전

그래서 이 시점을 정확하게 컨트롤하기 위해 Intersection Observer를 사용했습니다.

Intersection Observer를 사용한 Image Lazy Loading

각 section을 나누어 section 상단의 10%가 사용자의 화면에 관측될 때 이미지 요소를 불러오게 한다면 사용자에게 적절한 타이밍에 이미지를 보여줄 수 있을 것이라 생각했습니다.

type UseImageLazyLoadingProps<T extends HTMLElement> = {
  targetRef: React.RefObject<T>;
  src: string;
  threshold?: number;
};

관측할 요소 ref인 targetRef, 불러올 이미지의 주소 src, 특정 요소가 얼마나 관측될 때 callback을 실행할지 결정하는 threshold를 인자로 받게 했습니다.

const [imageSrc, setImageSrc] = useState<string | undefined>(undefined);

다음으로 useState로 imageSrc를 관리해줍니다. 특정 요소가 관측될 때 img 태그에 src를 넣어주기 위함이며 속성의 타입은 string | undefined로 img 태그의 src 타입과 동일하게 맞춰주었습니다.

useEffect(() => {
    if (targetRef.current && !imageSrc) {
      const observer = new IntersectionObserver(
        ([entry]) => {
          // 특정 요소가 관측될 때 setImageSrc 실행
          if (entry.isIntersecting) {
            setImageSrc(src); 

            // 요소가 관측된 후에는 더 이상 관측할 필요가 없으므로 unobserve
            if (targetRef.current) {
              observer.unobserve(targetRef.current);
            }
          }
        },
        {threshold},
      );

      if (targetRef.current) {
        observer.observe(targetRef.current);
      }

      // 컴포넌트가 unmount될 때 unobserve 
      return () => {
        if (targetRef.current) {
          observer.unobserve(targetRef.current);
        }
      };
    }

    return;
  }, [targetRef, src]);

useEffect 내부에 Intersection Observer 생성자를 사용해 observer를 생성해줍니다. 그 이유는 컴포넌트가 마운트 될 때 observer를 생성하고 observe를 시작하며, 컴포넌트가 언마운트 될 때 unobserve 해주는 것을 보장하기 위함입니다.

다음으로 entry.isIntersecting이 true일 때 (사용자 화면에 특정 요소가 threshold만큼 관측됐을 때) setImageSrc를 실행해주면 요소가 관측될 때 동적으로 img 태그에 src 값을 넣어주게 됩니다. img src가 채워질 때 S3에 이미지 요청을 보내게 되므로 필요한 시점에 이미지 요청을 할 수 있게 됩니다.

관측이 된 후 setImageSrc를 실행했다면 더 이상 이 observer는 관측할 필요가 없으므로 unobserve 해줘서 observe 기능을 해제시킵니다.

그리고 컴포넌트가 마운트되고 targetRef.current가 null이 아닐 때 observe를 시작함으로써 위 기능을 실행할 수 있습니다. 마지막으로 해당 컴포넌트가 언마운트 됐을 때 실행되는 cleanup으로 observer를 unobserve를 실행하면 Intersection Observer를 이용한 Image Lazy Loading을 할 수 있습니다.

const DescriptionSection = () => {
  const descriptionRef = useRef<HTMLDivElement>(null);

  const {imageSrc} = useImageLazyLoading({
    targetRef: descriptionRef,
    src: `${process.env.IMAGE_URL}/standingDog.svg`,
    threshold: 0.1,
  });

  return (
    <div ref={descriptionRef}>
      <img src={imageSrc} alt="행댕이" />
      ...
    </div>
  );
};

export default DescriptionSection;

사용처에서는 이렇게 훅을 사용해준 뒤 ref을 지정해주고, 훅의 반환값인 imageSrc를 img 태그의 src에 주면 됩니다.

개선 결과

총 14번의 request가 발생했고 761KB의 데이터 전송량, 1.3MB의 리소스 사용량, 모든 요소가 로드된 Finish time은 2.43초, DomContentLoaded는 331ms, Load는 332ms가 걸렸습니다.

화면이 보이지 않는 이미지를 미리 가져오지 않게 개선한 결과 데이터 전송량은 5.0MB에서 761KB로 3~4MB 감소, 리소스는 7.3MB에서 1.3MB로 6MB감소, Finish time은 4.67에서 2.43 s로 2s 감소, DomContentLoaded은 631ms에서 331ms로 절반 감소, Loading은 632ms에서 332ms로 절반이 감소한 모습을 볼 수 있습니다.

논의하고 싶은 부분(선택)

  • Intersection Observer threshold를 0.1로 설정했습니다. 이 값이 적절한지 논의해봤으면 해요
  • Intersection Observer를 하위 이미지 모든 요소에 걸지 말고 몇 개 묶어서 관측하자는 의견도 있었습니다. 이는 어떻게 생각하시나요?

🫡 참고사항

위 내용을 정리한 제 블로그 글을 첨부할게요
https://jinokim.tistory.com/41

@jinhokim98 jinhokim98 added 🖥️ FE Frontend 🚧 refactor refactoring labels Oct 20, 2024
@jinhokim98 jinhokim98 added this to the v2.1.2 milestone Oct 20, 2024
@jinhokim98 jinhokim98 self-assigned this Oct 20, 2024
Copy link
Contributor

@pakxe pakxe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지를 어떻게 불러올지 고민하느라 고생많았습니다!
제가 생각하기에 상황에 잘 맞는 해결책인 것 같아요.

threshold?: number;
};

const useImageLazyLoading = <T extends HTMLElement>({targetRef, src, threshold = 0.1}: UseImageLazyLoadingProps<T>) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 이게 가로스크롤이 적용된 새로운 랜딩페이지에서도 제대로 동작하나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 테스트 해봐야 할 것 같아요. 세로 기준으로 작업했던터라...

threshold?: number;
};

const useImageLazyLoading = <T extends HTMLElement>({targetRef, src, threshold = 0.1}: UseImageLazyLoadingProps<T>) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실제로 써본 결과 0.1보다 조금 더 커도 좋을 것 같습니다. 이미지가 없다가 생기는 시간차가 보였어요.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마지막 사진이 그렇죠.. 마지막 사진이 4MB여서 불러오는데 시간이 걸리는 것 같아요.
영역을 조금 더 적게 보여도 이미지를 불러오게 하자는 의미가 맞을까요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞습니다. 더 빨리 이미지를 로드해오면 좋을 것 같아요.
그리고 이미지 용량을 대폭 개선해두었습니다. 제가 메인페이지 실험할 때 pr에 올라온 모든 브랜치 풀받고 해봤는데 용량 개선 이미지임에도 불구하고 좀 나중에 뜨는 이미지가 있더라구요.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저 같은 경우는 네트워크 속도 제한을 걸지 않을 때는 이미지가 늦게 뜬 것은 없었어요.
다만 네트워크 상태가 좋지 않은 (엘레베이터, 지하) 곳에서 사용하면 웨디가 말해준 것 처럼 이미지 로드가 느릴 것 같긴 해요. 총 5개의 feature 이미지 중에서 1번은 3.95초 5번은 5.67초였어요!
결론, 웨디 리뷰처럼 반영해보고 이전과 성능을 비교해보면 더 좋을 것 같다 입니다 ~

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마지막 사진의 경우, 제가 작업했던 #764에서 파일 크기를 줄여서 새로 s3에 업로드 했습니다.
현재에는 219KB로 변경되었습니다~!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor

@pakxe pakxe Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토달 feature5 이미지와 50kb가 넘는 이미지는 모두 webp로 변경했어요~~

import {descriptionSectionStyle, imgStyle} from './DescriptionSection.style';

const DescriptionSection = () => {
const descriptionRef = useRef<HTMLDivElement>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref를 써야 옵저버를 쓸 수 있군요

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요! 각 ref는 intersection observer가 관찰하는 대상입니다. ref의 10%가 보였을 때 이미지 요청을 하기 때문에 ref가 필요해요

import {Text} from '@components/Design';

import {articleStyle, imageStyle, sectionStyle, textContainerStyle} from './CheckDeposit.style';

const CheckDeposit = () => {
const sectionRef = useRef<HTMLElement>(null);

const {imageSrc} = useImageLazyLoading({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지를 반환하는 것도 방법이지만, 아래와 같은 구조는 어떻게 생각하시나요?
굳이 훅에서 이미지를 인자로 받고 그걸 또 반환하지 않아도 될 것 같아요..!

const imageSrc = `https://,,,/feature3.svg';

useImageLazyLoading({ 
  src: imageSrc,
  // ... 
});

return (
  <img src={imageSrc} />
)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 imageSrc는 정적인 이미지 주소가 아니라 이미지 상태입니다. 특정 영역이 관측되기 전에는 imageSrc의 값은 undefined입니다. 그 후 사용자에게 특정 영역이 10% 관측될 때 s3 주소를 할당받게 됩니다.

그래서 hook 안에서 바깥으로 넘겨주도록 작성했어요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지 주소가 동적으로 바뀌는 것이었군요! 설명 고맙습니다 ㅎ.ㅎ

@@ -16,7 +28,7 @@ const RecordMemoryWithPhoto = () => {
정산은 투명하게, 추억은 오래오래 간직할 수 있어요.`}
</Text>
</div>
<img src={`${process.env.IMAGE_URL}/feature5.svg`} css={imageStyle} />
<img src={imageSrc} css={imageStyle} alt="record memory with photo" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alt 까지~~~!!! 👍
그치만 저희 페이지는 한국 사용자를 대상으로 하니 한국어 설명은 어떤가요?!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그러네요! 한글로 alt 작성해볼게요


useEffect(() => {
if (targetRef && !imageSrc) {
const observer = new IntersectionObserver(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

observer를 활용해서 이미지를 필요한 때에 로딩하는 방법은 정말 좋은 것 같아요!👍

Copy link
Contributor

@soi-ha soi-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

observer를 활용해서 이미지를 필요할 때만 사용하도록 하는 방법이 정말 좋은 것 같아요! observer를 이런 식으로 활용하다니 👍
덕분에 초기 로딩 속도가 조금이나마 더 빨라진 것 같습니다!

<div css={descriptionSectionStyle}>
<img css={imgStyle} src={`${process.env.IMAGE_URL}/standingDog.svg`} alt="행댕이" />
<div css={descriptionSectionStyle} ref={descriptionRef}>
<img css={imgStyle} src={imageSrc} alt="행댕이" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 행댕이 img를 토다리가 올려준 PR의 object? 태그를 활용하면 좋을 것 같아요!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soi-ha 이부분의 행댕이 svg는 사실 가짜 svg라서 크게 상관없을 것 같긴 해요!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alt에는 "행댕이" 라고만 적으면 듣는 입장에서 헷갈릴 수 있다는 생각도 드네요!
행댕이 - 행동대장 마스코트 라던지 부연 설명을 넣거나 "" 로 처리해도 좋겠다 싶어요~
전혀 상관은 없습니다 ㅎㅎ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하! 그러네요 저희만의 암묵적 언어이니 사용자 입장에서 이해하기 좋은 alt 값을 선언해야 할 것 같아요!

const {imageSrc} = useImageLazyLoading({
targetRef: sectionRef,
src: `${process.env.IMAGE_URL}/feature1.svg`,
threshold: 0.05,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useImageLazyLoading을 사용하고 있는 곳의 threshold가 다 0.05 인것 같은데, default threshold의 값을 0.1이 아닌 0.05로 변경해주는 건 어떠세용?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default 값을 변경해주는 것도 좋은 것 같아요..!

const {imageSrc} = useImageLazyLoading({
targetRef: descriptionRef,
src: `${process.env.IMAGE_URL}/standingDog.svg`,
threshold: 0.1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threshold가 default로 0.1인데 같은 값으로 중복 지정하고 있는 것 같아요~
혹시 default 값을 0.05로 변경하실 생각이 있으시다면 해당 코드는 그대로 두면 될 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗 놓치고 있었어요... 감사합니다~~

Copy link
Contributor

@Todari Todari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

미션에서 배웠던 interSectionObserver를 적재 적소에 매우 야무지게 적용한 코드라고 생각되네요!

고생 많았어요 쿠키~!

몇가지 comment 드렸지만, 전혀 중요한게 아니니 approve 하겠슴당

threshold?: number;
};

const useImageLazyLoading = <T extends HTMLElement>({targetRef, src, threshold = 0.1}: UseImageLazyLoadingProps<T>) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

마지막 사진의 경우, 제가 작업했던 #764에서 파일 크기를 줄여서 새로 s3에 업로드 했습니다.
현재에는 219KB로 변경되었습니다~!

threshold?: number;
};

const useImageLazyLoading = <T extends HTMLElement>({targetRef, src, threshold = 0.1}: UseImageLazyLoadingProps<T>) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

<div css={descriptionSectionStyle}>
<img css={imgStyle} src={`${process.env.IMAGE_URL}/standingDog.svg`} alt="행댕이" />
<div css={descriptionSectionStyle} ref={descriptionRef}>
<img css={imgStyle} src={imageSrc} alt="행댕이" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@soi-ha 이부분의 행댕이 svg는 사실 가짜 svg라서 크게 상관없을 것 같긴 해요!

<div css={descriptionSectionStyle}>
<img css={imgStyle} src={`${process.env.IMAGE_URL}/standingDog.svg`} alt="행댕이" />
<div css={descriptionSectionStyle} ref={descriptionRef}>
<img css={imgStyle} src={imageSrc} alt="행댕이" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alt에는 "행댕이" 라고만 적으면 듣는 입장에서 헷갈릴 수 있다는 생각도 드네요!
행댕이 - 행동대장 마스코트 라던지 부연 설명을 넣거나 "" 로 처리해도 좋겠다 싶어요~
전혀 상관은 없습니다 ㅎㅎ

<article css={articleStyle}>
<img src={`${process.env.IMAGE_URL}/feature2.svg`} css={imageStyle} />
<img src={imageSrc} css={imageStyle} alt="차등 정산 계산을 쉽게 해주는 UI 이미지" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이부분의 이미지들도 글로 설명이 되기 때문에, 오히려 alt가 비어도 괜찮겠다 싶기도 하구요.
lighthouse는 공백 alt보다 적힌 alt의 점수를 더 높게 주나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 생각하기엔 그림 이미지가 단순 배경이 아닌 의미가 있는 그림이라고 생각했습니다. 그래서 alt 값을 넣어줬어요!

Copy link

@Todari Todari merged commit 519e278 into fe-dev Oct 23, 2024
2 checks passed
@Todari Todari deleted the feature/#773 branch October 23, 2024 07:36
@Todari Todari mentioned this pull request Oct 23, 2024
Todari pushed a commit that referenced this pull request Oct 23, 2024
* feat: intersection api를 이용해서 특정 영역이 관측될 때 이미지 src를 채우는 hook 구현

* feat: useImageLazyLoading 훅 적용

* feat: 이미지 alt 값을 한국말로 변경

* fix: feature4,5 이미지를 4 불러올 때 한 번에 불러오는 방식으로 변경

* feat: threshold를 0.1에서 0.05로 조금 더 빨리 불러오도록 변경

* feat: alt 행댕이를 행댕이 - 행동대장 마스코트 라고 자세하게 설명

* feat: threshold default value 0.1 -> 0.05로 변경

* feat: 0.1 -> 0.05 놓친 부분 수정
Todari added a commit that referenced this pull request Oct 24, 2024
* refactor: 랜딩 페이지 디렉토리 구조 변경 (#767)

* refactor: 랜딩 페이지 디렉토리 구조 변경

* refactor: nav 관련 스타일 nav로 이동

* remove: 사용하지 않는 컴포넌트 제거

* style: div => section, article 태그로 변경

* style: 컴포넌트 이름 조금 더 의미있게 변경

* refactor: App을 제외한 페이지 컴포넌트 lazy loading

* refactor: QueryClient가 필요하지 않은 랜딩 페이지에서 tanstack-query script 제거

* refactor: tree shaking을 deep하게 적용하기 위해 package.json에 sideEffects false 적용

* feat: prod build 파일에서 sourcemap과 license 파일 제거

* feat: 문의하기 페이지 구현 (#772)

* feat: 문의하기 구글 forms 페이지 링크 연결

* fix: chromatic 에러 해결

* refactor 성능 개선 : Preconnect to requered origins (#771)

* refactor: 성능개선 Preconnect to requered origins (font)

* fix: storybook에서 pretendard 폰트가 적용되도록 스토리북 preview.tsx 수정

* refactor: 성능 개선 : 랜딩 페이지 이미지를 필요한 만큼만 불러오기 (#774)

* feat: intersection api를 이용해서 특정 영역이 관측될 때 이미지 src를 채우는 hook 구현

* feat: useImageLazyLoading 훅 적용

* feat: 이미지 alt 값을 한국말로 변경

* fix: feature4,5 이미지를 4 불러올 때 한 번에 불러오는 방식으로 변경

* feat: threshold를 0.1에서 0.05로 조금 더 빨리 불러오도록 변경

* feat: alt 행댕이를 행댕이 - 행동대장 마스코트 라고 자세하게 설명

* feat: threshold default value 0.1 -> 0.05로 변경

* feat: 0.1 -> 0.05 놓친 부분 수정

* refactor: 성능 개선 : Kakao script를 필요한 곳에서 다운로드 받기 (#776)

* feat: Kakao script 동적으로 불러올 수 있는 함수 작성

* feat: 드롭다운 버튼 베이스 onClick 메서드 추가

* feat: 모바일 환경에서 초대버튼 눌렀을 때 카카오 스크립트를 불러오도록 설정

* feat: KakaoInitializer 제거

* refactor: v2.1.1에서 구현한 랜딩페이지 개선 (#777)

* feat: 랜딩페이지 개선

* fix: 첫 스크롤이 이상하게 되던 오류 수정

* design: image가 꽉차게 보이도록 변경

* move: CreatorSection 파일 위치 변경

* fix: IOS 환경에서 svg 렌더를 위해 object tag 로 변경

* fix: import 잘못된 오류 수정

* style: lint 적용

* fix: `useMainPageYScroll.ts`를 FeatureSection 내부에서 호출하도록 변경

* refactor: avatar style 분ㄹ

* fix: avatar를 button이 아니라 a태그로 감싸도록 변경

* style: lint 적용 및 사용하지 않는 주석과 코드 제거

* refactor: Avatar 부분 리스트 렌더링으로 변경

* style: fix 적용

* fix: object tag에 alt property 제거

* fix: 이벤트 홈 페이지에 있을 땐 토큰이 있어도 지출 상세로 접근 불가하도록 수정 (#781)

* fix: cypress에서는 sideEffects를 tree shaking하지 않음

* refactor: 성능 개선 : Serve images in next-gen formats  (#784)

* feat: 랜딩페이지 개선

* fix: 첫 스크롤이 이상하게 되던 오류 수정

* design: image가 꽉차게 보이도록 변경

* move: CreatorSection 파일 위치 변경

* fix: IOS 환경에서 svg 렌더를 위해 object tag 로 변경

* fix: import 잘못된 오류 수정

* style: lint 적용

* chore: webp포맷의 이미지 추가

* chore: webp타입 추가

* feat: 이미지 호스팅 경로를 생성하는 함수 구현

* feat: src, fallbackSrc를 지정해 대체 이미지를 보여줄 수 있는 Image 컴포넌트 구현

* feat: Image컴포넌트를 사용해 이미지를 불러오도록 수정

* feat: Avatar 컴포넌트에서 이미지 경량화를 위한 Image 컴포넌트를 사용

* chore: 사용하지 않고있는 토스 아이콘 제거

* feat: 용량 큰 이미지를 사용하는 곳에선 webp이미지를 사용하도록 수정

* feat: 이미지 경로를 받아오는 함수가 svg포맷도 받아들일 수 있도록 수정

* fix: 이미지 크기가 넘쳐버리지 않도록 width 속성 추가

* feat: 은행 목록 이미지를 webp로 이미지 호스팅 서버에서 가져오도록 수정

* chore: 사용하지 않는 이미지 제거

* feat: 흔듯콘을 webp로 불러오도록 함

* fix: 흔듯콘에 width부여

* design: 행동개시 행댕이의 크기가 너무 커지지 않도록 maxWidth 속성 추가

---------

Co-authored-by: 이태훈 <[email protected]>

* feat: QR코드로 초대하기 기능 추가 (#783)

* fix: DropDown에 Tap 글씨가 위에 있는 에러 수정

* feat: QR코드로 초대하기 페이지 디자인 구현 및 navigate 추가

* feat: qrcode.react 라이브러리를 활용하여 행사 접속 QR코드 생성 구현

* feat: 데스크탑 초대하기를 DropDown으로 변경하여 QR코드 초대 기능 추가하기

---------

Co-authored-by: Soyeon Choe <[email protected]>
Co-authored-by: TaehunLee <[email protected]>
Co-authored-by: Pakxe <[email protected]>
Co-authored-by: 이태훈 <[email protected]>
Todari added a commit that referenced this pull request Oct 24, 2024
* refactor: 랜딩 페이지 디렉토리 구조 변경 (#767)

* refactor: 랜딩 페이지 디렉토리 구조 변경

* refactor: nav 관련 스타일 nav로 이동

* remove: 사용하지 않는 컴포넌트 제거

* style: div => section, article 태그로 변경

* style: 컴포넌트 이름 조금 더 의미있게 변경

* refactor: App을 제외한 페이지 컴포넌트 lazy loading

* refactor: QueryClient가 필요하지 않은 랜딩 페이지에서 tanstack-query script 제거

* refactor: tree shaking을 deep하게 적용하기 위해 package.json에 sideEffects false 적용

* feat: prod build 파일에서 sourcemap과 license 파일 제거

* feat: 문의하기 페이지 구현 (#772)

* feat: 문의하기 구글 forms 페이지 링크 연결

* fix: chromatic 에러 해결

* refactor 성능 개선 : Preconnect to requered origins (#771)

* refactor: 성능개선 Preconnect to requered origins (font)

* fix: storybook에서 pretendard 폰트가 적용되도록 스토리북 preview.tsx 수정

* refactor: 성능 개선 : 랜딩 페이지 이미지를 필요한 만큼만 불러오기 (#774)

* feat: intersection api를 이용해서 특정 영역이 관측될 때 이미지 src를 채우는 hook 구현

* feat: useImageLazyLoading 훅 적용

* feat: 이미지 alt 값을 한국말로 변경

* fix: feature4,5 이미지를 4 불러올 때 한 번에 불러오는 방식으로 변경

* feat: threshold를 0.1에서 0.05로 조금 더 빨리 불러오도록 변경

* feat: alt 행댕이를 행댕이 - 행동대장 마스코트 라고 자세하게 설명

* feat: threshold default value 0.1 -> 0.05로 변경

* feat: 0.1 -> 0.05 놓친 부분 수정

* refactor: 성능 개선 : Kakao script를 필요한 곳에서 다운로드 받기 (#776)

* feat: Kakao script 동적으로 불러올 수 있는 함수 작성

* feat: 드롭다운 버튼 베이스 onClick 메서드 추가

* feat: 모바일 환경에서 초대버튼 눌렀을 때 카카오 스크립트를 불러오도록 설정

* feat: KakaoInitializer 제거

* refactor: v2.1.1에서 구현한 랜딩페이지 개선 (#777)

* feat: 랜딩페이지 개선

* fix: 첫 스크롤이 이상하게 되던 오류 수정

* design: image가 꽉차게 보이도록 변경

* move: CreatorSection 파일 위치 변경

* fix: IOS 환경에서 svg 렌더를 위해 object tag 로 변경

* fix: import 잘못된 오류 수정

* style: lint 적용

* fix: `useMainPageYScroll.ts`를 FeatureSection 내부에서 호출하도록 변경

* refactor: avatar style 분ㄹ

* fix: avatar를 button이 아니라 a태그로 감싸도록 변경

* style: lint 적용 및 사용하지 않는 주석과 코드 제거

* refactor: Avatar 부분 리스트 렌더링으로 변경

* style: fix 적용

* fix: object tag에 alt property 제거

* fix: 이벤트 홈 페이지에 있을 땐 토큰이 있어도 지출 상세로 접근 불가하도록 수정 (#781)

* fix: cypress에서는 sideEffects를 tree shaking하지 않음

* refactor: 성능 개선 : Serve images in next-gen formats  (#784)

* feat: 랜딩페이지 개선

* fix: 첫 스크롤이 이상하게 되던 오류 수정

* design: image가 꽉차게 보이도록 변경

* move: CreatorSection 파일 위치 변경

* fix: IOS 환경에서 svg 렌더를 위해 object tag 로 변경

* fix: import 잘못된 오류 수정

* style: lint 적용

* chore: webp포맷의 이미지 추가

* chore: webp타입 추가

* feat: 이미지 호스팅 경로를 생성하는 함수 구현

* feat: src, fallbackSrc를 지정해 대체 이미지를 보여줄 수 있는 Image 컴포넌트 구현

* feat: Image컴포넌트를 사용해 이미지를 불러오도록 수정

* feat: Avatar 컴포넌트에서 이미지 경량화를 위한 Image 컴포넌트를 사용

* chore: 사용하지 않고있는 토스 아이콘 제거

* feat: 용량 큰 이미지를 사용하는 곳에선 webp이미지를 사용하도록 수정

* feat: 이미지 경로를 받아오는 함수가 svg포맷도 받아들일 수 있도록 수정

* fix: 이미지 크기가 넘쳐버리지 않도록 width 속성 추가

* feat: 은행 목록 이미지를 webp로 이미지 호스팅 서버에서 가져오도록 수정

* chore: 사용하지 않는 이미지 제거

* feat: 흔듯콘을 webp로 불러오도록 함

* fix: 흔듯콘에 width부여

* design: 행동개시 행댕이의 크기가 너무 커지지 않도록 maxWidth 속성 추가

---------

Co-authored-by: 이태훈 <[email protected]>

* feat: QR코드로 초대하기 기능 추가 (#783)

* fix: DropDown에 Tap 글씨가 위에 있는 에러 수정

* feat: QR코드로 초대하기 페이지 디자인 구현 및 navigate 추가

* feat: qrcode.react 라이브러리를 활용하여 행사 접속 QR코드 생성 구현

* feat: 데스크탑 초대하기를 DropDown으로 변경하여 QR코드 초대 기능 추가하기

---------

Co-authored-by: Soyeon Choe <[email protected]>
Co-authored-by: TaehunLee <[email protected]>
Co-authored-by: Pakxe <[email protected]>
Co-authored-by: 이태훈 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🖥️ FE Frontend 🚧 refactor refactoring
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

[FE] 성능 개선 : 랜딩 페이지 이미지를 필요한 만큼만 불러오기
4 participants