결론부터 말하자면, 대소문자 구분 없이 + 공백 구분없이 조회하는 조건을 추가해야 했다.
아래는 소환사 추가 API의 동작 순서이다.
사용자 요청(소환사 명: 묵직한큰주먹) => DB에 이미 존재하는지 조회 => (없으면) 라이엇 API에 정보 요청 => DB저장
이떄 "DB에 이미 존재하는지 조회"하는 로직을 라이엇API의 검증 로직과 동일하게 쿼리를 작성해야 했다.
아래는 라이엇 API 요청시 summonerName파라미터에 대한 조건이다.
라이엇DB측에서 저장하고 있는 소환사 명을 "공식 이름"이라 가정한다.
- 대소문자는 구분하지 않는다.
e.g. 공식 이름이 "Hide on bush"일떄, "hide ON BUSH"로 입력해도 된다.
- 띄어쓰기 구분은 상황에 따라 다르다.
1. 소환사명이 오직 영문으로만 구성된 경우 => 소환사 명의 띄어쓰기를 지켜야한다.
e.g. 공식 이름이 "Hide on bush"인 경우. "Hideonbush" 안됨.
2. 소환사명이 한글을 포함한 경우 => 띄어쓰기는 무시된다.
e.g. 공식 이름이 "묵직한큰주먹"인 경우. "묵직 한큰주먹", "묵직한 큰주먹" 모두 가능
다음과 같은 순서로 쿼리에 검증조건을 동적으로 추가하면 된다.
1. 대소문자는 구분하지 않는다.
2. 소환사 명이 순수 영문명인지, 아닌지(한글, 숫자포함) 판단
3. 한글이나 숫자가 포함되어 있으면, 띄어쓰기 무시하는 조건을 추가한다.
입력받은 summonerName을 소문자로 바꾸고, 쿼리문에 LOWER()함수를 사용하면 된다. (MYSQL을 사용하고 있으며, DB마다 다를 수 있다.)
public static boolean isPureEnglish(String summonerName) {
return summonerName.matches("^[a-zA-Z]+$");
}
isPureEnglish("abc")// true
isPureEnglish("한글Name123")// false
띄어쓰기를 무시하려면, 입력받은 summonerName의 공백을 제거하고, MYSQL의 REPLACE(summonerName, " ", "")함수를 이용하면 된다.
추가로, Querydsl에서 LOWER(), REPLACE()와 같은 SQL function을 사용하려면 Expressions.stringTemplate를 사용하면 된다.
Spring Data JPA, Querydsl을 같이 사용하고 있어서, custom repository를 따로 등록했고, custom repository안에 아래 코드를 추가하였다.
@Override
public Summoner findExistingSummoner(Long userId, String summonerName, String tagLine) {
summonerName = summonerName.toLowerCase();
JPAQuery<Summoner> query = queryFactory
.select(summoner)
.from(summoner)
.where(summoner.userId.eq(userId))
.where(summoner.tagLine.eq(tagLine));
if(isPureEnglish(summonerName)) {
query.where(Expressions.stringTemplate("LOWER({0})", summoner.summonerName).eq(summonerName));
}else {
summonerName = summonerName.replaceAll("\\s", "");
query.where(Expressions.stringTemplate("REPLACE(LOWER({0}), ' ', '')", summoner.summonerName).eq(summonerName));
}
Summoner content = query.fetchOne();
return content;
}
private boolean isPureEnglish(String summonerName) {
//공백은 무시
return summonerName.replaceAll("\\s", "").matches("^[a-zA-Z]+$");
}
소환사명: 묵직한큰주먹(순수 영문명이 아니라서, replace, lower 모두 잘 실행되었다.)
Hibernate:
select
s1_0.summoner_id,
s1_0.created_at,
s1_0.iconId,
s1_0.level,
s1_0.losses,
s1_0.mmr,
s1_0.rank1,
s1_0.summonerName,
s1_0.tagLine,
s1_0.tier,
s1_0.updated_at,
s1_0.user_id,
s1_0.wins
from
summoners s1_0
where
s1_0.user_id=?
and s1_0.tagLine=?
and replace(lower(s1_0.summonerName), ' ', '')=?
소환사명: Hide on bush (순수 영문명이여서 lower만 실행되었다.)
Hibernate:
select
s1_0.summoner_id,
s1_0.created_at,
s1_0.iconId,
s1_0.level,
s1_0.losses,
s1_0.mmr,
s1_0.rank1,
s1_0.summonerName,
s1_0.tagLine,
s1_0.tier,
s1_0.updated_at,
s1_0.user_id,
s1_0.wins
from
summoners s1_0
where
s1_0.user_id=?
and s1_0.tagLine=?
and lower(s1_0.summonerName)=?
참고자료
https://solbel.tistory.com/1091
https://engineeringcode.tistory.com/610
https://velog.io/@may_yun/Querydsl-SQL-Function-%ED%98%B8%EC%B6%9C