반응형

간단히 날짜 표시하는 앱을 구현해보겠습니다.

 

1.main.go

package main

import (
	"fmt"
	"time"

	sciter "github.com/sciter-sdk/go-sciter"
	"github.com/sciter-sdk/go-sciter/window"
)

// Specifying  havily used
// Singltons to make them
// package wide available
var root *sciter.Element
var rootSelectorErr error
var w *window.Window
var windowErr error

// Preapare Scitre For Execution ///
func init() {

	// initlzigin window for downloaer
	// app with appropriate properties
	rect := sciter.NewRect(0, 100, 200, 350)
	w, windowErr = window.New(sciter.SW_TITLEBAR|
		sciter.SW_CONTROLS|
		sciter.SW_MAIN|
		sciter.SW_GLASSY,
		rect)

	if windowErr != nil {
		fmt.Println("Can not create new window")
		return
	}
	// Loading main html file for app
	htloadErr := w.LoadFile("./main.html")
	if htloadErr != nil {
		fmt.Println("Can not load html in the screen", htloadErr.Error())
		return
	}

	// Initializng  Selector at global level as we  are going to need
	// it mostly and as it is
	root, rootSelectorErr = w.GetRootElement()
	if rootSelectorErr != nil {
		fmt.Println("Can not select root element")
		return
	}

	// Set title of the appliaction window
	w.SetTitle("Simple")

}

// Preaprare Program for execution ///
func main() {

	t := time.Now().Format("2006-01-02 15:04:05")
	date_now, _ := root.SelectById("date")
	date_now.SetText(t)
	//date_now.SetText("hello")

	w.Show()
	w.Run()

}

 

2.main.html

<html window-frame="default" window-blurbehind>
<head>
    <head>
        <title>Simple Calc</title> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <style>
          html{
            background: transparent;
          }
          #date{
            color: white;
            text-align: left;
            font-size:20px;
          }
        </style>
    </head>
</head>
<body>
  <label id="date">date</label>
</body>
</html>

 

결과는 아래와 같이~~

 

투명하게 처리된 프로그램. 보이시나요?

 

 

Golang과 HTML로 GUI 실행파일 만든다는게 꽤 재미있네요. 자주 활용할 수 있을 것 같습니다.

오늘은 이만~~

반응형
반응형

 

이번엔 인터넷에서 go-sciter를 이용한 간단한 계산기 프로그램을 우연히 발견하여 이를 투명하게 개조해보았습니다.

참고로 이번 프로그램에는 컬러값을 설정할 때 "github.com/fatih/color" 라는 패키지가 필요합니다.

go get "github.com/fatih/color"

를 수행해서 추가로 필요한 패키지를 설치해 줍니다.

 

그리고 아래 코드를 작성해줍시다.

 

1. main.go

package main

import (
	"fmt"

	"github.com/fatih/color"
	sciter "github.com/sciter-sdk/go-sciter"
	"github.com/sciter-sdk/go-sciter/window"
)

// Specifying  havily used
// Singltons to make them
// package wide available
var root *sciter.Element
var rootSelectorErr error
var w *window.Window
var windowErr error

// Preapare Scitre For Execution ///
func init() {

	// initlzigin window for downloaer
	// app with appropriate properties
	rect := sciter.NewRect(0, 100, 200, 350)
	w, windowErr = window.New(sciter.SW_TITLEBAR|
		sciter.SW_CONTROLS|
		sciter.SW_MAIN|
		sciter.SW_GLASSY,
		rect)

	if windowErr != nil {
		fmt.Println("Can not create new window")
		return
	}
	// Loading main html file for app
	htloadErr := w.LoadFile("./main.html")
	if htloadErr != nil {
		fmt.Println("Can not load html in the screen", htloadErr.Error())
		return
	}

	// Initializng  Selector at global level as we  are going to need
	// it mostly and as it is
	root, rootSelectorErr = w.GetRootElement()
	if rootSelectorErr != nil {
		fmt.Println("Can not select root element")
		return
	}

	// Set title of the appliaction window
	w.SetTitle("Simple Calc")

}

