엘리스 웹서비스 3차 프로젝트(5주)

박정훈·2022년 7월 10일
3

엘리스 AI트랙 4기

목록 보기
1/2

엘리스에서 1차 협업, 2차 협업, 3차 협업 프로젝트를 거쳐 왔습니다.
1차는 백엔드와 프론트엔드
2차는 백엔드와 프론트엔드와 데이터 분석
3차는 백엔드와 프론트엔드와 AI
파트로 나뉘어서 역할을 맡아서 프로젝트가 진행 되었습니다.
전 3번의 프로젝트 모두 프론트엔드 파트를 맡아서 진행 했습니다.
1, 2, 3차 모두 회고를 적어야 하는데 바쁘게 지내다보니(핑계..) 마지막 프로젝트가 끝나고 3차 회고를 작성하게 되었습니다.😭

원래 협업을 경험하고 다양한 주제로 사이트를 만들어 보고 싶어서 엘리스에 지원했던 것이라 프로젝트 기간때 만큼은 더욱 열심히 하려고 노력했습니다.
정말 감사하게도 3번의 프로젝트 기간동안 좋은 팀원들을 만나서 항상 목표했던 것 이상으로 결과물을 뽑아낼 수 있었습니다.
내가 좀 더 열심히 할껄.. 이라는 생각은 들지만 당시에는 최선을 다 했을 것이라 믿고 있습니다..!

3차 프로젝트는 총 5주간 진행 되었습니다.
서비스에 대한 내용은 git의 README에 상세하게 적혀있으니 간단하게만 적고 넘어가겠습니다.
손생님 github

📌주제

내가 속한 5팀의 마지막 인공지능 프로젝트의 주제는 수화 학습 사이트다.

👶타겟

청각장애 영유아, 초등학생을 고객층으로 잡았다.

📚데이터셋과 기술스택

✨메인 기능

학습

  • 26개의 알파벳 및 21개의 영어 단어수화&지화로 학습할 수 있게 영상 재생
  • 영상을 시청한 뒤 웹캠을 보며 배운 것을 그대로 따라하고 제출
  • 해당 영상이 올바른 지화인지 검사하여 결과 반환

퀴즈

  • 앞서 학습한 21개 영어 단어 랜덤 등장
  • 제한 시간 동안 10개 문제 풀기
  • 맞힌 문제를 점수로 변환해 순위표 등극

기술스택 선택 이유

📘TypeScript

  • JS는 존재하지 않는 프로퍼티의 접근을 허용하거나, 어떤 오류가 있어도 런타임에 오류를 뱉어냅니다.
  • 개발자의 실수도 쉽게 유발할 수 있습니다.
  • TS는 정적 타입 검사자 입니다. 프로그램을 실행시키지 않으면서 코드의 오류를 검출하는 것을 정적 검사라고 합니다.
  • 이러한 강점으로 미리 오류를 발견하고 고칠 수 있으며, 개발자의 실수를 줄일 수 있습니다.

따라서 TS로 타입의 안정성을 높이고 실수를 미연에 방지하고자 채택 했습니다.

📙Styled-components

  • 스스로 className을 생성합니다. className의 중복이나 오타로 인한 버그를 낮춰줄 수 있습니다.
  • props나 전역 속성을 기반으로 컴포넌트에 스타일 속성을 부여할 수 있습니다.
  • 기반이 되는 스타일 컴포넌트를 작성하고 해당 컴포넌트를 상속받아 사용, 확장 할 수 있습니다.

이 정도가 제가 느낀 styled-components의 장점 입니다. 스타일이 조금만 바뀌는데도 새로운 컴포넌트를 만들어야
하는 귀찮음(?)은 있지만 그 외에는 만족하고 사용하고 있었기에 채택 했습니다.

⚡Socket.io

mediapipe가 찍어주는 손과 얼굴의 좌표가 프레임마다 찍히게 되는데, 실시간으로 해당 데이터를 모아서
서버에 쏴주고, 서버에서 받은 좌표 데이터를 가지고, 맞는 답인지 판단한 다음 그 답을 다시 front로 넘겨받는
과정이 필요했습니다.

양방향 통신과 실시간 데이터 전송, 빠른 속도를 고려해 Socket.io를 채택했습니다.

📔Jotai

가벼운 전역 상태 관리 라이브러리가 필요 했습니다.
jotai는 리코일로부터 영감을 받아 atomic model로 리액트의 상태를 관리, React 컨텍스트의 추가 재렌더링 문제를 해결했다고 합니다.
또한 매우 가볍다고 하네요!
러닝커브를 고려해 진입장벽이 낮아 보이는 조타이를 채택했습니다.

🙌mediapipe

수화&지화를 캠으로 찍을 때 손의 좌표가 필요했습니다.
mediapipe 라이브러리의 hands가 해당 데이터를 제공했기에 채택했습니다.

💥트러블 슈팅

