<Spring & JPA 웹서비스 만들기 > 구현 (3) - Redis 자동완성
by BFine반응형
가. 검색어 자동완성 기능(AutoComplete)
a. 어떻게 구현할까?
- 거창하게 쓰긴 했지만 사실 단순 검색하는 기능으로 만들었다.
- 제대로 하려면 한글 형태소 분석하고 성능 문제도 해결 해야하지만
Redis로 하는 자료들이 없기도 하고 JPA 외에 시간을 쓰는 것 같아서 단순 검색으로 만들었다.
- Redis로 검색어 자동완성(autoComplete)을 만들어보자
b. 테스트 작성
@SpringBootTest
public class UserServiceTest {
@Autowired
RedisTemplate<String,Object> redisTemplate;
@Test
public void 유저이름검색테스트() {
String key = "USER_NAME";
HashOperations<String,String,Integer> hashOperations=
redisTemplate.opsForHash();
Set<String> a = hashOperations.keys(key);
hashOperations.put(key, "김철수", 0);
hashOperations.put(key, "김수철", 0);
ScanOptions scanOptions = ScanOptions.scanOptions().match("김*").build();
Cursor<Entry<String,Integer>> cursor= hashOperations.scan(key, scanOptions);
List<String> searchList = new ArrayList<>();
while(cursor.hasNext()){
Entry<String,Integer> entry = cursor.next();
searchList.add(entry.getKey());
}
assertEquals(searchList.size(), 2);
}
}
- HashOperation을 이용해서 Hash Key에는 이름, value는 0(이부분은 ID값)으로 처리했다.
- 검색어가 들어오면 Redis Scan으로 몽땅 검색해서 가져온다.
c. 서비스 작성
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final RedisTemplate<String,Object> redisTemplate;
private static final String SEARCH_KEY = "USER_NAME";
private static final String ASTERISK = "*";
private static final int TIME_LIMIT = 5;
public List<String> getSearchNameList(RequestDTO requestDTO){
HashOperations<String,String,Long> hashOperations= redisTemplate.opsForHash();
if(redisTemplate.getExpire(SEARCH_KEY) < 0){
List<User> nameList = userRepository.findAll();
Map<String,Long> nameDataMap = nameList.stream()
.collect(Collectors.toMap(User::getName,User::getId));
hashOperations.putAll(SEARCH_KEY, nameDataMap);
redisTemplate.expire(SEARCH_KEY,TIME_LIMIT,TimeUnit.SECONDS);
}
ScanOptions scanOptions = ScanOptions.scanOptions()
.match(requestDTO.getName()
+ASTERISK).build();
Cursor<Entry<String,Long>> cursor=
hashOperations.scan(SEARCH_KEY, scanOptions);
List<String> searchList = new ArrayList<>();
while(cursor.hasNext()){
Entry<String,Long> entry = cursor.next();
searchList.add(entry.getKey());
}
return searchList;
}
}
- 실제 코드에서는 DB에서 모든 User를 가져와서 Redis에 저장하고 5초동안 유지하는 해괴한 코드를 만들었다.
- 테스트 해보고 싶어서 만들었고 5초인 이유는 새로운 유저에 대한 정보 그리고 타이핑 하는 동안은
DB에 데이터를 가져와서 Redis 처리하는 부분 없이 Redis에서만 가져오도록 했다.
- 저 value 부분에 KEY의 형태소를 리스트 형태로 저장하면 형태소 검색이 되지 않을까란 생각도 든다.
- 추후에 검색엔진(엘라스틱서치, 솔라)로 만들어 봐야겠다.
나. 동작화면
a. 설정하기 부분
- Keyup 이벤트를 걸어서 모든 입력에 대해서 서버로 요청하여 이름목록을 가져오도록 만들었다.
반응형
'공부 > JPA' 카테고리의 다른 글
<Spring & JPA 웹서비스 만들기 > 구현 (5) - 달력 만들기 (0) | 2021.02.12 |
---|---|
<Spring & JPA 웹서비스 만들기 > 구현 (4) - 화면 구성 (0) | 2021.02.06 |
<Spring & JPA 웹서비스 만들기 > 구현 (2) - 서비스's (0) | 2021.01.31 |
<Spring & JPA 웹서비스 만들기 > 구현 (1) - 엔티티's (0) | 2021.01.21 |
<Spring & JPA 웹서비스 만들기 > 설계 (2) - DB & TDD (0) | 2021.01.15 |
블로그의 정보
57개월 BackEnd
BFine