옛날옛적에 했던 프로젝트 리팩토링 중
장르별로 영화를 불러오면 웬 이상한 성인영화도 같이 불러오길래 수정하기로 했다.
이 과정에서 async 함수도 다시 만듦.
사이트엔 장르별, 년도별로 불러오는 메뉴 두 개가 있었는데,
로직 자체는 비슷해서 이걸 하나의 함수로 묶고 싶었다.
그리고 너저분한 쿼리스트링을 만드는 함수도 따로 만들고 싶었다.
하지만 둘은 쿼리스트링이 다르게 들어가야 하는데 어떻게 해야하나...!!
이 과정에서 사용한 것이 ⭐️오버로딩⭐️
동일한 함수 이름에 매개변수를 다르게 받아오는 다른 버전의 함수를 여러개 만드는 것을 오버로딩이라 한다.
그래서 이걸 어떻게 만드느냐~!!
우선 fetch에 사용할 쿼리스트링을 함수로 만들어서 불러오자.
function buildTMDBQuery(discoverWith: 'genre', currentPage: number, genreId: string): string;
function buildTMDBQuery(discoverWith: 'year', currentPage: number, startYear: string, endYear: string): string;
function buildTMDBQuery(
discoverWith: 'genre' | 'year',
currentPage: number,
genreIdORStartYear: string,
endYear?: string,
): string { ... }
같은 이름으로 매개변수를 받는 소괄호까지만 쓴 후,
마지막에 실제로 사용할 함수를 만들고 내용을 넣어주면 끝!
이 과정에서 매개변수 이름을 a, b, c로 넣어주기도 하던데,
나는 헷갈릴것 같아서 알아볼 수 있는 변수명으로 적어뒀다.
그리고 쿼리스트링을 만드는 내부 로직은 아래처럼 만들었다.
{
const query = new URLSearchParams({
'certification.gte': 'ALL',
'certification.lte': '19',
certification_country: 'KR',
include_adult: 'false',
include_video: 'false',
language: 'ko-KR',
sort_by: 'popularity.desc',
});
if (discoverWith === 'genre') {
query.set('with_genres', genreIdORStartYear);
query.set('page', currentPage.toString());
} else if (discoverWith === 'year') {
query.set('primary_release_date.gte', `${genreIdORStartYear}-01-01`);
query.set('primary_release_date.lte', `${endYear!}-12-31`);
query.set('page', currentPage.toString());
}
return query.toString();
}
이 과정에서 성인물을 거를 수 있는 필터는
certification.gte, certification.lte, certification_country
이 세가지를 설정해줘야한다.
‼️주의할점‼️
certification.gte이다. certification_gte로 했다가
안 먹혀서 1시간동안 찾음 아오...^^...
⬇️ 전체 코드. TS를 사용하곤 있지만...혹시나 나중에 헷갈릴까 JsDoc도 야무지게 써 줌.
/**
* 장르 혹은 시작~종료 년도로 영화를 검색할 때 API 요청 query를 생성하는 함수
* @function
* @param discoverWith "genre" 혹은 "year"로 설정하여 장르 검색이나 연도별 검색을 지정할 수 있음
* @param currentPage 표시해 줄 page를 설정, url에 있는 page 파라미터를 넣으면 됨
* @param genreId 장르 id
* @param startYear 시작년도
* @param endYear 종료년도
*/
function buildTMDBQuery(
discoverWith: 'genre',
currentPage: number,
genreId: string,
): string;
function buildTMDBQuery(
discoverWith: 'year',
currentPage: number,
startYear: string,
endYear: string,
): string;
function buildTMDBQuery(
discoverWith: 'genre' | 'year',
currentPage: number,
genreIdORStartYear: string,
endYear?: string,
): string {
const query = new URLSearchParams({
'certification.gte': 'ALL',
'certification.lte': '19',
certification_country: 'KR',
include_adult: 'false',
include_video: 'false',
language: 'ko-KR',
sort_by: 'popularity.desc',
});
if (discoverWith === 'genre') {
query.set('with_genres', genreIdORStartYear);
query.set('page', currentPage.toString());
} else if (discoverWith === 'year') {
query.set('primary_release_date.gte', `${genreIdORStartYear}-01-01`);
query.set('primary_release_date.lte', `${endYear!}-12-31`);
query.set('page', currentPage.toString());
}
return query.toString();
}
그리고 이 쿼리스트링을 이용해서 데이터를 가져오는 함수를 만듦
똑같이 오버로딩을 사용해서 만들었다.
function getDiscoverMovie(
discoverWith: 'genre',
currentPage: number,
genreId: string,
): Promise<MovieListsType | undefined>;
function getDiscoverMovie(
discoverWith: 'year',
currentPage: number,
startYear: string,
endYear: string,
): Promise<MovieListsType | undefined>;
async function getDiscoverMovie(
discoverWith: 'genre' | 'year',
currentPage: number,
genreIdORStartYear: string,
endYear?: string,
): Promise<MovieListsType | undefined> {
if (discoverWith === 'genre') {
const genreQuery = buildTMDBQuery('genre', currentPage, genreIdORStartYear);
const res = await fetch(
`https://api.themoviedb.org/3/discover/movie?${genreQuery}`,
options,
);
return res.json();
} else if (discoverWith === 'year') {
const yearQuery = buildTMDBQuery(
'year',
currentPage,
genreIdORStartYear,
endYear!,
);
const res = await fetch(
`https://api.themoviedb.org/3/discover/movie?${yearQuery}`,
options,
);
return res.json();
}
}
그리고 결과는 대만족~!! region값도 넣어줬더니
한국에서 개봉한 영화들만 나와서 더 보기 편해졌다. 국b