728x90

https://www.bxieinfinity.com/airdrop?r=bolbtc 

 

액시인피니티에서 포크되어 나온 백시인피니티라고 합니다.

메타마스크 or 트러스트월렛를 BSC메인넷에 연결하고 이메일만 입력해주시면

백시코인 100개 + 랜덤박스( 귀여운 캐릭터 + 토지 + 아이템) 등 받을 수 있어요!

저는 5~20$ 가치의 귀여운 백시펫이 나왔네요 ㅎㅎ 

백시인피니티 P2E게임은 12월28일날 출시한다고해요 ! 

 

 

사전예약방법은  우선 메타마스크를 설치하시고 BSC를 추가해주셔야 되는데 아래 링크가 정리가 잘되있더라구요!

https://skuld2000.tistory.com/175

 

바이낸스 스마트 체인(BSC) 메타마스크 월렛 셋팅 방법

바이낸스 스마트 체인(Binace Smart Chain) 작년, 바이낸스에서 BSC(바이낸스 스마트 체인) 을 런칭 한 후 이를 기반으로 여러가지 디파이(Defi) 서비스 들이 출시되었습니다. BSC 기반의 디파이 서비스

skuld2000.tistory.com

 

 

 

메타마스크 설치 + BSC환경 셋팅이 되셨다면  https://www.bxieinfinity.com/airdrop?r=bolbtc  백시인피니티에 가셔서 

BSC주소와 이메일주소만 입력하면 100백시코인과 랜덤보상이 주어집니다

 

현재 백시코인은 5000백시 = 0.1BNB 이며 

현재 기준1백시당 약 10원정도 하는거같네요!

 

728x90
728x90

모듈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
import FinanceDataReader as fdr
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
import tensorflow as tf
 
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM, Conv1D, Lambda
from tensorflow.keras.losses import Huber
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
cs
 

 

데이터수집 

데이터수집은 FinanceDataReader 모듈을 통해 가져왔으며 추후 개발할 웹사이트와 상호작용하기 위해 외부db와 연결할 예정이다. 

1
samsung = fdr.DataReader('005930',start='1990')
cs

데이터 전처리

 

주가 데이터에 대하여 딥러닝 모델이 잘 학습하기위해 정규화(Normalization)을 해줘야한다.

 

표준화(Standardization)

표준화는 데이터의 평균을 0 분산 및 표준편차를 1로 만들어 주는 과정

표준화를 하는이유는

서로다른 통계 데이터들을 비교하기 쉽기 때문.

표준화를 하면 평균은 0 , 분산과 표준편차는 1로 만들어 데이터의 분포를 단순화시키고 비교를 용이하게 해준다.

 

ex) (6 10 2 4 8) 의 데이터셋이 있을경우 이를 표준화한다면 

데이터의 평균 = (6+10+2+4+8) = 6

분산 = (4^2 + 4^2 + 2^2 + 2^2) / (5-1 )  = 10 

표준편차는  10의 제곱근이 된다

 

                                                                     표준화공식

표준화 코드 

X_ = (X - X.mean() )  / X.std()

 

 

16
17
18
19
scaler = MinMaxScaler()
scale_cols = ['Open''High''Low''Close''Volume']
scaled = scaler.fit_transform(samsung[scale_cols])
scaled #표준화 확인 
 
cs

 

1
df = pd.DataFrame(scaled, columns=scale_cols) #표준화 한 데이터셋을 통해 데이터프레임 생성
cs

 

Train / test 분할 

Train

모델을 학습하기 위한 dataset이다. 한 가지 계속 명심해야할 중요한 사실은

"모델을 학습하는데에는 오직 유일하게 Train dataset만 이용한다"

 

Test

test set 학습과 검증이 완료된 모델의 성능을 평가하기위한 dataset이다.

보통 Train : Test 데이터를 8 : 2로 나눈다 . 

 

 

20
21
22
23
x_train, x_test, y_train, y_test = train_test_split(df.drop('Close'1), df['Close'], test_size=0.2, random_state=0, shuffle=False)
x_train.shape, y_train.shape #데이터확인 
x_test.shape, y_test.shape #데이터 확인 
x_train #데이터확인 
 
cs

train은 4800개의 데이터로 test는 1200개의 데이터 학습할 데이터와  성능을 평가하기 위한 데이터들을  

8:2 로 나눠주었다.

 

TensroFlow Dataset을 활용한 시퀀스 데이터셋 구성

 

1
2
3
4
5
6
7
8
9
10
def windowed_dataset(series,window_size,batch_size,shuffle):
    series = tf.expand_dims(series,axis=-1)
    ds = tf.data.Dataset.from_tensor_slices(series)
    ds = ds.window(window_size + 1, shift=1, drop_remainder=True)
    ds = ds.flat_map(lambda w: w.batch(window_size + 1))
    
    if shuffle:
        ds = ds.shuffle(1000)
    ds = ds.map(lambda w: (w[:-1], w[-1]))
    return ds.batch(batch_size).prefetch(1)
cs

#Series : 시리즈 클래스는 1차원 배열의 값(values)에 각 값에 대응되는 인덱스(index)를 부여할 수 있는 구조를 갖고 있음 우선은 하나의feature(종가)를 기준으로 LSTM모델을 돌릴거

 