// Preaprare Program for execution ///
func main() {

	addbutton, _ := root.SelectById("add")

	out1, errout1 := root.SelectById("output1")
	if errout1 != nil {
		color.Red("failed to bound output 1 ", errout1.Error())
	}
	addbutton.OnClick(func() {
		output := add()
		out1.SetText(fmt.Sprint(output))
	})

	w.Show()
	w.Run()

}

//////////////////////////////////////////////////
/// Function of calc                           ///
//////////////////////////////////////////////////

func add() int {

	// Refreshing and fetching inputs()
	in1, errin1 := root.SelectById("input1")
	if errin1 != nil {
		color.Red("failed to bound input 1 ", errin1.Error())
	}
	in2, errin2 := root.SelectById("input2")
	if errin2 != nil {
		color.Red("failed to bound input 2 ", errin2.Error())
	}

	in1val, errv1 := in1.GetValue()
	color.Green(in1val.String())

	if errv1 != nil {
		color.Red(errv1.Error())
	}
	in2val, errv2 := in2.GetValue()
	if errv2 != nil {
		color.Red(errv2.Error())
	}
	color.Green(in2val.String())

	return in1val.Int() + in2val.Int()
}

2.main.html

<html window-frame="transparent" window-blurbehind>
<head>
    <head>
        <title>Simple Calc</title> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0">  
        <style>
          html{
            background: transparent;
          }
          div{
            color: white;
            text-align: right;
          }
        </style>
    </head>
</head>
<body>
    <div>
      <label for="">No1</label>
      <input type="number" style="width: 100px; margin: 0 auto;" id="input1" >
      <br>
      <label for="">No2</label>
      <input type="number" style="width: 100px; margin: 0 auto;" id="input2" >
      <br>
      <input type="button" style="width: 50px; margin: 0 auto;" value="Add ( + )" id="add"> 
      <hr>
      <input type="number" style="width: 100px; margin: 0 auto;" id="output1" disabled>
    </div>

</body>
</html>

 

실행결과는 ..

 

 

 

투명하게 나오니까 역시 이쁘네요.

오늘은 여기까지~~

 

반응형
반응형

윈도우에서 위젯같은 프로그램을 만들려고 프레임/배경/타이틀바 등을 투명하게 할 수 있는 라이브러리를 찾다가 go-sciter라는 것을 찾았습니다. (다른 라이브러리로 투명 구현하려고 한참동안 헤메었네요.ㅜㅜ)

 

sciter는..

화면 구성은HTML, CSS를 쓰고 tiscript라는 스크립트로 뷰를 제어하고, 실행 부분에서는 golang, python, rust, c# 등 다양한 언어로 구축할 수 있습니다. 물론 무료이구요. (실행 파일 내부에 sciter.dll을 포함시키기 위해서는 돈을 내야 한다고 합니다. 배포시 sciter.dll을 한 폴더에 같이 배포하면 문제는 없겠네요.)

 

설치는..

1.SDK 설치: sciter.com/download/ 에서 SDK를 다운받아 압축을 해제하고, \sciter\bin.win\ 디렉토리의 본인 os에 맞는 sciter.dll 파일을 C:\windows\system32 폴더로 복사해 넣어줍니다. 

 

 

 

 

 

 

2. Go-binding 라이브러리 설치

go get -x github.com/sciter-sdk/go-sciter

 

설치가 완료되었으니, 간단히 투명 화면 구성하는 방법에 대해 알아보겠습니다.

 

main.go

package main

import (
	"fmt"

	"github.com/sciter-sdk/go-sciter"
	"github.com/sciter-sdk/go-sciter/window"
)

func main() {

	rect := sciter.NewRect(100, 100, 600, 400)
	window, windowCreationErr := window.New(sciter.SW_MAIN|sciter.SW_TITLEBAR|sciter.SW_ENABLE_DEBUG, rect)

	if windowCreationErr != nil {
		fmt.Errorf("Could not create sciter window : %s",
			windowCreationErr.Error())
		return
	}

	uiFileLoadErr := window.LoadFile("./main.html")
	if uiFileLoadErr != nil {
		fmt.Errorf("Could not load ui file : %s",
			uiFileLoadErr.Error())
	}

	window.SetTitle("Hello")
	window.Show()
	window.Run()

}

 

main.html

