- 2023.07.15 AWS 프리티어 지원 종료로 인해 배포가 종료되었습니다.
혼자 코딩하느라 지치시지는 않으신가요?
다양한 사람들과 함께 코딩하면서 교류해보세요!
MoCo는 스터디를 위한 게시판 웹 애플리케이션으로 마크다운 에디터를 이용한 게시판입니다.
일반적인 서버 - 클라이언트 구조의 아키텍처에 일부 컨텐츠를 이더리움 네트워크와 연동하였습니다.
- MacOS M1
- IntelliJ
- Visual Studio Code
- GitHub
- Docker
- DBeaver
백엔드
- Java 11
- SpringBoot 2.7.2
- Spring Security5
- Spring Data JPA
- QueryDsl 5.0.0
- Lombok
프론트엔드
- Html5/css3
- Javascript
- Thymeleaf
- Bootstrap 5
빌드 툴
- Gradle 7.5
데이터베이스
- Mysql
인프라
- AWS EC2
- AWS S3
- AWS Route53
- AWS RDS
- AWS ALB
- Github Actions
- Docker
- DockerHub
블록체인
- goerli network
- solidity
- Meta Mask
라이브러리
- web3.js
- openzeppelin-ERC20
- tippy.js
- toastui-editor
- tagify
- xeicon
- fabric
- copy-down
- kakaoMaps Api
- java smtp
2022-10-26 MoCo v1.1.0 릴리즈 보기
2022-11-01 MoCo v1.2.0 릴리즈 보기
😎 로그인화면 진입시 자동으로 로그인창 애니메이션이 작동합니다. - 로그인 접근성을 높였습니다.
2022-11-07 MoCo v1.3.0 릴리즈 보기
😎 NginX을 도입하여 무중단 배포 환경으로 업데이트 하였습니다.
2023-03-22 MoCo v2.0.0 릴리즈 보기
😎 Native Query -> QueryDsl 마이그레이션 하였습니다.
😎 쿼리 최적화를 위해 ERD 구조를 반정규화 하였습니다.
실서비스가 가능한 웹 애플리케이션 구축을 중점으로 배포와 설계, 기술적고민을 경험해 보는 것을 목표로 시작했습니다.
블록체인 네트워크 연동을 통해 Web3 서비스를 구현해 보면서 Dapp 개발의 전반적인 지식을 쌓으려고 했습니다.
첫 페이지 | 메인 페이지 | 로그인 | 회원가입 |
글작성 페이지 | 게시글 보기 | 출석체크 보상 | 설정 페이지 |
도트맵 페이지 | 땅구매 모달창 | 구매된 땅 표시 |
- 소셜 로그인
- 소셜 로그인 구현을 위해 스프링 시큐리티와, OAuth2 인증방식을 사용했으며, 엑세스 토큰으로 받아오는 유저 정보를 커스텀하여 사용하기 위해 Oauth2UserService 인터페이스를 상속받아 CustomOauth2UserService 클래스를 구현하였습니다.
CustomOauth2UserService
- 소셜 로그인 구현을 위해 스프링 시큐리티와, OAuth2 인증방식을 사용했으며, 엑세스 토큰으로 받아오는 유저 정보를 커스텀하여 사용하기 위해 Oauth2UserService 인터페이스를 상속받아 CustomOauth2UserService 클래스를 구현하였습니다.
- 일반 로그인
- 자체 로그인 방식으로는 회원가입시 입력한 비밀번호를 해시 암호화 알고리즘을 적용하여 나온 해시값을 DB에 저장합니다.
- 로그인시 사용한 해시 알고리즘을 찾아 비밀번호의 정합성을 검증합니다.
UserService
이미지 저장
- 게시글 작성은 NHN에서 개발한 오픈소스로, 마크다운과 위지윅 방식을 지원하는 생산성있는 라이브러리를 이용했습니다.
- 게시글 작성시 이미지 삽입은 base64형식의 단점을 보완한 hooks 옵션을 사용했습니다.
- 이미지의 base64 인코딩의 단점은 해상도에 따라 글자수가 기하급수적으로 올라가기 때문에 DB저장시 문제가 발생합니다.
- 따라서 이미지의 저장된 주소값인 url을 저장하도록 했습니다.
- 이미지 삽입시 hooks 옵션으로 blob 객체를 인터셉터합니다.
- Ajax로 blob 객체를 백엔드 서버로 저장 요청을 보냅니다.
- 백엔드 서버에서 blob 객체를 multipart로 받아 aws s3 버킷에 저장 요청을 보냅니다.
- 저장에 성공시 업로드된 url을 반환합니다.
글작성
- Toast Ui editor로 작성한 마크다운 문법을 html 로 파싱하여 저장하였습니다.
- 게시글 저장시 각 항목에 대한 유효성을 검사합니다. 에러 발생시 작성했던 내용들은 유지하면서 에러 내용또한 반환하도록 했습니다.
- tagify 라이브러리를 이용하여 태그를 작성할수 있습니다. 태그들은 Json 포맷으로 받아오며 ArrayList 자료구조로 파싱하여 한개의 태그당 한개의 컬럼으로 DB에 저장합니다.
글 수정
- 게시글 본문의 내용을 DB에 저장시 마크다운으로 저장해야 할지, Html태그로 변환후 저장해야 할지 고민이 많았습니다. 해당 이슈는 아래 링크에서 확인하실수 있습니다.
- 게시글 수정은 빈번하게 발생하는 작업이 아니기 때문에 html 태그로 저장후 게시글 수정시에 마크다운 문법으로 파싱하도록 구현하였습니다.
- 태그 수정시 삭제된 태그, 추가된 태그를 구분하기 위해 hashSet 자료구조의 차집합을 구할수 있는 removeAll() 메소드를 사용하였습니다.
글 삭제
게시글 읽기
대댓글의 경우 엔티티 구조안에서 셀프조인을 참조하여 계층을 가지도록 구현했습니다.
로그인, 회원가입시 에러가 나는경우 이를 처리하기위해 커스텀 클래스를 구현했으며, 로그인 관련 에러와 회원가입시 에러에 맞게 처리하였습니다. 발생한 에러들은 추적이 가능하도록 Log를 남겨 CloudWatch 모니터링 시스템을 이용하여 실시간으로 확인 가능하도록 처리했습니다.
-
QueryDsl를 사용하여 페이징을 구현하였습니다.
- 런타임 환경에서 발생할 수 있는 쿼리 오류 방지와, SQL 안티패턴인 서브쿼리 사용을 지양하기 위해 기존의 Native Query 를 QueryDsl로 마이그레이션 하였습니다.
- 기존의 Native Query
- QueryDsl
-
ajax를 이용한 무한스크롤
- 편한 스크롤링으로 콘텐츠가 로드되는 방식으로 특히 모바일 환경에서 더 나은 사용자 경험을 주며,콘텐츠의 노출을 쉽게 접할수 있도록 일반적인 페이지네이션을 두고 무한스크롤을 구현했습니다.
- 자바스크립트 무한스크롤
-
스크롤 위치와 데이터 유지
- 무한 스크롤의 단점인 렌더링된 게시글들과 스크롤링 했던 위치로 돌아올수 있도록 세션스토리지를 이용하였습니다.
- 게시글 리스트페이지를 벗어날때 세션스토리지에 스크롤의 위치와 렌더링 정보를 저장후 해당 페이지에 돌아왔을때 세션 스토리지에 저장된 값을 렌더링하며 이전 스크롤의 위치로 이동하도록 구현했습니다.
- 렌더링, 스크롤 위치기억하기
- 도트맵에서 구매된 땅을 탐색해 랜더링을 할수 있도록 자바스크립트로 구현하였습니다.
-
openzeppelin 라이브러리를 이용하여 웹 애플리케이션에서 사용할수 있는 ERC-20 기반 토큰을 만들었습니다.
-
Web3.js 라이브러리를 이용하여 배포한 컨트랙트를 호출하여 토큰을 받을 수 있습니다.
- 도트로 구성된 땅은 토큰으로 구매할수 있습니다. 도트는 지역별로 가격이 다르며 중앙에 위치할수록 비싸집니다.
- 구매 과정은 구매 함수를 호출후 해당 트랜잭션이 상태가 pendding -> success 될때까지 1초마다 감지하도록 구현했습니다.
- 출석체크 보상, 가입시 보상 모달창을 통해 모각코인을 메타마스크에 추가할수 있도록 구현했습니다.
반복적인 프로세스를 줄이고 유지보수의 편리함을 위해 지속적 통합과 지속적 배포 파이프라인을 구축하였습니다.
깃 허브액션이 master 브랜치로 push된 code를 감지하여 생성한 스크립트 설정파일에 따라 jar 파일로 빌드후 도커 이미지화 시킵니다.
도커 이미지화된 도커파일은 도커 이미지 저장소인 도커 허브로 push 됩니다.
push가 완료되면 ec2 인스턴스가 해당 도커 파일을 pull 하게 되며 실행중이었던 스프링부트 도커파일을 정지 -> 컨테이너 삭제 -> 새로 내려받은 도커파일 실행 순으로 작업을 진행합니다.
nginx를 도입하여 무중단 배포 환경을 구현하였습니다.
- 새로운 버전의 애플리케이션이 배포되면 사용하지 않는 포트를 확인하여 docker로 구동시킵니다.
- ex) 8080포트가 사용중이면 8081 / 8081번 포트가 사용중이면 8080으로 구동시킵니다.
- 구동된 앱의 health 를 체크하여 서버의 상태를 확인합니다.
- 정상 배포가 확인되면 nginx의 리버스 프록시 대상을 신규 버전의 앱의 포트로 변경합니다.
- 사용중이던 컨테이너와 이미지를 삭제 하여 서버 교체를 마무리 합니다.
브라우저의 안전한 접속과 , 브라우저 사이의 민감한 정보를 주고받을때를 대비해 aws ACM인증서를 받아 SSL 을 적용하였습니다. 가비아에서 구매한 도메인과 aws Route53을 이용해 도메인을 연결하였습니다.