본문 바로가기
AICC 과정 정리

node child python

by 미르아 2024. 12. 29.
728x90

node 서버 기본 세팅

node install

npm init -y

필요한 모듈 설치

$ npm install child_process

$ install path

$ npm install body-parser

참고 블로그 - https://bb-library.tistory.com/214

node index.js에 파일 내용 - local 테스트

const express = require('express'); // express 모듈 불러오기
const cors = require('cors'); // cors 모듈 불러오기
const PORT = 8000; // 포트 설정
const { spawn } = require('child_process'); // child_process 모듈 불러오기
const path = require('path'); // path 모듈 불러오기
const bodyParser = require('body-parser');

console.log(path.join(__dirname));

const app = express(); // express 모듈을 사용하기 위해 app 변수에 할당

app.use(bodyParser.json());
app.use(cors()); // cors 사용 설정 http, https 프로토콜을 사용하는 서버간의 통신을 허용한다
app.use(express.json()); // json 형식 사용 설정

const corsOptions = {
  origin: '<http://localhost:3000> ', // 클라이언트의 주소를 명시
  credentials: true, // 자격 증명 허용
};

app.get('/', (req, res) => {
  res.send('Hello World! node'); // get 요청 시 Hello World! 출력
});

app.post('/chat', (req, res) => {
  const sendQuestion = req.body.question; // 클라이언트에서 받은 질문을 변수에 할당
  const execPython = path.join(__dirname, 'chat', 'bizchat.py'); // 파이썬 파일 경로 설정)
  const pythonPath = path.join(__dirname, 'chat', 'bin', 'python3'); // 파이썬 파일 경로 설정
  const net = spawn(pythonPath, [execPython, sendQuestion]); // 파이썬 파일 수행

  output = '';

  //파이썬 파일 수행 결과를 받아온다
  net.stdout.on('data', function (data) {
    output += data.toString();
  });

  net.on('close', (code) => {
    if (code === 0) {
      res.status(200).json({ answer: output });
    } else {
      res.status(500).send('Internal Server Error');
    }
  });

  net.stderr.on('data', (data) => {
    console.error(`stderr: ${data}`);
  });
});

app.listen(PORT, () => console.log(`Server is runnig on ${PORT}`)); // 서버 실행 시 메세지 출력

node index.js에 파일 내용 - 리눅스 deploy 용

const express = require('express'); // express 모듈 불러오기
const cors = require('cors'); // cors 모듈 불러오기
const PORT = 8000; // 포트 설정
const { spawn } = require('child_process'); // child_process 모듈 불러오기
const path = require('path'); // path 모듈 불러오기
const bodyParser = require('body-parser');

console.log(path.join(__dirname));

const app = express(); // express 모듈을 사용하기 위해 app 변수에 할당

app.use(bodyParser.json());
app.use(cors()); // cors 사용 설정 http, https 프로토콜을 사용하는 서버간의 통신을 허용한다
app.use(express.json()); // json 형식 사용 설정

const corsOptions = {
  origin: '<http://localhost:3000> ', // 클라이언트의 주소를 명시
  credentials: true, // 자격 증명 허용
};

app.use(cors(corsOptions));

app.get('/', (req, res) => {
  res.send('Hello World! node'); // get 요청 시 Hello World! 출력
});

app.post('/chat', (req, res) => {
  try {
    const sendedQuestion = req.body.question;

    // EC2 서버에서 현재 실행 중인 Node.js 파일의 절대 경로를 기준으로 설정합니다.
    const scriptPath = path.join(__dirname, 'bizchat.py');
    const pythonPath = path.join(__dirname, 'venv', 'bin', 'python3');
    console.log(pythonPath);

    // Spawn the Python process with the correct argument
    const result = spawn(pythonPath, [scriptPath, sendedQuestion]);

    // result.stdout.on('data', (data) => {
    //   console.log(data.toString());
    //   // return res.status(200).json(data.toString());
    // });

    let responseData = '';

    // Listen for data from the Python script
    result.stdout.on('data', (data) => {
      // console.log(data.toString());
      // res.status(200).json({ answer: data.toString() });
      responseData += data.toString();
    });

    // Listen for errors from the Python script
    result.stderr.on('data', (data) => {
      console.error(`stderr: ${data}`);
      res.status(500).json({ error: data.toString() });
    });

    // Handle the close event of the child process
    result.on('close', (code) => {
      if (code === 0) {
        res.status(200).json({ answer: responseData });
      } else {
        res.status(500).json({ error: `Child process exited with code ${code}` });
      }
    });
  } catch (error) {
    return res.status(500).json({ error: error.message });
  }
});

app.listen(PORT, () => console.log(`Server is runnig on ${PORT}`)); // 서버 실행 시 메세지 출력

서버 업로드 용 bizchat.py 내용

load_dotenv()
client = openai.Client(api_key = os.getenv("OPENAI_API_KEY")) # 환경변수에 저장된 API_KEY를 사용

# 경로 추적을 위한 설정
os.environ["PWD"] = os.getcwd() # 현재 작업 디렉토리를 설정
# print("Current working directory:", os.getcwd())

#출력의 인코딩을 utf-8로 설정한다
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding='utf-8')

# 문서 로드
loader = DirectoryLoader('./data', glob="*.txt", loader_cls=TextLoader) # 경로, 타입, 사용 함수
documents = loader.load()
# print(len(documents))

./data > 원래는 ./chat/data 였는데 서버에 올릴 때는 data 폴더 전까지를 기본 경로로 잡아서
data만 잡아주면 됨

일단 해결 방법 중 하나가 python을 설치 하는 것

data 파일도 ignore에 있었기 때문에 해제해 주고 올라갈 수 있도록 설정

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.12 python3.12-venv python3.12-dev

리눅스 서버에 python을 설치해야하는 것이 맞는지 모르지만 설치 후 정상 작동

리눅스 리액트 서버 실행 방법 - build 폴더가 하위에 있는 폴더에서 실행

ex ) /www/html/youtube/front/build 폴더가 있으면 front 폴더에서 실행

serve -l 3001 -s build 3001 포트로 pm2에서 실행

react pm2 사용법 pm2 serve [빌드된 폴더의 경로] [포트번호] --spa

ex ) pm2 serve build 3000 --spa - 3000번 포트로 실행 위와 마찬가지로 front 폴더에서 실행

업로드 후 확인 사항

현재 back같은 경우는 ci/cd 적용이 되어 vs code에서 코드 수정 시 자동으로 적용 상태

front는 리눅스 서버에서 깃에 올라간 파일을 clone한 후 리눅스 자체에서 빌드하여 사용 중

그렇기 때문에 git clone 후에 yarn install로 모듈 설치 진행

그 후 npm run build로 빌드 실행

front는 코드 수정 시 npm run build를 해주어야 수정 코드 적용 됨

728x90

'AICC 과정 정리' 카테고리의 다른 글

docker-compose로 rabbitMQ, jenkins 세팅하기  (4) 2024.12.30
배포 환경 테스트  (1) 2024.12.30
맥에서 React와 Git 설치 및 설정 가이드  (7) 2024.12.28
Git 명령어 정리  (1) 2024.12.28
CSS / Animation  (3) 2024.12.27