<html window-frame="transparent" window-blurbehind>
    <head>
        <!--<title>Would be set from goLang code</title>-->
        <style>
          html{
            background: transparent;
          }
            h1{
                text-align: center
                
            }
        </style>         
          
    </head>
    <body>
        <h1>Hello Sciter</h1>     
    </body>
</html>

 

 

 

 

 

 

 

 

정말 간단하게 투명 UI가 생성되었네요. 이제 이걸 활용해서 뭔가 좀 더 만들어봐야겠습니다.

 

- 끝 -

반응형
반응형

React하면 아시다시피 frontend 라이브러리라고 하는데요.. React에서 Database의 내용을 가져오려면 어떻게 해야할까요? 오늘 실습은 이 질문에서 시작했습니다. PHP, JSP, Django 등 여러가지 backend 를 이용하여 Database를 접속할 수 있을텐데요. 저는 가장 간단할 것으로 예상되는 apache, php, mysql의 조합을 이용하여 php API를 구성하는 방법으로 구성해볼까 합니다.

 

그래서 필요한 것은 간단한 php API. 아래 코드를 test.php라는 파일로 작성하여 아파치 루트 다큐먼트 경로(예: C:\xampp\htdocs)에 저장합니다. (Database는 사전에 적당한 값으로 구성하셔야합니다.)

 

test.php

<?php
    $host = 'localhost';
    $user = 'root';
    $pw = '1234';
    $dbName = 'TestDB';
    
    $conn = mysqli_connect($host, $user, $pw, $dbName);
        
    $sql = "SELECT * FROM members";
    $result = mysqli_query($conn, $sql);    
    $row = mysqli_fetch_array($result);

    $list_array = array("name" =>$row['name'],
                        "email" =>$row['email'],
                        "phone" => $row['phone']);

    $result_array = json_encode($list_array);
    
    echo $result_array;
    
?>

이 파일은 localhostTestDB에 접속하여 members테이블의 모든 row를 추출해냅니다. 그리고

결과를 $row에 저장하고, 이를 다시

배열형태로 $list_array에 할당합니다.

다시한번 json형태로 인코딩하여 $result_array에 할당합니다.

echo 함수는 이 파일의 결과값으로 $result_array를 출력하게 합니다.

 

Backend에서의 동작은 구현했습니다. 80번 포트에서요. 이번에는 개발환경인 3000 포트에서 구동하는 React App을 구성할 차례인데요, 포트가 달라지면 쿠키라던지 데이터 전달에 제한을 받게되어 원래대로라면 여러가지 다른 방법을 시도해야 한다고 합니다. 그래서 proxy라는 걸 이용하는데요. package.json파일에 아래 한줄만 추가해주면 됩니다.

"proxy": "http://127.0.0.1:80",

위 코드를 package.json 내부 적당한 위치에 아래와 같이 넣어줍니다. 그러면 localhost의 접근 시도에 대해 proxy 주소로 자동으로 넘겨주고, 추후 구성할 React 앱에서도 라우팅 부분을 간소화할 수 있습니다.

 

App.js

아래와 같이 Hello라는 텍스트와 클릭 가능한 단순 버튼을 추가하겠습니다. 버튼은 클릭시 test.php를 실행하여 DB정보를 json형태로 가져오게 합니다. 보시는 바와 같이 원래대로라면 fetch('http://127.0.0.1:80/test.php')와 같이 작성해야하나 훨씬 간소하게 구성된 것을 볼 수 있습니다.

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render(){
    return (
      <div className="App">
        Hello
        <input type="button" value="get data" onClick={
          function(){
            fetch('/test.php')
            .then(function(response){
              return response.json();
            })
            .then(function(json){console.log(json);})
          }.bind(this)
        }></input>
      </div>
    );
  }
}

export default App;

 

이제 xampp도 실행하고, npm start로 리액트도 실행해 봅시다. localhost/test.php를 입력하면 DB 데이터가 json형태로 잘 출력됨을 볼 수 있습니다.

 

- 끝 -

 

반응형

'Programming > PHP' 카테고리의 다른 글

PHP와IIS 연동하기  (0) 2020.10.24
반응형

오늘은 Flask와 MySQL의 연동에 대해 알아보겠습니다. 진행할 과제는

 

1. DB 생성

2. Flask APP 구성

