피드관리 - Part 1 피드작성 (2) 장소 및 날씨 입력

Project Diary/React + MariaDB (PicShare WebApp)

사용자가 피드 작성 시 현재 위치나 입력한 장소의 날씨 정보를 가져오고, 이를 바탕으로 해시태그를 추천하는 기능을 구현합니다. 이 글에서는 날씨 API를 사용하여 위치와 날씨 정보를 가져오고, 이를 활용해 피드에 정보를 입력하는 과정을 다룹니다.


 

데이터베이스

  • locationName : 위치 이름
  • weatherInfo : 날씨 정보 (JSON)
  • weathericon : 날씨 아이콘

프론트엔드

 

1. 장소 및 날씨 입력 기능

 

1-1 날씨 API를 사용하여 위치에 따른 날씨 정보를 가져오는 함수

const getWeatherByCoords = async (lat, lon) => {
  const response = await axios.get(
    `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`
  );
  return response.data;
};

const getWeatherByLocationName = async (locationName) => {
  const response = await axios.get(
    `https://api.openweathermap.org/data/2.5/weather?q=${locationName}&appid=${API_KEY}&units=metric`
  );
  return response.data;
};

const getLocationNameByCoords = async (lat, lon) => {
  const response = await axios.get(
    `http://api.openweathermap.org/geo/1.0/reverse?lat=${lat}&lon=${lon}&limit=1&appid=${API_KEY}`
  );
  return response.data[0].name;
};
  • getWeatherByCoords : 위도와 경도로 날씨 정보를 가져옵니다.
  • getWeatherByLocationName : 장소 이름으로 날씨 정보를 가져옵니다.
  • getLocationNameByCoords : 위도와 경도로 장소 이름을 가져옵니다.

1-2 컴포넌트가 마운트될 때 현재 위치의 날씨와 장소 정보를 가져옴

useEffect(() => {
  navigator.geolocation.getCurrentPosition(async (position) => {
    const { latitude, longitude } = position.coords;
    setLatitude(latitude);
    setLongitude(longitude);
    const weatherData = await getWeatherByCoords(latitude, longitude);
    setWeather(weatherData);
    const locName = await getLocationNameByCoords(latitude, longitude);
    setLocationName(locName);
    fetchRecommendedHashtags(weatherData.weather[0].main.toLowerCase());
  });
}, []);

컴포넌트가 마운트될 때 사용자의 현재 위치를 가져오고, 해당 위치의 날씨 정보를 가져옵니다.

 

1-3 장소 이름으로 날씨 정보 가져오기

const handleGetWeatherByLocation = async () => {
  try {
    const weatherData = await getWeatherByLocationName(locationName);
    setLatitude(weatherData.coord.lat);
    setLongitude(weatherData.coord.lon);
    setWeather(weatherData);
    fetchRecommendedHashtags(weatherData.weather[0].main.toLowerCase());
  } catch (err) {
    console.error("Failed to fetch weather data:", err);
    alert("날씨 정보를 가져오는데 실패했습니다. 장소 이름을 확인해주세요.");
  }
};

 

1-4 위치 및 날씨 정보 입력 UI

<div className="location-section">
  <div className="checkbox-label">
    <p>위치와 날씨 정보를 게시하시겠습니까?</p>
    <label>
      <input
        type="checkbox"
        checked={showWeatherInfo}
        onChange={() => setShowWeatherInfo(!showWeatherInfo)}
      />
      <span style={{ color: "#09fc52", fontWeight: "bold" }}>
        위치 및 날씨 정보 게시
      </span>
    </label>
  </div>
  {showWeatherInfo && (
    <>
      <div className="weatherinputfield">
        <div className="infowrap">
          <p className="locationinfo">
            <MdPlace /> {locationName}
          </p>
          <div>
            <div className="weatherinfo">
              {weather && (
                <>
                  <img
                    src={`https://openweathermap.org/img/wn/${weather.weather[0].icon}.png`}
                    alt={weather.weather[0].description}
                  />
                  <p>{weather.main.temp}°C</p>
                </>
              )}
            </div>
            <p>{weather && weather.weather[0].description}</p>
          </div>
        </div>
        <div className="inputwrap">
          <div className="locationinput">
            <input
              type="text"
              placeholder="장소 이름을 입력하세요..."
              value={locationName}
              onChange={handleLocationChange}
            />
            <button type="button" onClick={handleGetWeatherByLocation}>
              날씨 정보 가져오기
            </button>
          </div>
          <span>
            * 현재 위치를 자동으로 불러오거나 직접 입력할 수 있습니다.
          </span>
        </div>
      </div>
      {weather && (
        <div>
          <div
            className="recommended-hashtags"
            style={{
              border: "none",
              display: "flex",
              alignItems: "center",
            }}
          >
            <p>이런 해시태그는 어떠세요?</p>
            {recommendedHashtags.map((hashtag, idx) => (
              <button
                key={idx}
                type="button"
                onClick={() => handleRecommendedHashtagClick(hashtag)}
                style={{
                  fontSize: "15px",
                  margin: "0 5px",
                  background: "#fff",
                  border: "1px solid #ccc",
                  borderRadius: "5px",
                  padding: "5px 10px",
                  color: "#aaa",
                  alignItems: "center",
                  fontWeight: "bold",
                }}
              >
                #{hashtag}
              </button>
            ))}
          </div>
        </div>
      )}
    </>
  )}
</div>

사용자가 위치와 날씨 정보를 입력하고, 해당 정보를 기반으로 추천 해시태그를 받을 수 있게 합니다.

 

1-5 장소 및 날씨 정보 제출

formData.append("weathericon", weather ? weather.weather[0].icon : null);

위치 및 날씨 정보를 formData에 추가하여 서버로 전송합니다.

 


 

위치 및 날씨 정보 입력