์ฑ ์์์ ๋ฉ์ธ ํ๋ฉด, ํ์ฌ ์ง๋์ ์ต๋ ์/๊ฒฝ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ธ.
- ์๋ต ๋ฐ๋
- ์ปจํธ๋กค๋ฌ
- ํ๋ก ํธ์์ ์ง๋ API๋ฅผ ์ฐ๋ํ๊ณ , ํด๋น ์ง๋ ํ๋ฉด์ ๊ธฐ์ค์ผ๋ก ์ต๋ ์/๊ฒฝ๋๋ฅผ ๊ฐ์ด ์์ฒญํ๋ค.
- ์๋น์ค
public List<StoreListXY> getStoreListByAddr(double maxX, double maxY, double minX, double minY) throws BaseException { //{minX, maxX, minY, maxY} double[] aroundXY = new double[]{minX, maxX, minY, maxY}; // ์ฃผ๋ณ ๋ฐ๊ฒฝ ๋ด ํ์ฌ ์ขํ๋ก ๊ฐ๊ฒ ์กฐํ try{ List<StoreListXY> storeListXY = appStoreDao.getStoreListByAddr(aroundXY); return storeListXY; }catch (Exception e) { throw new BaseException(DATABASE_ERROR); } }
- Dao
// ํ๋งค์๊ฐ ๊ฐ๊ฒ ๋ฑ๋ก์ ์๋ ํ ๋น ๋์๋ ๊ฐ๊ฒ์ฃผ์์ ์์น(๊ฒฝ/์๋) ์ขํ๋ฅผ ๊ธฐ์ค์ผ๋ก ์กฐํํ๋ค. // ๊ฐ๊ฒ์ ์นดํ ๊ณ ๋ฆฌ๋ ๊ฐ์ด ๊ฐ์ ธ์์ ์์ด์ฝ์ ๋ชจ์์ ๊ฒฐ์ ์ง์ด์ค. public List<StoreListXY> getStoreListByAddr(double[] aroundXY) { String query = "SELECT\n" + " storeIdx,\n" + " S.categoryIdx,\n" + " store_name,\n" + " store_address,\n" + " x,y\n" + "FROM Stores S\n" + "LEFT JOIN StroeCategories SC on S.categoryIdx = SC.categoryIdx\n" + "WHERE x BETWEEN ? AND ?\n" + "AND y BETWEEN ? AND ?"; //aroundXY = {minX, maxX, minY, maxY} Object[] params = new Object[]{aroundXY[0],aroundXY[1],aroundXY[2],aroundXY[3]}; return this.jdbcTemplate.query(query, (rs, rowNum) -> new StoreListXY( rs.getInt("storeIdx"), rs.getInt("categoryIdx"), rs.getString("store_name"), rs.getString("store_address"), rs.getDouble("x"), rs.getDouble("y") ), params); }
- ์๋ต ๋ฐ๋
- ์ปจํธ๋กค๋ฌ
- ๊ฐ๊ฒ ์์ด์ฝ ๋ชฉ๋ก์ ์๋ต์ผ๋ก ๋ณด๋ด์ค๋ ๋ฃ์ด๋จ๋ค storeIdx๋ฅผ ๊ฐ์ง๊ณ ์ ํํ ๊ฐ๊ฒ์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ํ์ธ
- ์๋น์ค
- ์๋๋ ํด๋น๊ฐ๊ฒ + 2๊ฐ ๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๋ คํ์ง๋ง, ํ๋ก ํธ์์ ํ๋๋ง ํ์๊ณ ํด์ ํ๋๋ง ๋ง๋ค๊ธฐ๋ก ํจ (๋๋จธ์ง 2๊ฐ ๋ ๋ฃ๋ ๊ณผ์ ์ ์ง์)
public List<StorePreviewRes> getStorePreview(int customerIdx, int storeIdx, Double longitude, Double latitude) throws BaseException{ // 2. ์ ํํ ๊ฐ๊ฒ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ๋ณด ์ผ๋จ ๊ฐ์ ธ์ค๊ธฐ StorePreviewDetails storePreview; try{ storePreview = appStoreDao.getStorePreview(storeIdx); }catch (Exception e) { throw new BaseException(DATABASE_ERROR); } // ์ ํํ ๊ฐ๊ฒ ๊น์ง ํฌํจํ๊ธฐ๊ธฐ aroundStoreList.add(0, storePreview); // 4. ๋ฐํํ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ๋ณด ๋ง๋ค๊ธฐ List<StorePreviewRes> storePreviewRes = new ArrayList<>(); for(StorePreviewDetails prevDetail : aroundStoreList){ // ๊ฐ๊ฒ ์ฌ์ง URL if(prevDetail.getStoreLogoUrl() != null && prevDetail.getStoreLogoUrl().length() != 0){ prevDetail.setStoreLogoUrl(""+s3Client.getUrl(bucketName, prevDetail.getStoreLogoUrl())); } if(prevDetail.getStoreSignUrl() != null && prevDetail.getStoreSignUrl().length() != 0){ prevDetail.setStoreSignUrl(""+s3Client.getUrl(bucketName, prevDetail.getStoreSignUrl())); } // ๊ฐ๊ฒํ์ double star = 0; try { star = appStoreDao.getStoreStar(prevDetail.getStoreIdx()); }catch(NullPointerException nullerr){ star = 0; }catch (IncorrectResultSizeDataAccessException error) { // ์ฟผ๋ฆฌ๋ฌธ์ ํด๋นํ๋ ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ 2๊ฐ ์ด์์ผ ๋ star = 0; } // ** ๋ด ์์น์์ ํด๋น ๊ฐ๊ฒ๊น์ง์ ๊ฑฐ๋ฆฌ ** int distance = (int) locationValue.getDistance(latitude, longitude, prevDetail.getY(), prevDetail.getX()); // 1Km (1000M) 16๋ถ ํ๊ตฐ ์์ // 100M : 1๋ถ 36์ด(96์ด) , 10M : 9.6์ด // ๊ฑฐ๋ฆฌ / 100M * 96์ด / 1๋ถ = int duration = locationValue.getDuration(distance); // ๋ถ // ๊ตฌ๋ ์ฌ๋ถ(์์ธ์ฒ๋ฆฌ ๋์ค์ ์ ๋๋ก ํ ๊ฒ, EXISTS ์จ์ null ์์ธ ์ฒ๋ฆฌ ์ํด๋๋ ์๋?) int subscribed; try{ subscribed = appStoreDao.getStoreSubscribed(customerIdx, prevDetail.getStoreIdx()); }catch (IncorrectResultSizeDataAccessException error) { // ์ฟผ๋ฆฌ๋ฌธ์ ํด๋นํ๋ ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ 2๊ฐ ์ด์์ผ ๋ subscribed = 0; }catch(Exception e){ throw new BaseException(DATABASE_ERROR); } StorePreviewRes prevRes = new StorePreviewRes( prevDetail.getStoreIdx(), prevDetail.getStoreName(), prevDetail.getStoreLogoUrl(), prevDetail.getStoreSignUrl(), star, distance, duration, subscribed ); storePreviewRes.add(prevRes); } return storePreviewRes; }
- ๊ฐ๊ฒ ์ ๋ณด์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ณธ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๋ฐํํ ๋ฏธ๋ฆฌ ๋ณด๊ธฐ ์ ๋ณด๋ฅผ ๊ฐ๊ณตํจ
2-1. ๊ฐ๊ฒ ์ฌ์ง URL ๋ง๋ค๊ธฐ S3์์ ์กฐํ
2-2. ๊ฐ๊ฒ ํ์ ์กฐํ
2-3. queryParam์ผ๋ก ๋ฐ์ ์/๊ฒฝ๋์ ๊ฐ๊ฒ์ ์/๊ฒฝ๋๋ฅผ ์ด์ฉํ์ฌ ๊ฑฐ๋ฆฌ ๊ณ์ฐํ๊ธฐ.
2-4. ํด๋น ๊ฐ๊ฒ์ ๊ตฌ๋งค์์ ๊ตฌ๋ ์ฌ๋ถ๋ฅผ ํ์ธ- ๋ฐ์ดํฐ ๋ง๋ ํ ์ ์๋ตํ๊ธฐ.
- ์ขํ ๊ธฐ์ค ๊ฑฐ๋ฆฌ ๊ตฌํ๊ธฐ
https://wildeveloperetrain.tistory.com/171public double getDistance(double lat1, double lon1, double lat2, double lon2) { double dLat = Math.toRadians(lat2 - lat1); // latitude : ์๋ y double dLon = Math.toRadians(lon2 - lon1); // longtitude : ๊ฒฝ๋ x double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon/2)* Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); double d = EARTH_RADIUS* c * 1000; // Distance with m return d; }
public int getDuration(int distance){ // 1Km (1000M) 16๋ถ ํ๊ตฐ ์์ // 100M : 1๋ถ 36์ด(96์ด) , 10M : 9.6์ด // ๊ฑฐ๋ฆฌ / 100M * 96์ด / 1๋ถ = return distance / 100 * 96 / 60; }
- Dao
// ๊ฐ๊ฒ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ณธ ์ ๋ณด(๊ฐ๊ฒid, ๊ฐ๊ฒ์ด๋ฆ, ๊ฐ๊ฒ ๋ก๊ณ /์ฌ์ง (s3 ๊ฐ์ฒด ํค), ์/๊ฒฝ๋ public StorePreviewDetails getStorePreview(int storeIdx) { String query = "SELECT\n" + " storeIdx,\n" + " store_name,\n" + " store_logo_url,\n" + " sign_url,\n" + " x, y\n" + "FROM Stores\n" + "WHERE storeIdx= ?"; return this.jdbcTemplate.queryForObject(query, (rs, rowNum) -> new StorePreviewDetails( rs.getInt("storeIdx"), rs.getString("store_name"), rs.getString("store_logo_url"), rs.getString("sign_url"), rs.getDouble("x"), rs.getDouble("y") ), storeIdx); }
// ๊ฐ๊ฒ ํ์ ๊ตฌํ๊ธฐ public double getStoreStar(int storeIdx) { String query = "SELECT\n" + " ROUND(AVG(star), 1) AS star_average \n" + "FROM Review\n" + "WHERE storeIdx = ? AND status != 'D'"; return this.jdbcTemplate.queryForObject(query, (rs, rowNum) -> rs.getDouble("star_average") , storeIdx); }
// ๊ฐ๊ฒ ๊ตฌ๋ ์ ๋ณด ํ์ธ public int getStoreSubscribed(int customerIdx, int storeIdx) { String query = "SELECT EXISTS(SELECT\n" + " *\n" + "FROM Subscribe\n" + "WHERE customerIdx = ? AND storeIdx = ?\n" + "AND status != 'D')"; Object[] params = new Object[]{customerIdx, storeIdx}; return this.jdbcTemplate.queryForObject(query, int.class, params); }
๊ตฌ๋งค์ ๋ก๊ทธ์ธ ID: dpranger, PW: @bcde12345, ์ด๋ฆ: ์์คํธ
์ขํ๊ธฐ์ค: ๋ด ์ง๊ทผ์ฒ์ธ ๋ค์ด ํ์ถ์ ~ ์ง๋๋ฒ ๊ฐ๊ฒ ๋ฑ๋ก์ ํ ๋๋ ์ฃผ๋ฅด๋ฅผ ํ๋ฒ API๋ก ๋ฏธ๋ฆฌ ๋ณด๊ธฐ ์กฐํ๋ฅผ ํด๋ณด๊ฒ ๋ค.
๊ฑฐ๋ฆฌ์ ๊ฑธ๋ฆฌ๋์๊ฐ์ด ๋ค์ด๋ฒ ์ง๋์ ๋์ค๋๊ฒ๊ณผ ๊ฑฐ์ ๋น์ทํจ!
์๊น๋ ์ ํํ ๊ฐ๊ฒ ์์ด์ฝ์ ๋ํ ํ๋์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ง๋ง, ํ์ฌ ๋ด ์์น๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฐ๊ฒ ๋ชฉ๋ก์ ํ์ธํ๋ค.
๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ฌ๋ฌ ๊ฐ์ธ ๋ชฉ๋ก ํ๋ฉด..!
- ์๋ต ๋ฐ๋
[GET] 2. /jat/app/stores/preview ์ ๊ฐ์
- ์ปจํธ๋กค๋ฌ
์ฌ์ฉ์์ ์๋/๊ฒฝ๋๋ฅผ ์๋ฒ์ ์ ์ฅํ๋๊ฒ๋ ๊ณ ๋ฏผํด๋ณด์์ง๋ง, ์ง๋๋ ์์ง์ด๋ ์์น์ ๋ฐ๋ผ ์์น ์ ๋ณด๊ฐ ๊ณ์ ๋ฐ๋์ด์ ์ฟผ๋ฆฌํ๋์ผ๋ก ์์ฒญํ๋๊ฒ ๋ ๋ซ๋ค๊ณ ์๊ฐํ๋ค.
- ์๋น์ค
public List<StorePreviewRes> getAppStoreList(int userIdx, Double longitude, Double latitude) throws BaseException { // 1. ์ฃผ๋ณ ๋ฐ๊ฒฝ ๊ตฌํ๊ธฐ (1500๋ฏธํฐ) //{minX, maxX, minY, maxY} double[] aroundXY = locationValue.aroundDist(longitude, latitude, 1500); // 2. ์ฃผ๋ณ ๊ฐ๊ฒ ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ // ๊ฐ๊ฒIdx, ๊ฐ๊ฒ์ด๋ฆ, ๊ฐ๊ฒ์ฃผ์, ์ขํ // ๋ณ์ , ๊ตฌ๋ ์ฌ๋ถ List<GetStoreList> storeList; try { storeList = appStoreDao.getAppStoreList(userIdx, aroundXY); } catch (Exception e) { throw new BaseException(RESPONSE_ERROR); } // 3. URL, ๊ฐ๊ฒ๊น์ง ๊ฑฐ๋ฆฌ ๊ตฌํ๊ธฐ List<StorePreviewRes> storePreviewRes = new ArrayList<>(); for(GetStoreList store : storeList){ // ๊ฐ๊ฒ ์ฌ์ง URL if(store.getStoreLogoUrl() != null && store.getStoreLogoUrl().length() != 0){ store.setStoreLogoUrl(""+s3Client.getUrl(bucketName, store.getStoreLogoUrl())); } if(store.getStoreSignUrl() != null && store.getStoreSignUrl().length() != 0){ store.setStoreSignUrl(""+s3Client.getUrl(bucketName, store.getStoreSignUrl())); } // ** ๋ด ์์น์์ ํด๋น ๊ฐ๊ฒ๊น์ง์ ๊ฑฐ๋ฆฌ ** int distance = (int) locationValue.getDistance(latitude, longitude, store.getY(), store.getX()); // 1Km (1000M) 16๋ถ ํ๊ตฐ ์์ // 100M : 1๋ถ 36์ด(96์ด) , 10M : 9.6์ด // ๊ฑฐ๋ฆฌ / 100M * 96์ด / 1๋ถ = int duration = locationValue.getDuration(distance); // ๋ถ storePreviewRes.add( new StorePreviewRes( store.getStoreIdx(), store.getStoreName(), store.getStoreLogoUrl(), store.getStoreSignUrl(), store.getStar(), distance, duration, store.getCustomerIdx() != 0 ? 1:0 ) ); } return storePreviewRes; }
- ๋ด ํ์ฌ ์์น ๊ธฐ์ค ์ง์ ๊ฑฐ๋ฆฌ ์ฝ 1500๋ฏธํฐ ์ฃผ๋ณ์ ๊ธฐ์ค์ผ๋ก ์ต๋/์ต์ ์/๊ฒฝ๋๋ฅผ ๊ตฌํ๊ธฐ.
- [GET] /jat/app/stores ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ฐ์ด ์ต๋,์ต์ ์/๊ฒฝ๋๋ฅผ ์ด์ฉํด ๊ฐ๊ฒ๋ฅผ ์กฐํํ๊ธฐ
- ๊ฐ ๊ฐ๊ฒ์ URL ์ฃผ์๋ฅผ S3๋ฅผ ํตํด์ ๊ฐ์ ธ์ค๊ณ ,
- ๊ฐ ๊ฐ๊ฒ๊น์ง์ ๊ฑฐ๋ฆฌ๋ฅผ ๋ด ํ์ฌ ์์น๊ธฐ์ค์ ํตํด์ ๊ตฌํ์ฌ ์๋ต๊ฐ์ผ๋ก ๋ง๋ค๊ธฐ.
- dao
// ์ต๋, ์ต์ ์/๊ฒฝ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์กฐํ // ๊ฑฐ๋ฆฌ ์์ผ๋ก ์กฐํํ ๋ ค ํ๋๋ฐ ์คํจํจ.. ๊ทธ๋๋ ์งํ์ค public List<GetStoreList> getAppStoreList(int userIdx, double[] aroundXY) { String query = "SELECT\n" + " S.storeIdx,\n" + " store_name,\n" + " store_logo_url,\n" + " sign_url,\n" + " store_address,\n" + " x, y,\n" + " ROUND(AVG(star), 1) as star,\n" + " SUB.customerIdx\n" + "FROM Stores S\n" + "LEFT JOIN Review R on S.storeIdx = R.storeIdx AND R.status != 'D'\n" + "LEFT JOIN Subscribe SUB on S.storeIdx = SUB.storeIdx AND SUB.status != 'D' AND SUB.customerIdx = ?\n" + "WHERE x BETWEEN ? AND ?\n" + "AND y BETWEEN ? AND ?\n" + "GROUP BY (S.storeIdx)\n" + "ORDER BY ABS(?+?/2 - x) DESC , ABS(?+?/2 - y) DESC ;"; Object[] params = new Object[]{ userIdx, aroundXY[0], aroundXY[1], aroundXY[2], aroundXY[3], aroundXY[1], aroundXY[0], aroundXY[3], aroundXY[2], }; return this.jdbcTemplate.query(query, (rs, rowNum) -> new GetStoreList( rs.getInt("storeIdx"), rs.getString("store_name"), rs.getString("store_logo_url"), rs.getString("sign_url"), rs.getString("store_address"), rs.getDouble("x"), rs.getDouble("y"), rs.getDouble("star"), rs.getInt("customerIdx") ), params); }