3. DB 모듈 생성 (mod_dbconn.py)

4. DB 연결 (__init__.py)

5. DB data 출력 (db.html)

 

의 순으로 진행하겠습니다.

 

1. DB 생성

이전 포스팅에서 설치한 XAMPP를 이용하여 MySQL을 실행하고 진행하겠습니다. XAMPP에서 Apache와 MySQL을 Start 해 줍니다. (Apache를 실행해야 MySQL 서버가 실행됩니다.)

다음으로 커맨드 창을 열고 비밀번호를 설정해 줍니다.

 

그리고서 XAMPP 컨트롤 창의 MySQL의 Admin 버튼을 누르거나 직접 URL을 입력하여 phpmyadmin사이트로 이동합니다. (로그인이 안될 수 있습니다. 이때는 설정파일(config.inc.php)을 열어 password 부분을 1234로 바꿔줍니다. 아래 수정할 파일 경로와 수정 부분 참조하세요)

 

이제 DB를 생성하겠습니다. '새로운'을 클릭하여 DB를 생성창을 열고, testDB라고 DB 이름을 부여한 후, 인코딩 방식을 아래와 같이 설정해주고(default), 만들기를 클릭해줍니다. 

 

삽입 창에서 적당히 데이터를 입력해 줍니다.

이렇게 기본적인 테스트 테이블 및 데이터를 생성하였습니다.

 

2. Flask APP 구성

Flask App의 구성은 이렇게 생겼습니다. 아래의 구성에 따라 파일들을 생성해 줍니다. 폴더구조 내부의 파일들은 차근차근 생성해 갈 예정이므로 폴더 트리를 먼저 구성해 줍시다.

다음으로는 Flask 와 MySQL DB연동을 위한 pymysql 모듈을 설치합니다.

pip install Flask
pip install pymysql

그리고 이제부터 내부 파일들을 구성하도록 하겠습니다.

(1) start_app.py:

프로그램 시작점입니다. 내부에서 app을 import 하는 것만으로도 __init__.py를 자동으로 구동하게 됩니다.

from app import app

app.run(host='0.0.0.0') # 127.0.0.1

 

(2) __init__.py : 

본격적인 Flask 앱입니다. 주로 라우팅 관련 설정을 다루고 있습니다. 아직은 '/' 루트로 연결 요청에 대해 'home.html'로 연결하는 1개의 라우팅밖에 없습니다.

from flask import Flask, render_template
from app import mod_dbconn

app = Flask(__name__)


@app.route('/')
def home():
    return render_template('home.html')

if __name__=='__main__':
    app.run(debug=True)

from app import app





(3) layout.html:

다른 html파일과 공유되는 base부분을 선언해줍니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask App</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
<body>
    <header>
        <div class="container">
            <h1 class="logo">Flask App</h1>
            <strong>
                <nav>
                    <ul class="menu">
                        <li><a href="{{ url_for('home') }}">Home</a></li>
                    </ul>
                </nav>
            </strong>
        </div>
    </header>
    <div class="container">
        {% block content %}
        {% endblock %}
    </div>

</body>
</html>

(4) home.html:

layout.html을 불러와 {% block content %} 부분이 끼워넣습니다.

{% extends "layout.html" %}
{% block content %}
<div class="jumbo">
    <h2>Hello Flask App</h2>
    <h4>'/' 요청 처리에 대한 페이지입니다.</h4>
</div>
{% endblock %}

(5) main.css

다른 분 소스를 참조했습니다.^^;;;;;

body {
  margin: 0;
  padding: 0;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  color: #444;
}

header {
  background-color: #2B2B2B;
  height: 35px;
  width: 100%;
  opacity: .9;
  margin-bottom: 10px;
}

header h1.logo {
  margin: 0;
  font-size: 1.7em;
  color: #fff;
  text-transform: uppercase;
  float: left;
}

header h1.logo:hover {
  color: #fff;
  text-decoration: none;
}

.container {
  width: 940px;
  margin: 0 auto;
}

div.jumbo {
  padding: 10px 0 30px 0;
  background-color: #eeeeee;
  -webkit-border-radius: 6px;
     -moz-border-radius: 6px;
          border-radius: 6px;
}

