- Published on
펀드매니저 매칭(verda) 서비스 | 최종프로젝트 후기
프로젝트 배포 ⚡ https://verda1.vercel.app/
프로젝트 깃허브 ⚡ https://github.com/kdt8-Team5-verda-project
노션 ⚡ https://kimmr.notion.site/verda-9362c1a22c00470da7a544b8f068bea1?pvs=4
Intro
약 한 달 여간의 최종 프로젝트가 끝났다. 프로젝트를 어떻게 준비하였고 어떤 방식으로 진행되었는지 이 포스팅에 기록하고자 한다. 프로젝트 주제를 선정할 때 많은 아이디어들이 나왔고 여러 번의 회의를 통해 하나로 간신히 하나의 주제가 정해졌다. 그것이 바로 펀드매니저 매칭 서비스, verda 이다.verda
- 최근 가파른 물가 인상과 경기 침체가 지속되면서, MZ 세대들은 투자나 재테크에 많은 관심을 보이고 있음.
- 그러나 투자 상담받기에 어려움을 느끼고 대부분 금융지식이 부족한 상태에서 투자를 진행하거나 문자나 인터넷에서 투자와 관련된 위험한 경로로부터 투자 제안을 받음.
- 앞서 말한 2가지 이유로 verda는 투자자와 전문가를 매칭하여 성공적인 투자 경험을 제공하기 위한 서비스
개발기간
2023.11.10 ~ 2023.12.08 (총 29일)주요기능
카카오로그인,회원가입
투자문의 작성,조회
투자제안서 작성,조회
투자자와 펀드매니저 사이 채팅
구현된 주요 기능
- 투자자는 투자문의를 작성할 수 있다.
- 투자자는 펀드매니저에게 온 제안서를 확인 할 수 있다. (총 3개의 제안서만 받을 수 있음)
- 펀드매니저는 고객들의 투자문의를 확인 할 수 있다.
- 투자자와 펀드매니저는 서로 채팅을 할 수 있다.
기능정의서
모든 기능들은 노션에 표로 정리하였다. (기능정의서 일부분만 발췌된 이미지)기술스택
- Frontend : next.js, tailwindCSS, react-query, Recoil, Npm, Stomp, Visual Studio Code
- Backend : Java Spring Boot, JPA, AWS(EC2, RDS, S3), IntelliJ, Stomp
- Database : MySQL, Redis
- DevOps : Docker, Jenkins, vercel
화면설계
피그마로 진행하였다. 원래는 각자 한 사람씩 화면을 담당해 그려오기로 했으나, 아무리 생각해도 시간 낭비인 거 같아서 내가 다 그리고 논의를 거쳐 추가할 화면 추가하고 제외할 것은 빼는 방식으로 진행하였다.적용기술
Next.js
기존 리액트의 문제점은 CSR(Client-side rendering)로 렌더링 되기 때문에 SEO에 최적화되어있지 않다는 단점이 있다. next.js는 SSR(Server-Side Rendering)로 SEO를 향상시킬 수 있기 때문에 유저를 더 잘 인입시키기 위해 사용되었다.아토믹 디자인
아토믹 디자인은 개발적인 방법론이라기보다는 디자인 시스템을 만드는 방법론이다. brad frost의 아토믹 디자인은 화학적 관점에서 영감을 얻은 디자인 시스템으로, 이 개념을 차용해서 컴포넌트를 atom, molecule, organism, template, page의 5가지 레벨로 나누어진다. 기존의 하나의 html 페이지에서 ui를 설계하던 방식은 제각각인 규칙으로 인해 관심사가 너무 많거나 재사용이나 확장할 수 없는 컴포넌트가 생기는 문제가 있었다. 이러한 문제를 해결하기 위해 공통 컴포넌트를 정의하여 다양한 컴포넌트들이 하나의 페이지를 구성하는 방식으로 보다 최적화된 컴포넌트를 설계하기 위해 아토믹 디자인 방법론을 도입하게 되었다. brad frost가 제안한 5단계이지만 의미가 비슷한 부분은 좀 더 간략화해서 총 4단계로 간소화하여 적용하였다.Atom은 박스나 폰트, 아이콘과 이미지 등의 요소를 Atom으로 적용하였고, MOLECURE에서는 Atom이나 타이틀 등이 모여 하나의 요소를 이룬 형태를 정의하였다. 그리고 이 요소들이 모여서 하나의 페이지를 이룬 것을 ORGANISMS & PAGES로 정의하였다.
fetch
axios는 백엔드랑 프런트엔드랑 통신을 쉽게 하기 위해 사용하는 HTTP 비동기 통신 라이브러리이다. 기존에 프로젝트 진행 시 많이 사용했던 라이브러리이나, 이번 프로젝트에서는 기존 프로젝트와 다르게 내장 함수인 fetch를 사용하여 개발을 하였다. 이렇게 사용한 이유는 fetch는 axios와 달리 npm 설치가 불필요하므로, 프로젝트 용량 전체의 크기를 줄일 수 있다. 또한 캐싱 기능과 재검증(revalidation) 기능이 기본적으로 구축되어 있기 때문에, 추가적인 과정을 거치지 않아도 되는 장점이 있다.
React-Query와 Intersection-Observer
ReactQuery는 데이터 요청과 관리를 쉽게 할 수 있도록 도와주는 라이브러리이다. 무한 스크롤을 구현하려면 페이지가 스크롤 될 때마다 새로운 데이터를 서버에 요청해야 하는데, ReactQuery는 이러한 데이터 요청을 간편하게 처리할 수 있도록 API를 제공한다.
Intersection Observer는 페이지의 요소가 화면에 보이는지를 감지하는 기능을 제공한다. 무한 스크롤을 구현하기 위해서는 사용자가 스크롤을 하면서 새로운 데이터를 로드해야 하지만 Intersection Observer는 화면에 특정 요소가 보이는지를 감지하므로, 스크롤 이벤트를 사용하지 않고도 효율적으로 데이터를 로드할 수 있으며, 이를 통해 사용자 경험을 향상시킬 수 있다.
import { useInfiniteQuery } from "react-query";
import { useInView } from "react-intersection-observer";
export default function ClientRequerstList() {
const { ref, inView } = useInView({ //Intersection Observer
threshold: 0.3,
});
const getClientRequerstList = async (
pageParam: null | number = 99999,
): Promise<any> => {
const res = await fetch(
`${process.env.BASE_URL}/api/board?lastPostId=${pageParam}&size=20`,
{
method: "GET",
},
);
return res.json();
};
const { data, hasNextPage, fetchNextPage } = useInfiniteQuery( //무한스크롤
["specialPostList"],
({ pageParam = 99999 }) => getClientRequerstList(pageParam),
{
getNextPageParam: (lastPage, allPages) => {
const nextPage = lastPage[lastPage.length - 1].postId;
return nextPage === 1 ? false : nextPage;
},
},
);
useEffect(() => { //다음페이지로 넘기기
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView]);
return (
<section>
<TextStore textStyle={TextStyle.TEXT_R_40}>투자문의</TextStore>
<div className="flex items-center flex-col text-black mt-5">
{data ? (
data.pages.map((page, idx) => {
return (
<Fragment key={idx}>
{page.map((post: any, id: number) => {
return (
<Link
href={`/fundmanager/clientrequest/${post.postId}`}
key={post.postId}
>
<ButtonListTitle>
{post.title.length > 15
? `${post.title.slice(0, 15)}...`
: post.title}
</ButtonListTitle>
</Link>
);
})}
</Fragment>
);
})
) : (
<TextStore textStyle={TextStyle.TEXT_R_24}>loading...</TextStore>
)}
</div>
<div ref={ref} className="h-[1rem]" /> //스크롤 마지막 부분 감지
</section>
);
}
Swagger
Swagger에 명세화된 API 문서를 통해 데이터를 fetching 하였다.협업관련
총 6명으로 구성된 우리 팀은 프런트 3명, 백엔드 3명으로 나누었다. 그리고 유저와 펀드매니저, 기능별로 나누고 프런트와 백이 각각 페어가 되어 기능 구현이 진행되었다.
형상관리
형상관리는 git-Organization을 이용하였다.진척관리
진척 관리는 만들어진 git-Organization에 있는 projects의 칸반 보드를 이용하여 관리하였다. 프런트와 백을 나누어 관리하였다.conventions
협업 시 컨벤션은 아래와 같다.깃 커밋 컨벤션- Feat: 새로운 기능 추가
- Fix: 버그 수정
- Docs: 문서 수정
- Style: 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
- Refactor: 코드 리팩토링
- Test: 테스트 코드, 리팩토링 테스트 코드 추가
- Chore: 빌드 업무 수정, 패키지 매니저 수정
- 변수명은 Lower Camel Case
- 함수, 인터페이스, Enum은 Upper Camel Case
- 각 함수 별 주석을 작성한다.
- 컴포넌트 명은 대문자로 작성한다.
- 컴포넌트 안의 함수는 익명함수로 작성한다.
스크럼
데일리 스크럼을 진행하여 매일매일 오전 9:10분, 오후 1:30분에 회의를 진행하면서 서로의 진행 상황이나 특이 사항 등을 공유하고 회의를 작성하였다.그라운드룰
원활한 협업을 위해 그라운드룰을 정하였다. 실제로 다들 잘 지키려고 노력해 주었다.- 지각/조퇴/결석 시 슬랙 or 카톡 or 면대 면으로 반드시 알린다.
- 매일 오전 9:10분, 오후 1:30분에 스크럼을 진행한다.
내가 맡은 역할
- 팀 리더를 맡아 팀 내의 룰 혹은 여러 가이드라인을 정하고 개발&협업 관련 문서 작성을 하였다.
- 펀드매니저 페이지를 담당하였으며, 투자문의 보러 가기, 투자문의 목록 보기, 투자문의 상세페이지 조회, 투자문의 상세페이지에서 채팅방이 있는지 없는지 확인 후 채팅방으로 라우팅 등 관련 기능을 구현하였다.
추가개발/개선사항
발표 후 질문 혹은 피드백 받은 사항으로는 아래와 같다.Q&AQ : 투자문의 목록 보기 같은 경우, 검색 기능이 없으니 사용자가 자신이 쓴 글이 밑에 있는 경우 나올 때까지 스크롤을 계속해야 하는데 페이지 네이션 방식이 더 좋지 않은지?
A : 요즘 앱 서비스들은 페이지 네이션보다는 무한 스크롤을 많이 사용하므로 ux 관점으로 참고해 진행하으며 검색 기능을 고려하였으나 시간 관계상 구현하지 못했다.
Q : fetch 기능이 데이터를 가져오는 데 있어서 더 효율적이라고 판단하신 거 같은데 실제로도 기존 방식(axios) 과는 차이가 유의미 한지?
A : 실제로 측정해 보진 않았으나 fetch는 next.js의 내장된 기능이며 캐싱 관련 기능을 확장하여 제공하고 재검증 기능이 구축되어 있기 때문에 사용하였다.
- 유저 투자 수익에 관련해서 BM에 대한 고민이 필요한 거 같다.
| 개인적으로 이 피드백은 정말 좋은 피드백인 거 같다. 사실 기획 단계에서 이 부분에 대해 생각을 하지 않은 것은 아니나, '매칭'에만 초점을 두어 진행하자!로 의견이 모여졌기 때문에 조금은 아쉬운 부분도 있었다. 지속 가능한 서비스를 만들기 위해서는 BM 관점에서 많은 고민이 필요한 거 같다.
Review
좋았던 점: 백과 프런트를 분리하여 진행해서 분업화를 확실하게 진행할 수 있어 각자 역할에 집중도를 높일 수 있었고 tailwind와 next.js, 아토믹 디자인을 적용해 재사용 가능한 컴포넌트 설계를 경험할 수 있어 좋았다.아쉬웠던 점: 타입 스크립트에 대한 지식이 부족하여 좀 더 정교한 타입 지정을 못해서 아쉽고 아직은 리액트도 익숙지 않아서 이 부분에 대한 공부를 깊게 해야겠다는 생각이 들었다
