"늘 그랬듯이"

라는 생각은 개발자에게 치명적이다.

 

그 현상을 더 이상

해결해야될 문제로 보지않고

안주하게 만들어버린다.

 

나에게 server.js 스크립트는

그런 대상이다.

 

수 많은 MVP 모델을 만들면서

server.js를 어떻게 구조화할지는

크게 고민하지않앗다.

 

express가 너무나도 쉽게 서버를 만들어주기에

필요할때 route만 더 붙여준다던지

cors를 설정해준다던지 하면 끝이었다.

 

// server.js
const express = require('express');
const api_v1 = require('../api/v1');

const app = express();
const http = require('http').createServer(app);

app.use('/api/v1/', api_v1);
http.listen(process.env.PORT, () => {
  console.log('server is listening on', process.env.PORT);
});

 

간단하게는

이정도면 충분히 훌륭한 앱서버가 된다.

 

문제는

서버에서 담당하는 역할이 많아지면서

여러가지가 붙다보면

코드가 지저분해지고

더이상 보기 싫은 스크립트가 되어버린다.

 

// server.js
const express = require('express');
const { Server } = require('socket.io');
const api_v1 = require('../api/v1');
const config = require('./config/server');

const app = express();
const http = require('http').createServer(app);
const io = new Server(http, {});

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());

app.use(function (req, res, next) {
  const allowedOrigins = config.allowedOrigin;
  const origin: any = req.headers.origin;
  if (allowedOrigins.indexOf(origin) > -1) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  res.header('Access-Control-Allow-Headers', 'Authorization, X-Requested-With, Content-Type, Accept');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS,PATCH');
  res.header('Access-Control-Allow-Credentials', 'true');
  req.method === 'OPTIONS' ? res.sendStatus(200) : next();
});

app.use('/api/v1/', api_v1);

io.sockets.on('connection', (socket) => {
  console.log('socket is connected..!');
});

http.listen(process.env.PORT, () => {
  console.log('server is listening on', process.env.PORT);
});

 

이정도만 되어도 보기싫어지기 시작한다.

우리는 class로 스크립트를 새로 짜보도록 하자.

 

// server.js
const express = require('express');
const { Server, createServer } = require('http');
const { Server as ioServer } = require('socket.io');
const api_v1 = require('../api/v1');
const config = require('./config/server');

const app = express();
const http = require('http').createServer(app);
const io = new Server(http, {});

class Server {
  private app: express.Aplication;
  private server: Server;
  private io: ioServer;
  
  constructor() {
    this.createApp();
    this.createServer();
    this.sockets();
    this.configure();
    this.routes();
    this.listen();
  }
  
  private createServer = (): void => {
    this.server = createServer(this.app);
  }
  
  private createApp = (): void => {
    this.app = express();
  }
  
  private sockets = (): void => {
    this.io = new ioServer(this.server);
  }
  
  private routes = (): void => {
    app.use('/api/v1/', api_v1);
  }
  
  private configure = (): void => {
    app.use(express.urlencoded({ extended: true }));
    app.use(express.json());
    app.use(cookieParser());

    app.use(function (req, res, next) {
      const allowedOrigins = config.allowedOrigin;
      const origin: any = req.headers.origin;
      if (allowedOrigins.indexOf(origin) > -1) {
        res.setHeader('Access-Control-Allow-Origin', origin);
      }
      res.header('Access-Control-Allow-Headers', 'Authorization, X-Requested-With, Content-Type, Accept');
      res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS,PATCH');
      res.header('Access-Control-Allow-Credentials', 'true');
      req.method === 'OPTIONS' ? res.sendStatus(200) : next();
    });
  }
  
  private listen = (): void => {
    this.server.listen(process.env.PORT, () => {
      console.log('server is listening on', process.env.PORT);  
    });
    
    io.sockets.on('connection', (socket) => {
      console.log('socket is connected..!');
    });
  }
}

const App = new Server();

 

이렇게 정리해놓고 보니