h2 {
  font-size: 3em;
  margin-top: 40px;
  text-align: center;
  letter-spacing: -2px;
}

h3 {
  font-size: 1.7em;
  font-weight: 100;
  margin-top: 30px;
  text-align: center;
  letter-spacing: -1px;
  color: #999;
}
.menu {
  float: right;
  margin-top: 8px;
}

.menu li {
  display: inline;
}

.menu li + li {
  margin-left: 35px;
}

.menu li a {
  color: #999;
  text-decoration: none;
}

이렇게 구성한 후 접속을 서버를 구동해 보겠습니다.

python start_app.py

이쁘게 잘 나오네요. 다음, 진짜 DB 연결부분으로 넘어가겠습니다.

 

3. DB 모듈 생성 (mod_dbconn.py)

DB 접속 및 실행 부분을 재사용을 위해 클래스로 구성해 둡니다.

import pymysql


class Database():
    def __init__(self):
        self.db = pymysql.connect(host='localhost',
                                  user='root',
                                  password='1234',
                                  db='testDB',
                                  charset='utf8')
        self.cursor = self.db.cursor(pymysql.cursors.DictCursor)

    def execute(self, query, args={}):
        self.cursor.execute(query, args)

    def executeOne(self, query, args={}):
        self.cursor.execute(query, args)
        row = self.cursor.fetchone()
        return row

    def executeAll(self, query, args={}):
        self.cursor.execute(query, args)
        row = self.cursor.fetchall()
        return row

    def commit(self):
        self.db.commit()

4. DB 연결 (__init__.py):

기능은 만들어 두었으니까(mod_dbconn.py) 실제 연결 요청부분을 만들겠습니다. 

from flask import Flask, render_template
from app import mod_dbconn

app = Flask(__name__)


@app.route('/')
def home():
    return render_template('home.html')


# 여기부터 추가
@app.route('/db')
def select():
    db_class = mod_dbconn.Database()

    sql = "SELECT id, name \
                FROM testDB.members"
    row = db_class.executeAll(sql)

    print(row)

    return render_template('db.html', resultData=row[0])

# 여기까지 추가



if __name__=='__main__':
    app.run(debug=True)

from app import app





 

데이터 흐름으로 보자면...이렇게 되겠네요^^. 즉 '/db' 접속 요청이 들어오면 해당 라우터를 찾아 select()함수를 실행시키는데, 우선 Database로부터 sql에 해당하는 data를 받아서 row에 저장시키고, 이를 resultData라는 변수에 할당하여 db.html로 함께 넘겨줍니다.

5. DB data 출력 (db.html)

마지막으로 전달받은 데이터를 출력하는 페이지를 작성합니다.

{% extends "layout.html" %}
{% block content %}
<div class="jumbo">
    <h2>Hello Flask App</h2>
    <h4>id : {{resultData.id}}</h4>
    <h4>name : {{resultData.name}}</h4>
</div>
{% endblock %}

이렇게 수정하고 다시 실행해봅시다. 

 

python start_app.py

그리고 localhost:5000/db로 url을 입력해 봅시다.

 부디 이렇게 같이 잘 나오셨길 빕니다.

 

- 끝 - 

반응형
반응형

오늘은 Flask 앱을 Apache와 연동시키는 작업을 해보겠습니다. 나중에 나오지만 mod_wsgi설치, httpd.conf파일 수정 등 산넘어 산입니다. ^^;;;

 

1. 아파치 직접 설치해도 되겠지만, 저는 XAMPP 를 깔겠습니다. 초보니까요..^^;; 이걸 사용하면 Apache, MySQL, PHP 서버를 버튼 클릭으로 간단히 켜고 끌 수 있게 해 줍니다. 주소는 https://www.apachefriends.org/index.html

설치 방법은 다른 글들을 확인하시기 바랍니다.

 

 

 

2. 아파치 인식시키기

우리 목표는 아래 명령을 수행해서 mod_wsgi를 설치하는게 우선적인 목표입니다.

pip install mod_wsgi

그런데, 아파치를 설치 했음에도 에러가 발생할 확률이 높습니다. 중간 부분에 아파치가 설치되지 않았다는 문구가 있을 겁니다. 그럴 때에는 아래와 같이 입력하여 아파치를 인식시켜줍니다. "F:\Apache24"부분은 각자의 apache 경로로 하시는거 주의하세요^^

