작품의 목적
동아리 활동을 진행하며, 가장 힘이 많이 드는 것이 활동하는 모든 인원이 참여 가능한 일정을 짜는 것이였습니다. 또한 대학생 커뮤니티 앱인 에브리타임은 군산대에서 운영하는 앱이 아니기에 대학 강의가 수정되거나 계획에 맞게 진행되지 않았을 때, 이를 처리해주지 않았습니다. 이러한 문제를 해결하고자 대학만의 대학생 커뮤니티 앱이 있어야 한다고 생각하였습니다.
사용된 기술
SPA(Single Page Application), Redux, Redux middleware, deploy, MySql2, Token, react, styled component, react router, firebase, axios, nodemon, express, crypto, cors
SPA
Multipage application은 다른 페이지로 이동 시, 서버로부터 새로운 리소스를 전달받아 브라우저 화면에 보여주는데, 이 과정에서 서버의 많은 자원을 할당 받습니다. Single Page Application는 초기에 한 번 html 파일로 불러오고, 이 후 변경된, 필수적인 데이터만 받아서 화면에 업데이트 합니다.
이는 페이지 간 전환이 빠르고 부드러운 특징이 있습니다.
Redux
Redux는 자바스크립트 애플리케이션의 상태를 중앙에서 관리하는 패턴 및 라이브러리입니다. Redux의 주요 구성요소는 reducer, action, store이 있습니다. 액션객체를 리듀서로 디스패치하여 정해진 로직에 따라 스토어 값을 변경합니다. 이 때 액션이 스토어로 전달되기 전에 비동기처리나 로깅, 액션 취소를 중간에서 처리해주는 Redux saga middleware를 사용했습니다.
middleware
애플리케이션의 요청과 응답 사이에 위치하여, 그 과정에서 특정 작업을 수행하는 함수 입니다. Redux middleware는 action과 reducer 사이에서 다양한 작업을 수행할 수 있게 하여, 애플리케이션의 상태 관리를 더 유연하고 강력하게 합니다. Redux에서는 Redux Thunk나 Redux Saga와 같은 middleware를 사용하여 비동기 작업을 처리합니다.
MySQL
오픈 소스 관계형 데이터베이스 관리 시스템(RDBMS)입니다. 데이터를 테이블로 구조화하여 저장하며, SQL(Structured Query Language)을 사용하여 데이터베이스를 관리하고 질의할 수 있습니다. 웹 애플리케이션에서 널리 사용되며, 대규모 데이터 처리에 적합합니다. 사용자 권한 관리, SSL/TLS 암호화, 데이터베이스 백업 및 복구 등의 보안 기능을 제공합니다. 높은 성능을 제공하고 큰 규모의 데이터와 복잡한 쿼리도 효율적으로 처리할 수 있습니다. 사용한 호스팅 사이트에서는 MySQL에 없었기에 mariadb를 사용했습니다. MySQL의 업그레이드 버젼으로 json 데이터를 관리할 수 있는 것이 특징이지만 mysql 8 버젼부터는 json 타입을 지원하고 있습니다. react에서 mariadb 모듈을 사용하는 것이 아닌, mysql2 모듈을 사용하여 해결하였습니다.
Express
Node.js 환경에서 웹 애플리케이션을 구축하기 위한 웹 프레임워크 최소한의 설정으로 웹 애플리케이션을 개발할 수 있도록 설계되었다. 간단하고 직관적인 API를 제공한다. 필요한 기능들을 모듈화 하여 추가할 수 있고, 이를 통해 애플리케이션의 성능을 쉽게 최적화 할 수 있다. 미들웨어 기능을 통해 요청과 응답 사이에 여러 기능을 추가 할 수 있다. Node.js의 비동기 I/O 모델을 기반으로 하여 비동기 처리를 지원하며, 이를 통해 높은 성능과 확장성을 유지하면서 동시에 많은 요청을 처리할 수 있다.
Token
인증 및 권한 부여를 위한 정보 단위이다. JSON Web Token(JWT)은 일반적으로 사용되는 토큰의 형태로, 사용자 정보를 포함한 페이로드를 안전하게 전달하기 위해 사용된다. 서버는 토큰을 검증하여 사용자 인증 상태를 확인한다. 사용자가 로그인 요청을 하면, 서버는 사용자의 정보를 확인하여 생성하고 이를 클라이언트에게 반환한다. 클라이언트는 전달받은 토큰을 로컬스토리지에 저장하고 이후에 요청시에 사용한다. 클라이언트는 요청을 보낼 때 마다 헤더에 토큰을 포함시킨다. 클라이언트로부터 요청을 받은 서버는 토큰의 유효성을 검증하고 유효하지 않은 토큰이나 만료된 토큰인 경우 인증 실패 응답을 반환한다. 토큰 방식은 상태를 서버에 저장하지 않아 서버간 확장성이 뛰어나다. 민감한 정보를 직접 전달하지 않고 토큰을 사용하여 전달하기 때문에 보안성을 높일 수 있다. 또한 다양한 클라이언트에서 동일한 방식으로 인증을 처리할 수 있다. 이러한 이유로 토큰 방식은 SPA(Single Page Application)등 다양한 현대적인 웹 애플리케이션에서 널리 사용된다.
MVVM (Model-View-ViewModel)
소프트웨어 아키텍처 패턴으로, 특히 GUI 애플리케이션에서 데이터 바인딩과 이벤트 관리를 효율적으로 하기 위해 설계되었다. 이는 애플리케이션의 UI와 비즈니스 로직을 분리하여 유지보수성과 테스트 용이성을 높인다.
비동기 요청 (Asynchronous Requests)
서버에 요청을 보내고, 서버의 응답을 기다리는 동안 애플리케이션의 다른 작업을 계속 수행할 수 있게 한다. 주로 AJAX(Asynchronous JavaScript and XML)나 Fetch API를 사용하여 구현된다. 이를 통해 사용자 경험이 향상되고, 애플리케이션이 더 반응적이 된다.
리액트 DevTool (React Developer Tools)
리액트 DevTool은 리액트 애플리케이션을 디버깅하고 분석하는 도구이다. 브라우저 확장 프로그램 형태로 제공되며, 컴포넌트 트리, 상태, props, 렌더링 성능 등을 검사할 수 있습니다. 이는 개발자가 리액트 애플리케이션의 동작을 이해하고 문제를 해결하는 데 도움을 준다.
WRK 벤치마킹 (WRK Benchmarking)
HTTP 서버 성능을 테스트하는 벤치마킹 도구이다. 멀티스레딩과 이벤트 기반의 구조로 높은 성능을 자랑하며, 다양한 부하 조건에서 서버의 처리 성능을 측정할 수 있다. 이를 통해 웹 애플리케이션의 성능 병목 지점을 파악하고 개선할 수 있다.
구현
로그인 페이지
DB에서 사용자의 정보를 비교하여 동일한 사용자가 존재한다면 해당 사용자의 정보를 쿠키에 저장하여 추후 진행될 인증 절차에서 사용함
프론트 개발 당시에는 firebase를 사용하여 개발을 진행하였고, 이후 Maria DB로 전환함
회원 가입 페이지
사용자가 입력한 데이터 양식이 정당한지를 평가하고, DB에 입력 데이터의 중복성 여부를 확인하고 동일한 사용자가 존재하지 않는다면 DB에 저장함
메인 페이지
로그인 페이지에서 받은 토큰을 통하여 유효성을 검사함
시간표 등록 페이지와 미팅시간 정하기 페이지의 이동을 위한 버튼을 제공함, 로그아웃 버튼을 누르면 토큰을 제거하여 로그인 상태를 해제함
시간표 등록 페이지
강의명, 강사명으로 강의를 검색 후 원하는 시간표를 작성 후 DB에 JSON 데이터로 정형화 한 후 저장
시간이 겹치는 시간표에 경우 이용자에서 이를 확인시키고 다른 강의를 선택할 것을 권유함
새로고침을 진행하거나 처음 접속할 시에 토큰에 기록된 시간표 데이터를 이용하여 이용자의 데이터를 불러옴
미팅시간 정하기 페이지
검색창에 학번을 검색하면 DB에서 해당 학번을 가진 이용자를 불러오게 됨
이용자를 선택하면 시간표 정보를 대조하여 미팅이 가능한 시간을 사용자에게 보여줌
공통
styled component를 사용하여 창 크기에 비례하여 크기를 자동 조절하고, 미디어 쿼리를 통하여 모바일 환경에서 원활한 사용을 가능케 함 페이지 이동 시 토큰값을 기반으로 인증 검사를 하여 토큰이 없을 시 로그인 페이지로 이동함
성능 평가
적은 양의 데이터를 렌더링 하는 시간
최적화 이전 지연 시간

