검색 기능 - 회원 검색(닉네임으로 검색), 피드 검색(해시태그로 검색, 날씨 및 장소 정보로 검색)

Project Diary/React + MariaDB (PicShare WebApp)

검색 기능은 사용자가 ID로 회원을 검색하거나, 해시태그, 날씨 및 장소 정보로 피드를 검색할 수 있도록 도와줍니다. 이를 위해 Redux 설정, 검색 컴포넌트 작성, 그리고 필요한 유틸리티 함수들을 작성합니다.


1. Redux 설정

 

1-1 모든 회원 목록 fetch - Redux Slice: 회원 상태 관리

import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";

const serverUrl = import.meta.env.VITE_API_URL;

const memberSlice = createSlice({
  name: "member",
  initialState: {
    user: null, // 현재 로그인한 사용자 정보
    users: [],  // 전체 사용자 목록
  },
  reducers: {
    userLogin(state, action) {
      state.user = action.payload;
      sessionStorage.loging = JSON.stringify({
        userNo: action.payload.userNo,
        email: action.payload.email,
      });
    },
    localUser(state, action) {
      state.user = action.payload;
    },
    userLogout(state) {
      state.user = null;
      sessionStorage.clear();
    },
    initUsers(state, action) {
      state.users = action.payload;
    },
  },
});

export const { userLogin, userLogout, localUser, initUsers } = memberSlice.actions;

export const fetchUsers = () => (dispatch) => {
  axios
    .get(`${serverUrl}/auth/users`)
    .then((res) => {
      dispatch(initUsers(res.data));
    })
    .catch((err) => console.log(err));
};

export default memberSlice.reducer;

 

1-2 모든 게시물 목록 fetch - Redux Slice: 피드 상태 관리

import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";

const serverUrl = import.meta.env.VITE_API_URL;

const feedSlice = createSlice({
  name: "feed",
  initialState: {
    feeds: [],    // 전체 피드 목록
    loading: false, // 로딩 상태
    error: null,   // 에러 상태
  },
  reducers: {
    initFeedStart(state) {
      state.loading = true;
      state.error = null;
    },
    initFeedSuccess(state, action) {
      state.feeds = action.payload;
      state.loading = false;
    },
    initFeedFail(state, action) {
      state.error = action.payload;
      state.loading = false;
    },
  },
});

export const { initFeedStart, initFeedSuccess, initFeedFail } = feedSlice.actions;

export const fetchAllFeed = () => (dispatch) => {
  dispatch(initFeedStart());
  axios
    .get(`${serverUrl}/feed/all`)
    .then((res) => {
      dispatch(initFeedSuccess(res.data));
    })
    .catch((err) => dispatch(initFeedFail(err)));
};

export default feedSlice.reducer;

 

2. 검색 컴포넌트 (SearchComponent)

 

1-1 초기 데이터 로드

useEffect(() => {
  if (currentUser) {
    dispatch(fetchFollowingList(currentUser.userNo));
  }
  dispatch(fetchUsers());
  dispatch(fetchAllFeed());
}, [dispatch, currentUser]);
  • fetchFollowingList, fetchUsers, fetchAllFeed는 각각 팔로우 목록, 사용자 목록, 전체 피드 목록을 서버에서 가져옵니다.

1-2 검색어와 검색 유형에 따른 필터링

useEffect(() => {
  if (searchType === "user") {
    const userResults = allUsers.filter(
      (user) =>
        user.userNo !== currentUser.userNo &&
        user.userNickname.toLowerCase().includes(searchTerm.toLowerCase())
    );
    setFilteredUsers(userResults);
    setFilteredFeeds([]);
  } else {
    const feedResults = allFeeds.filter((feed) => {
      if (searchType === "hashtag") {
        return feed.feedHashtags.some((hashtag) =>
          hashtag.toLowerCase().includes(searchTerm.toLowerCase())
        );
      } else if (searchType === "location") {
        return (
          (feed.locationName &&
            feed.locationName
              .toLowerCase()
              .includes(searchTerm.toLowerCase())) ||
          (feed.weatherInfo &&
            feed.weatherInfo.toLowerCase().includes(searchTerm.toLowerCase()))
        );
      }
      return false;
    });
    setFilteredFeeds(feedResults);
    setFilteredUsers([]);
  }
}, [searchTerm, searchType, allUsers, allFeeds, currentUser]);
  • useEffect는 검색어(searchTerm)와 검색 유형(searchType)이 변경될 때마다 필터링을 수행합니다.
  • allUsers와 allFeeds에서 검색어에 해당하는 결과를 필터링하여 setFilteredUsers와 setFilteredFeeds로 상태를 업데이트합니다.

2-3 슬라이더 및 검색 버튼 설정

const settings = {
  dots: true,
  infinite: false,
  speed: 500,
  slidesToShow: 1,
  arrows: false,
};

const goToSlide = (index) => {
  if (sliderRef.current) {
    sliderRef.current.slickGoTo(index);
  }
  setCurrentSlide(index);
  if (index === 0) setSearchType("user");
  else if (index === 1) setSearchType("hashtag");
  else if (index === 2) setSearchType("location");
};
  • goToSlide는 슬라이더 이동 함수로, 슬라이더 인덱스에 따라 검색 유형(searchType)을 변경합니다.