project BPM - client

Enzo·2022년 6월 27일
0

project BPM

목록 보기
3/4

화면에 구현해야할 내용이 많았기 때문에 프론트엔드를 맡으신 분 혼자하기 버거울 것 같아서 백엔드 2명이 빨리 끝내고 도와주기로 합의하였다.
계획대로 빠르게 서버 프로그래밍을 마치고 프론트엔드를 하게 되었다.
이때 원래 프론트엔드를 맡아주신 팀원분께서 퍼블리싱에 조금 더 흥미가 있으시고 능력이 있으셔서 퍼블리싱 위주로 맡아주셨고, 후에 합류한 나는 기능 붙이기를 주로 하였다.

리액트를 타입스크립트로 해보자는 의견이 나와서 이번에는 타입스크립트를 사용하였다.

기술스택

Typescript, React, ethers.js, redux, redux-persist, material-ui


개발

로그인

로그인은 메타마스크 지갑을 이용해서 하도록 만들어주었다.
처음 접속하는 회원의 경우 메타마스크 인증 후에 닉네임과 이메일을 적으면 가입하게 하고, 다시 방문한 유저의 경우 메타마스크 인증을 거치면 바로 로그인이 되게 설계하였다.
ehters.js를 사용하여 클라이언트에 메타마스크와 연동을 하는 코드를 작성하였다.
로그인이 성공하게 되면 서버에서 jwt를 담은 쿠키가 오게되고 이를 이용하여 인증이 필요한 요청을 처리하게끔 설계하였다.
후에 클레이튼 체인과도 연결하여 사용가능하게 만들려 했기 때문에 kakas지갑과도 연결을 시도했으나 리액트 버전과 caver.js의 버전 충돌이슈로 잠정 중단되었다.

마이페이지

마이페이지에서 기본적인 이름과 정보들을 불러오는 코드를 작성했고, 수정을 가능하게 만들었다.
이때 ui적으로 어떤 식으로 수정을 만들면 좀 더 미관이 좋을지 생각하다가 수정하고 싶은 정보를 더블클릭하면 수정할 수 있는 버튼이 나오게끔 설계하였다.

댓글과 좋아요

모든 글들에 댓글과 좋아요 기능을 만들어주었다.
이때 좋아요는 중복되게 눌리면 안되기때문에 useEffect로 페이지가 뜰때 checklike를 실행하도록 만들어주었다.
댓글은 글자 수 제한을 걸어주었다.

게시판 생성

우리 프로젝트의 중요한 역할을 하는 게시판 생성 파트를 맡게 되었다.
토큰을 소각할 수 있는 이벤트가 게시판 생성이었고 일정 토큰을 소모하면 게시판 생성권한을 주는 것을 구현하면 되었다.
ethers.js를 사용하여 컨트랙트 객체를 생성한 후 transfer를 통해 서버 지갑에 토큰을 보내는 방식으로 구현하였다. 토큰을 보내는 서명을 하면 게시판 생성 api를 실행하여서 게시판이 생성되게 만들었다.

문제는 서명 후에 트랜잭션을 취소시키더라도 게시판 생성 api는 동작한다는 것이다. 토큰 송금 트랜잭션이 성공적으로 체결된 후에 동작시키는 방식으로 리팩토링 해야 할 것 같다.

	const createBoard = () => {
		const provider = new ethers.providers.Web3Provider(window.ethereum);
		const signer = provider.getSigner();
		const contract = new ethers.Contract(
			"0x0d5Ba334df6Df1b8c7D1C650e7D43Cef5077c50b",
			tempoabi,
			signer
		);

		contract
			.transfer(
				"0x6e8894086eEE0a251aC1Fe32e686ccb4685E91B4",
				ethers.utils.parseUnits("1500", 18)
			)
			.then((res: any) => {
				axios
					.post("http://localhost:4000/board/create", {
						title: title,
						subtitle: subtitle,
					})
					.then((res) => {
						if (
							res.data.message === "요청하신 게시판은 검토를 통해 생성됩니다."
						) {
							alert("게시판 생성 성공");
							setOpen(!open);
							navigate("/community/62903268742075468af6996c");
						}
					});
			})
			.catch((e: Error) => {
				console.log("error : ", e);
				alert("토큰이 부족합니다.");
				setOpen(!open);
			});
	};