Render : 18.9ms Layout effects : 0.2ms Passive effects : 2.5ms
최적화 이후 지연 시간
컴포넌트들을 분리하고, 메모이제이션 방식을 통하여 최적화를 한 뒤의 렌더링 시간

Render : 14.4ms Layout effects : 0.1ms Passive effects : 2.8ms
벌크 데이터 생성 후 렌더링 하는 시간
10,000개의 벌크 데이터를 서버에 저장한 후, 10,000개의 데이터를 렌더링 시의 지연 시간
최적화 이전 지연 시간

Render : 130.8ms Layout effects : 0.1ms Passive effects : 2.3ms
최적화 이후 지연 시간

Render : 15.4ms Layout effects : 0.1ms Passive effects : 3.5ms
월별 수행일정
4월
| 로그인 페이지 | 로그인 및 로그아웃 기능을 통해 사용자가 시스템에 로그인하고 로그아웃 할 수 있다. 이를 위해 백엔드 팀과 협력하여 데이터 검증 및 데이터 베이스와의 연동을 수행했다. 토큰 방식을 사용하여 사용자의 정보를 관리하였다. 이를 위해 프론트 팀과 백엔드의 협업을 통해 토큰 방식을 이용한 사용자 유효성 검사 코드를 구현하였다. 사용자가 로그인 버튼을 누르면 Container에서 정의한 Callback함수를 실행하여 백엔드에 정의한 URL로 로그인을 요청한다. 정상적인 응답을 클라이언트가 받은 경우 메인페이지로 이동하고 토큰을 부여받고 문제가 발생한 경우 피드백을 진행한다. |
|---|---|
| 회원가입 페이지 | 사용자가 회원가입 정보를 요청내용에 담아 서버에서 구현한 특정 API로 요청하면 회원가입이 진행되도록 코드를 구현했다. 만약 비밀번호란과 비밀번호 확인란의 데이터가 다른 경우, 사용자 명이 입력되지 않은 경우는 불필요한 서버로의 요청을 막기위해 프론트코드에서 제어한다. 회원가입 버튼을 누르거나 Enter를 누르면 Container에서 정의한 Callback함수가 실행되어 백엔드에 정의한 URL로 회원가입을 요청한다. 정상적인 응답을 클라이언트가 받은 경우 메인페이지로 이동하고 토큰을 부여받고 문제가 발생한 경우 피드백을 진행한다 |
| 메인 페이지 | React Router를 통해 메인 페이지와 로그인페이지 회원가입페이지간의 이동을 구현하였다. |
| 시간표 등록 페이지 | 강의 검색 및 장바구니 기능은 React.useState함수를 통해 상태관리를 진행하였다. Container에서 시간표를 등록하는 Callback function을 정의하여 Component에서 사용할 수 있도록 props로 전달하였다. React Router로 시간표 등록페이지의 URL을 정의하고 접속시 보여주는 컴포넌트를 지정해주었다. |
| 미팅 시간 정하 기 페이지 | React Router를 통해 메인 페이지에서 미팅시간 정하기 페이지로 이동할 수 있게 하였다. Container에서 다른 사용자의 이름을 검색하는 Callback function을 정의하였다. 백엔드에서 정의한 URL로 요청하여 데이터베이스로부터 다른 사용자의 유저 정보와 시간표정보를 받아 클라이언트로 응답한다. Component에서 응답받은 다른 사용자의 정보를 렌더링하고 특정 사용자의 유저 정보를 클릭하면 현재 사용자의 시간표 데이터와 다른 사용자의 시간표 데이터를 비교하여 미팅가능 시간을 렌더링한다. |
| 교육망 서버통신 문제 해결 시작 | 포트포워딩을 통해 교육망에서 백엔드개발이 가능하도록 하였으며 MySQL 서버를 외부 IP에서 접속시에 발생하는 문제들을 해결하였다. |
5월
| 코드 관리 | 기존의 상태관리 코드는 이해하기 어렵고 방대하여 Action Creator function 및 Reducer function을 최신 버전의 createAction f unction 및 handleActions함수로 대체하였다. 또한 redux middle ware로 Redux Saga를 사용했는 데, 모든 요청에 대한 최초 요청 타입, 성공시 타입과 실패시 타입에 대한 코드가 방대하여 createRequestSaga와 같은 Custom middleware function으로 리팩터링하였다. |
|---|---|
| 데이터 로딩 시 사 용자 피드백 제공 | 데이터 로딩시 문제가 발생하는 경우는 서버에 문제가 발생한 경우, 클라이언드의 요청이 잘 못된 경우가 있다. 각각의 경우에 대해서 클라이언트에게 피드백하는 부분을 추가하였다. |
| 기능 전환 완료 | 교육망에서의 서버 통신 문제를 해결하는 동안 프론트엔드 개발은 클라우드 서버를 통해 진행되었다. 교육망에서의 개발이 가능해진 후 mysql과 express로의 전환을 진행하면서 여러 기능을 개발하였고 모든 기능이 Firebase에서 Express와 MySQL로 전환이 완료되었다. |
| 로그인 시 사용자 피드백 추가 | 로그인을 실패하는 경우는 사용자가 적절한 아이디를 입력하지 않은 경우, 잘못된 비밀번호를 입력한 경우, 서버에 문제가 발생한 경우가 있다. 이때 각각의 경우에 대해서 사용자에게 Alert한다. |
| 회원가입시 문제가 발생하는 경우에 대해 프론트 코드에서 제어할 수 있는 부분은 비밀번호란과 비밀번호확인란의 불일치경우, 서버에 문제가 발생한 경우가 있다. 이를 프론트 코드에서 피드백 하는 부분을 추가하였다. | |
| 프론트 코드 성능 테스트 및 최적화 | 렌더링 성능을 측정하기 위해 React DevTools를 사용했으며 적은 양의 데이터를 렌더링하는 경우와 10000개의 벌크 데이터를 생성하여 렌더링하는 성능을 측정하였다. 이 후 각 컴포넌트들을 분리하여 메모이제이션 방식을 사용해 최적화를 진행하였고, 최적화된 성능을 확인하였다. |
| Trunk base 방식의 GitHub 협업 | GitHub를 사용하여 코드 공유 및 프론트 코드를 자동으로 배포하였다. |
| Netlify와 Cloudtyp e을 활용한 배포 | 백엔드 코드의 자동 배포를 위해 Netlify와 Cloudetype을 활용하였다. |
| Cloudtype에서 MySQL을 지원하지 않아 MariaDB로의 전환을 진행하였다. MariaDB에서 JSON데이터를 통신하는데 어려움이 있어 text를 직접 파싱하는 방식으로 전환하였다. |
개선 사항
보안 및 권한 설정
MySQL이 기본적으로 localhost에서만 접속 가능하도록 설정되어 있어, 다른 IP에서의 접근을 허용하기 위해 전역 범위를 가지는 root 계정과 tester 계정에 권한을 부여해야 한다. my.ini 파일에서 bind-address를 0.0.0.0으로 변경하여 모든 네트워크 인터페이스에서 접속을 허용하도록 설정한다.
문자 인코딩 문제
MySQL 로그가 ASCII 형식으로 생성되어 확인할 수 없는 문제를 해결하기 위해 로그 파일의 인코딩을 UTF-8로 변경한다.
네트워크 설정 및 포트 문제
고정 IP로 인해 포트 3306이 차단되어 외부 접속이 불가능한 문제를 해결하기 위해 방화벽 규칙을 조정하고 MySQL 포트를 43306으로 변경한다
백엔드 미들웨어 미 적용
DB를 구축한 Cloudtype에서의 자체적인 미들웨어는 적용되었으나, 자체적인 미들웨어는 구현하지 못했음
협업 및 배포
기존에는Trunk base 방식의 GitHub 협업을 진행 해왔음 Trunk base방식은 master 브랜치에서 분기를 만들고 분기당 한 가지 씩의 문제만을 해결하여 master 브랜치에 병합하는 방식임이 방식은 빠른 개발이 가능하고, 자동 배포방식을 사용할 수 있다는 장점이 존재하였음 git flow방식은 master 브랜치에서 relase 분기를 만들어 해당 분기에서 분기를 추가로 만들어 기능을 추가한 후 배포 전 확인을 진행하고, master와 병합 후 오류 발생시 hotfix 브랜치를 분기하여 오류를 해결하는 방식입니다. 해당 방식은 매우 복잡하며, 한명의 Github 관리자가 필요하며, 개발간의 간격이 크기에 자동 배포가 불가능합니다
사용자 경험 개선
데이터를 로딩할 때 사용자에게 어디가 잘못되었는지에 대한 피드백이 존재하지 않았음 이는 백엔드에서 문제가 발생하였을 때의 상태정보를 프론트 코드에 전송하여, 사용자에서 어느 부분이 잘못되었는지에 대한 피드백을 전달함
기술 이전 계획
프론트 코드를 개발하였을 때, 테스트를 위해 firebase를 사용하였으나 DB구축후에는 사용중인 DB의 전환과정이 필요하였음, node.js에서 지원하는 mysql2 모듈을 사용하여 DB를 연결하였고, 세션방식을 추천하였으나, 개발중인 웹 어플리케이션과 맞지 않다고 생각하여 토큰 방식으로 개발을 진행하였음
Netlify와 Cloudtype을 활용한 배포
Netlify는 아마존에서 제공하는 AWS를 프론트 코드를 올리기 좋게 만들어주는 호스팅 사이트입니다. Github의 레퍼지토리를 읽어 자동 배포해주는 기능을 존재하기에 이 플래폼을 선정하였습니다. cloudtype은 한국의 플랫폼 회사이며, 무료로 DB까지 호스팅이 가능한 플래폼이며, 한국의 기업이라 오류 발생시 관리자에게 요청할 시 한국어로 답변을 받을수 있기에 해당 플래폼을 선정 하였습니다. 이 과정에서 cloudtype은 MySQL을 지원하지 않았기에 Maria DB로 전환을 진행하였으나, MySQL은 8버젼 이후 json 데이터를 지원하기에 json 데이터를 활용하여 시간표 데이터를 관리하였으나 Maria DB는 json 파일로 저장하는 것이 아닌 text 파일이 json도 지원하는 방식으로 전환되며, json 데이터로 저장되는 것이 아닌 text 형식으로 저장되며 각종 문제가 발생하였고 대부분 해결하였음.
앞으로의 계획
es-hangul 도입
토스에서 개발한 한글 초성 등의 다양한 기능을 가진 es-hangul을 사용하여 사용자의 편의성 증가
소셜 로그인 도입
소셜 로그인을 도입할 예정
사용자 정보 창 도입
현재 사용자의 정보를 수정할 수 있는 페이지가 존재하지 않음, 이를 도입 예정
게시판 도입
사용자끼리와 사용자와 운영자간 소통 할 수 있는 게시판을 추가할 예정
Kakao map API 도입
미팅 장소를 정할 수 있는 카카오 맵 API를 도입할 예정
Email.js나 Kakao API 도입
현재 회원 가입시 인증 없이 가입이 가능하나, 이를 해결하기 위한 인증 시스템 도입 예정
Git Flow 방식 도입
현재 Trunk base 방식으로 협업을 진행하였으나, 기존 틀이 잡혔기에 git flow 방식의 도입의 필요를 느낌
그 외 도입 고려 사항
rest.api JPA service 레이어 response entity DAO TDD 전역 exception setter validator bulider 패턴 webflux