목적에 맞는 코드끼리 분리되어

유지보수가 확실히 수월해진듯한 느낌이든다.

 

코드를 짤때는 내 코드를

함께 공유할 개발자도 배려하는 자세를 갖도록 해야겠다.

728x90
반응형

pm2를 이용해서

앱서버를 백그라운드 환경으로 운영이 가능하다.

 

여기서 한발 더 나아가

cluster mode로 실행중인 node.js서버를

pm2를 이용해 돌리곤 했었다.

 

하지만 배포할때마다 일시적으로 중단되어버리는 서버.

원인은 restart로 배포하기때문.

 

reload 명령어를 통해

kill -> restart

reset 형식으로 서버 중단없이

무중단 배포가 가능하다.

pm2 reload index.js

 

근데 이를 제대로 활용하려면

몇가지 설정이 필요하다

 


 

pm2 ecosystem

 

위 명령어로 ecosystem.config.js 파일을 얻을수 있다.

다양한 설정들이 기본으로 세팅되어있는데

docs를 보면서 입맛에 맞게 설정하면 된다.

 

진짜 간단히는

module.exports = {
    apps: [
        {
            name: 'server',
            script: './index.js',
            watch: '.',
            instances: -1, // 클러스터 모드
            // exec_mode: 'cluster', <-- 이것도 클러스터 모드
        },
    ],
};

이렇게만 설정해도 된다

 

package.json을 수정하면

npm 명령어로 서버에서

간편히 실행 혹은 reload 하는것도 가능하다.

scripts: {
  "start": "pm2 start ./ecosystem.config.js --only server",
  "reload": "pm2 reload server"
}

 

고객에게 불편을 주지말자

 


여기서 더 나아간다면

실행중인 process가 덮어씌워지는 경우를

방지하고

reload할 수 있다.

 

// server.js

const app = express();


let disableKeepAlive = false;

// 중단이 감지되면 Keep 상태인 요청 닫음
app.use((req, res, next) => {
    if (disableKeepAlive) {
        res.set('Connection', 'close');
    }
    next();
});

const service = app.listen(process.env.PORT, () => {
    console.log(`The application is listening on port ${process.env.PORT}`);
    if (process.send) {
        console.log('send')
        process.send('ready');
    }
});

process.on('SIGINT', async () => {
    disableKeepAlive = true;
    service.close();
    process.exit(0);
});

이런식으로 구성해주면 된다.

728x90
반응형

취미생활로 브이로그 제작을 시작하였습니다.

 

파일정리가 필요해 지다보니

 

귀찮은 작업을 최소화 하기위해

 

파일 정리 라이브러리를 만들었습니다. (비디오 파일 정리 세팅 되어있음)

 

필요 하신 분들은 이용하시면 될것같습니다.

 

https://github.com/jaekwangLee/organize_video

 

GitHub - jaekwangLee/organize_video

Contribute to jaekwangLee/organize_video development by creating an account on GitHub.

github.com

 

728x90
반응형

base64? buffer? stream?

일반적으로 자주 사용하지는 않으나

파일 처리를 할때면 나타나 곤란한 상황을 만드는 녀석들이다.

 

이번에 우연한기회에

AWS에 업로드된 파일 URL을 노출시키지 않으면서

클라이언트에서 파일을 내려받게 해줘야하는 상황이 발생했다.

 

해당 과정에서 삽질하며 얻은 조각 지식들을 공유한다.

 

[ 가정 ]

1. 클라우드 저장소에 파일이 있다.

2. 클라이언트에서 파일 다운로드 요청 발생.

3. 서버에서 해당 파일을 불러온다.

4. 클라이언트에 해당 파일을 전송한다.

5. 다운로드 실시

 

1.  클라우드 저장소에 파일이 있다.

- AWS의 S3에 특정 파일이 저장되어있는 상황입니다.

- 해당 파일은 비문은 아니지만 공유를 원치않아 파일의 링크는 노출되지 않기를 원합니다.

