프로젝트 회고 - 첫 대외 서비스를 마치고
- -
올해 2월, 약 1년 동안 진행한 프로젝트가 마무리 됐다. 프로젝트 중간중간 과정들을 메모해 두었는데 지금의 생각과 같이 정리해 보면 좋을 것 같아서 글을 작성해 본다.
1. 프로젝트 기획
진행하게 될 프로젝트는 병원 업무와 관련 있었다. 초기 기획과 요구조건은 다음과 같았다.
- 관리자 사이트는 권한을 부여받은 병원 직원에게만 서비스된다.
- 관리자 사이트에서는 각 병원들을 관리할 수가 있고 입력된 정보들을 토대로 병원 홈페이지 접속 시 내용이 보여야 한다. 병원 홈페이지는 불특정 다수를 대상으로 서비스되며 메인이 되는 기능은 예약이다.
- ex) 병원 소개 정보, 시술 정보, 이벤트 정보, 예약 정보 등
- 병원 홈페이지는 하나의 도메인에 여러 개의 서브 도메인을 갖고 이것은 하나의 병원 브랜드가 된다.
- ex) 클리닉 브랜드 => a.clinic.co.kr : 클리닉 A점, b.clinic.co.kr : 클리닉 B점
- 인증번호 전송, 카카오 알림톡, 모바일앱 푸시 등 외부 API 연동이 필요하다.
- 관리자 사이트에서는 실시간으로 어떤 직원이 예약을 확인하는지 알 수 있어야 한다.
2. 개발 기획
요구조건을 토대로 프로젝트는 3개로 나누었다. 각각 별도의 서비스로 관리하고 서로 다른 서버에 위치시켰다.
- 병원 홈페이지 ⇒ 불특정 다수를 대상으로 한 서비스
- 관리자 사이트 ⇒ 병원 직원을 대상으로 한 서비스
- API ⇒ 병원 홈페이지와 관리자 사이트에서 공통으로 사용하게 될 API 서비스
이제 개발과 직접 관련된 여러 가지 구성들이 남았다.
- 개발 언어와 프레임워크 선택
- 서버 구성과 인프라는 구축
- 빌드&배포
- 서비스 후 모니터링툴 선택(이건 좀 나중에)
특히 서버 구성과 인프라 구축은 나에게는 꽤나 큰 도전이 될 것 같았다.
3. 기술스택 선정과 서버 구성
개발 언어와 프레임워크는 개발 팀장이 없는 상황 속에서 답은 정해져 있었다.(나에게 실무 경험은 자바&스프링이었기에..)
백엔드는 Java, Spring Boot를 사용하기로 했고 프런트엔드는 jsp, javascript, jstl을 사용하기로 했다. 리액트 경험이 있었다면 리액트로 구성을 하고 싶었지만 프런트엔드는 신입 개발자분들이었고 우리에게 시간이 충분하지 않았다. 그동안의 실무 경험과 지식을 토대로 프로젝트를 진행할 수 있어야 했다.
Java, Spring 환경에서 가장 자신 있는 서버 구성은 Apache - Tomcat 구성이었다. Apache를 Tomcat과 연결시켜 리소스(이미지나 영상) 파일은 Apache단에서 처리하고 이외에는 Tomcat에서 처리할 수 있게 하면 될 것 같았다. Tomcat은 최소 2대를 두어 로드밸런싱을 할 생각이었다. 그리고 DB 연결은 WAS 단에서 JNDI를 통해 구축하는 편이 좋아 보였다. 왜냐하면 DB 커넥션 풀도 효율적으로 사용할 수 있고, DB 설정정보도 파악이 쉽기 때문이었다.
돌이켜보면 전 직장에서의 서버 구성 경험이 많은 도움이 되었던 것 같다.
그리고 프로젝트별로 어떤 기술이 필요할까 고민했다.
프로젝트 공통
- 대부분 회사에서 JDK 1.8 버전을 최소로 하고 있기 때문에 우리도 JDK 1.8을 사용하는 것이 좋겠다고 판단했다.
- Spring Boot 버전은 무난한 2.6 이상으로 잡았다.
- 복잡한 쿼리는 MyBatis를 이용하기로 했고, 단순 Select문은 JPA를 이용하기로 했다. 온전히 JPA를 사용하기에는 나의 기술이 부족했다. DB 설계가 잘되어있는 상태에서 JPA는 큰 빛을 발한다는 글을 본 적이 있었는데 DB 설계도 맡아야 했기 때문에 자신이 없었다. (화면에 따라 테이블을 설계하게 되다 보니..)
- 프런트엔드에서는 javascript ES6를 표준으로 하되 필요한 경우 jquery를 이용하기로 했다. 다만 css 표준은 지식이 없기 때문에 이 부분은 프런트 개발자분들께 온전히 맡겼다...
- 코드 컨벤션 같은 경우 class, name, id 정도만 카멜케이스와 스네이크케이스로 네이밍 규칙을 정했다.
병원 홈페이지
- 병원 코드를 키값(PK)으로 관리하고 접속 도메인을 통해 병원 구분을 했다.
- 고정된 메뉴를 사용하고 메뉴가 적기 때문에 페이지 전환은 동기식으로 이동시마다 서버에서 Model을 통해 필요한 데이터를 내려주고 화면단에서는 jstl을 이용해 데이터를 토대로 화면을 그리도록 계획했다.
- Tiles를 도입해 header, footer는 공통으로 관리하고 body 부분에 페이지가 로드되도록 하기로 했다.
- 로그인 기능이 들어가고 개인 정보가 수집되는 서비스기 때문에 Spring Security를 도입해 보안 관련 설정을 하기로 했다.
- 수집하는 정보 중 패스워드는 단방향, 전화번호는 양방향 암호화를 통해 DB에 관리하기로 했다.
- 단방향 알고리즘은 SHA256 + SALT값을 이용해 암호화 수준을 높였다.
- 양방향 알고리즘은 AES256를 이용하고 복호화 키는 따로 관리했다.
- JNDI를 적용하기 위해서 Spring Boot의 Embedded Tomcat 방식이 아닌 외장 톰캣을 이용했다. 그리고 war파일로 배포했다.
- Tomcat을 두 대 올려놓고 사용하게 된다면 세션 클러스터링이 필수로 들어가야 하는데 Tomcat Session Clustering을 이용하는 것이 좋아 보였다. 이후에는 실제 서비스를 하게 되면서 Redis를 도입해 세션 클러스터링을 적용했다.
관리자 사이트
- 관리자 사이트도 여러 가지로 보안 관련 설정이 편리한 Spring Security를 도입했다.
- 메뉴를 DB로 관리해야 될 것 같았다. 고정되지 않은 다수의 메뉴가 존재하기 때문에 페이지 전환 시 비동기로 호출된 페이지를 body 부분에 넣는 방식이 좋을 것 같았다.
- header, left, footer를 Tiles로 관리하고 body 부분만 페이지가 로드되도록 했다.
- 패스워드와 전화번호는 병원 홈페이지와 동일하게 관리하기로 했다.
- Tomcat 관련 설정도 병원 홈페이지와 동일하게 하기로 했다.
API
- 초기 기획에서 필요해 보인 API는 문자 서비스, 카카오 알림톡, 실시간 예약 확인 기능이었다. 문자 서비스, 카카오 알림톡 서비스는 병원 홈페이지와 관리자 사이트 두 곳에서 같이 사용될 것으로 보였다. 때문에 외부 API를 사용하게 된다면 API 쪽에 기능을 몰아넣을 계획이었다.
- Embedded Tomcat 방식을 이용하고 jar로 배포하면 될 것 같았다. 화면이 따로 존재하지 않지만 혹시 생긴다면 Thymeleaf를 이용하기로 했다.
- @RestController를 이용하고 데이터 포맷은 JSON으로 설정했다.
- 클라이언트에 리턴하는 ResponseEntity는 공통으로 정의하고 enum 타입으로 상태 코드를 약속하고 공유하기로 했다.
- 실시간 기능을 개발한다면 양방향이 필요하지 않는 한 SSE를 계획했다.
- Swagger를 도입해 제공되는 API의 테스트를 가능하게 했다.
4. 소스 관리와 빌드&배포
개발 인원은 백엔드(1), 프런트엔드(2) 총 3명이었다. 현 상황에서는 git보다 svn이 더 빠르게 개발이 가능할 것으로 판단했다.
서버단 소스를 혼자 만들고, 화면 퍼블리싱과 스크립트는 프런트가 각 화면을 나눠서 하기 때문에 피쳐별로 브랜치를 나누어 개발할 필요가 없다고 보았기 때문이다. 하지만 서비스가 어느 정도 완성되고 인원이 더 생긴다면 git으로 전환해야 한다고 생각했다.
빌드 도구로는 Maven을 선택했고 배포는 Jenkins를 이용하기로 했다. Jenkins를 오랫동안 사용해왔기도 하고 혼자서 구축한 경험이 있기 때문이었다.
5. 인프라 구축
프로젝트, 서버 구성은 어느 정도 그림이 나왔고 이제 인프라를 회사 내부에서 할지 클라우드를 이용할지 정해야 했는데 회사에서는 AWS 사용을 권했다.
사실 실무에서 처음 사용해 보기 때문에 걱정이 앞섰다. 그래도 마무리만 잘된다면 좋은 경험이 될 것 같았다. 다행히도 구글에서 AWS 관련 자료를 많이 얻을 수 있었다.
EC2 서버를 3대로 구성하고, RDS - MySQL을 이용하기로 했다. 그리고 도메인은 가비아에서 여러 개를 사두었기 때문에 AWS의 Route 53을 이용해 네임 서버를 연결하고 Certificate Manager를 SSL 인증서를 등록해 연결시켜 주었다.
6. 개발과 서비스 오픈
올해 1월 오픈을 목표로 프로젝트가 시작됐다. 중간에 사정이 생겨 2월 초로 오픈이 미뤄지는 일이 있었지만 우여곡절 끝에 잘 마무리되었다.
기획이 새로 추가되기도 했고, 개발이 완료된 후 엎어진 적도 있었다. 또 프리랜서를 통해 모바일 애플리케이션도 개발이 됐는데 Flutter를 간접적으로 배울 수 있어서 좋았다. 웹뷰라는 걸 처음 알게 되기도 했고, 스크립트 채널을 이용해 모바일과 웹 구분을 하는 방법도 배웠다.
오픈한 서비스는 큰 이슈없이 잘 흘러가고 있지만 개인적인 아쉬운 점은 남아 있다. DB 설계 같은 부분을 조금 더 경력이 있는 전문적인 사람이 했다면 어땠을까 같은.
현재 서비스 유저수는 7,000명을 넘겼고 2개의 신규 병원이 가입됐다. 오픈 전에는 팀원들과 이 서비스를 잘 마무리할 수 있을까 걱정했는데 서비스되고 있는 모습이 신기할 뿐이다. 운영 단계에 들어서면서 모니터링이 필요하다고 보았고 Scouter를 도입했다.
7. 마무리
개발을 하면서 처음 보는 버그들이 참 많았는데 특히 서버 쪽에서 버그들을 마주할 때는 혼자 고민하고 해결하는 시간이 참 힘들었다. 또 모바일앱 유지보수를 할 때도.. 몇 가지 기억나는 것을 적어보면 다음과 같다.
- 모바일앱 안드로이드의 document.referer 이슈 (모바일앱 유지보수를 할 때 생긴 이슈)
- 배포 시 자동 로그인이 끊기는 이슈 ⇒ 병원 홈페이지는 웹뷰를 이용해 모바일앱을 개발했다.(자동 로그인 기능 제공, 모바일앱 내부의 세션 스토리지를 이용) 두 대의 was를 운영했고, 톰캣 세션 클러스터링을 적용했는데, 배포를 할 때 자동 로그인 상태가 끊어지는 현상이었다. 프로젝트 배포는 1번, 2번 서버를 한 대씩 내렸다 올리는 형태로 구성했는데 1번 서버를 먼저 배포할 때, 아파치 로드밸런싱을 통해 1번 서버에 붙어있는 사용자의 세션이 끊어지던 것.. 이후 Redis를 세션 스토리지로 변경해 해결할 수 있었다.
- 예약 시간을 조회할 때 특정 순간에 데이터를 조회할 수 없는 이슈 ⇒ JNDI의 커넥션 풀 설정문제
- 운영단계에 들어서며 프리티어 인스턴스를 업그레이드하자 원격 접속이 안되던 이슈 ⇒ 인스턴스 변경 시 퍼블릭 아이피가 바뀜. 이후에 탄력적 IP를 적용하면 되는 것을 알았다.
- 잘되던 배포가 안 돼서 확인해 보니 프리티어 서버의 용량(war파일을 백업해 두어 생긴..)이 가득 차서 안되던 이슈
- yum update를 하면서 배포 서버의 JDK 버전이 업데이트되며 젠킨스 서버가 켜지지 않던 이슈
- 배포 서버 인바운드 규칙으로 회사의 외부 아이피를 등록해서 사용 중이었는데 공유기가 꺼지면서 아이피가 변경돼 배포 서버 접속이 안되던 이슈
다행인 것은 세상에 정보가 정말 많다는 것이다. 구글에는 없는게 없는 것 같다. 스택오버플로우나 기술 블로그들이 없었다면 이 프로젝트가 잘 마무리될 수 있었을까..? 특히나 요즘은 ChatGPT, Bing의 등장으로 버그 잡는 일이 많이 수월해진 것 같다.
이렇게 나의 첫 대외 서비스 프로젝트가 종료됐다.
프로젝트 경험은 몇 번 있었지만 이번 프로젝트는 나에게 큰 의미가 있었다. 외부로 서비스되는 것이기도 했고 A~Z까지 결정을 직접 해야 했기 때문이다. 사실 지금의 연차에 개발 팀장 역할을 해야 한다는 게 부담이 컸다. 내가 잘할 수 있을까라는 생각이 컸고 그럴 때마다 선배들을 만나 용기를 구했던 것 같다.
이번 프로젝트를 계기로 조금은 더 나은 개발자가 되지 않았나 생각한다.
올해는 영어 공부와 알고리즘 공부에 힘써봐야지.
'일상' 카테고리의 다른 글
광명뉴타운 아파트 실거래가 조회앱 출시, 광명 입주를 바라보며 (1) | 2024.08.21 |
---|---|
GDG Devfest Songdo 2023 후기 (0) | 2023.12.13 |
클린코드(Clean code) 리뷰 (0) | 2022.01.17 |
중기청 100% 전세대출 후기 (9) | 2021.05.14 |
[MG]듀얼 건담 어설트 슈라우드 (1) | 2020.07.19 |
소중한 공감 감사합니다.