set "MOD_WSGI_APACHE_ROOTDIR=F:\Apache24"

 

3. mod_wsgi 설치 관련 C++ 컴파일러 설치

여기서부터가 본격적인 시작이라고 보시면 되겠습니다. 리눅스 환경에서는 구성하기가 나름 쉬운 것 같은데, 윈도우 환경에서는 조금 까다롭습니다. 아직은 여전히 pip install mod_wsgi를 해도 빨간 에러가 계속 나올겁니다. 이제 C++ 컴파일러를 설치해야 합니다. VC++ 14.0 이상이 설치되어 있어야 한다고 합니다. 인터넷 검색하셔서 VC Build Tools 다운받으시면 됩니다. 찾기 어려울까봐 인터넷에 돌아다니는 파일 올립니다.  

 

visualcppbuildtools_full.exe
3.14MB

 

 

이거 깔고 pip install mod_wsgi 이렇게 설치하시면 아마 될겁니다. 그 다음에도 안되는 다른 사이트 좀 더 살펴보시기 바랍니다...저는 여기까지만...ㅠㅠ

 

 

 

다른 OS의 경우에는 F:\Apache24\modules\mod_wsgi.so 파일이 생성된다는데, 윈도우는 좀 다릅니다. 설치하고 나면 위 경로와 같이 Python 설치 경로의 Scripts 폴더에 가 보시면 mod_wsgi-express.exe 파일이 있을 겁니다. 제대로 설치 된 것이라고 보면 됩니다.

 

4. httpd.conf 파일 설정

다음으로 아파치 환경설정파일을 손을 봐줘야 합니다. 위치는 F\Apache24\conf\httpd.conf 이고 넣을 내용은 

mod_wsgi-express module-config

라고 치면 나오는 내용을 복사해 넣습니다.

 

 

파이썬이 C:\program Files\Python38 을 사용하고 있는줄 알았는데, 아나콘다에서 다시 설치한 버전이 있었네요. wsgi는 다른 곳에 딸렸는데, 실행은 anaconda 버전으로 한다??...ㅠㅠ. 암튼 그 내용을 httpd.conf에 넣어줍니다.

 

LoadFile "c:/programdata/anaconda3/python38.dll"
LoadModule wsgi_module "c:/programdata/anaconda3/lib/site-packages/mod_wsgi/server/mod_wsgi.cp38-win_amd64.pyd"
WSGIPythonHome "c:/programdata/anaconda3"

파일을 열면 내용이 엄청 많은데, LoadModule 뒷부분에 바로 이어서 넣어주면 됩니다.

 

 

위 그림에서 WSGIScriptAlias / "D:/05_Program_dev/04_python/04_flaskapp/httpd.wsgi" 부분은 잠시 뒤에 설명하겠습니다.

 - LoadFile과 LoadModule 부분은 mod_wsgi 모듈을 로드하기 위한 부분이고

 - WSGIPythonHome은 파이썬 실행파일이 있는 폴더를 인식시켜주는 부분입니다.

 

5. httpd.wsgi 작성

실제 앱을 구동시킬 wsgi파일을 구현합니다.

import sys

sys.path.insert(0, "D:/05_Program_dev/04_python/04_flaskapp")

from app import app as application

필자의 앱은 아래와 같이 구성되어있는데, 위 코드의 sys.path.insert의 두번째 인자는 이 flask앱 폴더(04_flaskapp)를 경로 포함하여 넣어주면 되고, 임포트 하는 부분에서는 내부의 앱을 불러오면 됩니다. from app import app 하게 되면 파이썬 특성에 따라 __init__.py가 자동으로 실행되고, __init__.py 내부에 선언한 라우팅에 따라 template들을 출력하게 됩니다. 

 

 

사실 프로그램 구동을 위한 start_app.py를 실행하려고 했는데 직접 __init__.py를 불러오는 꼴이 되었습니다. 한단계 덜 거치는게 좋은 것도 같은데... 어떤게 좋은 건지는 계속 공부해보도록 하겠습니다.

 

6. httpd.conf에 연결

