Merge branch 'iipbs/sn/dev' into iipbs/dm/dev
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
## Project
|
||||
This repository contains a Next.js web application.
|
||||
|
||||
Main technologies:
|
||||
- Next.js
|
||||
- TypeScript
|
||||
- pnpm workspace
|
||||
- turborepo
|
||||
|
||||
이 저장소는 pnpm workspace + Turborepo 기반 monorepo이다.
|
||||
|
||||
- 워크스페이스 범위는 `apps/*`, `apps/common/*`, `packages/*`, `packages/common/*`
|
||||
- 루트 스크립트는 `turbo run build`, `turbo run dev` 를 사용한다
|
||||
- `build` 작업은 의존 패키지의 `build` 를 먼저 수행한다 (`dependsOn: ["^build"]`)
|
||||
- `dev` 는 캐시하지 않는 지속 실행 작업이다
|
||||
- 변경 범위만 선택 실행할 수 있으므로, 전체 빌드보다 `--filter` 사용을 우선한다
|
||||
|
||||
## Encoding
|
||||
- UTF-8
|
||||
- 한글이 깨지지 않도록 주의할 것
|
||||
|
||||
## 주석 comment
|
||||
- 한글 주석을 삭제하지 말 것
|
||||
|
||||
## Monorepo structure
|
||||
apps/
|
||||
_template
|
||||
as
|
||||
cm
|
||||
cs
|
||||
dc
|
||||
dm
|
||||
dm_new
|
||||
fo
|
||||
sn
|
||||
st
|
||||
wr
|
||||
|
||||
@@ -48,6 +48,16 @@ type SuggestionSeed = {
|
||||
bldgNoMno: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* 주소 검색 API를 호출해 우편번호/주소 목록을 조회한다.
|
||||
* @param searchQuery 조회 조건 객체
|
||||
* @param searchQuery.roadNm 도로명
|
||||
* @param searchQuery.bldgNoMno 건물 본번
|
||||
* @param searchQuery.bldgNoSno 건물 부번
|
||||
* @param searchQuery.page 0부터 시작하는 페이지 번호
|
||||
* @param searchQuery.size 페이지당 조회 건수
|
||||
* @returns 주소 목록과 전체 건수를 포함한 응답 객체
|
||||
*/
|
||||
async function findAddress(searchQuery: ZipSearchParams): Promise<ZipListResponse> {
|
||||
if (!searchQuery) return {};
|
||||
|
||||
@@ -68,6 +78,12 @@ async function findAddress(searchQuery: ZipSearchParams): Promise<ZipListRespons
|
||||
return (await response.json()) as ZipListResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 자동완성 후보를 만들기 위해 주소 항목에서 도로명과 건물 본번을 추출한다.
|
||||
* 우선 API 응답 필드의 값을 사용하고, 값이 없으면 표시 주소 문자열을 파싱해 보정한다.
|
||||
* @param item 주소 검색 결과 1건
|
||||
* @returns 자동완성 생성에 사용할 도로명/건물본번 또는 추출 실패 시 null
|
||||
*/
|
||||
function extractSuggestionSeed(item: Zip): SuggestionSeed | null {
|
||||
const ext = item as Zip & {
|
||||
roadNm?: string;
|
||||
@@ -97,6 +113,11 @@ function extractSuggestionSeed(item: Zip): SuggestionSeed | null {
|
||||
return { roadNm, bldgNoMno };
|
||||
}
|
||||
|
||||
/**
|
||||
* 검색어에 허용되지 않는 특수문자나 SQL 예약어가 포함되어 있는지 검사한다.
|
||||
* @param search 사용자가 입력한 검색 문자열
|
||||
* @returns 검색 가능하면 true, 차단 대상이면 false
|
||||
*/
|
||||
function searchFilter(search: string): boolean {
|
||||
if (search.length === 0) return true;
|
||||
|
||||
@@ -132,6 +153,13 @@ function searchFilter(search: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 입력 주소 문자열을 "도로명 + 건물번호" 구조로 파싱해 API 조회 파라미터로 변환한다.
|
||||
* 예) "테헤란로 152-1" -> { roadNm: "테헤란로", bldgNoMno: 152, bldgNoSno: 1, page }
|
||||
* @param input 사용자가 입력한 주소 검색어
|
||||
* @param page 1부터 시작하는 요청 페이지 번호
|
||||
* @returns 파싱 성공 시 API 조회 파라미터와 정규화된 검색어, 실패 시 오류 메시지
|
||||
*/
|
||||
export function parsePostcodeInput(
|
||||
input: string,
|
||||
page = 1,
|
||||
@@ -205,6 +233,12 @@ export function parsePostcodeInput(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 도로명 주소 문자열에서 재검색에 사용할 "도로명 건물번호" 입력값만 추출한다.
|
||||
* 예) "테헤란로 152, OO빌딩" -> "테헤란로 152"
|
||||
* @param roadAddr 화면에 표시된 도로명 주소 문자열
|
||||
* @returns 재검색 입력란에 넣을 수 있는 문자열, 추출 실패 시 빈 문자열
|
||||
*/
|
||||
export function extractSearchInputFromRoadAddr(roadAddr: string): string {
|
||||
const firstSegment = roadAddr.split(",")[0]?.trim() ?? "";
|
||||
if (!firstSegment) return "";
|
||||
@@ -216,6 +250,12 @@ export function extractSearchInputFromRoadAddr(roadAddr: string): string {
|
||||
return `${parts.slice(0, -1).join(" ")} ${bldgToken}`.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자가 입력 중인 도로명을 기준으로 자동완성 후보를 조회한다.
|
||||
* 건물번호가 함께 입력된 경우에는 마지막 숫자 토큰을 제외한 도로명만으로 후보를 찾는다.
|
||||
* @param input 사용자가 입력창에 입력한 원본 문자열
|
||||
* @returns 최대 5개의 "도로명 건물본번" 자동완성 문자열 목록
|
||||
*/
|
||||
export async function fetchPostcodeSuggestions(input: string): Promise<string[]> {
|
||||
const normalized = input.replace(/\s+/g, " ").trim();
|
||||
const parts = normalized.split(" ");
|
||||
@@ -252,6 +292,15 @@ export async function fetchPostcodeSuggestions(input: string): Promise<string[]>
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 우편번호 검색 API를 호출해 화면 표시용 우편번호 목록 형태로 변환한다.
|
||||
* @param params 조회 조건 객체
|
||||
* @param params.roadNm 검색할 도로명
|
||||
* @param params.bldgNoMno 건물 본번
|
||||
* @param params.bldgNoSno 건물 부번
|
||||
* @param params.page 1부터 시작하는 화면 페이지 번호
|
||||
* @returns 전체 건수와 화면 표시용 주소 목록
|
||||
*/
|
||||
export async function fetchPostcode(
|
||||
params: PostcodeSearchParams,
|
||||
): Promise<PostcodeSearchResult> {
|
||||
|
||||
Reference in New Issue
Block a user