배경(Problem)
친구들과 여행을 다녀오거나, 혼자 여행을 다녀온 뒤 사진을 클라우드 서비스(구글 드라이브, 네이버 mybox 등)를 통해 공유하고는 합니다.
하지만 이렇게 공유된 사진은 날짜 별로 정리되어 있어서 어디에 다녀왔는지 한 눈에 확인하기 힘들다는 문제점을 가지고 있습니다.
이러한 문제점을 해결하고자 사용자가 여행 사진을 그룹 별로 공유하고 각 사진을 지도에 표시할 수 있는 웹 어플리케이션을 만들고자 하였습니다. 이 서비스를 통해 사용자는 여행 그룹을 생성하고, 그룹 멤버들과 함께 사진을 업로드하여 특정 장소에서의 추억을 공유할 수 있습니다.
서비스 소개(Solution)
서비스 사이트: https://goormfinal.vercel.app/
•
회원 가입 및 로그인
◦
◦
로그인의 경우 카카오 API를 활용해 카카오 소셜 로그인도 가능합니다.
◦
사용자는 자신의 비밀번호를 변경할 수 있고, 회원을 탈퇴할 수 있습니다.
•
여행 지도
◦
로그인 후 사용자는 가장 최근에 생성한 위치 핀을 기반으로 하여 여행 지도를 볼 수 있습니다.
◦
사용자는 마우스 우클릭을 통해 지도 위에 새로운 위치 핀을 생성할 수 있습니다.
◦
사용자는 위치 핀을 클릭하여 해당 장소에서 찍은 사진들을 추가하거나 삭제할 수 있습니다.
•
그룹 (추가 예정)
◦
사용자는 지도 내 왼쪽 배너를 통해 그룹 별로 위치 핀을 볼 수 있습니다.
◦
사용자는 초대할 상대방의 이메일을 입력하여 자신이 생성한 그룹으로 초대할 수 있습니다.
아키텍처 및 핵심 기능
•
데이터 흐름
1.
사용자 요청: 웹 클라이언트에서 REST API 호출.
2.
백엔드 처리: Spring Boot 백엔드에서 요청 처리 및 데이터베이스 쿼리.
3.
응답 반환: 클라이언트로 JSON 데이터 또는 파일 전달.
•
핵심 기능
◦
멤버(로그인 및 회원가입) 기능
▪
회원가입
▪
로그인
▪
카카오 API를 활용한 카카오 소셜 로그인
▪
회원 정보 수정
▪
회원 탈퇴
▪
JWT(JSON Web Token)를 활용해 사용자 인증 및 권한 부여
◦
그룹 기능
▪
그룹 생성/조회/수정/삭제
▪
그룹 초대 URL 생성해 멤버 추가
◦
위치 핀 기능
▪
위치 핀 생성/조회/삭제
▪
공개 범위 설정 및 수정
◦
사진 기능
▪
사진 저장/조회/삭제
▪
AWS S3 pre-signed URL을 활용한 사진 업로드 및 조회
활용 라이브러리 및 개발 환경
•
프론트엔드 기술 스택(최재혁)
◦
React, Tailwindcss, Next.js, Axios, TypeScript, React Query
•
백엔드 기술 스택 (강동완, 김예은)
◦
언어 및 프레임워크: Java, Spring Boot
◦
데이터베이스: Spring Data JPA, H2 database, AWS RDS MySQL
◦
외부 서비스
▪
JWT: 로그인 및 권한 기반 접근 제어를 통해 안전한 사용자 관리
▪
AWS S3: pre-signed URL을 통해 클라이언트가 서버에 파일을 전달하는 것이 아닌 클라이언트가 직접 AWS S3에 업로드 및 조회하도록 함으로써 서버 과부화 최소화 및 대용량 파일 효율적 관리
▪
AWS EC2: 백엔드 프로젝트 서버 배포
트러블 슈팅
•
AWS EC2 배포: EC2 서버로 배포 자체가 안됐던 문제
◦
로컬(IntelliJ)에서 Gradle의 bootjar 명령어를 실행하여 배포용 jar 파일을 만들고 이를 EC2 서버에 보내서 실행해도 안됐음
◦
application.yml 파일에 있는 민감한 정보들을 환경변수로 사용 중이었고, 이를 실제 값들로 바꿔서 배포해보니 서버가 잘 띄워짐을 확인함
◦
[ 기존 ] bash.profile 파일에 환경변수 설정
[ 해결 ] /etc/environment 파일에 환경변수 설정
•
Spring Security (로그인 JWT 토큰): CORS 설정 및 서버에서는 JWT 토큰을 발행하지만, 프론트에서 이를 잡지 못했던 문제
◦
스프링 시큐리티에 대한 기초가 적어 에러의 원인을 찾기 어려웠음.
◦
에러가 한 번에 다 터지는 게 아니고 하나를 해결하면 그 다음 다른 에러가 뜨는 식으로 줄줄이 이어졌음.
◦
이 문제를 해결하기 위해 코드 아래에 인포용 로그를 하나씩 두고 걸릴 때 마다 하나씩 해결함.
•
카카오 로그인 API 사용 문제: 등록된 팀원만 가입되는 문제
◦
카카오 API에서 정보를 가져오기 위해 비즈앱으로 전환, 사업자번호등록을 건너뛰기 위해 테스트용 REST API 키를 사용해서 로그인
◦
테스트용은 등록된 팀원만 가입할 수 있었음.
◦
[ 해결 ] 이메일, 이름 정도의 정보를 가져오려면 테스트용을 사용하지 않아도 됐고, 일반 비즈앱으로 연결해서 정보를 가져올 수 있었음.
•
S3 Presigned URL: S3 Presigned URL을 사용했는데, 업로드 및 조회가 되지 않았던 문제
◦
PUT과 GET 메서드용 Presigned URL을 발급할 때 Content-Type 헤더를 안받아도 되게 코드 수정했지만 실패함.
◦
[ 해결 ] S3 버킷 설정에서 모든 퍼블릭 액세스를 허용, 버킷 정책에 GetObject, PutObject 액션을 S3용 IAM 사용자에게 열어두도록 하는 정책 생성
•
DB 생성/수정 시간: AWS RDS MySQL에 자동으로 들어가는 생성/수정 시간이 UTC로 표기되었던 문제
◦
@EnableJpaAuditing, @EntityListeners 어노테이션과 TimeZone의 기본값을 변경하는 메서드를 구현했으나 KST 기준으로 저장 실패
◦
[ 해결 ] 환경변수로 설정한 MySQL URL에 파라미터로 serverTimezone=UTC를 발견했고, 이를 serverTimezone=Asia/Seoul로 변경함
•
카카오 맵 API 사용 문제: 카카오맵을 웹페이지로 띄우려고 했으나 최초 실행이 안되는 문제
◦
처음에는 React를 사용해 KakaoMap API를 활용하려 했으나, JavaScript로 직접 스크립트를 등록하는 방식이 React와 호환되지 않아 실패
◦
스크립트를 직접 작성했지만 여전히 React와의 충돌 문제가 발생
◦
다양한 React 기능을 활용해 문제를 해결하려 했지만, 화면에 지도가 바로 렌더링되지 않는 오류가 지속됨.
◦
[ 해결 ] Next.js의 Script 컴포넌트를 활용하여 Root Layout의 <head>에 스크립트를 미리 로드하는 방식으로 수정함.
•
프론트-백엔드 API 소통 이슈: API Response Body가 객체인지 혹은 리스트인지 확인할 수 없었던 문제
◦
API 응답으로 Json 데이터를 받았으나 이를 풀어쓰는 과정에서 API 명세서가 제대로 작성되지 않아 어떤 식으로 해당 API를 쓰면 되는지 헷갈리는 상황
◦
[ 해결 ] 여러개의 객체들을 포함한 리스트를 반환하는 경우 대괄호 [] 를 이용해 묶어주고 한 눈에 알아보기 쉽도록 API 명세서의 Response Body 부분에 공백을 추가함
◦
타사이트 API 명세서를 참고하여 이후 수정이 필요
•
이후 추가 및 개선할 부분들은 다음과 같습니다.
◦
카카오 로그인 API
◦
API 명세서 재작성
◦
깃허브 액션에 따른 AWS 배포 자동화
◦
그룹 생성, 삭제, 조회
◦
그룹 관리 기능 (그룹별 인원 관리, 초대 URL 확인)
◦
그룹별 위치 마커
◦
프로필 사진 설정
◦
알림 기능 (그룹 내 인원 사진 게시, 그룹 초대 받을 시)
◦
캘린더에 폴더명 표시 기능
◦
사진 찍은 위치 기반으로 모아주기 (자동 폴더 생성)
팀 소개
•
강동완 | 백엔드, 팀장 | ghd04001@gmail.com
◦
위치 핀 기능, 사진 기능 구현
◦
데이터베이스 구축 및 백엔드 프로젝트 서버 배포
◦
사용 기술 스택: Java, Spring Boot, Spring Data JPA, H2 database, AWS RDS MySQL, AWS S3, AWS EC2
◦
프로젝트 리뷰
스프링 강의를 통해 배운 것들을 직접 사용해보면서 내가 들었던 내용이 온전히 내 것이 되지 않았음을 느낄 수 있었습니다. 또한 강의로 들었던 것들 외에도 더 많은 것들을 습득해야 되겠다는 생각도 들었습니다. 특히 스프링 시큐리티, DB, AWS, 테스트 코드와 API 문서 작성법 등은 좀 더 확실하게 공부해야겠습니다.
이번에 발생한 문제점들과 이를 해결하고자 참고하고 시도했던 방법들에서 많은 것들을 배울 수 있었기 때문에 이를 잘 정리해둬야겠다는 생각도 들었습니다.
•
김예은 | 백엔드 | dadaa-@naver.com
◦
멤버(로그인 및 회원가입) 기능, 그룹 기능 구현
◦
사용 기술 스택: Java, Spring Boot, Spring Data JPA, H2 database, JWT, AWS RDS MySQL
◦
프로젝트 리뷰
이번 프로젝트를 통해 정확한 동작 원리와 기초 지식의 중요성을 절실히 느꼈습니다. 원하는 대로 동작하지 않는 경우가 많아 답답했는데, 이러한 문제들은 정확한 이해가 있다면 쉽게 해결될 문제인 경우가 많았습니다. 물론 문제를 해결해 나가는 과정에서 많은 것을 배울 수 있었지만, 그만큼 시간이 많이 소모되었습니다.
실제로 직접 해보며 학습하는 것이 중요하다는 점도 느꼈고, 정확히 알고 있어야 팀원들과 원활하게 소통할 수 있다는 사실을 깨닫게 되었습니다.
•
최재혁 | 프론트엔드 | chl7780@naver.com
◦
Photo Map의 기본적인 틀과 사용자 인터페이스(UI) 설계 및 구현
◦
REST API를 호출해 데이터를 렌더링
◦
사용 기술 스택: React, Tailwindcss, Next.js, Axios, TypeScript, React Query
◦
프로젝트 리뷰
이번 프로젝트를 통해 소통의 중요성을 깊이 깨달았습니다. 정확한 용어와 명확한 표현을 사용해 의견을 전달하고, 필요한 점을 확실히 언급해야 효과적인 소통이 이루어진다는 것을 배웠습니다. 그리고 코드에 대한 이해를 더욱 깊이 해야 한다는 필요성을 느꼈습니다. 코드의 동작 원리와 구현 방식을 명확히 설명할 수 있어야 팀원들과의 소통이 한층 원활해질 것이라고 생각합니다. 앞으로 기술적 역량을 강화해 보다 효율적인 협업을 목표로 노력할 것입니다.