- 마찬가지로 해당 파일의 버킷은 퍼블릭 버킷이 아닙니다.

- 따라서, 허가된 key를 가진 사용자만 파일을 호출할 수 있습니다. (즉, 서버에서만 요청 가능)

 

2. 파일을 필요로 하는 클라이언트는 지정된 서버로 요청을 보냅니다.

- 지정된 서버는 당연히 해당 AWS계정의 접근권한, key를 가진 서버겠죠.

 

3. 서버는  S3로부터 파일을 가져옵니다.

const AWS = require('aws-sdk')

const confg = {
  accessKeyId: '',
  scretAccessKey: '',
  region: '',
  signatureVersion: 'v4',
};

AWS.config.update(config);
const S3 = new AWS.S3();

function getObjectFromS3(key_name) {
  return new Promise((resolve, reject) => {
    S3.getObject({ Bucket: '', Key: key_name }, (err, data) => {
      if (err) reject(err);
      else resolve(data);
    })
  });
}

 

getObjectFromS3를 이용하면 쉽게 파일을 읽어올 수 있습니다.

자, 지금부터가 집중이 필요합니다.

불러온 데이터는 JSON 형태인데

파일은 Body에 Buffer형태로 따라옵니다.

 

이, Buffer를 어떤식으로 클라이언트로 반환해줄건지

이걸 받으려면 클라이언트는 어떻게 해야하는지

주목해야합니다.

 

다시, 돌아가 클라이언트에서 파일을

어떻게 요청해야되는지 살펴봅시다.

 

4. 클라이언트에서 서버에 특정 파일 요청하기

const requestPrivateFile = () => {
  axios.post(url, {}, { responseType: 'arrayBuffer' })
  .then(resp => {
    const { data } = resp;
    console.log(data);
    ...
  });
}

 

자, 일반적인 API요청과 다르게  responseType으로 arrayBuffer을 지정해주었습니다.

이걸 놓치면 백날 삽질해도 소용없습니다.

 

서버에서도 그러면 값을 맞춰서 반환해줘야겠죠?

 

5. 서버에서 불러온 파일 반환해주기

const getPrivateFile = async (req, res) => {
  ...
  
  const file = await getObjectFromKey('something.pdf');
  
  res.writeHead(200, [ 
    ['Content-Type', 'application/pdf'], //  다른 형식의 파일이면 알맞는 mime/type을 지정해주세요.
  ]);
  res.end(Buffer.from(file.Body, 'base64'));
}

sendFile이나 send 등이 아니라 위와 같은 방식으로

파일을 리턴해주게됩니다.

 

6. 자, 그러면 파일을 받아서 한번 다운로드해볼까요?

const requestPrivateFile = () => {
  axios.post(url, {}, { responseType: 'arrayBuffer' })
  .then(resp => {
    const { data } = resp;

    downloadFile(data, 'something.pdf');
  });
}

function downloadFile(buffer, filename) {
  const blob = new Blob([buffer], { type: 'application/pdf' });
  const url = window.URL.createObjectURL(blob);
  
  const a = document.createElement('a');
  a.download = filename; // download될때의 파일명을 지정해줍니다.
  a.href = url;
  
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a); // 더 이상 필요없으므로 삭제
}

 

자, 여기까지 "서버로부터 buffer 형식으로 파일 전송받아 처리하기"를 해보았습니다.

알고나면 간단하지만 모를때는 조각조각 흩어져있는

토막지식들로인해 어려움을 주는 사항이었습니다...

 

여러가지 상황에 응용이 가능하니 알아두면 좋을것같습니다.

728x90
반응형

nodejs에서 pdfjs-dist 라이브러리를 사용하기위해 canvas가 필요했다.

(pdfjs가 canvas에 의존적이기 때문)

 

그런데 linux기반 서버에서 canvas설치 후 실행시 다음과 같은 에러가났다.

Cannot find module '../build/Release/canvas'

 

한참을 헤맸다.