🧐TS Type

팀 프로젝트에서 TS를 적용 해 보는 것은 처음이었습니다. 그래서인지 라이브러리가 요구하는 타입을 맞추는 과정에서 자주 문제가 발생했었습니다. 물론 라이브러리뿐 아니라 여러가지 상황에서 TS는 불평을 했습니다.

인덱스

interface UserLogin {
  id: string;
  password: string;
}

const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  setLoginInfo((cur): UserLogin => {
    const newInfo: UserLogin = { ...cur };
    newInfo[e.target.name] = e.target.value;
    return newInfo;
  });
};

'string' 형식의 식을 'UserLoigin' 인덱스 형식에 사용할 수 없으므로 요소에 암시적으로 'any'형식이 있습니다. 'UserLogin' 형식에서 'string'형식의 매개 변수가 포함된 인덱스 시그니처를 찾을 수 없습니다.

키 값의 타입을 정확하게 지정해 주지 않아서 발생한 문제였습니다. 간혹

[Key: string]: string

을 해결방법으로 제시하는 글을 볼 수 있지만, 좋은 방법이라고는 생각하지 않습니다. 키 값에 어떤 string 값이 들어가도 에러를 뱉지 않을 것입니다.

newInfo[e.target.name as keyof UserLogin] = e.target.value;

정확히 UserLogin의 key값으로 사용해라 라고 지정해줍니다.

framer motion ref

통통 튀는 듯한 애니메이션과 드래그를 굉장히 쉽게 적용할 수 있어서 선택한 라이브러리입니다.
라이브러리에서 useRef를 사용해야 할 일이 있었는데, 상위 요소에 ref를 잡고, 자식요소의 dragConstraints 속성에 해당 ref를 넣어주면 되는 거였습니다.

