작업일지에 들어가며
이전 중간 프로젝트에서 JSP를 사용하여 카카오에서 제공하는 주소 찾기 API를 구현하였다.
이번 프로젝트는 리액트를 사용하기 때문에 처음에는 적용하기 어렵지 않으려나 생각했었는데
이미 여러 사람들이 리액트로도 API를 잘 구현하여 개인 블로그에 잘 정리하여 포스팅해주어서
잘 모르는 부분이나 에러가 나는 부분들은 쉽게 해결할 수 있었다.
내가 구현했던 과정을 하기에 좀 더 상세하게 기록을 남겨보겠다.
리액트 다음 주소 API
카카오에서 제공하는 다음 우편번호 서비스 공식 설명 페이지이다.
API의 특징과 기본 사용법이 아주 상세하게 설명되어있으니 처음 사용하는 사람들도 손쉽게 사용 가능하다.
하지만 본인은 공식 페이지의 설명만으로는 리액트에서 적용하기 쉽지 않아 쉽게 적용할 수 있는 방법이 있을까?
검색하던 도중 npm 사이트에서 다음 주소 API 설명 페이지를 찾아내었다.
리액트로 구현하고자하는 사람들은 해당 사이트를 참고하는 것이 훨씬 좋을 것 같다.
API 적용 개발 과정
1. 라이브러리 설치
아래 코드를 입력하여 리액트 버전 다음 우편번호 서비스 라이브러리를 설치해준다.
npm install react-daum-postcode
# or
yarn add react-daum-postcode
2. 컴포넌트 생성
팝업창을 띄울 것이기에 컴포넌트에 useDaumPostcodePopup을 임포트 해주었다.
import { useDaumPostcodePopup } from 'react-daum-postcode';
참고로 DaumPostcodeEmbed 컴포넌트를 사용하여, 우편번호 검색 서비스를 임베드 방식으로 사용할 수 있다.
import DaumPostcodeEmbed from 'react-daum-postcode';
3. 예제 코드
npm에서 제공하는 예제 코드이다. 본인의 프로젝트에 맞게 수정하여 사용하면 될 것 같다.
import React from 'react';
import DaumPostcodeEmbed from 'react-daum-postcode';
const Postcode = () => {
const handleComplete = (data) => {
let fullAddress = data.address;
let extraAddress = '';
if (data.addressType === 'R') {
if (data.bname !== '') {
extraAddress += data.bname;
}
if (data.buildingName !== '') {
extraAddress += extraAddress !== '' ? `, ${data.buildingName}` : data.buildingName;
}
fullAddress += extraAddress !== '' ? ` (${extraAddress})` : '';
}
console.log(fullAddress); // e.g. '서울 성동구 왕십리로2길 20 (성수동1가)'
};
return <DaumPostcodeEmbed onComplete={handleComplete} {...props} />;
};
4. 필요 코드 추가
4-1 팝업창 객체 생성
먼저 팝업창을 생성해야하기 때문에 스크립트 주소를 넣어준다.
// Daum 우편번호 팝업창 스크립트 주소
const open = useDaumPostcodePopup('//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js');
4-2 팝업창 열기
우편번호 찾기 버튼 클릭시 팝업창을 열기 위한 함수를 작성해준다.
// 버튼 클릭 시 우편번호 팝업 열기
const handleClick = () => {
open({ onComplete: handleComplete }); // 팝업 오픈 및 완료 시 핸들러 설정
};
4-3 주소 담기
handleComplete 함수 내에 사용자가 선택한 주소를 담을 코드를 작성해준다.
// 우편번호와 도로명 주소 업데이트
setValue("postcode", data.zonecode); // 우편번호
setValue("roadAddress", fullAddress); // 도로명 주소
4-4 포커스 이동
사용자 경험(UX) 측면에서 주소 선택 완료 시 상세주소 입력 필드로 포커스를 자동으로 이동시켜주려고 한다.
참고 : 우편번호와 도로명 주소가 입력되기도 전에 포커스가 이동할 수 있으니 보험 차원에서 setTimeout을 이용하였다.
// 팝업창 닫힌 후 상세 주소 입력 필드로 포커스 이동
setTimeout(() => {
const detailAddress = document.querySelector("#detailAddress"); // 상세 주소 입력 필드 선택
if (detailAddress) {
detailAddress.focus(); // 상세 주소 입력 필드로 포커스 이동
}
}, 100); // 100ms 후에 포커스 이동
};
4-5 버튼 만들기
return (
<Button
type="button"
onClick={handleClick}
colorPalette="orange"
width="full"
size="lg"
>
우편변호 찾기
</Button>
);
4-6 컴포넌트 완성
PostCode.jsx : 해당 컴포넌트를 필요한 곳에 넣고 사용하면 되겠다!
import { Button } from "@chakra-ui/react";
import React from "react";
import { useDaumPostcodePopup } from "react-daum-postcode";
export const DaumPostAPI = ({ setValue }) => {
// Daum 우편번호 팝업창 스크립트 주소
const open = useDaumPostcodePopup(
"//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"
);
// 우편번호 검색 완료 시 호출되는 함수
const handleComplete = (data) => {
let fullAddress = data.address; // 전체 주소 초기화
let extraAddress = ""; // 추가 주소 초기화
// 주소 타입이 'R' (도로명 주소)일 경우
if (data.addressType === "R") {
// 건물명(bname)이 존재하면 추가 주소에 추가
if (data.bname !== "") {
extraAddress += data.bname;
}
// 건물명(buildingName)이 존재하면 추가 주소에 추가
if (data.buildingName !== "") {
extraAddress +=
extraAddress !== "" ? `, ${data.buildingName}` : data.buildingName;
}
// 전체 주소에 추가 주소를 붙임
fullAddress += extraAddress !== "" ? ` (${extraAddress})` : "";
}
// 우편번호와 도로명 주소 업데이트
setValue("postcode", data.zonecode); // 우편번호
setValue("roadAddress", fullAddress); // 도로명 주소
//console.log(fullAddress);
// 팝업창 닫힌 후 상세 주소 입력 필드로 포커스 이동
setTimeout(() => {
const detailAddressInput = document.querySelector("#detailAddress"); // 상세 주소 입력 필드 선택
if (detailAddressInput) {
detailAddressInput.focus(); // 상세 주소 입력 필드로 포커스 이동
}
}, 100); // 100ms 후에 포커스 이동
};
// 버튼 클릭 시 우편번호 팝업 열기
const handleClick = () => {
open({ onComplete: handleComplete }); // 팝업 오픈 및 완료 시 핸들러 설정
};
return (
<Button
type="button"
onClick={handleClick}
colorPalette="orange"
width="full"
size="lg"
>
우편변호 찾기
</Button>
);
};
5. 회원가입 컴포넌트에 적용
const AuthRegister = () => {
const {
register,
handleSubmit,
setValue,
setError,
formState: { errors },
} = useForm();
... 생략
<Box
display="flex"
alignItems="center"
justifyContent="space-between"
width="full"
>
<Box flex="7" mr="4">
<Field
label="주소"
invalid={!!errors.postcode}
errorText={errors.postcode?.message}
>
<Input
size="md"
placeholder="우편번호"
readOnly
width="100%"
{...register("postcode", {
required: "우편번호는 필수 입력입니다.",
})}
/>
</Field>
</Box>
<Box flex="3">
<Field
label=" "
invalid={!!errors.postcode}
errorText=" "
>
<DaumPostAPI setValue={setValue} />
</Field>
</Box>
</Box>
<Field
invalid={!!errors.roadAddress}
errorText={errors.roadAddress?.message}
>
<Input
size="md"
placeholder="도로명 주소"
readOnly
width="100%"
{...register("roadAddress", {
required: "도로명 주소는 필수 입력입니다.",
})}
/>
</Field>
<Field
invalid={!!errors.detailAddress}
errorText={errors.detailAddress?.message}
>
<Input
id="detailAddress"
size="md"
placeholder="상세 주소"
width="100%"
{...register("detailAddress", {
required: "상세 주소는 필수 입력입니다.",
})}
/>
</Field>
... 생략
);
};
export default AuthRegister;
6. 결과
회원가입 컴포넌트에 적용 버튼 클릭시 팝업창 생성
주소 선택 주소 선택 완료 시 상세 주소 입력 필드로 포커싱
작업일지를 마치며
✨ 나의 생각
역시 오늘도 이렇게 좋은 API를 제공해준 사람들에게 감사 인사를 먼저 전해야겠다.
이번 API 구현 과정이 이전 JSP로 우편번호 찾기를 구현했을 때보다 상대적으로 조금 더 할 것이 많았다.
진행하면서 큰 에러는 없었지만 그 때는 그냥 공식 페이지에서 코드만 복붙하고 설명에 맞게 각 입력 필드를 매핑시켜주면 되었었는데
이번에는 팝업을 생성할 함수, 클릭 시 발생하는 함수, 사용자가 선택한 주소를 담고 넘겨줘야했기 때문에
이런 추가적인 부분에 있어서 쉽지만은 안았던 것 같다. 그렇지만 이번에 꽤나 만족스럽게 구현을 완료했기 때문에
다음에 이런 기회가 다시 온다면 별 부담없이 코드를 짤 수 있을 것 같다.
'Project > Team' 카테고리의 다른 글
프로젝트 작업일지 : 회원가입 (스프링 - 리액트 회원가입) (0) | 2024.12.24 |
---|---|
프로젝트 작업일지 : 회원가입 (폼 만들기_React Hook Form) (0) | 2024.12.23 |
프로젝트 작업일지 : DB 테이블 설계, ERD 작성 (2) | 2024.12.14 |
프로젝트 작업일지 : 기능 정의서 작성 (0) | 2024.12.13 |
프로젝트 작업일지 : 화면 정의서 작성 (1) | 2024.12.12 |