Skip to content

SSDA-Side/SSDA-Front

Repository files navigation

SSDA팀의 Dassda.

소중한 일상을 공유해보세요 /released 240225

dassda-og-image

서비스 소개

당신의 일상을 공유하고, 소중한 순간을 함께 나누는 '공유 일기장' 어플!

  • 다양한 일기 작성 탬플릿과 특별한 기능으로, 더 심플하게 일기를 쓸 수 있어요.
  • 회원 등급에 따라 차별된 서비스를 제공하며, 공유 일기장을 통해 친구들과 소통하세요.
  • 기분 스티커, 댓글, 좋아요 기능을 통해 더 풍성한 일기 작성 경험을 제공해요.
  • 모바일웹을 통해 언제 어디서든 편리하게 이용 가능합니다.

함께 쓰는 일기장으로 더 특별한 순간을 기록해보세요🙌

서비스 정보 개요

개발 인원

  • 총 6명
역할 이름 연락처 비고
📝 PM 이세은 wntkfkd95@naver.com 팀장
🎨 DE 유수 - -
⚙ BE 권동휘 hocci0222@kakao.com BE 리드
⚙ BE 김범준 - -
📺 FE 김주현 sang.pok.e@gmail.com FE 리드
📺 FE 이어진 - -

개발 기간

  • 총 4달, 2023년 11월 02일 ~ 2023년 02월 25일
  • 기존 팀원: 이세은, 유수, 권동휘, 김범준
  • 24년 01월 01일 이후 합류 팀원: 김주현, 이어진

리팩토링

  • 총 3일, 2024년 03월 01일 ~ 3일
  • 총 2명
역할 이름 연락처 비고
⚙ BE 권동휘 hocci0222@kakao.com -
📺 FE 김주현 sang.pok.e@gmail.com -

배포 주소

화면설계 URL

기술 스택 /Frontend

React, Typescript

  • 2차 배포 목표가 PWA이기 때문에 하나의 어플리케이션으로 느끼게 만들고 싶어 React UI Library를 사용하였습니다.

Module SCSS

  • CSS in JS는 스타일을 직렬화하는 과정에서 런타임 오버헤드가 걸리고 번들 크기를 늘리는 단점이 있습니다.
  • 초기 로딩을 최대한 앞당기기 위함과, 스코프 지정 스타일을 사용하기 위해 Module SCSS를 선택했습니다.

React Query, Recoil

  • 서버 사이드 상태를 효율적으로 캐싱하기 위해 React Query를 사용하였습니다.
  • Header Config 등 클라이언트 상태를 효율적으로 관리하기 위해 Recoil을 사용하였습니다.

Axios

  • Axios에서 제공하는 많은 편리성, 예를 들면 헤더 설정 및 Multipart 전송 등이 개발 경험을 좋게 만들어주어 선택하였습니다.

협업 /팀 전체

Jira: 팀 전체 진도 현황을 공유하였습니다.

Figma: 서비스 화면 및 기능에 대한 의견을 주고 받았습니다.

Slack: 주 소통 채널로서 팀원 또는 팀끼리의 협업에 대한 이야기를 나누거나 자료를 공유하였습니다.

협업 /FE팀

Github Action을 통한 티켓 넘버 관리

  • Github Action을 작성하여 Github Issue를 작성 시, 자동으로 Jira에 이슈를 생성합니다.
  • 생성한 Jira 이슈의 티켓 넘버를 받아와 develop에서 branch를 따와 생성합니다.

Husky를 통한 커밋 컨벤션 관리

  • 위의 상황과 마찬가지로, Commit 내용에도 해당 티켓 넘버가 포함되어 있어야 연동이 됩니다.
  • Github Hook을 편하게 사용할 수 있게 제공해주는 Husky를 통해 커밋 시 자동으로 티켓 넘버가 기입되게 만들었습니다.

서비스 특징

Oauth(Kakao) 로그인

  • Oauth를 통한 간편한 로그인을 제공하였습니다.
  • 서비스 내에 로그인을 필요로 하는 Entry Point가 두 군데 존재하였습니다.
  • Access Token을 받아오는 콜백 주소는 고정하되, localStorage를 통해 다음 서비스 경로를 지정해주는 흐름으로 구현하였습니다.
  • 사용자 인증 방식은 JWT 방식을 사용하였습니다.
쓰다 로그인 흐름 순서도
쓰다 로그인 흐름

