Skip to content

johj703/dalgona

Repository files navigation

🟡 달고나 🟡


🔎 목차

🔗 - 1. 프로젝트 소개
🔗 - 2. 팀소개
🔗 - 3. 아키텍쳐
🔗 - 4. 기술 및 도구
🔗 - 5. 주요 기능
🔗 - 6. 프로젝트 파일 구조
🔗 - 7. 트러블슈팅


🍭 프로젝트 소개

달고나는 나만의 일상 아카이브, 감정과 추억을 함께 기록할 수 있는 라이프스타일 플랫폼입니다.

  • 기획이유
    현대인들은 자신의 삶을 기록하고 공유하는데 높은 관심을 보이고 있으며, 이러한 흐름은 SNS와 일기 앱의 지속적인 성장세로 확인할 수 있습니다. 하지만 대부분 기존 플렛폼은 텍스트 중심으로 설계되어 있어서 감정과 기록을 생생하게 표현하는데 한계가 있다고 생각했습니다.
    이에 저희는 이런 시장 수요와 트렌드를 반영하여 글 뿐만 아니라 직접 그림을 그리며 감정과 기억을 생생하게 표현할 수 있는 특별한 공간을 만들고자 기획하게 되었습니다.

    어릴 적 그림일기를 쓰던 추억을 되살려서 재미있게 소중한 추억을 정리해보세요!

  • 개발기간 : 2024.10.18(금) ~ 2024.11.21(목)


👨‍👩‍👧‍👦 팀 소개

이름 역할 담당
박준호 FE/Leader 그림일기(CRUD) 페이지, 마이페이지
공통 컴포넌트(헤더, 버튼, 날짜 파싱 등)
@PJH-FE
강지우 FE/Sub-Leader 기록의 방(대표 일기 설정, 월별 모아보기)
갤러리(이번 달, 전체 그림 모아보기)
@wldndnwl
정희록 FE/Member 메인페이지(피드형 타임라인, 캘린더), 검색페이지
공통 컴포넌트(푸터)
@heerokj
조현준 FE/Member 로그인/회원가입, 회원정보 수정 @johj703
김현정 디자이너 웹디자인 모바일디자인 메인로고 아이콘 @lucstrike
정혜지 디자이너 웹디자인 모바일디자인 메인로고 아이콘 @gesundewurzeln

🏗️ 아키텍쳐

Web App Reference Architecture


🛠️ 기술 및 도구




💡 주요 기능

Canvas API 를 활용한 캔버스 기능 제공

  • 펜의 굵기를 조절하여 그림을 그릴 수 있습니다. 또한 지우개를 선택하여 그렸던 그림을 지울 수 있습니다.
  • 펜은 다양한 색상 선택을 할 수 있으며 스포이드 기능을 이용해 화면 픽셀과 일치하는 색을 선택할 수도 있습니다.
  • 그림을 그리는 도중 뒤로가기 버튼과 다시 되돌리기 버튼을 사용할 수 있습니다.
  • 초기화 버튼 클릭 시 그림이 초기화 됩니다.

그림 일기 (CRUD)

  • 제목, 날짜, 감정, 그림, 일기장 속지, 글을 작성 및 선택하여 기록합니다.
  • debouncing을 이용한 자동 임시저장을 해줍니다. 사용자는 필요에 따라 저장했던 일기를 불러올 수 있습니다.
  • 상세페이지에서 일기 작성한 날짜, 감정, 그림, 글을 확인할 수 있습니다.
  • 일기 작성자는 자신이 작성한 일기에 대해 수정 및 삭제 버튼을 사용할 수 있습니다. 이 기능은 작성자가 일기를 관리하고 필요에 따라 수정하거나 삭제할 수 있도록 합니다.

캘린더 기능 (달력 셀 클릭 및 조회범위 설정 시 해당 일기 조회)

  • 일기를 작성할때 등록한 감정 아이콘을 달력 형식으로 한눈에 확인 할 수 있습니다.
  • 일기를 보고 싶은 날짜를 클릭 하면 해당 일기를 볼 수 있습니다.
  • 조회기간 버튼을 클릭하면 조회기간 범위를 설정할 수 있으며 그 기간에 해당하는 일기 리스트를 볼 수 있습니다.
  • 캘린더의 오늘 버튼 클릭 시 오늘 날짜로 돌아옵니다.

