문제
- sql실습
stockInfo 테이블 생성 후
stockName(varchar 100), stockUrl (varchar 500) 컬럼 생성, 선정한 주식 5종목 정보 저장(naver 증권에서 url 추출)
-오픈소스 프로그래밍
80포트 사용
/ 접속시 페이지 로드
/main 접속시 페이지 로드
/getStockInfo API : DB에 저장된 주식 목록 조회
/getStockPrice API : DB에 저장된 해당 주식의 url로 네이버 request를 전송하여 가격을 조회
-웹ui
selectbox에 DB에 저장된 5개 종목을 선택할 수 있게 하여 가격보기 버튼을 클릭 시
현재시점부터 최대 30초까지의 주식 정보를 1초에 한번씩 실시간으로 그래프로 출력
- 제출파일
1. heidisql에서 테이블 오른쪽버튼 클릭 -> 데이터베이스를 sql로 내보내기 후 데이터베이스 생성x, 테이블 생성x -> db.sql로 파일 저장
2. app.js 서버파일
3. main.html html파일
제목 : 이름_기말고사
세 파일을 압축 후 파일 첨부해서 870222@hanmail.net 으로 제출
방법 1.
app.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app).listen(80);
console.log("\n\nServer is running...\n\n")
var mysql = require('mysql');
var request = require('request');
var connection = mysql.createConnection({
host: 'localhost',
port: 3308,
user:'root',
password: '1234',
database: 'javascript'
});
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({limit: '50mb', extended: false}));
app.use(bodyParser.json({limit: '50mb'}));
app.get('/', function (req, res) {
res.sendfile("stockList.html");
});
app.get('/main', function (req, res) {
res.sendfile("stockList.html");
});
app.get('/realTimePrice', function (req, res) {
res.sendfile("realTimePrice.html");
});
// 메인 페이지 접속시 stockInfo 테이블 정보를 가져오는 라우터
app.get('/getStockInfo', function (req, res) {
var query = `SELECT * FROM stockInfo`;
connection.query(query, function (err, rows, fields) {
if (err) throw err;
// console.log(rows);
res.send(rows);
}
);
});
// 실시간 주식 정보를 가져오는 라우터
app.get('/getStockPrice', function (req, res) {
var name = req.query.company;
var query = `SELECT stockUrl FROM stockInfo WHERE stockName = '${name}'`;
connection.query(query, function (err, rows, fields){
if (err) throw err;
// var response = JSON.stringify(rows); // 이렇게 하면 Object를 [{"stockUrl":"https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:000660|SERVICE_RECENT_ITEM:000660"}] 로 변환해준다.
var targetUrl = rows[0].stockUrl;
const options = {
url:`${targetUrl}`,
method: 'GET'
}
request.get(options, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
res.send(''+price);
});
});
});
// 서버 기동시 매 초마다 DB에 주식 정보를 기록
const hynix = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:000660|SERVICE_RECENT_ITEM:000660',
method: 'GET'
}
const coway = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:021240|SERVICE_RECENT_ITEM:021240',
method: 'GET'
}
const lgelectronics = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:066570|SERVICE_RECENT_ITEM:066570',
method: 'GET'
}
const cj = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:001040|SERVICE_RECENT_ITEM:001040',
method: 'GET'
}
const chongkundang = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:185750|SERVICE_RECENT_ITEM:185750',
method: 'GET'
}
setInterval(function () {
request.get(hynix, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO hynix (price) VALUES('${price}');`)
});
request.get(coway, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO coway (price) VALUES('${price}');`)
});
request.get(lgelectronics, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO lgelectronics (price) VALUES('${price}');`)
});
request.get(cj, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO cj (price) VALUES('${price}');`)
});
request.get(chongkundang, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO chongkundang (price) VALUES('${price}');`)
});
},1000);
stockList.html (http://localhost/)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>주식 리스트</title>
</head>
<body>
<h>주식 리스트 페이지입니다</h>
<input type="button" value="실시간 주식 정보 조회하러 가기" id="mainBtn" onclick = "goToRealTimePrice()">
<br><br>
<span id="stockList"></span>
</body>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$.ajax({
url : 'getStockInfo',
data : {
},
success : function(res){
$("#stockList").append(`저장된 주식 리스트는 다음과 같습니다.<br>`);
for (var i=0; i<res.length; i++) {
var name = res[i].stockName;
$("#stockList").append(`${name}<br>`);
}
}
});
function goToRealTimePrice() {
location.href = "/realTimePrice"
}
</script>
</html>
realTimePrice.html (http://localhost/realTimePrice)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>실시간 주식 정보</title>
</head>
<body>
<h>실시간 주식 정보 페이지입니다</h>
<input type="button" value="주식 리스트 보러 가기" id="mainBtn" onclick = "goToStockList()">
<br>
<select name="company" id="company">
<option value="hynix">하이닉스</option>
<option value="coway">코웨이</option>
<option value="lgelectronics">LG전자</option>
<option value="cj">CJ</option>
<option value="chongkundang">종근당</option>
</select>
<input type="button" value="가격보기" onclick="sendRequest()">
<br><br>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
</body>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
function goToStockList() {
location.href = "/"
}
var time;
var stockPrice;
var graphValue = [];
var myGraph;
// var graphValue = new Array(30);
function sendRequest() {
// 버튼 누를 때 초기화
time = 0;
graphValue = [];
clearInterval(myGraph);
var company = $("#company option:selected").val();
// 버튼 누른 후 반복되는 부분
myGraph = setInterval(function () {
$.ajax({
url : '/getStockPrice',
type : 'GET',
data : {
company : `${company}`
},
success : function(res) {
stockPrice = res;
// console.log(res);
graphValue.push([time,Number(stockPrice)])
if (graphValue.length > 30) {
graphValue.shift();
}
time++;
drawCurveTypes(graphValue); // 구글 차트를 그려주는 함수를 호출한다.
}
});
},1000);
};
google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(drawCurveTypes);
function drawCurveTypes() {
var data = new google.visualization.DataTable();
data.addColumn('number', '시간(초)');
data.addColumn('number', '가격');
// data.addColumn('number', `${company}`);
data.addRows(graphValue);
var options = {
hAxis: {
title: '시간(초)'
},
vAxis: {
title: '가격(원)'
},
series: {
1: {curveType: 'function'}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</html>
방법 1은 realTImePrice.html이 서버에 요청을 보내면 /getStockPrice 라우터가 매 초 요청이 들어올 때마다 DB에서 URL을 새로 가져왔다. 그래서 방법 2에서 버튼을 누르면 setInterval이 시작되기 전에 /getStockInfo 라우터에 한 번 가서 URL을 가져오고 그것을 변수에 담아 /getStockPrice에 요청을 보내도록 수정했다. (방법 2가 방법 1보다 서버 부하를 줄이기 위해 개선되었음)
하지만 방법 1에서 배울 부분은 DB가 주는 response는 언제나
[
{ Key1 : Value1,
Key2 : Value2,
Key3 : Value3
}
]
형태의 객체라는 것이다.
자바에서 DB가 보내주는 response를 ResultSet으로 받아서 객체의 i번째의 Key로 Value를 가져와 String으로 변환했던 것을 생각하자.
자바스크립트에서도 마찬가지로 객체의 i번째의 Key에 접근해서 Value를 가져와야한다.
첫 번째 방법은,
var response = JSON.stringify(rows); 이렇게 하면 Object를
[{"stockUrl":"https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:000660|SERVICE_RECENT_ITEM:000660"}]
로 변환해준다. Object에서 이제 우리가 볼 수 있는 자료의 모습으로 바꿔주었고, 그 다음 response[0].stockUrl을 하면 된다.
두 번째 방법은 자바스크립트는 관대한 언어라 바로 이렇게만 해도 꺼내올 수 있다.
var targetUrl = rows[0].stockUrl;
방법 2.
app.js와 realTimePrice.html 2개만 바뀌었다.
app.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app).listen(80);
console.log("\n\nServer is running...\n\n")
var mysql = require('mysql');
var request = require('request');
var connection = mysql.createConnection({
host: 'localhost',
port: 3308,
user:'root',
password: '1234',
database: 'javascript'
});
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({limit: '50mb', extended: false}));
app.use(bodyParser.json({limit: '50mb'}));
app.get('/', function (req, res) {
res.sendfile("stockList.html");
});
app.get('/main', function (req, res) {
res.sendfile("stockList.html");
});
app.get('/realTimePrice', function (req, res) {
res.sendfile("realTimePrice.html");
});
// 메인 페이지 접속시 stockInfo 테이블 정보를 가져오는 라우터, 실시간 주식 정보 페이지에서 '가격보기' 버튼 클릭시 해당 기업 주식 URL 정보 가져오는 라우터
app.get('/getStockInfo', function (req, res) {
var query = `SELECT * FROM stockInfo`;
connection.query(query, function (err, rows, fields) {
if (err) throw err;
// console.log(rows);
res.send(rows);
}
);
});
// 실시간 주식 정보 페이지에서 '가격보기' 버튼 클릭시 주식 정보 읽어오는 라우터
app.get('/getStockPrice', function (req, res) {
var stockUrl = req.query.stockUrl;
const options = {
url:`${stockUrl}`,
method: 'GET'
}
request.get(options, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
res.send(''+price);
});
});
// 서버 기동시 매 초마다 DB에 주식 정보를 기록
const hynix = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:000660|SERVICE_RECENT_ITEM:000660',
method: 'GET'
}
const coway = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:021240|SERVICE_RECENT_ITEM:021240',
method: 'GET'
}
const lgelectronics = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:066570|SERVICE_RECENT_ITEM:066570',
method: 'GET'
}
const cj = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:001040|SERVICE_RECENT_ITEM:001040',
method: 'GET'
}
const chongkundang = {
url:'https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:185750|SERVICE_RECENT_ITEM:185750',
method: 'GET'
}
setInterval(function () {
request.get(hynix, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO hynix (price) VALUES('${price}');`)
});
request.get(coway, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO coway (price) VALUES('${price}');`)
});
request.get(lgelectronics, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO lgelectronics (price) VALUES('${price}');`)
});
request.get(cj, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO cj (price) VALUES('${price}');`)
});
request.get(chongkundang, function(err,httpResponse,body){
response = JSON.parse(httpResponse.body);
var price = response.result.areas[0].datas[0].nv;
connection.query(`INSERT INTO chongkundang (price) VALUES('${price}');`)
});
},1000);
realTimePrice.html (http://localhost/realTimePrice)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>실시간 주식 정보</title>
</head>
<body>
<h>실시간 주식 정보 페이지입니다</h>
<input type="button" value="주식 리스트 보러 가기" id="mainBtn" onclick = "goToStockList()">
<br>
<select name="company" id="company">
<option value="hynix">하이닉스</option>
<option value="coway">코웨이</option>
<option value="lgelectronics">LG전자</option>
<option value="cj">CJ</option>
<option value="chongkundang">종근당</option>
</select>
<input type="button" value="가격보기" onclick="sendRequest()">
<br><br>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
</body>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
function goToStockList() {
location.href = "/"
}
var time;
var stockPrice;
var graphValue = [];
var myGraph;
// var graphValue = new Array(30);
function sendRequest() {
// 버튼 누를 때 초기화
time = 0;
graphValue = [];
clearInterval(myGraph);
var company = $("#company option:selected").val();
var stockUrl;
$.ajax({
url : 'getStockInfo',
data : {
},
success : function(res){
for (var i=0; i<res.length; i++) {
if (company == res[i].stockName) {
stockUrl = res[i].stockUrl;
return;
}
}
}
});
// 버튼 누른 후 반복되는 부분
myGraph = setInterval(function () {
$.ajax({
url : '/getStockPrice',
type : 'GET',
data : {
stockUrl : `${stockUrl}`
},
success : function(res) {
stockPrice = res;
// console.log(res);
graphValue.push([time,Number(stockPrice)])
if (graphValue.length > 30) {
graphValue.shift();
}
time++;
drawCurveTypes(graphValue); // 구글 차트를 그려주는 함수를 호출한다.
}
});
},1000);
};
google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(drawCurveTypes);
function drawCurveTypes() {
var data = new google.visualization.DataTable();
data.addColumn('number', '시간(초)');
data.addColumn('number', '가격');
// data.addColumn('number', `${company}`);
data.addRows(graphValue);
var options = {
hAxis: {
title: '시간(초)'
},
vAxis: {
title: '가격(원)'
},
series: {
1: {curveType: 'function'}
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</html>
방법 1은 realTImePrice.html이 서버에 요청을 보내면 /getStockPrice 라우터가 매 초 요청이 들어올 때마다 DB에서 URL을 새로 가져왔다. 그래서 방법 2에서 버튼을 누르면 setInterval이 시작되기 전에 /getStockInfo 라우터에 한 번 가서 URL을 가져오고 그것을 변수에 담아 /getStockPrice에 요청을 보내도록 수정했다. 수정을 위해 app.js와 realTimePrice.html이 바뀌었다.
DB
stockInfo
CREATE TABLE javascript.stockInfo (
stockName varchar(100) NULL,
stockUrl varchar(500) NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
hynix
CREATE TABLE javascript.hynix (
price varchar(100) NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
coway
CREATE TABLE javascript.coway (
price varchar(100) NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
lgelectronics
CREATE TABLE javascript.lgelectronics (
price varchar(100) NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
cj
CREATE TABLE javascript.cj (
price varchar(100) NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
chongkundang
CREATE TABLE javascript.chongkundang (
price varchar(100) NULL,
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NULL
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8
COLLATE=utf8_general_ci;
네이버 주식 real time 기본 폼
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:[종목코드번호]|SERVICE_RECENT_ITEM:[종목코드번호]
셀트리온
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:068270|SERVICE_RECENT_ITEM:068270
네이버
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:035420|SERVICE_RECENT_ITEM:035420
카카오
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:035720|SERVICE_RECENT_ITEM:035720
하이닉스 hynix
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:000660|SERVICE_RECENT_ITEM:000660
코웨이 coway
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:021240|SERVICE_RECENT_ITEM:021240
LG전자 lgelectronics
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:066570|SERVICE_RECENT_ITEM:066570
CJ cj
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:001040|SERVICE_RECENT_ITEM:001040
종근당 chongkundang
https://polling.finance.naver.com/api/realtime.nhn?query=SERVICE_ITEM:185750|SERVICE_RECENT_ITEM:185750
'개발자 > Javascript' 카테고리의 다른 글
Refused to apply style from ~~~ because its MIME type ~~~ 에러 (0) | 2020.10.28 |
---|---|
Javascript (자바스크립트) Crawling, Excel Download 8.27 (0) | 2020.09.24 |
Javascript (자바스크립트) 네이버 주식 DB 저장, 구글 차트 06.25 (0) | 2020.07.01 |
Javascript (자바스크립트) setInterval, setTimeout 06.18 (0) | 2020.07.01 |
Javascript (자바스크립트) Query Table Join (aircraft 06.11) (0) | 2020.07.01 |