위에서 만든 httpd.wsgi를 아파치 서버에서 실행하도록 연결해 주려면 아까 수정하던 httpd.conf를 사용하여 인식시켜줘야 합니다.

WSGIScriptAlias / "D:/05_Program_dev/04_python/04_flaskapp/httpd.wsgi"

라우팅 "/" 로 들어오는 경우에는 "D:/05_~~~~.wsgi"를 실행한다 정도로 이해하시면 되겠습니다.

 

..

....

......

 

다른 블로그들을 보면 <Directory> <Files> 등을 설정하는 부분이 있는데, 현재로서는 의미를 잘 모르고, 이렇게만 해도 인식이 되는 것을 확인했습니다. 

 

아래는 이것저것 시도해보았지만 잘 안된 부분인데, 주요 인자가 있어서 혹시 필요한 경우를 대비해 기록으로 남겨놓을 까합니다.

LoadFile "c:/programdata/anaconda3/python38.dll"
LoadModule wsgi_module "c:/programdata/anaconda3/lib/site-packages/mod_wsgi/server/mod_wsgi.cp38-win_amd64.pyd"
WSGIPythonHome "c:/programdata/anaconda3"

<VirtualHost *:80>
    ServerName localhost
    WSGIScriptAlias / "D:/05_Program_dev/04_python/04_flaskapp/httpd.wsgi"
    <Directory "D:/05_Program_dev/04_python/04_flaskapp/">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    <Directory "D:/05_Program_dev/04_python/04_flaskapp/app">
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>

</VirtualHost>

 

<IfModule wsgi_module>
## 웹서비스 "/" 경로에 wsgi 인터페이스 경로 지정
WSGIScriptAlias / /apps/python/src/flask/httpd.wsgi
## Python app 프로세스 실행 환경 설정
WSGIDaemonProcess app user=python group=apps threads=1
</IfModule>

## Python app 서비스를 위한 app source 경로 권한 설정
<Directory "/apps/python/src">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Directory /apps/python/src/flask>
    WSGIApplicationGroup %{GLOBAL}
    Order deny,allow
    Allow from all
</Directory>

VirtualHost *:80 => 호스트를 지정하며 포트는 80포트를 사용한다. 포트가 겹쳐도 호스트가 다르기 때문에 상관없다.

ServerAdmin => 서버의 주인.

ServerName => 서버의 주소. 이 주소를 통해서 접근.

ServerAlias => 축약된 형태로 접근할 별명.

ErrorLog => 서버 접근시 일어는 에러 메시지를 기록하는 파일을 정한다. 이 속성을 정했다면 반드시 해당폴더가 존재해야한다.

CustomLog => 서버 기록을 기록하는 파일을 정한다. 이 속성을 정했다면 반드시 해당폴더가 존재해야한다.

WSGIDaemonProcess => wsgi를 데몬으로 실행시킬 때 프로세스 이름. 사용자 정의 가능

WSGIProcessGroup => wsgi프로세스 그룹이름. 사용자 정의가능

WSGIScriptAlias => wsgi를 실행시킬 스크립트의 위치. 우리가 만든 파일의 위치를 지정해준다.

Alias => 특정 파일의 별면. 보통 static으로 해야 하는데, 이는 WAS가 static에 접근해야하기 때문

 

 

- 끝 - 

 

반응형
반응형

matplotlib를 활용하여 그래프 그리는 예시입니다. 툴은 spider를 이용하여 그려보겠습니다. 

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl


x = np.random.rand(100)
y = np.random.rand(100)

plt.plot(y, 'b:')
plt.title('1Green Solid Line')
plt.title('2Blue Dotted Line')

plt.ioff()
plt.figure()


plt.plot(y, 'g-')
plt.title('3Green Solid Line')
plt.show()

plt.ion()

plt.figure()
h=plt.plot(y, 'g-')
plt.getp(h)
plt.setp(h, 'color', 'red')

plt.figure()

plt.plot(y, alpha=0.5, ls='-.', lw=3, marker='o', mec='red', mew=2, mfc="blue", ms=10)


 

이번에 데이터 분석 공부하면서 spider라는 툴을 사용해 보는데요, pycharm도 좋지만 spider도 또다른 편리한 점이 많네요. 그래프를 별도의 팝업이 아니라 이렇게 IDE의 기본 창에서 확인할 수 있도록 해주는 것도 편리한 것 같습니다. 

 