pagenation

게시판의 글들과 댓글들 마이페이지에 자신이 작성한 글들 모두 페이지네이션을 해주었다.
mui에 적절한 페이지네이션을 찾아서 적용하였더니 크게 어렵지 않게 페이지네이션을 구현할 수 있었다.

기타

유효성 체크가 필요한 부분에 대한 처리와 인증이 필요한 기능은 jwt를 통해 로그인 후에 사용할 수 있게 처리해주었다.
또 jwt 유효기한이 지나면 로그인이 풀리게 설계를 해두었다.

리팩토링

1차 리팩토링

팀원이 react-async 라이브러리로 api요청 뼈대를 다 잡아주셨다. 그런데 문제는 react-async는 새로운 요청시에 항상 새로고침을 하는 방식이었다. 댓글 작성을 만들면서 useState를 사용하여 글을 받을 생각이었는데 상태변경이 일어나면 react-async에서 새로고침 후에 새롭게 화면을 그리는 이슈가 있었다.
처음에는 이에 맞춰서 formData로 작성했으나 글자수제한을 구현하기 위해서는 한계가 있었다.
또 상태변경시에 항상 새로고침이 일어나기때문에 화면이 계속 깜빡이는 현상이 있었다.
결국 필요한 부분 이외에 모든 react-async를 리팩토링하여 useEffect로 리팩토링 해주었다.
화면을 그리면서 비동기요청을 해주는 라이브러리라서 코드가 간결해지고 쉬워지기는 하지만 잦은 상태변경이 필요한 곳에서는 부적합하다는 것을 배웠다.

2차 리팩토링

처음에 모든 상태를 useState를 사용했고 props형태로 필요한 부분에서 받아 쓰는 방식으로 만들었지만 전역에서 사용하는 상태는 리덕스를 사용하자고 이야기가 나왔고 이에 맞춰서 로그인 관련한 상태는 리덕스를 사용하게끔 리팩토링 해주었다.
또 로그인 상태유지를 위해서 redux-persist를 이용하여 store유지를 시켜주게 리팩토링 하였다.


회고

프론트엔드를 하면서 백엔드때보다 더 많은 문제를 겪었다.
인증 관련해서 쿠키를 사용하였는데 보안을 위해서 http옵션을 주게 되면서 프론트엔드에서는 쿠키에 접근할 수가 없었다. 로그아웃을 하면 쿠키를 삭제시켜주어야 하는데 코드로 접근이 불가하기 때문에 서버쪽에서 쿠키를 지워주려고 했으나 동작하지 않았다.
아직도 이 문제를 해결하지 못했다. postman에서 테스트했을때는 분명 쿠키가 잘 지워지지만 브라우저를 사용하면 쿠키가 지워지지 않는다. 인터넷을 검색해가며 3일이상을 투자하였지만 문제를 해결하지 못했고, agora-state에 올려서 조언을 구했지만 돌아온 답변은 모두 시도해봤던 코드들 뿐이었다.

또 타입스크립트를 사용했는데 생각지도 못한 에러를 마주하는 등의 일들도 있었다. 나는 처음 프로그래밍 언어를 강타입언어인 go로 배웠기때문에 타입에 익숙하다고 생각하고 있었는데 자바스크립트를 오래하면서 금새 잊어버린 모양이다. 타입때문에 귀찮은 적이 한 두번이 아니었다.
이번에 사용한 타입스크립트는 제대로 배우고 사용했다기보다는 자바스크립트에 타입만 살짝 적어준 느낌으로 주먹구구식으로 사용해서 아쉬운 부분이 많다. 그래서 타입스크립트를 제대로 공부해보려고 준비하고 있다.

profile
고통수집가

0개의 댓글