๐Ÿ—บ๏ธ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰

๋ฐ•์ƒ์€ยท2022๋…„ 6์›” 20์ผ
0

๐Ÿ›’ blemarket ๐Ÿ›’

๋ชฉ๋ก ๋ณด๊ธฐ
6/7

prisma์™€ Next.js๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

Geolocation API๋ฅผ ์ด์šฉํ•ด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํ—ˆ์šฉํ•˜๋ฉด ํ˜„์žฌ ๋””๋ฐ”์ด์Šค์˜ ์œ„๋„/๊ฒฝ๋„ ๊ฐ’์„ ์–ป์–ด๋ƒ…๋‹ˆ๋‹ค.
ํ•ด๋‹น ์œ„๋„์™€ ๊ฒฝ๋„๋ฅผ ๊ฒŒ์‹œ๊ธ€ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๊ฒŒ์‹œ๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์œ„๋„/๊ฒฝ๋„, ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ์„ ํƒํ•œ ๊ฑฐ๋ฆฌ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ ํ—ˆ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š” ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€์ด ์œ„์น˜ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰์—์„œ ์ œ์™ธ๋˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ™‚ ์œ„๋„/๊ฒฝ๋„ ์–ป๋Š” ํ›…

useCoords() hook ์ฐธ๊ณ 

๐Ÿ˜Œ ์œ„๋„/๊ฒฝ๋„ ์ปฌ๋Ÿผ ์ถ”๊ฐ€

model Post {
  # ์•„๋ž˜ ๋‘ ๊ฐœ ์ถ”๊ฐ€
  latitude  Float?
  longitude Float?
  
  # ... ๋‚˜๋จธ์ง€ ์ƒ๋žต
}

๐Ÿ˜ฏ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰

์š”์ฒญ API -> /api/posts?latitude&longitude&distance&page&offset
query string์„ ์ด์šฉํ•ด์„œ ์œ„๋„, ๊ฒฝ๋„, ๊ฑฐ๋ฆฌ, ํŽ˜์ด์ง€, ๊ฐœ์ˆ˜ ๊ฐ’์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

1. ํ”„๋ก ํŠธ

input[type="range"]๋ฅผ ์ด์šฉํ•ด์„œ 1~100KM๋ฅผ ์„ ํƒํ•˜๊ณ  onChange()์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ’์ด ๋ณ€๊ฒฝํ•œ๋‹ค๋ฉด ๋‹ค์‹œ ๊ฒ€์ƒ‰ํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
๋‹จ, ๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋””๋ฐ”์šด์Šค๋ฅผ ์ ์šฉํ•ด์„œ ์—ฐ์†์ ์ธ ์š”์ฒญ์ค‘ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์š”์ฒญ๋งŒ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

// 2022/04/13 - ๊ฒ€์ƒ‰ํ•  ๊ฑฐ๋ฆฌ - by 1-blue
const [distance, setDistance] = useState(10);
// 2022/04/23 - ๋””๋ฐ”์šด์‹ฑ - by 1-blue
const [debounce, setDebounce] = useState(false);
// 2022/04/23 - timerId - by 1-blue
const timerId = useRef<any>(null);
// 2022/03/28 - ๊ฑฐ๋ฆฌ ์กฐ์ ˆ - by 1-blue
const onChangeDistance = useCallback(
  (e: React.FormEvent<HTMLInputElement>) => {
    if (!debounce) {
      clearTimeout(timerId.current);
      timerId.current = setTimeout(() => {
        setDebounce(true);
      }, 300);
    }
    setDistance(+e.currentTarget.value);
  },
  [debounce, setDebounce]
);

<input
  type="range"
  min={1}
  value={distance}
  onChange={onChangeDistance}
  className="w-full py-4 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 focus:rounded-md"
/>
// usePagination()์€ useSWR()์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•œ ๊ฒƒ์ž„
// ์œ„์—์„œ input์„ ๋ณ€๊ฒฝํ•ด์„œ "debounce"๊ฐ€ true๊ฐ€ ๋˜๋Š” ์ˆœ๊ฐ„ ํ˜„์žฌ ์ ์šฉํ•œ ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์š”์ฒญํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

// 2022/04/13 - ๊ฒ€์ƒ‰ ์กฐ๊ฑด์— ์˜ํ•ด ๊ฒ€์ƒ‰๋œ ๊ฒŒ์‹œ๊ธ€๋“ค - by 1-blue
const [{ data: searchedPost, isValidating }, { page, setPage }, { offset }] =
usePagination<IPostResponse>(
  +condition === SEARCH_CONDITION.AROUND &&
    latitude &&
    longitude &&
    debounce
    ? `/api/posts?latitude=${latitude}&longitude=${longitude}&distance=${distance}`
    : null,
  {}
);

2. ๋ฐฑ์—”๋“œ

// ๋‚˜๋จธ์ง€ ์ƒ๋žตํ•˜๊ณ  ํ•ต์‹ฌ ๋กœ์ง๋งŒ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
const page = +req.query.page - 1;
const offset = +req.query.offset;

let where = {};
// ์ธ๊ทผ ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰ ์‹œ ์‹คํ–‰
if (req.query.distance) {
  // ๊ฑฐ๋ฆฌ, ์œ„๋„, ๊ฒฝ๋„ ์ˆซ์ž๊ฐ’์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
  const distance = +req.query.distance;
  const parsedLatitude = parseFloat(req.query.latitude.toString());
  const parsedLongitue = parseFloat(req.query.longitude.toString());

  // 1KM ๊ทผ์‚ฌ์น˜๊ฐ€ 0.008
  // ๋ฐ˜๊ฒฝ "distance"KM ๋‚ด์—์„œ ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€์„ ๊ฒ€์ƒ‰ํ•˜๋Š” ์กฐ๊ฑด
  where = {
    latitude: {
      gte: parsedLatitude - 0.008 * distance,
      lte: parsedLatitude + 0.008 * distance,
    },
    longitude: {
      gte: parsedLongitue - 0.008 * distance,
      lte: parsedLongitue + 0.008 * distance,
    },
  };
}

// ์•„๋ž˜ ๋ถ€๋ถ„์€ ๋‚˜์ค‘์— Promise.all()์„ ์ด์šฉํ•ด์„œ ๊ฐ’์„ ์ถ”์ถœํ•จ
const postsPromise = prisma.post.findMany({
  take: offset,
  skip: page * offset,
  where,
  include: {
    user: {
      select: {
        name: true,
      },
    },
    _count: {
      select: {
        answers: true,
        recommendations: true,
      },
    },
  },
  orderBy: [
    {
      createdAt: "desc",
    },
  ],
});

๐Ÿ“ฝ๏ธ ๊ตฌํ˜„

  • ๋””๋ฐ”์šด์Šค ๋ฏธ์ ์šฉ

  • ๋””๋ฐ”์šด์Šค ์ ์šฉ

0๊ฐœ์˜ ๋Œ“๊ธ€