node-gyp rebuild니 permission 에러니...

 

정답은 늘 가까이에 있고, 많이 사용하는 라이브러리는 늘 답안이 나와있다. (감사해요 stackoverflow)

I just use "npm uninstall canvas" and then install using "npm i canvas"

 

이 단 한줄의 문장으 내 머리를 후려쳤다.

생각해보니 canvas에서 지시한 지시사항을 실행하기 전에 canavs를 먼저 설치한것이다.

 

sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev

 

위는 canvas에서 ubuntu환경일 경우 먼저 설치하라고 안내해준 library들이다.

 

나는 이미 진행했으므로

npm uninstall canvas
npm install canvas

 

canvas를 다시 설치해주는것만으로 해결되었다.

 

pdfjs는 pdf to png작업을 위해 사용하였는데, 곧 관련내용을 정리해볼 예정이다.

728x90
반응형

오랜만에 포스팅을 합니다.

 

운영중인 프로그램이 대규모 업데이트가 연속적으로 이루어지고있어

 

포스팅할 시간이 없네요.

 

대규모 업데이트를 하다본니, 이것만큼은 꼭 공유해주고 싶다! 라고 생각이 든 파트가 있어 포스팅하게되었습니다.

 

바로 로깅 시스템인데요.

 

 

다양한 라이브러리에서 로깅시스템을 지원해주지만,

내가 만들어 자유자재로 쓰는 가벼운 로깅시스템은 디버깅에서 최고의 효율은 발휘해주는것 같습니다.

 

예를들어, try/catch구문에서  해당 코드의 디렉토리 위치부터 에러발생 시간, 에러 내용을 모두 표시해준다면
에러복구에 정말 유용하겠죠?

따라서, fs시스템을 이용해 간단한 로깅메서드를 만들어 해당 시스템을 구축해 보도록 하겠습니다.

 

# 순서

1. 로깅 메서드 만들기

2. 활용 예제

3. 응용 예제

 

 


 

1. 로깅 메서드 만들기

const fs = require('fs');
const moment = require('moment');

export const logging = log => {
  const today = moment().format('YYYYMMDD');
  const date = moment().format('YYYY.MM.DD HH:mm:ss');

  const file = `./log/${today}_server.log`;
  const newLine = `[${date}] - ${log}`;

  fs.readFile(file, (err, data) => {
    if (err) {
      return console.error('read log err: ', err);
    }
    
    fs.writeFile(file, data + '\n' + newLine, err => {
      if (err) {
        return console.error('write log err: ', err);
      }
    });
  });
  
};

# 예제 키워드: fs, moment, 백틱

파일을 읽어오고 줄을 바꿔 내용을 덧붙이는 예제입니다.
writeFile은 해당 파일이 존재하지 않으면 기본적으로 create & write하게 되어있습니다.

 

(추가적으로, 해당 옵션은 flag옵션으로 변경가능합니다.)


2. 활용 예제

const { logging } = require('./util');

try {
  // something ...
  
} catch(error) {
  console.log('check system error log: ', error); // 콘솔에서 에러 확인 (개발에 활용)
  logging(error); // 로그파일에 기록 (나중에 확인하기 위함)
  return 'error;
}

 

우리의 logging 예제코드가 util파일에 있다고 가정했을때의 예제입니다.

이렇게, logging(error) 한줄 추가해주는것만으로

" [날짜] - 에러내용 "

 

구조의 에러 리포트를 누적해둘수있습니다.

예외처리에 빠짐없이 잘 써둔다면 디버깅에서 아주 유용하게 쓰일것으로 보입니다.

 

좀더 실용적이고 쓸만한 메서드로 개선해볼까요

 

 

3. 응용예제

# util
const fs = require('fs');
const moment = require('moment');