한개 더 해봅시다.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

plt.style.use('ggplot')

z = np.linspace(-1, 1, 100)
w = np.sqrt(1-z**2)
xo = np.concatenate([z,z[::-1][1:100]])
yo = np.concatenate([w, -1*w[::-1][1:100]])

plt.ion()
fig, axs = plt.subplots(2, 2, sharex='col', sharey='row', gridspec_kw={'hspace':0, 'wspace':0})
(ax1, ax2), (ax3, ax4) = axs
fig.suptitle('Sharing x per column, y per row')
ax1.plot(xo-1, yo)
ax2.plot(xo-1, yo-1, 'orange')
ax3.plot(xo+1, yo+1, 'green')
ax4.plot(xo+1, yo, 'red')

반응형
반응형

1. 미들웨어

미들웨어는 http요청과 routing 사이에 들어가는 작업입니다.

예)

var express = require('express');
var app = express();
var user = require('./routes/user');

// 미들웨어 작성
var myLogger = function (req, res, next) {
    console.log(req.url);
    next();
};

// 미들웨어 사용
app.use(myLogger);

app.get('/', function (req, res) {
    res.send('Hello World');
});

app.use('/user', user);

app.listen(3000, function () {
    console.log('Example App is listening on port 3000');
});

 

2. 주요 미들웨어 설치

(1) morgan: 로깅미들웨어

(2) body-parser: json 형태의 데이터를 request해서 파싱해주는 미들웨어

 

main.js

 

var express = require('express');
var app = express();
var user = require('./routes/user');
var morgan = require('morgan'); // morgan 불러오기
var bodyParser = require('body-parser');    // body-parser 불러오기


app.use(morgan('dev'));         // morgan 사용
app.use(bodyParser.json());     // body-parser 사용

app.get('/', function (req, res) {
    res.send('Hello World');
});

app.use('/user', user);

app.listen(3000, function () {
    console.log('Example App is listening on port 3000');
});

 

user.js

var express = require('express');
var router = express.Router();


router.get('/:id', function (req, res) {
    res.send('Received a GET request, param:' + req.params.id);
});

router.post('/', function (req, res) {
    console.log(JSON.stringify(req.body, null, 2)); //JSON형태의 데이터('req.body') 를 출력. 'null, 2': 잘 출력하기 위한 옵션
    res.json({
        success: true,
        user: req.body.username
    });
});

router.put('/', function (req, res) {
    res.status(400).json({ message: 'Hey, you. Bad Requst!' });
});
router.delete('/', function (req, res) {
    res.send('Received a DELETE request');
});

module.exports = router;

 

확인은 postman에서 아래와 같이 입력합니다.

  1. Body, 2. raw, 3. JSON을 선택하고 입력창에 값을 입력합니다.

  4. Send 버튼을 클릭하면 아래쪽 출력 화면에서 success와 user가 출력되는 것을 볼 수 있습니다.

 

 

 

3. static 파일관리 미들웨어

express에서 기본으로 제공하는 함수를 사용하여 접근 가능합니다. 별다른 임포트가 필요 없이 아래와 같이 입력하면 됩니다.

var express = require('express');
var app = express();
var user = require('./routes/user');
var morgan = require('morgan'); 
var bodyParser = require('body-parser');    


app.use(morgan('dev'));         
app.use(bodyParser.json());     
app.use('/', express.static('public')); // public 폴더에 접근

app.use('/user', user);

app.listen(3000, function () {
    console.log('Example App is listening on port 3000');
});

그리고 public 폴더에 index.html 파일, about.html파일을 예시로 만들어줍니다. 이때

app.get('/', ...) 부분과 app.use('/', express.static('public')); 이 어느 항목이 먼저오느냐에 따라 보이는 페이지가 달라질 수 있습니다. 여기서는 app.get('/', ...) 부분을 삭제하고 진행하겠습니다.

 

 

 

 

(ps) nodemon을 설치하면 편리하게 테스트작업을 수행할 수 있습니다.

npm install -g nodemon	// 설치
nodemon main.js       	// 실행

 

- 끝 - 

반응형

+ Recent posts