티스토리 뷰

Project/종합설계프로젝트

Street Review

JJIINDOL 2025. 1. 10. 18:40

1. 프로젝트 소개

'Street Review' 서비스는 지역 주민들만 알고 있는 숨은 장소나 골목 정보를 공유함으로써, 해당 지역의 매력을 알리고 지역 사회의 활성화를 돕기 위해 기획되었습니다. 사용자들은 GPS를 기반으로 지역에 위치한 정보를 확인하고, 사진을 첨부하거나 댓글을 남기며 소통할 수 있습니다

 

담당 업무  백엔드 개발, 서버 관리
참여인원 / 기여도  3명 / 40%
개발환경 Spring Boot, Spring Security, Spring Data JPA, MySQL, MongoDB, Docker, AWS Code Deploy, Github Actions, Jira
담당 기능  위치 기반 정보 처리, 사용자 콘텐츠 관리, 관리자 시스템 구축, 신고 기능

 

 

2. 주요 성과

✔️ 구글맵 API를 활용한 위치 기반 서비스

구글맵 API를 활용하여 사용자 위치를 기반으로 반경 5km 이내의 지역 정보를 제공하는 서비스를 구현하였습니다. 사용자가 자신의 GPS 위치를 설정해야 게시글을 작성할 수 있도록 설계하여, 지역에 한정된 신뢰성 높은 정보를 공유하도록 유도하였습니다. 이를 통해 지역 정보를 중심으로 하는 사용자 경험을 향상시켰습니다.

 

 

 

✔️ Agile 방법론 도입

Agile 방법론을 도입하여 일정 지연과 요구사항 변경 문제를 해결했습니다. 데일리 스크럼과 스프린트를 통해 작업을 체계적으로 관리하고, Jira의 Planning Poker 기능을 활용해 기능 우선순위를 명확히 정리하여 정해진 일정 내에 주요 기능을 안정적으로 구현할 수 있었습니다.

 

 

 

3. 트러블슈팅 - 1

✔️ 문제점

GPS 좌표를 활용한 반경 검색 쿼리를 관계형 데이터베이스인 MySQL로 작성하는 과정에서 성능 저하 문제가 발생했습니다. 복잡한 공간 연산과 대량의 데이터 처리로 인해 응답 시간이 길어지고, 특히 공간 인덱스를 활용한 경우에도 성능이 기대에 미치지 못했습니다.

 

✔️ 상황 분석

MySQL의 공간 인덱스는 대규모 데이터셋에서 GPS 좌표 기반의 거리 계산 쿼리를 처리할 때 성능 저하를 유발하는 한계를 가지고 있었습니다. 특히, 복잡한 거리 계산 쿼리가 실행될수록 시스템 응답 속도가 느려졌으며, 이는 사용자 경험을 저하시키는 문제로 이어졌습니다. RDBMS는 정형 데이터 처리에 강점을 가지지만, 공간 연산과 같은 비정형 데이터를 처리하는 데 적합하지 않다는 것을 알게 되었습니다.

 

✔️ 해결

MongoDB를 도입해 GPS 좌표 데이터를 처리하도록 설계했으며, GeoJSON 데이터 타입과 2dsphere 인덱스를 활용해 반경 검색과 거리 계산의 성능을 최적화했습니다. 또한, MySQL은 관계형 데이터와 비즈니스 로직 처리를 담당하고, MongoDB는 공간 데이터의 저장 및 검색을 전담하는 하이브리드 데이터베이스 구조를 설계해 역할을 분리했습니다. 이를 통해 검색 속도가 기존 MySQL 대비 30% 이상 개선되었습니다.

 

 

4. 트러블슈팅 - 2

✔️ 문제점

좋아요 기능을 구현할 때, 사용자가 특정 게시글에 좋아요 버튼을 여러 번 누를 수 있었습니다. 처음에는 좋아요 개수(count)만 증가시키는 방식으로 구현했지만, 한 사용자가 동일 게시글에 여러 번 좋아요를 누르는 문제가 생겼습니다. 이는 기획 의도와 달리 한 게시물에 한 번만 좋아요를 누를 수 있어야 하는 요구사항을 충족하지 못한 상황이었습니다.

 

 