const MyComponent = () => {
  const constraintsRef = useRef(null);

  return (
     <motion.div ref={constraintsRef}>
         <motion.div drag dragConstraints={constraintsRef} />
     </motion.div>
  )

저는 부모 요소에서 ref를 잡고 해당 ref를 forwardRef로 넘겼습니다.
ref를 넘기는 방식은 반드시 forward ref를 사용해야 가능한 것으로 알고 있었습니다.
그렇지만 이렇게는 type이 맞춰지질 않아서 계속 에러가 났습니다.
forwardRef를 단순히 부모 요소를 넘겨주는 용도로 잘못 사용하고 있었던 것입니다.
ref를 그냥 props로 넘기는 방법이 있었고, props로 넘겨서 해결 되었습니다.
(forwardRef는 어떤 컴포넌트 안에 있는 요소를 부모에서 컨트롤 하고 싶을 때 사용!)

🧐Mediapipe

미디어파이프 라이브러리를 사용하는데 vanila js를 react로 옮기는 과정과, 사용법에 있어서 많은 시간이 소요 되었습니다.
미디어파이프의 onResults함수는 매 프레임마다 마디의 좌표를 찍고, 캔버스로 라인을 그리고 있었습니다.

const onResults: h.ResultsListener = (results) => {
  ...
}

holistic.onResults(onResults);

MediaPipe
그래서 미디어파이프의 카메라는 계속 프레임이 돌고 있으면서, 우리가 원하는 시점에 좌표를 찍고 라인을 그리는 함수는 멈추게 하고 싶었습니다. 여러가지 테스트를 해보고 내린 결론은 onResults 함수를 비워야 한다 였고

  useEffect(() => {
    if (cameraOn) {
      holistic.onResults(onResults);
    } else {
      holistic.onResults(() => undefined);
      setMediapipeData([]);
    }
  }, [cameraOn]);

다음과 같이 플레이 버튼을 누르면 바뀌는 cameraOn state에 따라 컨트롤 했습니다.

🧐Socket.io

AI 서버와 어떤 방식으로 통신하는 것이 가장 빠를지, 정확할지 많은 고민이 있었습니다.
1. 일정 시간동안 데이터를 축적, 한번에 쏴주는 방식
2. 3번에 나눠서 데이터를 축적해서, 3번에 나눠 쏴주는 방식
3. 프론트에서 데이터를 일정 텀으로 축적해서(프레임 마다가 아닌 34ms 마다 데이터 축적) 계속 쏴주는 방식
4. 3번의 방식에서 데이터를 축적하다가 한번에 쏘는 방식
여러가지 경우의 수를 두고 테스트를 해보고 결과물이 가장 정확하고 빠른 1번으로 진행하게 되었습니다.

🤔개인적으로 신경썼던 부분

중복되는 페이지 구성

페이지의 구성은 같고 내용물만 달라지는 페이지가 있었습니다. 두개의 페이지로 나눠 만들기보다는 pathname으로 알파벳을 학습하러 왔는지, 단어를 학습하러 왔는지 여부를 체크해서 뿌려주는 데이터를 다르게 했습니다.

타겟층에 맞는 UI/UX 고려

유아 및 초등생이 타겟이다 보니 아기자기하고 서비스를 사용하는데 있어 설명이 딱히 필요없어야 한다고 느꼈습니다.
크고 아기자기하며 직관적이게 보이도록 구성했고, framer motion을 활용해서 애니메이션을 추가했습니다.

저작권

아무래도 퀄리티가 좋은 이미지를 가져다 쓰고 싶어서, freepik에서 제공하는 알파벳, 배경화면 등의 이미지를 저작권 표시(footer)를 하고 사용했습니다. (추후 이미지들은 팀원분이 그린 그림으로 대체될 가능성이 있습니다!)

🎉우수작 선정🎉

이 프로젝트를 끝으로 6개월간의 엘리스 트랙이 끝이 났습니다. 프로젝트가 끝나고 바로 팀 마다 프로젝트 결과물을 가지고 발표를 했습니다. 사이트에 대한 평가는 발표 하루전에 미리 끝났고, 발표 직후 발표 점수까지 합산해서 바로 우수작들이 선정되었습니다.
그 결과!
5팀 우수작
5팀이 우수팀 안에 선정되었습니다 👏👏👏👏👏👏👏🎉🎉🎉🎉🎉
정말 운이 좋게도 2차 프로젝트 1등, 3차 프로젝트 우수작안에 들어가게 되었네요!
좋은 팀원들을 만나 함께 열심히 한 결과라고 생각합니다.😁

후에 3팀으로 좁혀져서 오프라인에서 발표를 하게 된다고 하네요. 기업에서도 오셔서 발표를 들으신다고 하는데...
기분이 좋으면서도 걱정도 되고... 아무튼 선정된건 기쁘네요!

🔨개선사항

중간에 한번 더 평가를 거쳐 3팀으로 좁혀지게 될 텐데, 그 사이에 개선사항들을 추가 해 오면 반영이 된다고 합니다.
그래서 저희 팀도 부랴부랴 스크럼을 하고 어떤점을 개선하면 좋을지 의견을 나눴습니다.

웹캠 여부

웹캠이 없는 환경에서 학습과 퀴즈 사이트에 들어가지 못하는 상황이 발생했습니다. (완전히 놓쳤던 부분입니다...)
이는 저희 최종 발표 때 들어왔던 피드백입니다. 이를 반영해, 웹캠이 없는 환경에서도 학습할 수 있도록 할 계획입니다.

로그인이나 가입 시 알림

현재 로그인 실패나 가입시에 알려주는 모달창이나 경고문이 없어 사용자가 헷갈릴 수 있습니다.
이러한 부분에서 좀 더 UX에 신경 쓸 계획입니다.

로그인 유저 차별화

로그인 한 유저와 로그인 하지 않은 유저의 차이점이 없다는 피드백을 받았습니다.
현재 로그인 유저는 학습 및 퀴즈를 맞추면 포인트가 누적되는데, 이를 확인할 수 있게 하고, 별도로 페이지를 만들어 포인트를 사용할 수 있게 할 계획입니다.

마치며

처음 써보는 프로젝트 회고 아닌 회고였습니다. 작성하는게 생각보다 쉽지 않다는것을 느꼈습니다.
다행히 이슈와 진행 사항들이 문서화와 깃 이슈로 잘 남아있어서 많이 참고해 가며 작성했습니다.

5주라는 시간이 굉장히 길것만 같았는데 하다보니 정말 빠르게 지나가더군요.
그만큼 재밌었고, 재밌었기에 프로젝트에 빠져있었습니다.
사용자들에게 내가 기여한 서비스를 제공하고 이를 사용해주면 얻는 뿌듯함이 개발자라는 타이틀의 큰 매력인거 같습니다.
더욱 더 매력적인 가치를 창출해 내는 개발자가 되기 위해 게을러지지 않아야 겠습니다!

진짜 끝으로! 3차 프로젝트 개선사항까지 잘 반영해서 유종의 미를 거뒀으면 좋겠습니다!

엘리스를 마치고...

이후 같이 프로젝트를 진행해 보자는 엘리스 동기분들이 계셔서 알약 프로젝트를 시작하려고 합니다.
알약을 사진으로 찍으면 해당 약에 대한 정보를 알려주는 기능을 제공할 계획입니다.
Next.js를 기반으로 한 앱이 될것 같네요. 공부해야겠어요!
이 프로젝트는 가능한 주마다 회고를 작성해보려고 합니다. 이 프로젝트도 열심히 달려서 멋지게 만들어 내보고 싶습니다.

profile
그냥 개인적으로 공부한 글들에 불과

1개의 댓글

comment-user-thumbnail
2022년 7월 14일

너무 멋있는 프로젝트와 회고입니다! 다음 프로젝트는 어떤 것을 공부하시고 회고로 남기실 지 궁금하네요 지켜보겠습니다😎

답글 달기