<django> 검색어 자동완성 구현

Sinjae Lee·2021년 7월 6일
1

검색어 자동완성 기능을 만들고 싶다

이런 기능 말이다

자 참고로 말하자면 지금 내가 작업하고 있는 프로젝트는 왓차피디아의 사이트 틀에 영화 카테고리 대신 편의점 상품들을 구성시켜서 추천 및 리뷰 등의 기능이 담긴 서비스 사이트를 만들고자 한다 어떤 부분을 어떻게 구현해야 할까?

1) 새로운 글자가 입력될때마다 request 가 날라오게 한다. 그러면 나는 request 안에 담긴 해당 글자를 필터링해서 db 내 상품 이름이나 카테고리 이름 과 같은것에 매칭이 된다면 추가 시켜서 respond 보낸다.

request 안에 input 이 담겨서 오니까 body 에 담겨서 오나? 그러면 post method 사용하면 되겠네!
라고 생각했지만 땡땡땡

query parameter 라고 들어보았는가?

이렇게 url 엔드포인트의 끝에 ? 부터가 query str 이라고 할 수 있다.

예를 들어 상품이 여러가지 있는 아래와 같은 페이지가 있고, 상품을 누르면 상세페이지로 이동한다고 해보자 그러면 상품을 누를때마다 리퀘스트에 새로운 body 를 담아서 날려줄까? 아니다 /menu?id=1 이런식으로 엔드포인트 뒤에 query str을 담아서 날려줄 수 있다.

그러면 이렇게 날라오는 query str 을 어떻게 사용해줄 수 있을까?
아래 4번째 줄의 request.GET.get('word', '') 코드로 활용해줄 수 있다.

class SearchView(View):
    def get(self, request):
        try:
            word = request.GET.get('word', '')
            results=[]

            ko_name       = Product.objects.filter(korean_name__icontains = word).exists()
            en_name       = Product.objects.filter(english_name__icontains = word).exists()
            category_name = Category.objects.filter(name__icontains = word).exists()
            
            if ko_name:
                products  = Product.objects.filter(korean_name__icontains = word)
                for product in products:
                    results.append({
                        'word' : product.korean_name
                    })

            if en_name:
                products  = Product.objects.filter(english_name__icontains = word)
                for product in products:
                    results.append({
                        'word' : product.english_name
                    })

            if category_name:
                categories = Category.objects.filter(name__icontains = word)
                for category in categories:
                    results.append({
                        'word' : category.name
                    })
            
            return JsonResponse({'results': results}, status=201)
        
        except Exception as error:
            return JsonResponse({'message': error}, status=400)

위의 code로 아래의 db 를 가지고 한번 테스트 해보자

아래와 같이 respond 보내는것을 볼 수 있다.

class SearchView(View):
    def get(self, request):
        try:
        	print(request)
            word = request.GET.get('word', '')
            print(word)
            print(type(word))

해당 코드의 request와 word 가 어떻게 날라올까 궁금해서 print 찍어봤다

WSGI 가 web 과 통신하는 부분이라고 듣긴 했는데 추가적으로 공부해봐야겠다.
request.GET.get('word', '') 는 코
라는 한글자가 출력되었다
일단 201ok 니까 str 맞겠지만 혹시 몰라 type 도 찍어봤더니 역시 str
post 라고 생각했던 많은 기능들을 get 으로 작성 가능하겠다

추가로 공부할 부분

오늘 프로젝트 진행하며 내일 추가로 공해야 겠다고 생각된 것은
1) WSGI
2) 200ok or 201ok?? 400, 401 ... ? - 생각해보니 정확하게 모르고 그냥 쓰고 있었다

추가로 알게된 내용

오늘 작업하며 추가로 알게된 사실들이다
1) 앱은 테이블 단위로 쪼개는 것이 best 라고 할 수 있다.
모델링을 작성하다가 앱을 나누는 기준이 궁금해져서 병민님께 여쭤보았다.
이런 조그마한 프로젝트 아니고 실무에서는 migrations 한번에 서버가 휘청거릴 수도 있다.
그렇기에 내가 rating 테이블을 만들고 rating table 을 활용해서 추후 새로운 기능과 모델을 추가한다고 했을때 해당 모델이 user 나 product 같은 앱 안의 모델로 존재한다면?
이런것이 개발자들이 이야기 하는 scalable 하게 개발하라는 이야기인가 생각되었다
똑같은 예로 image table 같이 추후 계속 db에 늘어날 것은 미리 만들어 주어라

2) 좋아요 나 follower 의 count 가 필요하다. 어떤 방법이 좋은 걸까?
나는 처음에 query set울 count 로 다 찾고 계산 로직을 쓰는것이 오히려 속도나 개발효율등이 더 좋지 않은 것이 아닌가? 그렇기 때문에 처음부터 product 나 user table에 like_count, follower_count 같은 column을 추가하고 로직을 통해 계산해주는 것이 맞지 않나 라고 생각했었다.
맞지 않는 생각이었다.
column 하나도 메모리를 잡아먹는 행위다 column 과 모델링은 간소화 될 수록 좋다.
이미 만들어 놓은 테이블이 있다면 해당 테이블에서 활용하자

3) 추가로 검색어를 사실 ㄱ, ㅋ 같이 자음 하나 단위로 검색어 완성이 날라오게 완성하고 싶었는데 elastic search 를 사용해야한다고 한다. 추후 공부해보자!

profile
Back-end developer

0개의 댓글