개인 프로젝트 개발 일지를 정리해서 올리려고 하는데 항상 글 쓸때마다 제목 정하기가 너무 어렵다!!
그래서 앞으로 버전 관리처럼 올려보려고 한다.
큰 업데이트가 있을때는 v1, v2, v3으로
작은 업데이트는 v0.1 v0.2 v0.3으로
오늘의 업데이트는 v0.1 !
🎯v0.1 업데이트 내용
💡입력 폼 업데이트
✅기존에 항상 보여지고 있던 입력 폼을 사용자가 직접 열고 닫을 수 있게 변경하였습니다.
✅사용자 경험 개선을 위해 X좌표와 Y좌표를 카카오 맵 API의 window.kakao.maps.services.Geocoder의 coord2Address를 이용해 도로명 주소로 표기하였습니다.
(메서드 참고 : https://apis.map.kakao.com/web/sample/coord2addr/)
✅x좌표와 y좌표에 입력되던 좌표값을 hidden 필드로 둬서 값은 넘겨지지만 사용자에게는 도로명 주소만 보이게 개선하였습니다.
✅저장하기 버튼 클릭 시 현재 좌표가 자동으로 DB에 저장됩니다.
const [address, setAddress] = useState(""); // 도로명 주소 상태
// currentPosition이 변경될 때 formData에 자동으로 반영
useEffect(() => {
if (currentPosition.lat && currentPosition.lng) {
setFormData((prevState) => ({
...prevState,
storeX: currentPosition.lat.toFixed(6), // X좌표 6개까지
storeY: currentPosition.lng.toFixed(6), // Y좌표 6개까지
}));
// Kakao Maps Geocoder
if (window.kakao && window.kakao.maps) {
const geocoder = new window.kakao.maps.services.Geocoder();
geocoder.coord2Address(
currentPosition.lng,
currentPosition.lat,
(result, status) => {
if (status === window.kakao.maps.services.Status.OK) {
const roadAddress = result[0]?.road_address?.address_name || "주소 없음";
setAddress(roadAddress);
}
}
);
}
}
}, [currentPosition]);
<label>
<span>주소</span>
<input
type="text"
value={address} // 도로명 주소 추가
readOnly
placeholder="주소 가져오는 중..."
/>
</label>
{/* X, Y 좌표 hidden 필드 */}
<input type="hidden" name="storeX" value={formData.storeX} />
<input type="hidden" name="storeY" value={formData.storeY} />
💡DB에 도로명 주소 추가
✅ 기존 X,Y좌표뿐만 아니라 도로명 주소도 DB에 저장되게 하였습니다.
추후 팝업창에서 제공되는 주소는 도로명 주소로 제공될 예정입니다.
📒업데이트 공부하기
✏️입력 폼 업데이트
리액트에서는 컴포넌트 내부에서 값이 변경될 때마다 자동으로 UI를 업데이트 하기 위해 state라는 상태를 사용하는데,
리액트의 useState 훅을 통해 상태를 선언하고 관리할 수 있다.
그래서 useState를 통해 도로명 주소를 저장하는 상태값(address)과 해당 상태(address)를 변경하는 함수(setAddress)를 선언했다.
const [address, setAddress] = useState("");
그런 후에 useEffect 훅을 사용해서 현재 위치(currentPosition)가 바뀔 때마다 도로명 주소 상태를 업데이트 하게 했다.
useEffect의 두 번째 값으로 currentPosition을 넣어 위치 값이 바뀔 때마다 도로명 주소를 가져오도록 했다.
도로명 주소는 Kakao Maps API의 coord2Address 메서드를 사용해 위도,경도를 도로명 주소로 바꾸게 했다.
마지막으로는 setAddress를 통해 변환된 도로명 주소를 address 상태에 저장했다.
useEffect(() => {
if (currentPosition.lat && currentPosition.lng) {
// Kakao Maps API Geocoder
if (window.kakao && window.kakao.maps) {
const geocoder = new window.kakao.maps.services.Geocoder();
geocoder.coord2Address(
currentPosition.lng,
currentPosition.lat,
(result, status) => {
if (status === window.kakao.maps.services.Status.OK) {
const roadAddress = result[0]?.road_address?.address_name || "주소 없음";
setAddress(roadAddress); // 상태 업데이트
}
}
);
}
}
}, [currentPosition]);
저장한 address는 UI의 label에 value값으로 사용해서 사용자가 확인할 수 있게 했다.
<label>
주소 :
<input
type="text"
value={address} // 도로명 주소 상태값
readOnly
placeholder="도로명 주소를 가져오는 중..."
/>
</label>
✏️도로명 주소 백엔드 추가
X,Y좌표는 사용자들에게 친숙하지 않기 때문에 X,Y값을 도로명으로 변환한 일반적인 도로명 주소를 저장하고, 추후에 팝업창에 제공할 수 있게 새로운 속성을 추가했다.
entity > controller > service 순으로 수정했다.
Entity
text형식의 store_address 속성 추가하기
@Column(columnDefinition = "TEXT", nullable = false)
private String storeAddress;
Controller
@RestController
@RequestMapping("/fishstore")
public class FishstoreController {
@Autowired
private FishstoreService service;
@PostMapping
public ResponseEntity<FishstoreEntity> saveFishstore(
@RequestParam("storeName") String storeName,
@RequestParam("storeAddress") String storeAddress, //가게 주소 추가
@RequestParam("storeX") Double storeX,
@RequestParam("storeY") Double storeY,
@RequestParam(value = "storeMenu", required = false) String storeMenu,
@RequestParam(value = "storeInfo", required = false) String storeInfo,
@RequestParam(value = "storeImage", required = false) MultipartFile storeImage) {
FishstoreEntity savedFishstore = service.saveFishstore(storeName, storeAddress, storeX, storeY, storeMenu, storeInfo, storeImage);
return ResponseEntity.ok(savedFishstore);
}
Service, ServiceImpl
public interface FishstoreService {
FishstoreEntity saveFishstore(String storeName, String storeAdress, Double storeX, Double storeY, String storeMenu, String storeInfo, MultipartFile storeImage);
}
@Service
public class FishstoreServiceImpl implements FishstoreService {
@Autowired
private FishstoreRepository repository;
@Override
public FishstoreEntity saveFishstore(String storeName, String storeAddress, Double storeX, Double storeY, String storeMenu, String storeInfo, MultipartFile storeImage) {
byte[] imageBytes = null;
try {
if (storeImage != null && !storeImage.isEmpty()) {
imageBytes = storeImage.getBytes();
}
} catch (Exception e) {
throw new RuntimeException("이미지 변환 중 오류 발생: " + e.getMessage());
}
FishstoreEntity fishstore = new FishstoreEntity();
fishstore.setStoreName(storeName);
fishstore.setStoreAddress(storeAddress); //sotreAddress 추가
fishstore.setStoreX(storeX);
fishstore.setStoreY(storeY);
fishstore.setStoreMenu(storeMenu);
fishstore.setStoreInfo(storeInfo);
fishstore.setStoreImage(imageBytes);
return repository.save(fishstore);
}
✏️ 클라이언트 수정
다음으로는 클라이언트에서 서버로 요청하는 값을 수정했다.
제출되는 formData에 도로명 주소 필드 추가!
const [formData, setFormData] = useState({
storeName: "",
storeX: "",
storeY: "",
storeAddress: "", //도로명 주소 추가
storeMenu: "",
storeImage: null,
storeInfo: "",
});
그리고 실시간으로 x,y좌표를 주소로 바꿔주기 때문에 여기서 바꾼 값을 formData에 추가했다.
useEffect(() => {
if (currentPosition.lat && currentPosition.lng) {
// X, Y 좌표 상태 업데이트
setFormData((prevState) => ({
...prevState,
storeX: currentPosition.lat.toFixed(6),
storeY: currentPosition.lng.toFixed(6),
}));
// Kakao Maps Geocoder
if (window.kakao && window.kakao.maps) {
const geocoder = new window.kakao.maps.services.Geocoder();
geocoder.coord2Address(
currentPosition.lng,
currentPosition.lat,
(result, status) => {
if (status === window.kakao.maps.services.Status.OK) {
const roadAddress = result[0]?.road_address?.address_name || "주소 없음";
setAddress(roadAddress);
setFormData((prevState) => ({
...prevState,
storeAddress: roadAddress, // formData에 도로명 주소 추가
}));
}
}
);
}
}
}, [currentPosition]);
입력된 가게 데이터는 formData로 전송되기 때문에 axios요청에서 따로 바꾼건 없었다. 그대로 formData 제출!
테스트 해보기
저장 완료!
'Develop > React' 카테고리의 다른 글
붕어빵 프로젝트 업데이트 v0.2 (0) | 2024.12.18 |
---|---|
붕어빵 지도 프로젝트 도메인으로 배포하기 (2) (1) | 2024.12.15 |
붕어빵 지도 프론트 + 백엔드 (1) (3) | 2024.12.14 |
붕어빵 지도 프로토타입 (0) | 2024.12.13 |
붕어빵 지도 만들기! (0) | 2024.12.12 |