이번 로그에서는 TypeORM으로 BillyZip 프로젝트의 하우스 필터링 기능을 구현하는 방법에 대해 기록하고자 한다.
BillyZip 프로젝트에서는 다양한 유형의 하우스가 존재하기에 서비스를 이용하는 유저가 수 많은 하우스들을 하나하나 확인하는 것은 굉장히 힘든 일이다. 따라서 유저의 취향을 반영할 수 있는 필터링 기능을 구현하도록 하였다. 물론 전문적이고 체계적인 필터링 기능이라고는 말씀드릴 수 없지만 이번 프로젝트에서 구현하고자 하는 서비스에 필요한 수준의 필터링 기능을 제공하고자 한다.
먼저 하우스에는 해당 하우스과 관련된 다양한 정보가 포함된다. 이 중 필터링 하는데 있어 가장 필수적인 요소를 먼저 선별하였다.
클라이언트에서는 필수요소들에 대한 선택지를 버튼 형태로 유저에게 제공을 하도록 하였다. 그리고 유저는 본인이 원하는 요소를 선택하고 검색하기를 누르면 선택된 정보가 서버로 POST 요청을 보내게 된다.
여기에서 중요한 두 가지는 1)유저가 모든 필수요소를 누르지 않아도 필터링이 가능해야 한다. 2)각 요소들은 'WHERE AND'의 개념으로 서로 관계된 하우스를 가져올 수 있어야 한다는 것이었다.
(이에 대해서는 서버 편에서 다루도록 하겠다.)
이를 위해 클라이언트에서는 userState()에 null을 기본 값으로 넣어, 유저가 선택하지 않으면 해당 요소는 null로 서버에 요청을 보내도록 하였다.
그리고 선택된 요소들은 각각의 state에 선택된 값을 넣어 요청이 되도록 하였다.(아래 소스코드 참고)
위와 같이 각각의 요소를 선택하고(또는 선택하지 않고) 검색하기 버튼을 누르면 서버에서는 해당 요청을 아래와 같이 받게 된다. 그리고 이 조건을 기준으로 데이터베이스에서 적합한 하우스들을 응답하게 된다.
{
plan: '30',
type: 'villa',
year: 20,
access: 10,
adminDistrict: null
}
결과적으로 서버의 응답을 받은 클라이언트는 아래와 같이 필터에 의해 조건이 만족하는 하우스를 렌더링하게 된다.
function NormalSearchForm(props: Props): JSX.Element {
// 생략
const [plan, setPlan] = useState(null);
const [type, setType] = useState(null);
const [year, setYear] = useState(null);
const [access, setAccess] = useState(null);
const [adminDistrict, setDistrict] = useState(null);
const planButtons = [
'전체',
'30',
'50',
'70',
'100',
'150'
];
const typeButtons = [
'전체',
'원룸',
'아파트',
'빌라',
'오피스텔',
'주택'
];
const yearButtons = [
'전체',
'1년 이내',
'5년 이내',
'10년 이내',
'20년 이내',
'30년 이내',
];
const accessButtons = [
'전체',
'5분 이내',
'10분 이내',
'20분 이내',
'30분 이내',
'60분 이내',
];
return (
// 생략
<View>
<Button
title="검색하기"
type="solid"
onPress={(): void => {
axiosInstance
.post('houses/filter', {
plan,
type,
year,
access,
adminDistrict,
})
.then((res) => {
props.navigation.navigate('SearchResult', { data: res.data });
})
.catch((err) => console.error(err));
}}
/>
</View>
</View>
);
}