✔️ 상황 분석

기존 설계는 좋아요를 누를 때 게시글의 좋아요 개수만 관리했을 뿐, 누가 좋아요를 눌렀는지는 기록하지 않는 구조였습니다. 이로 인해 동일한 사용자가 중복해서 좋아요를 누르더라도 이를 제한할 방법이 없었습니다. 이러한 설계로 인해 데이터의 정확성이 떨어질 가능성이 높아졌으며, 사용자별로 좋아요 기록을 관리할 필요성을 느꼈습니다.

 

 

✔️ 해결

  • 테이블 설계
    사용자가 게시글에 좋아요를 누른 여부를 기록하기 위해 review_like라는 별도 테이블을 설계했습니다. 이 테이블은 member_idreview_id를 복합 기본 키로 설정하여 중복 데이터를 방지하였습니다. 또한, liked라는 Boolean 필드를 추가하여 사용자가 좋아요를 눌렀는지 여부를 명확히 판단할 수 있도록 하였습니다.

  • 상태 관리
    기존에는 게시글의 좋아요 수를 단순히 count 필드로 관리했지만, 이를 Boolean 값 기반으로 변경했습니다. 사용자가 좋아요 버튼을 누를 때마다 review_like 테이블의 liked 값을 토글(참/거짓 변경)하도록 구현했으며, 이에 따라 게시글의 좋아요 수를 실시간으로 동기화하도록 수정했습니다.

 

 

5. 트러블슈팅 - 3

✔️ 문제점

리뷰 서비스에서 특정 (x, y) 좌표에 등록된 리뷰 개수를 조회해야 하는 기능이 필요했습니다. 처음에는 countByXAndY() 같은 JPA 기본 제공 메서드를 활용하려 했으나, 이 방식은 개별 좌표에 대한 개수만 조회할 수 있었습니다. 그러나 여러 개의 좌표별 리뷰 개수를 한 번에 조회해야 하는 기능이 필요해 JPA 기본 메서드만으로는 해결할 수 없었습니다.

 

 

✔️ 상황 분석

기존 countByXAndY(x, y) 방식은 특정 좌표에서 개수를 조회하는 데에는 문제가 없었지만, 여러 좌표별 리뷰 개수를 한 번에 가져오기엔 제한이 있었습니다. GROUP BY를 적용할 수 없기 때문에, 전체 좌표별 리뷰 개수를 한 번에 조회하는 방법이 필요했습니다. 이를 해결하기 위해 JPA 기본 메서드 대신 JPQL을 활용한 SQL 최적화 전략을 적용했습니다.

 

 

✔️ 해결

JPA 기본 메서드로는 GROUP BY를 활용한 좌표별 리뷰 개수 조회가 어려웠기 때문에, JPQL을 사용하여 쿼리를 직접 작성했습니다. 기존 방식에서는 특정 (x, y) 좌표의 개수만 조회할 수 있었지만, JPQL을 활용하여 GROUP BY를 적용함으로써 여러 좌표의 리뷰 개수를 한 번에 조회할 수 있도록 개선했습니다. 또한, COALESCE(COUNT(r), 0)를 사용하여 데이터가 없는 경우에도 NULL이 아닌 0을 반환하도록 처리하여 안정성을 높였습니다. 이를 통해 불필요한 데이터 조회를 방지하고 필요한 데이터만 효율적으로 가져올 수 있도록 쿼리를 최적화했습니다.

 

public interface ReviewRepository extends JpaRepository<Review, Long> {

    @Query("SELECT COALESCE(COUNT(r), 0) FROM Review r WHERE r.x = :xValue AND r.y = :yValue GROUP BY r.x, r.y")
    Optional<Integer> groupAndCountByXAndY(@Param("xValue") Double xValue, @Param("yValue") Double yValue);
    
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함