tf.expand_dims()는 배열의 차원을 늘려줍니다.
input에는 늘려질 배열을 넣습니다.
axis는 몇 번째 차원의 크기를 늘릴 건지 숫자를 넣습니다.

 

axis = -1은 가장 안쪽차원을 추가한다. 

ex) shape => ([10,10,3]) 일때  tf.expande_dims( axis= -1)일경우 shape => [10, 10, 3, 1]

 

tf.data.Dataset.from_tensor_slices 함수는 tf.data.Dataset 를 생성하는 함수로 입력된 텐서로부터 slices를 생성합니다. 예를 들어 학습데이터로 (60000, 28, 28)가 입력되면, 60000개의 slices로 만들고 각각의 slice는 28×28의 구조의 데이터를 갖게 됩니다. 위코드는 1차원구조의 데이터셋을 생성함

 

dataset.window는 3개의 인자를 전달받는데 window_size와 shift, drop_remainder

window는 요소를 shift만큼 묶어서 서브 dataset을 생성한다. 

 

window_size가 데이터셋의 크기를 초과하는경우가 존재하는데

이를 방지하기 위해 drop_remainder = True 인자를 넣어주면된다.

 

1
2
#하이퍼파라미터 정의
WINDOW_SIZE=20
BATCH_SIZE=32
cs

 

 

1
2
train_data = windowed_dataset(y_train, WINDOW_SIZE, BATCH_SIZE, True)
test_data = windowed_dataset(y_test, WINDOW_SIZE, BATCH_SIZE, False)
#train_data는 학습용데이터, test_data는 train_data를 통한 학습결과를 검증하기 위한 데이터셋
cs

 

1
2
3
4
5
# X: (batch_size, window_size, feature)
# Y: (batch_size, feature)
for data in train_data.take(1):
    print(f'데이터셋(X) 구성(batch_size, window_size, feature갯수): {data[0].shape}')
    print(f'데이터셋(Y) 구성(batch_size, window_size, feature갯수): {data[1].shape}')
cs

 

 

모델 미구현

728x90
728x90

필요 모듈 

1
2
3
import FinanceDataReader as fdr
import pymysql
import csv
cs

 

FinanceDataReader은 FinanceData.KR 에서 만든 오픈소스 금융 데이터 수집 라이브러리 이다.

 

 

  • 한국거래소(KRX)에 상장된 주식종목 리스트와 코넥스(비상장)에 있는 주식종목 리스트: 'KRX', 'KOSPI', 'KODAQ', 'KONEX'
  • 글로벌 주식종목 리스트: 'NASDAQ', 'NYSE', 'AMEX' and 'S&P500', 'SSE'(상해), 'SZSE'(심천), 'HKEX'(홍콩), 'TSE'(도쿄)
  • 개별 종목은 물론 금,원유 같은 원자재 지수도 지원한다. 

설치

pip install finance-datareader
pip install pymysql
pip install csv


참고 PyMySQL는 낮은 수준의 API를 지원하지 않습니다 

요구사항 

  • 파이썬 – 다음 중 하나:
  • MySQL 서버 – 다음 중 하나:

 

소스코드



1

2
3

 
conn = pymysql.connect(host="uws7-176.cafe24.com",user="아이디"
,password="패스워드",db="soll0803",charset="utf8")
curs=conn.cursor()
conn.commit()
cs

 

● pymysql.connect() 메소드를 이용하여 SQL에 연결 

host : 접속할 서버 주소

port : 접속할 서버 포트번호

user : sql id

password : sql password

db : 접속할 데이터베이스

charset : 인코딩

 

● line 1에서 접속이 성공하였다면 conn 객체로부터 cursor()메서드를 호출하여 cursor 객체를 가져옴

 

4
5
 