검색 기능 (특정 키워드 검색기능)

  • 특정 키워드를 입력하여 일기 검색이 가능합니다. (제목, 내용 검색 가능)
  • 입력할 때마다 즉각적인 검색 결과를 제공합니다. 검색어를 변경하더라도 새로고침 없이 결과가 자동으로 갱신됩니다.
  • setTimeout 함수로 디바운싱을 적용하여 입력 시마다 불필요한 검색호출을 최소화하여 사용자가 원활하게 결과를 확인할 수 있습니다.

마이페이지 기능

  • 사용자 프로필, 닉네임, 생년월일, 성별, 혈액형을 수정할 수 있는 기능을 제공합니다.
  • 이번 달 감정의 통계를 모아볼 수 있으며 사용자가 그린 그림도 랜덤으로 모아볼 수 있습니다.
  • 더보기 버튼 클릭 시 갤러리 페이지로 이동합니다.

그림을 모아볼 수 있는 갤러리 (이번 달, 전체 그림 모아보기)

  • 사용자가 그린 그림을 앨범형식으로 확인하고 관리할 수 있습니다. 앨범은 이번달 모음, 랜덤 형식의 추억모음으로 관리됩니다.
  • Swipe로 사용자가 작성한 모든 그림을 확인할 수 있습니다. 스와이프에 있는 그림을 클릭하면 해당 그림을 크게 볼 수 있으며 상세 페이지로 이동합니다.

기록의 방 페이지 (대표일기 설정, 월별 모아보기)

  • 등록하기 버튼을 클릭하면 원하는 날짜를 선택하여 일기를 서치할 수 있으며 선택하여 대표일기를 선정할 수 있습니다.
  • 한 해 작성한 일기를 월별로 필터링하여 볼 수 있습니다.
  • 월이 적혀진 책을 클릭하면 그 달에 작성한 일기 리스트를 확인할 수 있습니다.

로그인/회원가입 기능

  • 로그인 / 회원가입 화면 진입 전에 스플레시 화면을 볼 수 있습니다.
  • supabase를 활용한 로그인 및 회원가입 기능을 구현했습니다.
  • 사용자가 값을 입력하고 form이 제출되었을때 경고 문구를 띄어 사용자에게 피드백을 제공합니다.

무한스크롤


🗂️ 프로젝트 파일 구조

📦src
┣ 📂app
┃ ┣ 📂(auth)
┃ ┃ ┣ 📂sign-in
┃ ┃ ┗ 📂sign-up
┃ ┣ 📂artworkprev
┃ ┣ 📂diary
┃ ┣ 📂fonts
┃ ┣ 📂gallery
┃ ┣ 📂library
┃ ┣ 📂main
┃ ┣ 📂mypage
┃ ┣ 📜favicon.ico
┃ ┣ 📜globals.css
┃ ┣ 📜layout.tsx
┃ ┣ 📜not-found.tsx
┃ ┗ 📜page.tsx
┣ 📂components
┣ 📂hooks
┣ 📂lib
┣ 📂queries
┣ 📂style
┣ 📂types
┣ 📂utils
┗ 📜middleware.ts

❓ 트러블 슈팅

1. 이미지 CORS 문제로 인해 Canvas 오염 발생

  • 이슈
    이전에 그렸던 그림을 이미지로 불러와 수정하려 할 때, Canvas에 새로 그림이 그려지지 않는 문제 발생

  • 원인
    보안 문제로 인해 CORS를 거치지 않고 로컬이 아닌 외부 소스에서 가져온 이미지를 Canvas에 적용하면 Canvas가 오염됨

  • 해결
    이미지 객체의 crossOrigin 속성을 "anonymous"로 설정하여 해결
    이를 통해 외부 이미지의 CORS 정책을 우회하여 Canvas에 정상적으로 그림을 불러올 수 있게 됨

const pathPic = new Image();
pathPic.crossOrigin = "anonymous";

2. 초기 데이터 로딩 실패

  • 이슈
    useInfiniteQuery를 사용하여 무한 스크롤을 구현하는 과정에서 첫 페이지의 데이터를 로드하지 못하는 문제가 발생

  • 원인
    TanStack Query v5 버전에서 첫 페이지의 매개변수를 설정하는 옵션이 추가되었으나, 해당 옵션 설정이 누락

  • 해결
    initialPageParam 옵션을 추가하여 첫 번째 페이지가 1로 시작하도록 설정하여 문제 해결

