MOAMOA는 전국의 숨겨진 축제와 독특한 체험 을 발견할 수 있는 소셜 네트워크 서비스입니다. 이 플랫폼은 사용자들이 각지에서 열리는 문화 행사와 축제 정보를 쉽게 탐색하고, 직접 참여한 체험을 공유할 수 있는 공간을 제공합니다. MOAMOA는 사람들이 개인적인 경험을 사진, 리뷰를 통해 공유하며, 다른 이용자들과 소통할 수 있도록 도와줍니다.
MOAMOA 사용자들은 축제 또는 체험을 홍보할 수 있습니다. 회원 가입 단계에서 기업 및 기관을 선택하여 가입하면 상품 등록 권한이 생깁니다. 행사 운영진 은 직접 행사 정보를 게시할 수 있으며, 일반 회원 은 다양한 축제 소식과 참여 방법을 쉽게 접할 수 있습니다.
테스트 계정 (관리자 ID)
ID: moa_festa@moamoa.com
PW: 13231323
테스트 계정 (사용자 ID)
ID: likefesta@test.com
PW: 123123
📁 MOAMOA
📦src
┣ 📂API
┃ ┣ 📂Auth
┃ ┣ 📂Comment
┃ ┣ 📂Follow
┃ ┣ 📂Image
┃ ┣ 📂Post
┃ ┣ 📂Product
┃ ┣ 📂Profile
┃ ┗ 📂Search
┣ 📂Assets
┃ ┣ 📂icons
┃ ┗ 📂images
┣ 📂Components
┃ ┣ 📂Button
┃ ┣ 📂Chat
┃ ┣ 📂Comment
┃ ┣ 📂Common
┃ ┣ 📂Follow
┃ ┣ 📂Header
┃ ┣ 📂Modal
┃ ┣ 📂Post
┃ ┣ 📂Product
┃ ┣ 📂Profile
┃ ┣ 📂Search
┃ ┣ 📂Skeleton
┃ ┗ 📂Splash
┣ 📂Hooks
┃ ┣ 📂Auth
┃ ┣ 📂Common
┃ ┣ 📂Product
┃ ┗ 📂Search
┣ 📂Pages
┃ ┣ 📂Auth
┃ ┣ 📂Chat
┃ ┣ 📂Follow
┃ ┣ 📂Home
┃ ┣ 📂Post
┃ ┣ 📂Product
┃ ┣ 📂Profile
┃ ┣ 📂Search
┃ ┗ 📂Splash
┣ 📂Recoil
┣ 📂Router
┗ 📂Utils
┣ 📜App.css
┣ 📜App.js
┣ 📜GlobalStyle.jsx
┣ 📜fonts.css
┣ 📜index.css
┣ 📜index.js
┗ 📜md.md
코드의 일관성과 가독성을 높이기 위해 코드 형식을 자동으로 지정해주는 Prttier를 사용했습니다.
일관된 코드 스타일 유지, 잠재적인 오류 식별을 위해 ESLint를 사용했습니다.
리액트의 prop drilling 문제를 해결하기 위해 상태를 유연하게 관리할 수 있는 Recoil을 사용했습니다.
props를 전달하여 동적으로 스타일을 적용하는 경험을 해보고 싶어서 Styled-Components를 사용했습니다.
Axios는 fetch보다 많은 기능을 지원해주고 문법이 간소화되어서 사용했습니다. XSRF Protection 보안 기능, 응답 데이터가 기본적으로 JSON 타입이라는 점, fetch처럼 객체를 문자열로 변환한 뒤 body에 할당하는 작업이 필요하지 않다는 점(자동 문자열 변환)이 장점이라 생각했습니다.
로그인
홈 화면(팔로우 하는 유저 없는 경우)
홈 화면(팔로우 하는 유저 있는 경우)
내 프로필 페이지 (기관) - 상품 등록
내 프로필 페이지 (기관) - 상품 수정
내 프로필 페이지 (기관) - 상품 삭제
내 프로필 페이지 - 프로필 수정
다른 사용자 프로필 페이지 - 채팅방
다른 사용자 프로필 페이지 - 팔로우/언팔로우
다른 사용자 프로필 페이지 - 공유하기
팔로우/팔로워 리스트
게시물 작성
게시글 앨범형 / 목록형
댓글 등록
댓글 삭제
행사 상세 - 상품 수정
행사 상세 - 상품 삭제
행사 상세 - 문의하기
사용자 친화적인 서비스 제공을 위해 무한스크롤 구현
장소 추천 컴포넌트 추가
카카오 지도 API 활용
이미지 등록 시 크롭기능 추가
반응형 웹 구현
접근성, SEO, 성능 점수 개선
이미지의 종횡비에 따라 등록이 되지 않는 오류
const resizeImage = async ( url , maxWidth , maxHeight ) => {
return new Promise ( ( resolve ) => {
const img = new Image ( ) ;
img . onload = ( ) => {
const canvas = document . createElement ( 'canvas' ) ;
const ctx = canvas . getContext ( '2d' ) ;
let newWidth , newHeight ;
if ( img . width > maxWidth || img . height > maxHeight ) {
const aspectRatio = img . width / img . height ;
if ( aspectRatio > 1 ) {
newWidth = maxWidth ;
newHeight = newWidth / aspectRatio ;
} else {
newHeight = maxHeight ;
newWidth = newHeight * aspectRatio ;
}
} else {
newWidth = img . width ;
newHeight = img . height ;
}
canvas . width = newWidth ;
canvas . height = newHeight ;
ctx . drawImage ( img , 0 , 0 , newWidth , newHeight ) ;
resolve ( canvas . toDataURL ( 'image/jpeg' ) ) ;
} ;
img . src = url ;
} ) ;
} ;
const resizedImageUrl = await resizeImage ( reader . result , 700 , 500 ) ;
useImage.jsx에서 resizeImage 함수를 작성하여 해결했습니다. resizeImage 함수는 사용자가 이미지를 등록할 때 width가 700px , height가 500ox보다 큰 이미지는 캔버스를 이용해 리사이징을 하는 코드입니다.
resizeImage 함수를 작성하여 비율이 맞지않아 등록이 되지않는 문제를 해결하였고,리사이징이 되어 이미지의 용량도 압축되는 결과를 얻었습니다.
개선 전
개선 후
축제&체험 리스트 페이지의 성능 개선을 위한 무한스크롤 구현
초기에 이미지를 불러올 때의 시간을 줄여 성능을 개선하려 시도하였습니다.
const [ nextPage , setNextPage ] = useState ( 4 ) ;
const handleObserver = useCallback ( ( entries ) => {
const [ target ] = entries ;
console . log ( target ) ;
if ( target . isIntersecting ) {
setNextPage ( ( prev ) => prev + 4 ) ;
}
} ) ;
const observerElem = useRef ( null ) ;
useEffect ( ( ) => {
let options = {
root : null ,
rootMargin : '10px' ,
threshold : 0.5 ,
} ;
const observer = new IntersectionObserver ( handleObserver , options ) ;
const element = observerElem . current ;
if ( element ) observer . observe ( element ) ;
return ( ) => {
if ( element ) observer . unobserve ( element ) ;
} ;
} , [ handleObserver ] ) ;
-intersection Observer API를 사용하여 화면에 제일 하단에 관찰할 요소를 넣어 감지되면 4개씩 행사를 불러오게 만들었습니다.
개선 전
개선 후
-lighthouse 성능 측정을 하였고, 12점 향상시켰습니다.
회의 전 회의록을 작성하여 계획과 일정을 미리 공유했습니다.
중요 사항들을 잊지 않도록 회의록에 기록했습니다.
우리가 사용하는 기술을 왜 사용하는지 명확하게 이해하기 위하여 서로 공부한 자료들을 공유하였습니다.
오류나 어려움을 겪은 부분은 트러블 슈팅 페이지에 기록하여 조원들과 공유하였습니다.
매일 아침 디스코드를 통해 데일리 스크럼을 진행했습니다.
작업을 진행하다가 도움이 필요한 상황, 혹은 확인이 필요한 상황이 발생하면 즉각적으로 디스코드 회의실 내 채팅방을 이용하여 문제를 겪는 부분을 실시간으로 공유하며 작업하였습니다.
피그마를 이용하여 디자인 작업을 하였고, API 명세와 비교를 하였습니다.
초반 작업은 전체적인 흐름의 이해를 위하여 작업 순서도를 그렸습니다.
프로젝트를 진행하면서 변수로 작용할 부분은 어디가 될지 생각하며 디자인 수정을 거쳤습니다.
효율적인 협업과 작업 품질 향상을 위하여 깃헙 Project, Issue template, PR template을 사용하였습니다.