export const logging = (log, dir) => {
  const today = moment().format('YYYYMMDD');
  const date = moment().format('YYYY.MM.DD HH:mm:ss');

  const file = `./log/${today}_server.log`;
  const newLine = `[${date}] - ${log} ${ dir ? '\n'+ 'directory: ' + dir : ''}`;

  fs.readFile(file, (err, data) => {
    if (err) {
      return console.error('read log err: ', err);
    }
    
    fs.writeFile(file, data + '\n' + newLine, err => {
      if (err) {
        return console.error('write log err: ', err);
      }
    });
  });
  
};


# server
const { logging } = require('./util');

try {
  // something ...
  
} catch(error) {
  console.log('check system error log: ', error); // 콘솔에서 에러 확인 (개발에 활용)
  logging(error, __filename); // 로그파일에 기록 (나중에 확인하기 위함)
  return 'error;
}

# 예제 키워드: __filename

 

 

이렇게 간단한 수정만으로 파일의 디렉토리까지 남겨가며 모든 에러를 추적하게됩니다.

 

728x90
반응형

Node는 기본적으로 싱글스레드 기반이기 때문에

내부적으로 서버를 Fork해서 여러 스레드를 쓰는 방법을 지원해준다.

바로 cluster.

기본적으로 내장되어있으며 그 위력은 어마어마하다.

 

그런데 linux에서 cluster를 실행한 코드를 pm2로 실행하다보니

난관에 봉착했다.

 

에러가 발생한다.

cluster가 설정된 코드를 실행할수없었다.

 

그런데 node의 공식문서에서 방법을 찾았다.

문서의 일부 내용을 발췌했다.

 

======================================================

PM2 사용

애플리케이션을 PM2에 배치하면, 애플리케이션 코드를 수정하지 않고도 클러스터링을 활용할 수 있습니다. 먼저 여러분의 애플리케이션이 stateless인지 확실하게 해야합니다. 어떠한 로컬 데이터도 프로세스에 저장되지 않아야 합니다. (세션이나 웹소켓 같은 것들 말입니다).

PM2로 애플리케이션을 실행하고 있을 때, 특정한 수의 인스턴스에 실행하는 클러스터 모드를 켤 수 있습니다. 머신의 가용 CPU 수같은 것들이 특정한 수입니다. 애플리케이션을 끌 필요 없이 pm2 커맨드라인 명령을 이용해 클러스터에 있는 프로세스의 수를 직접 바꿀 수도 있습니다.

 

아래와 같은 방법으로 클러스터 모드를 킵니다.

# Start 4 worker processes

$ pm2 start app.js -i 4 # Auto-detect number of available CPUs and start that many worker processes

$ pm2 start app.js -i max

이 수는 PM2 프로세스 파일 (ecosystem.config.js나 그와 유사한 파일) 안의 exec_mode를 cluster나 instances를 설정해서 수정될 수 있습니다.

 

실행이 시작되면, app으로 이름지어진 애플리케이션을 아래와 같은 방법으로 스케일링 할 수 있습니다.

# Add 3 more workers

$ pm2 scale app +3 # Scale to a specific number of workers

$ pm2 scale app 2

PM2의 클러스터링에 관한 추가 정보는 PM2 문서의 Cluster Mode를 참고해주세요.

======================================================

 

 

728x90
반응형

암호화에는 대칭키와 비대칭키 방식이 있다.

 

대칭키 방식은 암호화와 복호화에 같은 키를 이용하는 방식이다.

주로 서버에서 암/복화하를 모두 하는 경우에 사용한다.

 

 

비대칭키 방식은 암호화 복호화에 각기 다른 키를 사용하는 방식이다.

먼저,  (복호화를 위한)개인키를 생성하고

개인키를 가지고  (복화화를 위한)공개키를  생성한다.

 

클라이언트와의 통신간에 암호화를 필요로 하는 경우 비대칭키를 사용하게되는데,

이는 대칭키 방식에 비해 속도가 다소 떨어진다고 한다.

 

나는 이번에 계좌번호, 카드번호 등의 데이터 교환을 위해 비대칭키 방식을 사용하게 되었다.

 

 

