목표
구현과정(1)에는 영상의 자막에 관한 내용을 ai가 만들어주고, 자동으로 저장하고 불러와서 사용했다면 (2)에는 영상을 만드는 중간과정을 생략하고, 만들어진 영상을 특정 경로에 저장했을 때 유튜브에 업로드할 수 있도록 구현하려 한다.
현재 vrew를 통해 가볍게 영상을 만들어서 업로드하는 방향으로 하고 있고, 자막을 db에 저장하는 이유는 vrew에서는 ai의 목소리를 지원하고 있어서 자막을 그대로 가져다가 쓰면서 조금 수정하면 간단한 쇼츠영상을 제작할 수 있기 때문이다.
그렇다면 이제 만들어진 영상을 유튜브에 업로드하도록 구현하려 한다.
다만, 제목과 같이 나의 경우는 잠시 어쩔 수 없이 진행이 더뎌지게 되었다. 유튜브 업로드 권한의 경우 구글의 심사가 필요했기 때문이다. 그렇기 때문에 몇일 간 기다리게 생겼다... ㅠㅠ 나중엔 이 부분을 먼저 선행하면 좋을 것 같다.
유튜브 api 연동 전 초기 세팅 과정
별도로 api를 구현하는 과정을 떠나서 기존에도 유튜브에 업로드하려면 먼저 해야 하는 과정이 있다.
당연하지만, 로그인을 해야 한다. 그렇기 때문에 Oauth를 먼저 구현해야 한다.
Oauth 로그인에 관해서는 수많은 포스팅이 있기도 하고, 현재 진행하는 과정이 로그인에 중점을 두고 있지 않으므로 설명은 생략하려 한다. 구글 Oauth 로그인을 구현하게 되면 자연스레 클라이언트id, 클라이언트 비밀번호, redirect uri 값을 알 수가 있다.
이 부분은 구글클라우드의 사용자 인증정보에서 OAuth 클라이언트를 생성하고 확인하면 되겠다.
그리고, 먼저 선행해야 한다고 하는 부분은 이것인데, 유튜브에 업로드하는 부분에 관한 권한 설정이다.
OAuth 동의화면에서 진행하는데, 앱에 관해 설정하다보면 '범위 추가 또는 삭제'를 클릭하면
현재 추가할 수 있는 권한이 어떤 것이 있는지 확인할 수 있다.
그리고 목록에 없다면 상단 안내에 따라 링크를 통해 필요한 권한에 대해 추가할 수 있다.
그렇게 추가하고 나면 민감한 범위에 대해서는 앱을 인증받아야 한다고 한다.
신용안전팀에 양식이 접수되었습니다. 필요한 경우 연락처 이메일을 통해 연락을 드립니다. 검토 절차는 최대 4~6주가 걸릴 수 있습니다. 신용안전팀에서 3~5일 내에 첫 이메일을 보내 드립니다. 마지막으로 승인된 동의 화면이 계속 사용됩니다.
라고 하는데, 꽤 기다려야 하나보다. 그렇기에 먼저 선행하고 기다리는 동안 코딩을 하는 것이 수월해보인다.
환경변수 세팅
앞서 말한 클라이언트id, 클라이언트 비밀번호, redirect uri 값을 환경변수로 저장해 주었고,
환경변수에 관한 내용은 config에서 관리했다.
이전에 내가 답답했던 부분을 시원하게 해소한 것이 있다. 할거 다해놓고 env는 제대로 세팅이 된건지,, 정확히 알 수가 없다보니 실제로 테스트할 때가 되서야 입력이 되니, 환경변수 세팅의 문제였음을 안 적이 있는데, 그 이후로는 환경변수를 통제하되, 환경변수 세팅의 유무를 먼저 조회하는 기능을 구현했다.
다음은 config 디렉토리의 index.ts이다.
import dotenv from "dotenv";
import { Config } from "../types/config";
dotenv.config();
const getEnv = (key: string, defaultValue?: string): string => {
const value = process.env[key] ?? defaultValue;
if (!value) {
throw new Error(`${key} 환경 변수가 필요합니다.`);
}
return value;
};
const getEnvNumber = (key: string, defaultValue?: number): number => {
const value = Number(process.env[key]) ?? defaultValue;
if (!value && value !== 0) {
throw new Error(`${key} 환경 변수가 필요합니다.`);
}
return value;
};
const config: Config = {
/** [포트] 포트 번호 */
port: getEnvNumber("PORT"),
database: {
/** [데이터베이스] 데이터베이스 호스트 */
DB_HOST: getEnv("DB_HOST"),
/** [데이터베이스] 데이터베이스 사용자 */
DB_USER: getEnv("DB_USER"),
/** [데이터베이스] 데이터베이스 비밀번호 */
DB_PASSWORD: getEnv("DB_PASSWORD"),
/** [데이터베이스] 데이터베이스 이름 */
DB_NAME: getEnv("DB_NAME"),
},
openai: {
API_KEY: getEnv("OPENAI_API_KEY"),
organization: getEnv("OPENAI_ORGANIZATION"),
},
youtube: {
CLIENT_ID: getEnv("GOOGLE_CLIENT_ID"),
CLIENT_SECRET: getEnv("GOOGLE_CLIENT_SECRET"),
REDIRECT_URI: getEnv("GOOGLE_REDIRECT_URI"),
},
};
export default config;
getEnv함수에서 첫 번째 매개변수에는 입력한 값의 env를 확인하고 없을 경우 두 번째 매개변수의 값으로 입력되도록 세팅하고, 첫 번째 매개변수에만 입력했다면 env에 해당 값이 없을 때 서버를 시작하자마자 환경변수에 관한 에러가 먼저 발생한다.
그리고 별도로 config 디렉토리 안에 config.ts를 만들었다. 컨트롤러 에서는 클라이언트 단에서 생기는 에러처리나 req에 관련된 로직을 수행해야 하는데, 다른 외부의 api로직을 수행하는데까지 전부 컨트롤러에 담기엔 구분이 모호해서 별도의 config으로 관리했다.
import { Configuration, OpenAIApi } from "openai";
import config from "./index";
import { google } from "googleapis";
const { API_KEY, organization } = config.openai;
const configuration = new Configuration({
apiKey: API_KEY,
organization: organization,
});
export const openai = new OpenAIApi(configuration);
export const { CLIENT_ID, CLIENT_SECRET, REDIRECT_URI } = config.youtube;
const scopes = [
"https://www.googleapis.com/auth/youtube.upload",
];
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URI
);
const authorizationUrl = oauth2Client.generateAuthUrl({
access_type: "offline",
scope: scopes,
include_granted_scopes: true,
});
// Google API 클라이언트 초기화
const youtube = google.youtube("v3");
export { youtube, oauth2Client, authorizationUrl };
이 부분에는 해당 환경변수를 사용한 로직에 관한 코드를 담아 컨트롤러 단에서는 req관련된 로직을 수행하고, config에서 환경변수에 관한 로직을 불러내서 가져가도록 했다.
일반 로그인을 예시로 들 때, 클라이언트 / DB 관련된 로직을 구현하게 되는데, OAuth 로그인은 해당 외부 서비스에 로그인하는 것이므로 클라이언트 / OAuth 로직으로 구분되기 때문에 대부분 Oauth 로직으로 구성하게 된다. 별도의 config에서 관리하며 컨트롤러에서 가져다가 쓰게 되면 가독성 및 유지보수 면에서 수월하리라 생각한다.
OAuth 를 사용하여 로그인만 구현한다면 컨트롤러에서 로직을 사용해도 괜찮겠지만, 로그인 이후 유튜브에 업로드하는 부분이 있다보니, 클라이언트 id, 비번, 리다이렉트uri가 들어가는 oauth2Client함수를 재사용하기 위함이다.
'개발 > 프로젝트' 카테고리의 다른 글
[백킹트랙 생성 프로젝트] 기획, 구성, api 명세서 (0) | 2023.07.30 |
---|---|
[세션 / 토큰 로그인 프로젝트] 고도화(2) 멱등성에 대한 생각, 미들웨어 구현 결과 (0) | 2023.07.29 |
[유튜브 쇼츠 간편 생성 프로젝트] 구현 과정(1) ai의 대답 DB에 저장하기 (0) | 2023.07.27 |
[유튜브 쇼츠 간편 생성 프로젝트] 초기 기획 feat.ERD (5) | 2023.07.26 |
[세션 / 토큰 로그인 프로젝트] 고도화(3) 쿠키를 통한 팝업 관리 (0) | 2023.07.25 |