기능구현 (1) : 외부API데이터 내부DB저장
1. XML 데이터를 Javabean으로 변환하여 쓰는 변환하기 : Jackson API를 사용해서 변환하는법 배우기
2. x,y좌표를 Point라는 MYSQL에서 인식할 수 있는 데이터 객체로 변경: geometry factory 사용법 배우기
3. Point라는 객체를 MYSQL에 전달하기 위해서 필요한 Dependency 추가 : Hibernate Spatial에 대해서 배우기
4. whil문을 통해서 외부 API가 더이상 존재하는 레코드가 없을때까지 반복하여 외부 API의 레코드를 entity로 변환하여 repo에 saveAll() 시행
Trouble
외부API의 데이터 구성이 불완전하여 여러가지 중복되는 레코드가 존재하여 saveAll() 할 시 Duplicate Error가 발생하였음
-> on duplicate update 기능을 사용하기 위해서 custom쿼리를 작성하여 1개씩 업데이트 처리를 진행함 : JPQL학습
@Modifying
@Query(value = "INSERT INTO heritage_entity"
+ " (heritage_Id, heritage_Name, location, heritage_Grade, basic_Description)"
+ " VALUES (:heritageId, :heritageName, :location, :heritageGrade, :basicDescription)"
+ " ON DUPLICATE KEY UPDATE"
+ " heritage_Name = :heritageName, location = :location, heritage_Grade ="
+ " :heritageGrade, basic_Description = :basicDescription", nativeQuery = true)
int insertOrUpdate(String heritageId, String heritageName, Point location,
String heritageGrade, String basicDescription);
기능구현 (2) : 위치기반 내주변 검색
1. x,y coordinate를 client로부터 받아서 이를 point 객체로 변환함
2. point로 변환된 객체를 서비스 층으로 전달하고 이를 repository를 통해 geolocation에 기반한 find 쿼리를 실행함
3. geoSpatialData를 기반으로 조회하는 MySQL native query사용 : MYSQL에서 geolocation을 다루는 방법에 대해서 학습, GeospatialData에서 Btree 유지를 위한 인덱스 학습, JPQL 생성에 대해서 학습
3. 특정 거리에 떨어진 문화재를 찾아서 리스트를 받환받을 것.
* CLEAN ARCHITECTURE 지킬 수 있는 데이터 Conversion의 레이어 고민
기능구현 (3) : 유적 방문처리
1. 유저라는 entity를 생성하여 erd대로 필드를 설정함.
- 고려점 : ManytoMany관계를 만들때, eagerloading, lazyloading설정 그리고 양방향성과 단방향성에 대해서 어떻게 설정할것인지 스터디 및 고민
-> heritage에서 방문자를 굳이 조회할 일은 없을 것같아서 단방향성으로 하고 lazyloading으로 설정하는 것이 좋을듯.
2. Controller을 통해서 entity를 생성하고 저장하는 service, repo를 만듬
3. 해당 entity의 방문리스트를 추가해서 update해주는 service method를 만듬
방문리스트 HashSet을 조회해서 수정해야하기때문에 N+1 문제가 발생할 수 있지만 캐쉬로 DB접근을 최소화함.
-> N+1 문제를 원천적으로 차단하기 위해서 manytomany 방식의 엔티티에서의 관리보다 manytoone repository를 직접관리하여 저장하는것으로 코드수정.
기능구현 (4) : 지도조회
- 사용자는 특정지역의 사각형을 선택하여 그 구역 내의 지도를 요청한다. bounding box의 좌표정확도는 FE에서 잘 보낸다고 생각.
- bounding box를 균일한 사이즈로 나누어서 grid로 나눔.
- 편의를 위해서 위도와 경도를 기준으로 나눈다.
- boundingbox 내에서 존재하는 모든 문화재 리스트를 찾는다.
- boundingbox내에서 존재하는 모든 방문문화재를 찾는다.
- grid 내에 방문문화재가 존재하는지 검색하는 과정을 거친다.
- 존재하는 grid는 별도의 flag를 심어서 표기할 수 있도록 객체를 정의한다(?)
- 지도는 두가지 정보를 담는다. 1. 해당 지역에서 방문한 문화재의 정보 (위치정보 포함) 2. 지역을 grid로 나누어
특정지역의 사각형 (크기는 배율의 문제이니 상관없음)을 선택하면 그 구역 내에 내가 방문한 유적을 모두 보여주는 기능
여러가지 adapter와 service들이 엮여있기때문에 이들을 정리할 orchestration service가 도입될 필요가 있다. orchestration service는 메소드를 계층적으로 쌓아나가서 최종적으로 하나의 메소드로 묶는 역할을 한다.
기능구현 (5) : 경로탐색
- 사용자는 주변 유적탐색을 통해서 유적지 리스트를 반환받는다
- 나의 현위치로부터 유적지를 탐색하는 경로를 찾는다 (Greedy 탐색)
-> 나의 현위치로부터 유적지 간의 경로를 외부 API를 통해서 찾는다. (나중에 다시쓸거니 저장)
-> 나의 현위치에서 유적지 + 유적지관람시간 + 유적지에서 현위치 복귀시간을 계산하여 유저의 요청시간 내에 탐색가능한 루트인지 검증한다
-> 시간당 효용성을 계산하여 가장 효율적인 루트를 선정한다.
-> 위의 행위를 반복한다.
어떤 API를 사용할지 검토
카카오, 네이버, 구글 중에 쓰기 편한것 확인
기능구현(5) Global Exception Handler생성
Global Handler를 만들면서 Exception처리의 함의에 대해서 좀 생각해본다. 일단 시켜서 CustomExcpetion을 만들긴하는데, 실제로 CustomException을 만드는 이유가 무엇인지 모든 케이스에 대해서 Exception을 만들면 어떤 점이 좋은지 좀 고찰해보고 멘토와 토론해본다?
기능구현 (6) : 경로탐색
- 내 주변 위치검색을 통해서 문화재를 탐색한다
- 문화재 리스트의 정보를 API호출을 통해서 시간을 추가한다.
- 동선당 점수를 계산하여 최적의 동선을 greedy하게 찾는다
greedy하지않으면 factorial하게 증가하기때문에 greedy를 도입하였으며 API콜 다수로 multithread도입진행
\
'개발 프로젝트 > 2024 제로베이스 프로젝트' 카테고리의 다른 글
제로베이스 개인프로젝트 진행록6 - 성능개선 리팩터링/캐쉬 (0) | 2024.10.20 |
---|---|
제로베이스 개인프로젝트 진행록5 - 성능개선 리팩터링/멀티스레드 (2) | 2024.10.14 |
제로베이스 연습프로젝트 : 매장 테이블 예약 서비스 (3) 최적화 고려 (0) | 2024.09.22 |
제로베이스 개인프로젝트 진행록3 - 기능고려/readme/성능최적화 초안 구상 (2) | 2024.09.20 |
제로베이스 개인프로젝트 진행록2 - 개발기획/리뷰 (2) (5) | 2024.09.18 |