알림

  • 서비스를 이용하면서 놓칠 수 있는 부분을 알림으로 알려주고 있습니다.
  • 총 5종류로 알림을 구분하였고, 각 종류별 마다 적절한 경로로 따라가게 했습니다.
  • React QueryuseSuspenseInfiniteQuery Hook을 사용하여 무한 스크롤 패칭을 구현하였습니다.
  • useInfiniteObserver라는 Custom Hook을 만들어 스크롤 위치를 감지하였습니다.
    • MutationObserver, Intersection Observer interface를 사용하여 구현하였습니다.
    • 해당 방식은 쓰다 서비스의 무한 스크롤 방식의 모든 목록에 적용되었습니다.
쓰다 알림 화면 알림 종류 명세
image image 57

공유 일기장 초대

  • 상대방을 초대하기 위해선 공유 링크를 생성해야 합니다.
  • 서버와 API 통신을 통해 해당 일기장 초대에 대한 해시값을 받아 링크를 생성합니다.
  • Clipboard API를 통해 복사하거나, 카카오톡 SDK에서 제공하는 공유하기 기능을 통해 초대를 보냅니다.
  • 초대 링크 화면에서는 해시값을 조회하고 유효한 해시인지 판별합니다.
  • 사용자가 참여하기 액션을 하면 일기장 참여 핸들러 경로로 이동하여 참여를 시도합니다.
    • location에 state를 담아 핸들러로 보냅니다. 직접 경로로 들어오는 경우 state가 없으므로 유효하지 않은 접근입니다.
쓰다 초대하기 모달 카카오톡 공유하기 공유 링크 접속 화면
image image GIF 2024-03-02 오후 11-07-55
* Network Throttle이 적용된 화면입니다
쓰다 초대하기 흐름 순서도
쓰다 초대 흐름

스켈레톤 로딩 및 오류 화면 대응

  • Skeleton UI를 적용하여 사용자에게 데이터 패칭 중임을 알려주고, 앞으로 나올 콘텐츠의 위치를 미리 알려주어 균일감 있는 경험을 제공합니다.
  • SuspenseError Boundary를 활용하여 오류 화면과 로딩 화면을 비즈니스 로직에서 분리하였습니다.
  • React QueryQueryErrorResetBoundary를 활용하여 재시도를 제공하였습니다.
  • QueryErrorResetBoundary, Error Boundary, Suspense를 한 번에 처리하도록 AsyncBoundary Provider를 사용하였습니다.
일기 스켈레톤 오류 화면 대응
GIF 2024-03-03 오전 12-44-20 GIF 2024-03-03 오전 12-48-01

ID 기반 모달 관리

  • Recoil을 통해 모달 정보를 담은 전역 배열을 만들었고, ModalController를 통해 렌더링합니다.
  • 필요한 모달을 Component Modal, Confirm, Alert, Sheet로 구분하여 관리하였습니다.
  • prop으로 필요한 정보를 넘겨줄 수 있도록 만들었습니다.
  • 모달의 기본 기능을 제공함으로써 모달 콘텐츠는 본인의 역할에만 집중할 수 있도록 했습니다.

| ModalController

const ModalController = () => {
  const { modals } = useModal();

  const getTypedComponent = ({ id, type, isOpened, payload }: Modal) => {
    if (type === 'Component') {
      return <ComponentModal key={id} id={id} isOpened={isOpened} {...(payload as ComponentPayload)} />;
    }

    if (type === 'Alert') {
      return <Alert key={id} id={id} isOpened={isOpened} {...(payload as AlertPayload)} />;
    }

    if (type === 'Confirm') {
      return <Confirm key={id} id={id} isOpened={isOpened} {...(payload as ConfirmPayload)} />;
    }
  };

  return modals.map(getTypedComponent);
};

| openModal 코드

const openModal = useRecoilCallback(
  ({ set }) =>
    ({ type, payload }: { type: ModalType; payload: ModalPayloadType }) => {
      const newId = uuid();

      set(ModalStore, (prevState) => {
        return [
          ...prevState,
          {
            id: newId,
            type,
            payload,
            isOpened: true,
          } as Modal,
        ];
      });

      return newId;
    },
  [],
);

| openComponentModal Usage

openComponentModal<CreateShareLinkModalProps>({
  title: '초대하기',
  children: InviteMemberModal,
  props: { board },
});

About

SSDA Frontend Repository입니다

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •