Wavy의 Client는 위 개발 스택을 사용하여 개발되었습니다.
Wavy는 현재 위 URL에서 서비스되고 있습니다.
| Main - Video card |
|---|
![]() |
| Main - Tag |
|---|
![]() |
| Main - Tag scroll |
|---|
![]() |
| Practice |
|---|
![]() |
| Challenge - start |
|---|
![]() |
| Challenge - end |
|---|
![]() |
| Analysis |
|---|
![]() |
| Player - Marker and Loop |
|---|
![]() |
| Review - Statistics |
|---|
![]() |
| Reviw - Search |
|---|
![]() |
| Search |
|---|
![]() |
| Sign in |
|---|
![]() |
| Storage - Empty |
|---|
![]() |
| Store |
|---|
![]() |
src
├── assets
│ └── images
│ └── videos
├── components
│ └── App.tsx
│ └── Common
│ └── [PageName]
├── constants
├── hooks
│ └── api
│ └── Common
│ └── [PageName]
├── pages
│ └── [PageName]
├── router
├── store
│ └── Common
│ └── [PageName]
├── styles
│ └── global
│ └── theme
├── types
├── utils
└── index.tsx
기본적으로 파일 유형 이후 라우트에 의한 분리를 적용하였습니다.
상태 관리 라이브러리는 Recoil을 사용하였습니다.
// ConcreteDecorator
import { atom } from "recoil";
export const isPlayingState = atom<boolean>({
key: "isPlayingState",
default: false,
});// Decorator
import { useRecoilState } from "recoil";
import { isPlayingState } from "store";
const useControllerPlaying = () => {
const [isPlaying, setIsPlaying] = useRecoilState(isPlayingState);
const toggleIsPlaying = () => setIsPlaying((prev) => !prev);
return { isPlaying, setIsPlaying, toggleIsPlaying };
};
export default useControllerPlaying;// Component
import useControllerPlaying from "hooks/useControllerPlaying";
const someComponent = () => {
const { isPlaying, toggleIsPlaying } = useControllerPlaying();
return (
<button onClick={toggleIsPlaying}>{isPlaying ? "중지" : "재생"}</button>
);
};전역 상태의 경우 store의 atom을 ConcreteDecorator 로써, hook을 Decorator 로써, Component를 Component 역할로써 Decorator 패턴을 각색하여 개발 및 사용하였습니다.
해당 프로젝트는 소프트웨어 마에스트로 사업의 지원을 받아 개발되었습니다.
| FE: hyesungoh | AI: haeseoklee | BE: Yeonwu |
|---|---|---|
Wavy는 MIT License를 적용하고 있습니다.