export const useInfiniteQuerySearchDiaries = (searchKeyword: string) => {
  const { data, isError, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({
    queryKey: ["searchDiaries", searchKeyword],
    enabled: !!searchKeyword,
    initialPageParam: 1, //👈 첫 번째 페이지를 1로 설정
    queryFn: ({ pageParam }) => getSearchPaginatedDiaries(pageParam, 10, searchKeyword),
    getNextPageParam: (lastPage) => {
      return lastPage?.hasNext ? lastPage.nextPage : undefined;
    }
  });

  return { data, isError, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage };
};

3. 일기 데이터 필터링 오류

  • 이슈
    갤러리에서 메인 그림이 변경될 때마다 컨테이너 안 미리 보기 그림의 위치도 자동으로 중앙에 오게끔 해놨었는데 1024 이상 px일 때 중앙을 벗어남

  • 해결
    이미지의 위치 (offsetLeft)와 컨테이너 크기 (containerWidth)를 기반으로 스크롤 위치 계산하던 로직을 이미지 인덱스 (imageIndex)와 너비 (imageWidth)로 계산하도록 변경
    (imageWidth + 8) * imageIndex + imageWidth / 2
    선택된 이미지의 스크롤 위치를 이미지의 너비와 간격 (8px)을 더해 선택된 이미지의 인덱스를 곱한 값에 이미지 너비의 절반을 더하기

  // 메인그림(mainEntry)이 변경될 때마다 스크롤 위치 조정
  useEffect(() => {
    if (mainEntry && imageListRef.current) {
      const container = imageListRef.current;
      const selectedImageElement = document.getElementById(`image-${mainEntry.id}`);

      if (selectedImageElement) {
        const imageWidth = selectedImageElement.offsetWidth;
        const imageIndex = Number(selectedImageElement.dataset.idx);

        const scrollPosition = (imageWidth + 8) * imageIndex + imageWidth / 2; //👈

        container.scrollTo({
          left: scrollPosition,
          behavior: "smooth"
        });
      }
    }
  }, [mainEntry]);
<img
    id={`image-${entry.id}`}
    src={entry.draw}
    alt={`Artwork ${entry.id}`}
    data-idx={idx} //👈
    className={`w-full h-full object-cover cursor-pointer bg-white border border-gray02 lg:rounded lg:border-gray04  ${
      entry.id === mainEntry?.id ? "border-2 border-[#D84E35]" : ""
    }`}
    onClick={() => handleSwipeSelect(entry)}
  />

4. 오류 메세지가 계속 나타나는 현상

  • 이슈
    비밀번호 유효성 검사 시 비밀번호 형식 오류 메세지가 계속 나타남

  • 원인
    비밀번호 형식이 올바르지 않은 경우에만 오류 메세지가 표시되도록 처리했으나,
    정규식 검사에서 요구하는 조건이 너무 엄격해서 사용자가 입력한 비밀번호가 유효하지 않다고 판단함

  • 해결
    비밀번호 입력 필드에 대한 정규식(Regex)을 재검토하고, 유효한 형식의 비밀 번호를 입력해야 한다는 조건을 명확하게 정의함 사용자에게 더 구체적인 오류 메세지를 제공하고, 입력 형식이 유효하지 않을 때만 오류 메세지를 표시하도록 수정함

  // 비밀번호 유효성 검사 함수
  const validatePassword = (password: string) => {
    const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
    return passwordRegex.test(password);
  };

  // 로그인 처리 함수
  const handleSignIn = async (e: React.FormEvent) => {
    e.preventDefault();

    setEmailError("");
    setPasswordError("");
    setErrorMessage("");

    if (email === "" || password === "") {
      if (email === "") {
        setEmailError("이메일을 입력해 주세요.");
      }
      if (password === "") {
        setPasswordError("비밀번호를 입력해 주세요.");
      }
      return; // 여기에서 중단되는지 확인
    }

    if (!validateEmail(email)) {
      setEmailError("아이디를 다시 확인해주세요. 아이디는 이메일 형식입니다.");
      return; // 여기에서 중단되는지 확인
    }

    if (!validatePassword(password)) {
      setPasswordError("비밀번호가 잘못 입력되었습니다. 다시 확인해주세요.");
      return; // 여기에서 중단되는지 확인
    }

About

그림으로 일상을 기록하고 감정까지 담아보는 나만의 일기장, 달고나

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors