[Node JS] 자동완성 구현

HTTP GET request

Node JS express, ajax, sqlite3 그리고 python script를 이용해 검색박스에 자동완성 기능을 구현했다.

Summary

  1. 클라이언트에서 서버로 GET요청
    • 클라이언트 측에서 검색박스에 키보드 타이핑을 할때마다 텍스트값이 ajax통신을 이용해 서버로 GET요청을 타고 들어간다.
  2. 서버에서 파이썬 함수 호출
    • 서버의 해당 미들웨어에선 미리 만들어둔 파이썬 스크립트가 인자로 전달받은 텍스트값과 sqlite로 만들어둔 DB와 비교해 일치하는지 확인 후 일치하는 값 모두를 리턴해준다.
  3. 서버에서 GET요청에 대한 응답
    • 파이썬 리턴이 완료되면 미들웨어에서 마지막으로 전달받은 리턴값을 클라이언트 측으로 응답한다.

What is

HTTP

http는 웹서버와 웹브라우저간의 통신을 하기 위한 표준 방식이다. 한 컴퓨터에서 다른 컴퓨터로 데이터를 요청하고 응답해주기 위한 규칙이라고 생각하면 된다. 텍스트, 이미지 및 기타 멀티미디어 파일과 같은 데이터들이 웹에서 공유될 수 있다.

HTTP GET request

• 읽을때
• 길이제한 있음
• 민감한 정보 포함 X
• 브라우저 히스토리에 매개변수가 남을수 있음
URL에 데이터가 노출 O

HTTP POST request

• 작성할때
• 길이제한 없음
• 브라우저 히스토리에 매개변수가 남을수 없음
URL에 데이터가 노출 X
• 데이터는 http requestrequest body에 저장

HTTP PUT request

•수정할때

HTTP DELETE request

•삭제할때

Response

Response는 서버에서 만들어지며 클라이언트로 보내진다. 클라이언트에서 Request를 보냈을때 Response로 답장할 수 있다.

References:

  1. https://www.w3schools.com/tags/ref_httpmethods.asp
  2. https://www.ibm.com/docs/en/cics-ts/5.2?topic=protocol-http-responses
  3. https://www.geeksforgeeks.org/http-full-form/

1. 클라이언트에서 서버로 GET요청

아래는 GIF이미지에 나오는 html파일 코드의 일부분이다.
htmloninput이벤트를 사용해 키보드 입력이 있을때마다 자바스크립트의 sendAjax()함수를 호출하도록 해놨다.

<!-- keystroke.html -->
<label for="Country">Country</label> 
<input name="Country" type="text" id="Country" placeholder="Enter Country" oninput='sendAjax()' /> <br>
answer:  <span id="answer"></span> <br><br>
  1. sendAjax()함수가 호출되면 검색박스의 텍스트값을 document.getElementById('Country').value변수를 이용해 country변수에 넣어준다.

    2-1. 만약 country변수 값이 없다면 ajax함수를 호출하지 않고 answer.innerHTML에 빈값을 넣어준 후 sendAjax()함수를 끝낸다.
    2-2. 만약 country변수 값이 있다면 ajax함수를 호출하고 ajax함수를 호출한다.
    미들웨어 요청타입과 ajax함수의 type: "get"부분, 그리고 url: 'http://localhost:8080/keystroke/:country'부분과 Node JS미들웨어 경로 부분이 일치해야 통신이 가능하니 잘 확인해 주어야 한다. data:{country:country}에서 왼쪽 country는 서버측에서 사용되어질 변수 이름이고 오른쪽 country는 지금 자바스크립트에서 사용하는 변수다.

//javascript
<script>
	function sendAjax() {
		var country = document.getElementById("Country").value;
		if (country==='') { // if country variable has nothing, change answer.innerHTML variable to empty varaible.
			answer.innerHTML = '';
			return ;
		}
		$.ajax({
			type: "get",
			url: 'http://localhost:8080/keystroke/:country',
        // left side 'country' var is used in the server side later,
        // right side 'country' var is being used here in javascript. 
			data: {country:country},
			dataType:'json',
			success: function(res) {
				answer.innerHTML = res.country;
			}
		});
	}
</script>

2. 서버에서 파이썬함수 호출

▼index.js▼

지금까지 html파일을 이용해 클라이언트 측에서 작업해 둔 내용을 서버에서 돌리려면 res.sendFile()메소드를 사용하면 된다. 이렇게 하면 해당 url에 대한 GET요청이 들어왔을때 방금까지 만들어 줬던 keystroke.html파일로 응답할 수 있다.

app.get('/keystroke', function(req, res) {
    res.sendFile(__dirname + '/keystroke.html');
});

검색상자에서 sendAjax()함수를 이용한 /keystroke/:country경로로 get요청이 들어왔을때 해당 경로를 가진 GET타입의 미들웨어가 실행된다. 해당 미들웨어는 파이썬 스크립트를 실행할 수 있는 내용을 포함하고 있다. 추가로 파이썬 스크립트를 실행하기 위해서 python-shell설치와 import 해주도록 하자.

npm install python-shell
//  importing python-shell
var PythonShell = require('python-shell');
app.get('/keystroke/:country', function(req, res) {
    var options = {
        mode: 'json',
        pythonPath:'',  
        pythonOptions:['-u'],
        scriptPath:'',
        args: [req.query.country]
    };
    PythonShell.PythonShell.run('./pythonScript/prePopulate.py', options, function(err, results) {
        if(err) throw err;
        res.status(200).send(results[0]);
    });
});

▼prePopulate.py▼
파이썬 함수에서 인자로 받은 변수에 접근은 sys.argv를 통해 가능하다.
sys.argv[0]은 변수의 갯수를 담고있고 sys.argv[1:]가 넘겨받은 변수이다.

import sqlite3
import sys
import json

def main(arg):
    #sql processing
    conn = sqlite3.connect("test.db")
    cursor = conn.cursor()
    cursor.execute("SELECT name FROM COUNTRY")
    data = cursor.fetchall()

    results = {}
    results["country"] = []
    last_answer = ''

    #comparing with the db file
    for row in data:
        for word in row:
            if word != last_answer and arg == word[:len(arg)].strip().lower():
                results["country"].append(word)
                last_answer = word
    return_value = json.dumps(results)
    print(return_value)

if __name__ == '__main__':
    main(sys.argv[1])

3. 서버에서 GET요청에 대한 응답

파이썬 스크립트가 끝나면 리턴값은 results변수에 담겨져 나온다.
res.status(200).send()메소드를 이용해 클라이언트측으로 응답할 수 있다.

PythonShell.PythonShell.run('./pythonScript/prePopulate.py', options, function(err, results) {
	if(err) throw err;
	res.status(200).send(results[0]);
});

sendAjax()함수의 ajax함수에서 응답을 받아서 answer.innerHTML변수를 이용해 결과값을 클라이언트측에 나타낼 수 있다.

$.ajax({
	type: "get",
	url: 'http://localhost:8080/keystroke/:country',
	data: {country:country},
	dataType:'json',
	success: function(res) {
		answer.innerHTML = res.country;
	}
});

마지막으로 폴더의 상태는 아래와 같다.

좋은 웹페이지 즐겨찾기