실제로, 어떻게 구현해 나가면 되는지 알아보자.

1. 개인키를 생성한다.

 - openssl genrsa -out private.key 2048 // 나는 이거로는 안심이 안된다. 4096을 사용

 

2. 개인키를 가지고 공개키를 생성한다.

 - openssl rsa -in private.key -out public.key -pubout (PKCS#8 표준)

 

3. PKCS#1 을 사용하고자 한다.

 - openssl rsa -pubin -in public.key -RSAPublicKey_out

 

4. 환경변수를 쉽게 사용하게 해주는 dotenv를 정의하는 .env파일에 다음과 같이 정의한다.

 - private키의 줄 끝마다 \n를 붙여 한줄로 합쳐준다.

// before
asdfasdf
asdfasdf
asdfasdf

// after
asdfasdf\nasdfasdf\nasdfasdf

 

5. 사용할 때는 다음과 같은 코드를 통해 사용할 수 있다

export const getPrivateKey = () => {
    return process.env.PRIVATE_KEY.replace(/\\n/g, '\n');
};

 

6. 이후의 암복화하는 일상 하던것과 다르지 않다...

728x90
반응형

Youtube API와 관련된 Nodejs 레퍼런스가 많이 부족한것 같습니다.

Youtube가 현재 대세인 것을 고려하면 너무나 안티까워 간단하게 Youtube api사용법을 공유하려 합니다.

 

* API로 유튜브 영상을 지우기

Youtube.videos.delete를 사용하게되며 영상의 id값만을 parameter로 보내줍니다.

Youtube.videos.delete({ id }, (err, data) => { ...something });

 

이전의 게시물에서 충분히 사전내용을 기록해두었기에 간단히 기록해보았습니다. (이전 게시물에 Youtube API서용법이 상세히 나와있으니 참고하시길 바랍니다..^^)

 

* 다만, 기억할것이 있습니다.

다른 api들과 같이 YoutubeAPI 역시 일일할당 트래픽량이 존재랍니다.

1인당 하루 10000트래픽이 허용되며, 초과시 사용이 더 이상 불가능합니다.

 

영상 업로드 api를 사용하다보면 금방 초과되버립니다 (7~8개쯤 영상업로드 테스트중 초과해버렸네요

..)

list를 가져오는 경우에는 거의 소요되지않지만 업로드 api를 사용해야 한다면,

정말 꼭 필요한 경우에만 쓰도록 하는게 좋을듯 합니다...

 

 

 


웹사이트 개발 / 홈페이지 제작 / android앱 개발 / ios 앱 개발 / server / client / aws / fullstack / buisness partner / 외주 / 용역

https://open.kakao.com/o/sNETgUJb

http://self-made.cloud

 

 

728x90
반응형

Youtube가 정말 핫합니다.

그래서 유튜브를 좀 더 적극적으로 활용하기 위해 Youtube API를 nodejs와 함께 쓰는법에 대해 포스팅을 해보겠습니다.

 

먼저, 목적에 따라 쓰는법이 달라질 수 있으니,

제가 쓰고자 하는 목적에 따라 아래의 가이드를 선택적으로 살펴보세요.

 

Type A: 단순히, 영상 id를 통해 목록 혹은 영상의 정보를 호출하고자 하는경우

Type B: 계정에 영향을 주는 작업, 예를들어 영상업로드나 수정과 같은.

 

* Type A

이 경우에 작업은 매우 간단하다.

GCP 계정을 생선한 다음 credentials에서 web용 api-key를 발급받습니다.

 

영상정보를 호출하고자 하는 경우,

https://www.googleapis.com/youtube/v3/videos

위의 url로 params: { key, id, part } 정보와 함께 get 요청을 하면됩니다.

part의 값으로는 'snippet,contentDetails'와 같은 값이 올 수 있습니다.

https://www.googleapis.com/youtube/v3/videos?key=abcabccom&id=wowow10&part=snippet

 

 

* Type B

이 경우에는 작업이 다소 복잡합니다...

우선, OAuth의 인증 작업을 걸쳐야 합니다.

따라서, 클라이언트와의 연계작업이 불가피하게 들어가게 됩니다. (여기서 말하는 연계작업이란, 클라이언트 사이드에서의 로그인 인증 과정을 말합니다.)

 

아래와 같이 작업해볼까요?.

Nodejs서버에 npm의 youtube-api, dotenv 세개의 라이브러리를 설치합니다. (없어도 구현가능 하지만, 예제에서는 사용하도럭 하겠습니다.)

 

다음, GCP credentials에서 OAuth client를 하나 생성하겠습니다.

이 때, callback url은 자유롭게 설정해도 되나, 예제와 같이하려면 /oauth2callback을 콜백url로 지정하는게 속편하겠죠?.

예를들면, "http://localhost:9000/oauth2callback"

생성한 계정정보를 가지고 앞으로의 작업을 진행할 것입니다.

const OAuth = Youtube.authenticate({
    type: 'oauth',
    client_id: process.env.OAUTH_ID,
    client_secret: process.env.OAUTH_PW,
    redirect_url: 'http://localhost:9000/oauth2callback',
});

 

OAuth를 통해 인증작업을 진행해보도록 하겠습니다..

*** dotenv모듈을 설치하면 .env파일에 저장한 정보들이 환경변수로 지정되며 위와같이 process.env.변수명 으로 불러올 수 있다.

*** 사용을 희망하는 파일에서 require('dotenv').require()와 같이 파일 맨 상단에 불러와주면 된다.

 

const data = { ...뭐시기뭐시기 };

const url = OAuth.generateAuthUrl({
  access_type: 'offline',
  scope: ['https://www.googleapis.com/auth/youtube.upload'],
  state: JSON.stringify(data),
});

return res.redirect(url); or return res.send(url);

 

위 코드에서  data는 클라이언트에서 받아온 정보이거나, 하여튼 무언가 정보가 있을수 있습니다.

(예를들면 영상과 영상정보)

callback에서 해당 정보를 전달받기 위해서는 위와 같이 state에 값을 string형태로 저장해 보내주면 됩니다.

아마 작업을 하시다보면 꼭 필요한 부분일것입니다. 잘 응용하시길 바랍니다.

 

이제, callback을 받아볼까요?

app.get('/oauth2callback', async (req, res) => {
    let { code, state } = req.query;
    state = JSON.parse(state);

    OAuth.getToken(code, (err, tokens) => {
        OAuth.setCredentials(tokens); //신뢰할 수 있는 사이트 지정

        const config = {
            part: 'snippet,status',
            resource: {
                snippet: {
                    title: state.title} 아이디어 발표영상,
                    description: state.description,
                    tags: ['유튜브api', '테스트'],
                },
                status: {
                    privacyStatus: 'public', // public, unlisted, private
                },
            },
            media: {
                body: state.media, // media
            },
        };
 

        Youtube.videos.insert(config, (err, data) => {
            if (err) return res.status(500).send('failed');
            else return res.status(200).send('success');
        });
    });
});

 

여기서 media파일이 중요합니다.

위의 경우에는 s3에 저장된 영상을 getObejct하여 바로 createReadStream() 처리해 받아온 경우이기 때문에 바로 사용할 수 있었습니다.

 

만약, 서버에 저장된 영상파일을 올려야한다면,

fs.createReadStream(media)와 같이 처리해야합니다.

 

 

 


웹사이트 개발 / 홈페이지 제작 / android앱 개발 / ios 앱 개발 / server / client / aws / fullstack / buisness partner / 외주 / 용역

https://open.kakao.com/o/sNETgUJb

http://self-made.cloud

 

 

728x90
반응형
  1. 초보 2021.03.24 10:06

    문의 드리고자합니다.

    client_id: process.env.OAUTH_ID, 에서 OAUTH_ID는 그냥 구글 계정인 건가요?