df = fdr.DataReader(symbol="005930",start='2000'#종목코드 005930 -> 삼성전자
df.to_csv('test.csv') #df를 csv파일로 저장
 
 
cs

#type(df) -> dataframe

 

6
7
= open('test.csv','r') #파일읽기모드
csvReader = csv.reader(f) #csvReader객체 생성
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
for row in csvReader:
    Date1 = (row[0])
    Open1 = row[1]
    High1 = row[2]
    Low1 = row[3]
    Close1 = row[4]
    Volume1 = row[5]
    Change1 = row[6]
 
    sql = "INSERT INTO stock_data (Date,Open,High,Low,Close,Volume,Change2) values(%s,%s,%s,%s,%s,%s,%s)"
    curs.execute(sql,(Date1,Open1,High1,Low1,Close1,Volume1,Change1))

conn.commit()
f.close()
conn.close()

 
cs

curs.execute를통해 sql문 실행 

 

전체소스 코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import FinanceDataReader as fdr
import pymysql
import csv
 
#삼성전자 주가데이터2020~오늘 데이터를 csv로 변환
#df = fdr.DataReader(symbol="005930",start='2020')
#df.to_csv('test.csv')
 
conn = pymysql.connect(host="uws7-176.cafe24.com",
user="아이디",password="패스워드",db="soll0803",charset="utf8")
curs=conn.cursor()
conn.commit()
 
df = fdr.DataReader(symbol="005930",start='2000'#종목코드 005930 -> 삼성전자
df.to_csv('test.csv')
 
= open('test.csv','r')
csvReader = csv.reader(f)
 
for row in csvReader:
    Date1 = (row[0])
    Open1 = row[1]
    High1 = row[2]
    Low1 = row[3]
    Close1 = row[4]
    Volume1 = row[5]
    Change1 = row[6]
 
    sql = "INSERT INTO stock_data (Date,Open,High,Low,Close,Volume,Change2) values(%s,%s,%s,%s,%s,%s,%s)"
    curs.execute(sql,(Date1,Open1,High1,Low1,Close1,Volume1,Change1))
conn.commit()
f.close()
conn.close()
cs

 

결과

728x90
728x90

개요

 

파이썬으로 request.get을 통해 웹을 크롤링하던 도중 원하는 데이터가 크롤링되지않아 처음엔 당황스러웠다.

하지만 크롤링이 되지않는 이유는 get방식으로 웹이 동작하는게 아니라 post방식을 통해 작동하기 때문이었다.

이를 확인하는 방법은 크롤링할 웹사이트로 이동할때 주소창이 변할경우 get방식으로 작동하고 

주소창이 바뀌지않을경우 post방식으로 작동한다는것을 알수있다.

 

 

특징

GET 방식은 다음과 같은 특징이 있습니다.

- 클라이언트가 입력한 값이 URL과 결합되어 스트링 형태로 서버에 전달됩니다
- 서버의 DB에 정보를 요청하는 것이 아니라 해당 웹페이지에서 보여지는 그대로를 가져오는 것입니다.
- 한번 요청시 데이터 양에 제한이 있습니다.

 

POST 방식은 다음과 같은 특징이 있습니다.

- 클라이언트와 서버 간에 스트링 형태로 그대로 서버에 전달되지 않고 인코딩이라는 과정을 거칩니다.
- 헤더를 통해 요청이 전송되는 방식입니다. 이 때문에 GET 방식과 같이 URL이 노출되지 않습니다.
- 요쳥시 GET 보다 더 많은 양의 정보를 교환할 수 있습니다.
- 페이지에서 날짜를 설정하고 조회하기 버튼을 눌렀을 때 서버는 DB에서 해당 기간에 해당되는 정보를 불러와 우리에게 보여줍니다.  이 때 사용하는 방식이 바로 POST 방식입니다. 조회하기 버튼을 눌렀을 때 URL 이 client 에게 노출이 되지 않으며, GET방식에 비해 더 많은 양의 정보를 받아올 수 있다는 장점이 있습니다. 

 

실습

 

 

>>> import requests

 

크롤링할 데이터는 바이낸스에서 상위트레이더의 포지션을 실시간으로 크롤링하는 프로그램을 짜보겠습니다.

https://www.binance.com/en/futures-activity/leaderboard?type=myProfile&tradeType=PERPETUAL&encryptedUid=CCF3E0CB0AAD54D9D6B4CEC5E3E741D2 

 

Binance Futures Leaderboard | ROI & PNL Rankings | Binance Futures

 

www.binance.com

 

위에 주소로 입력하게 될경우 TraderT라는 닉네임을 가진 트레이더의 포지션을 볼수있는데

이 데이터는 get방식으로 작동하는게 아닌 post방식을 통해 클라이언트가 서버(https://www.binance.com/bapi/futures/v1/public/future/leaderboard/getOtherPosition) 

이부분으로 request.post 요청을 하면 서버에서 응답을 해주는 방식으로 작동한다.

 

 

크롬f12를 눌러 개발자모드를 통해  network를 보면 post동식으로 동작하며

 

response로 원하는 데이터가 response오는걸 확인할수있다.

header쪽을 좀더보면 클라이언트가 서버로 post방식으로 request할때

request payload와 form data 두개의 방식으로 서버에게 전달하는데

 

 

Content-Type: application/json다음과 같은 요청이 있을 수 있습니다.

POST /some-path HTTP/1.1

Content-Type: application/json { "foo" : "bar", "name" : "John" }

AJAX별로 이것을 제출하면 브라우저는 단순히 페이로드 본문으로 제출하는 내용을 보여줍니다. 데이터가 어디에서 오는지 전혀 모르기 때문에 할 수 있는 모든 것입니다.

 

method="POST"and Content-Type: application/x-www-form-urlencoded/ 와 함께 HTML 양식을 제출하면 Content-Type: multipart/form-data요청은 다음과 같을 수 있습니다.

POST /some-path HTTP/1.1 Content-Type: application/x-www-form-urlencoded foo=bar&name=John

이 경우 form-data는 요청 페이로드입니다. 

여기에서 브라우저는 더 많이 알고 있습니다. bar가 제출된 양식의 입력 필드 foo 값이라는 것을 알고 있습니다. 그리고 그것이 당신에게 보여주고 있는 것입니다.

따라서 Content-Type데이터가 제출되는 방식은 다르지만 차이 가 있습니다. 두 경우 모두 데이터는 메시지 본문에 있습니다.

 

출처:https://stackoverflow.com/questions/23118249/whats-the-difference-between-request-payload-vs-form-data-as-seen-in-chrome

 

import requests
import websocket
import time
import json


url = 'https://www.binance.com/bapi/futures/v1/public/future/leaderboard/getOtherPosition'

payload = {
    'encryptedUid':'CCF3E0CB0AAD54D9D6B4CEC5E3E741D2',
    'tradeType':'PERPETUAL'
}
response1 = requests.post(url,json=payload)
#print(type(response1.text))
dict = json.loads(response1.text)
print(list.__len__(dict['data']['otherPositionRetList']))
print('심볼\t: 시작가격\t : 포지션수량\t : 포지션수량(usdt)')

for i in range(0,list.__len__(dict['data']['otherPositionRetList'])):
    print(dict['data']['otherPositionRetList'][i]['symbol'] +' : ' + str(dict['data']['otherPositionRetList'][i]['entryPrice'])+ ' : ' + str(dict['data']['otherPositionRetList'][i]['amount']),end='\t : ')
    usdt_amount = (int(dict['data']['otherPositionRetList'][i]['entryPrice'])*int(dict['data']['otherPositionRetList'][i]['amount']))
    print(usdt_amount)

 

출력결과

728x90
728x90

websocket을 설명하기에 앞서 HTTP에 대해 간략히 설명하겠습니다.

 

HTTP에 대한 간략한 설명

HTTP(Hyper Text Transfer Protocol)은 웹상에서 정보를 주고받을 수 있는 프로토콜인데

주로 html문서를 주고받을때 사용되며 HTTP는 클라이언트와 서버 사이에 이루어지는

요청(request)과 응답(response) 프로토콜입니다 

 

HTTP의 한계점 

HTTP의 특징중하나로 클라이언트가 서버에게 요청(request)를 보내고 서버가 답(response)을 주면

그대로 연결이 끊긴다.

서버와 다수의 클라이언트가 연결을 유지한다면 서버에 많은 리소스 낭비가 생기는데

HTTP프로토콜에는 이러지 않고 요청(request)에 응답(response)를 주면 연결이 끊기기 때문에

리소스 낭비가 적다.

 

하지만 이러한 http에는 여러 단점이 존재한다.

1. 요청(request)를 보낼 때 페이지가 리로딩 된다.

2. 동일한 요청에 중복된 헤더파일을 보낸다.

3. 실시간 상호작용성이 떨어진다.  

 

-Polling(폴링)

 

 

폴링기술은 클라이언트가 서버에게 계속해서 http requests를 날려 response(응답)을 받는 방식이다.

 

딱봐도 클라이언트는 서버에게 계속 요청(request)를 날리기 때문에 서버에 부담이온다.

 

또한 유저(클라이언트)가 아무것도 하지않아도 쓸데없이 서버의 리소스를 낭비하게된다.

 

또한 클라이언트에서 실시간정도의 빠른응답을 기대하기도 힘들다

 

-Long Polling

롱폴링은 클라이언트가 서버로 일단 http 요청을 날린다. 이 상태로 계속 기다리다가 서버에서 해당 클라이언트로 전달한 이벤트가 생기면 그순간 응답 메세지를 전달하면서 연결이 종료된다. 하지만 곧바로 클라이언트는 다시 요처을 날려 서버의 다음 이벤트를 기다리는 방식이다.

 

요약하자면

  1. 클라이언트가 웹서버로 HTTP 요청을보낸다
  2. 요청을 받은 웹서버는 데이터가 있을 때 까지(이벤트가 발생할 때 까지) 기다린다
  3. 데이터 혹은 이벤트가 발생하면 클라이언트로 HTTP응답을보낸다
  4. 응답을 받은 웹브라우저(클라이언트)는 데이터를 출력하고 HTTP연결을 끊는다
  5. 그리고 웹브라우저(클라이언트)는 다시 HTTP요청을 보낸다
  6. 기다린다
  7. 반복

Streaming

클라이언트가 서버에게 http request 를 보내고 서버는 응답을 끊임없이 흘려보낸다.(trickles out)

 

각 기술들의 문제점을 요약하자면

HTTP 통신규약 : 서버에게 요청보내고 응답 받으면 연결이 끊긴다. 서버-클라이언트 실시간 상호작용이 안된다.

 

그래서 실시간 상호작용할 수 있게 효과만 내본 기술들

Polling 기술 : 서버로 계속해서 요청보내기(근데 서버에 이벤트 없어도 계속 요청보냄>서버,클라이언트 무리)

 

Long polling기술 : 서버에 요청보내고 이벤트가 생겨 응답 받을 때 까지 연결안끊기. 응답받으면 끊고 다시 새요청보냄(근데 새 이벤트 생기면 모든 사용자가 연결 끊고 동시에 새요청보내게됨>서버무리)

 

Streaming 기술 : 서버에 요청보내고 끊기지 않은 연결상태에서 끊임없이 데이터받기(근데 클라이언트가 서버로 요청을 보내기 좀 힘듬. 스트리밍에서는 하나의 포트써서 읽고 쓰기 동시에 안됨)

 

 

이러한 기술들의 문제점인 실시간네트워킹이 가능한것이 바로 WebSocket이다

 

websocket(웹소켓)은 http를 기반으로 하면서 http의 문제점해결을 목표로 나온 기술이다.

이전의 통신과 달리 이중통신(full-duplex통신) 즉 수신과 송신을 동시에 처리가 가능하다.

socket connection을 유지하기 때문에 양방향 통신, 실시간통신, 데이터 전송이 가능하고

html5에 포함되어 프로토콜로 제정되어있다.

 

기존의 TCP SOCKET과 차이점은 웹소켓은 최초 접속이 일반 http요청을 이용한

handshaking으로 이루어진다. 또한 TCP Socket에서는 바이트 스트림을 사용하지만

웹소켓을 통해  전달되는 텍스트는 UTF-8형식을 가진다.

 

웹소켓길술은 real-time web application(서버 또는 클라이언트 쪽 데이터가 실시간으로 업데이트 되는 웹 어플리케이션)에서 많이 사용한다.

 

웹소켓 작동원리

 

서버와 클라이언트간 웹소켓 연결(connect)은 http프로토콜을 통해 이루어진다

HANDSHAKE과정이 성공적으로 끝나면 HTTP를 웹소켓프로토콜로 바꾸는 Protocol switching과정이 진행된다.

그러면 웹소켓을 위한 위한 새로운 소켓이 만들어지고 이소켓을 이용해 통신을한다!(ws나 wss)

데이터의 구조는 텍스트와 바이너리 모두 양방향 통신이 가능하며 텍스트의 경우 시작 바이트가 0x00, 끝 바이트가 0xFF로 끝나며 UTF-8데이터를 포함.

 

웹소켓 주소는 ws나 wss로 시작하는데 ws는 일반 웹소켓이고 wss는 SSL이적용된 웹소켓이다(Https)

 

이슈

  • stateful한 만큼 서버와 클라이언트 연결을 계속 유지해야하고, 비정상적 연결이 끊어졌을때를 대응해야함.
  • 서버와 클라이언트간의 socket 연결을 하는 것 자체가 비용이 많이 든다(트래픽이 많은 서버 같은 경우 CPU부담이 될 수 있다)

 

파이썬 웹소켓 크롤링 예제(비트맥스에서 1분 OHLCV 가져오기)

모듈 설치

pip install websocket-client

 

코드

import websocket
def on_message(ws, message):
    print("메시지: " + message)
def on_error(ws, error):
    print("에러 : " +error)
    ws.on_close(ws)
def on_close(ws):
    print("### closed ###")
    ws.close()
def on_open(ws):
    print("### open ###")
def run(endpoint):
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp(endpoint,
                                on_open = on_open,
                                on_message = on_message,
                                on_error = on_error,
                                on_close = on_close)
    ws.run_forever()
if __name__ == "__main__":
    command = 'subscribe=tradeBin1m:XBTUSD'
    endpoint = 'wss://www.bitmex.com/realtime?'+command   
    run(endpoint)

 

728x90
728x90

https://ititit1.tistory.com/99

 

안드로이드 앱 외부 데이터베이스 연동(Android<-> PHP <-> Maria DB) 1. 기본 설치

안드로이드 어플리케이션은 외부 DB에 바로 접근해서 데이터를 불러오지 ㅗㅅ합니다. 보안상의 이유때문에 '외부' 데이터베이스에 바로 접근은 하지못합니다. 따라서 위와같은 방식으로 애플리

ititit1.tistory.com

 

위 글에서 이어지는 내용 입니다.

 

Apache, MariaDB, PHP가 제대로 동작한다고 가정하고 진행하겠습니다.

 

우선 Apache 를 Start눌러 서버를 시작합니다.

 

그후 DB 테이블을 만들어야되는데

 

1. test 데이터베이스 접속하기

관리자 권한으로 cmd를 실행한 후 mysql test -u root -p 를 입력하여 접속합니다.

 

2. table 만들기 

create table member_test(

   userid varchar(30),

   userpassword varchar(30),

   username varchar(30)

);

 

 

2-1 테이블 구조 출력하기 

desc member_test;

 

+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| userid       | varchar(30) | YES  |     | NULL    |       |
| usdrpassword | varchar(30) | YES  |     | NULL    |       |
| username     | varchar(30) | YES  |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+

 

3. 테이블에 필드(데이터)값 넣기

insert into member_test(userid,userpassword,username)
                      values('soll0803','dlwlsthf1','leejinsol');

 

3-1 필드 출력

select * from member_test;

 

+----------+--------------+-----------+
| userid   | userpassword | username  |
+----------+--------------+-----------+
| soll0803 | dlwlsthf1    | leejinsol |
+----------+--------------+-----------+

 

userid 열만 출력하기

MariaDB [test]> select userid from member_test;
+----------+
| userid   |
+----------+
| soll0803 |

+----------+

 

 

connect.php 파일 만들기 

 

C:\xampp\htdocs 경로에 connect.php 파일을 생성해줍니다.

 

코드는 다음과 같이 작성합니다.(저는 member_test 테이블에 값들을 4개 넣어줬습니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<html>
<head>
    <title> :::DB TEST::</title>
    <meta charset="utf-8"/>
</head>
 
<body>
    
<?php
//1. DBMS 접속
$connect = mysqli_connect("localhost","root","비밀번호","test");
 
//2. 쿼리 실행
$query = "select * from member_test";
$result = mysqli_query($connect,$query);
$num = mysqli_num_rows($result); //행의 개수 
 
echo "rows count : ",$num;
 
 
//3. 데이터 가져오기
echo "      /     ";
 
$row = mysqli_fetch_array($result); //연관배열 형태로 들어옴
echo $row['userid'] . " " . $row['userpassword'] . " " . $row['username'];
//echo $query; 
 
echo ' / ';
$row = mysqli_fetch_array($result); //연관배열 형태로 들어옴
echo $row['userid'] . " " . $row['userpassword'] . " " . $row['username'];
 
echo ' / ';
$row = mysqli_fetch_array($result); //연관배열 형태로 들어옴
echo $row['userid'] . " " . $row['userpassword'] . " " . $row['username'];
 
echo ' / ';
$row = mysqli_fetch_array($result); //연관배열 형태로 들어옴
echo $row['userid'] . " " . $row['userpassword'] . " " . $row['username'];
 
 
 
//원래는 while문으로 돌리는게 일반적임
?>
 
</body>
</html>
cs

 

저장후 localhost/connect.php에 접속하여 확인합니다.

rows 값과

테이블의 필드값들이 성공적으로 웹에서 출력이 됩니다.

 

 

필드값들을 JSON 형태로 출력하기 

<test.php>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
    $con=mysqli_connect("localhost","root","비밀번호","test");
    mysqli_set_charset($con,"utf8");
 
    $res = mysqli_query($con,"select * from member_test");
    $result = array();
    
    while($row = mysqli_fetch_array($res)) {
        array_push($result,
            array('userid'=>$row[0],'userpassword'=>$row[1],'username'=>$row[2]));
    }
    echo json_encode(array("Tree"=>$result), JSON_UNESCAPED_UNICODE);
    mysqli_close($con);
?>
 
cs

 

위 내용들을 json viewer사이트에서 보게되면 

 

https://jsonformatter.org/json-viewer

 

Best JSON Viewer Online

Secure JSON Viewer is online JSON Viewer tool to Visualize JSON data in Tree View.

jsonformatter.org

사진대로 JSON형태로 출력이 됩니다.

728x90
728x90

안드로이드 어플리케이션은 외부 DB에 바로 접근해서 데이터를 불러오지 못합니다.

보안상의 이유때문에 '외부' 데이터베이스에 바로 접근은 하지못합니다.

 

 

따라서 위와같은 방식으로

애플리케이션 < -> PHP+아파치서버 <-> db에 통신하여 db를 가져오게된다.

즉, PHP에서 Mysql의 데이터에 접근해 echo 로 웹페이지에 mysql의 내용을 띄워 주면, 그 내용을 안드로이드에서 읽어오는 것이다. 간단히 그림으로 설명하자면 다음과 같다

 

안드로이드에서 http 요청을 통해 아파치 웹서버의 php파일이 출력하고 있는 내용을 읽어오는 것이다. 즉, 위 사진에서 

Seq : 1 Author : Yong...... 등의 내용을 가져온다. 위 웹페이지에서 띄워진 내용들은 모두 echo로(JSON 형태 ) 띄운 것이다.

 

 

먼저 실습을위해 

 

Maria DB , 아파치 , PHP 를 설치해야되는데

1. Maria DB 설치

Maria DB를 설치를 위해서 https://downloads.mariadb.org/mariadb/10.3.17/

 

MariaDB 10.3.17 Stable - MariaDB

 

downloads.mariadb.org

 

본인의 운영체제에 맞게 설치해주시면 되고 

Maria DB가 설치가 완료 되면

시작메뉴를 열어서 Heider SQL을 실행해줍니다

 

신규를 눌러서 새로운 세션을 만들어주고

세션을 우클릭하여 이름을 변경해주신후 암호를 입력하고 열기를 누르면

test1의 DB가 열리게 됩니다

 

 

 

2. XAMPP 설치

아파치와 PHP는 XAMPP 를 통해 설치해준다. 

XAMPP는 Apache, MariaDB, PHP, Perl의 약자로 설치하려는 소프트웨어를 포함하여 여러가지 기능을 제공하고 있습니다.

 

 

XAMPP를 설치하기 위해서 먼저 https://www.apachefriends.org/index.html 링크로 들어갑니다.

 

들어가셔서 본인의 운영체제에 맞게 설치해주시면 됩니다.

 

설치가 완료되면 Apache 를 Start 해줍니다.

 

 

3. 설치,동작 확인 

 

 

C:\xampp\htdocs 폴더로 가셔서 info.php 파일을 만들어주시고

 

코드를 다음과같이 작성합니다.

 

 

 

1
2
3
4
5
<?php
    $con=mysqli_connect("localhost","root","비밀번호") or die("MariaDB 접속 실패");
    phpinfo();
    mysqli_close($con);
?>
cs

이제

 

localohost/info.php 에 접속하시고

 

이런 화면이 나온다면  Apache, MariaDB, PHP가 제대로 동작된다고 보시면 됩니다.

 

참고:https://1d1cblog.tistory.com/

 

728x90
728x90

SW Expert Academy는 알고리즘테스트(코딩테스트)를 준비하기에 정말 좋은사이트 인것같다.

프로그래머스도 공부하기 좋지만 SW Expert 아카데미는 삼성에서 직접 운영중인 웹사이트이며

자신의 실력을 테스트하는 코딩테스트를 통해 학습 로드맵을 제공해주는게 정말 좋은사이트이다.

 

 

https://swexpertacademy.com/main/main.do

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

CodeProblem Solving매주 제공되는 난이도별 SW 연습문제에 도전하세요. 

LearnIntensive Study프로그래밍 역량강화를 위한 필수 이론 및 지식을 개인 역량에 따라 스스로 학습할 수 있도록 다양한 유형의 학습 컨텐츠를 제공합니다.

TalkSocial Learning함께 코드를 리뷰하고 토론하세요. 서로 소통하며 협업하는 가운데 모두의 실력이 향상됩니다.

 레벨 테스트를 통하여 개인 역량에 맞는 컨텐츠를 추천 받아 학습할 수 있습니다.

 

또한 알고리즘을 시각적으로 확인할수있다는 큰 장점이있다!

728x90
728x90

 

퀵정렬(Quick sort)

 

퀵정렬은 대표적인 분할정복 알고리즘중에 하나이다.

분할정렬이란 하나의 특정한 값을 기준으로 양 쪽을 나눠서 정렬하는 것이다.

 

퀵정렬은 운이좋으면 아주빠르게 처리되기때문에 붙은이름이며

평균적으로 시간복잡도가 O(N * logN) 입니다.

 

 

 

3 7 8 1 5 9 6 10 2 4을 오름차순으로 정렬하시오

 

▶퀵 정렬

풀기 어려운 큰 문제를 작은 문제로 나누어 푸는 분할 정복을 이용합니다. 방법은 아래와 같습니다.

1. 입력 받은 리스트에서 기준이 되는 값인 pivot을 설정한다.

2. pivot을 기준으로 pivot보다 작은 값은 왼쪽에, 큰 값은 오른쪽에 옮겨진다.

3. 왼쪽, 오른쪽 리스트의 크기가 1이 될 때까지, 1,2번을 반복한다.

 

이러한 정렬을 퀵소트를 통해 정렬시킬수 있습니다.

 

퀵정렬은 피봇이라는 기준값을 사용하는데 보통 첫번째 값을 피봇으로 사용합니다. 위에 예시를 봤을때 

 

 

3 7 8 1 5 9 6 10 2 4

1. 맨앞에 있는값(3)을 피봇으로 설정합니다

왼쪽부터(7부터) 피봇값(3)보다 큰값을 찾습니다.

오른쪽(4)부터 피봇값(3)보다 작은값을 찾습니다.

큰값은 7, 작은값은 2가 될것이며

둘의 위치를 바꿔 줍니다.

 

3 2 8 1 5 9 6 10 7 4

2. 또다시 피봇은 3인채로 똑같이 왼쪽부터 큰값을, 오른쪽부터 작은값을 찾습니다.

큰값은 8 작은값은 1이 될것입니다.둘의 위치를 바꿔줍니다.

 

3 2 1 8 5 9 6 10 7 4

 

 

3. 또 피봇은3인채로 왼쪽부터 피봇보다 큰값을, 오른쪽부터 피봇보다 작은값을 찾습니다.

큰값 8 , 작은값 1이 발견될텐데 이때 작은값의 인덱스가 큰값의 인덱스보다 작습니다.

따라서 피봇값과 작은값은 자리를 바꿔줍니다. 이를 엇갈렸다고 표현하겠습니다.

엇갈렸을때 피봇값과 작은값의 자리를 바꾸는데 그 바꾼후 피봇값(3)은 자리가 고정이 됩니다.

왜냐하면 3의 왼쪽에는 자기보다 작은값만존재하고 , 오른쪽에는 자기자신보다 큰값만 존재하기 떄문

 

2 3 8 5 9 6 10 7 4

4. 피봇값3을 기준으로 배열은 반으로 쪼개서 방금까지 했던 작업들을 각각 합니다.즉 왼쪽(1 2 ) 부터 생각하면

 

2

4-1(왼쪽) 1을 피봇으로 설정하고 왼쪽부터 피봇값(1)보다 큰값을 오른쪽부터 피봇값(1)보다 작은값을 찾습니다.

큰값은 2, 작은값은 1(자기자신) 이떄 작은값의 인덱스가 큰값의 인덱스보다 작으므로 마찬가지로 작은값과 피봇의 인덱스를 바꿔줍니다(즉 작은값1, 피봇값1 이므로 변화는없습니다)  엇갈렸으므로 1은 자리가 고정이되고

1의 왼쪽값들을 퀵소트해주는데 왼쪽값이 없으므로 생략,

1의 오른쪽값들을 퀵소트해주는데 값이 2 하나이므로 2도 자리가 고정이되며

1, 2 3 은 자리가 확정이됩니다.

이제 아까3의 오른쪽값들을 퀵소트해줍니다.

 

8 5 9 6 10 7 4

 

4-2(오른쪽)  피봇을 첫번째값(8)로 설정하고 왼쪽부터 피봇값(8)보다 큰값을 오른쪽부터 피봇값(8)보다 작은값을 찾습니다.

큰값9, 작은값 4가 정해질것이며 둘의 자리를 바꿉니다.

8 5 4 6 10 7 9

 

4-3 또 피봇값(8)보다 왼쪽부터 큰값을, 오른쪽부터 작은값을 찾습니다. 

작큰값은 10, 작은값은 7 둘의 자리를 바꿉니다.

 

8 5 4 6 7 10 9

4-4 피봇값보다 왼쪽부터 큰값을 오른쪽부터 작은값을 찾습니다.

큰값은 10이며 작은값은 7 

이떄 작은값의 인덱스가 큰값의 인덱스보다 작으므로 엇갈렸다고 표현할수있습니다.작은값과 피봇과 자리를 바꿉니다.

 

 

7 5 4 6 8 10 9

4-5 8은 자리가 고정이 되었고 이제 8을 기준으로 왼쪽 7 5 4 6을 퀵소트해주고 

8의 오른쪽 10 9를 퀵소트 해줍니다.

 

 

5 4 6 

맨앞의 값을 피봇으로 정하고 왼쪽부터 큰값을 오른쪽부터 작은값을 찾습니다.

이떄 작은값6과 큰값x

이떄도 엇갈렸다고 표현하는데 피봇과 작은값의 자리를 바꿔주고 7은 자리가 고정이되며바꾼 피봇값의 자리를기준으로 왼쪽 오른쪽을 나눠서 퀵소트를 진행해줍니다.

5 4 6 7

 

 

 

5 4 6 

 

5를 피봇으로 왼쪽부터 큰값 오른쪽부터 작은값을 찾습니다.

큰값6 작은값 4엇갈렸으므로 작은값과 피봇값의 자리를바꾸고 바꾼 피봇값은 고정이되며 또 왼쪽 오른쪽을 나눠서 퀵소트를 진행

 

 4 5 6 

5는 고정된값이며 왼쪽값이 하나이므로 4도 고정

5의 오른쪽도 정렬할 값이 하나이므로 6도 고정

 

 

7 5 4 6 8 10 9 여기서 왼쪽값들을 전부 정렬했습니다. 따라서 현재               1 2 3 4 5 6 7 8 10 9 이며 피봇값8의 오른쪽을 퀵소트 해면 정렬이 완료됩니다.

소스코드 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
 
int number = 10;
int data[] = {1, 10, 5, 8, 7, 6, 4, 3, 2, 9};
 
void show() {
   int i;
   for(i = 0; i < number; i++) {
      printf("%d ", data[i]);
   }
}
 
void quickSort(int* data, int start, int end) {
   if (start >= end) { // 원소가 1개인 경우 그대로 두기 
      return;
   }
   
   int key = start; // 키는 첫 번째 원소
   int i = start + 1, j = end, temp;
   
   while(i <= j) { // 엇갈릴 때까지 반복
      while(i <= end && data[i] <= data[key]) { // 키 값보다 큰 값을 만날 때까지 
         i++;
      }
      while(j > start && data[j] >= data[key]) { // 키 값보다 작은 값을 만날 때까지 
         j--;
      }
      if(i > j) { // 현재 엇갈린 상태면 키 값과 교체 
         temp = data[j];
         data[j] = data[key];
         data[key] = temp;
      } else { // 엇갈리지 않았다면 i와 j를 교체 
         temp = data[i];
         data[i] = data[j];
         data[j] = temp;
      }
   } 
   
   quickSort(data, start, j - 1);
   quickSort(data, j + 1, end); 
}
 
int main(void) {
   quickSort(data, 0, number - 1);
   show();
   return 0;
}
cs
728x90
728x90

 

1.준비사항

2. SQL BBS테이블 생성

3.  NODEJS로 웹페이지 HELLO WORLD 띄우기

 

1.준비사항

 

 

NodeJS 설치 

ORACLE DATABASE18C EXPRESS EDITION설치

ORACLE SQL DEVELOPER 

 

 

 

오라클 DATABASE와 SQL DEVELOPER는  다음 링크에서 다운받으면 됩니다.

 

https://www.oracle.com/downloads/

 

NODE JS는 여기서 설치하시면됩니다.

최신버전보다 14.17.0 LST를 설치하는걸 추천합니다

https://nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

 

 

DATABASE와 SQL DEVELOPER 와 NODE JS설치가 성공적으로 되었을경우 

2. SQL문 작성

 

CREATE TABLE BBS(
    NO NUMBER(10) NOT NULL,
    TITLE VARCHAR(255),
    WRITER VARCHAR(100),
    CONTENT VARCHAR(4000),
    REGDATE DATE,
    OK NUMBER(1) DEFAULT 1,
    TEMP VARCHAR(100),
    PRIMARY KEY(NO)
);

COMMIT;
CREATE SEQUENCE bbs_seq START WITH 1 INCREMENT BY 1 MAXVALUE 100000 CYCLE NOCACHE;  --1부터 1씩증가 10만까지 글번호가 자동으로 증가하기위해 
SELECT * FROM BBS;

INSERT INTO BBS values(bbs_seq.NEXTVAL  , 'DB타이틀' , '이진솔', 'DB 글내용', sysdate,1);
INSERT INTO BBS values(bbs_seq.NEXTVAL  , 'DB타이틀2' , '이진솔2', 'DB 글내용2', sysdate,1);

CREATE SEQUENCE bbs_seq START WITH 1 INCREMENT BY 1 MAXVALUE 100000 CYCLE NOCACHE; 를 한이유는

각 글의 고유번호 NO1,2,3,4... 를 하나씩 증가시키기위해 작성한 SQL문이다.

 

3. HELLO WORLD 띄우기

const express = require('express');
const app = express();

const server = app.listen(3000, () =>{
    console.log('start server : localhost:3000!!');
});

app.set('views',__dirname + '/views'); //dirname 현재디렉토리
app.set('view engine','ejs');
app.engine('html',require('ejs').renderFile);

app.get('/',function(req,res){
    res.render('index.html')
//    res.send('hello world');
})

app.get('/about',function(req,res){
    res.send('about page')
})

 

실행은 CMD에서 node '파일명'.js 입력하시면 실행되며

성공적으로 실행됐을때 start server : localhost:3000!! 이 터미널에 출력될것이다.

728x90

+ Recent posts