구조

실습을 통해 만드는 서비스 구조

클라우드 저장소 만들기

# 변수명 설정. 버킷 유일성을 보장하기 위하여 postfix를 붙임.
export PROJECT_ID=$(gcloud info --format='value(config.project)')
export IV_BUCKET_NAME=${PROJECT_ID}-upload
export FILTERED_BUCKET_NAME=${PROJECT_ID}-filtered
export FLAGGED_BUCKET_NAME=${PROJECT_ID}-flagged
export STAGING_BUCKET_NAME=${PROJECT_ID}-staging

# 클라우드 저장소 버킷 만들기
gsutil mb gs://${IV_BUCKET_NAME}
gsutil mb gs://${FILTERED_BUCKET_NAME}
gsutil mb gs://${FLAGGED_BUCKET_NAME}
gsutil mb gs://${STAGING_BUCKET_NAME}
gsutil ls

 

Pub/Sub 만들기

클라우드 저장소 통지 메시지와 클라우드 함수간 메시지 전송용으로 사용.

export UPLOAD_NOTIFICATION_TOPIC=upload_notification
gcloud pubsub topics create ${UPLOAD_NOTIFICATION_TOPIC}
gcloud pubsub topics create visionapiservice
gcloud pubsub topics create videointelligenceservice
gcloud pubsub topics create bqinsert
gcloud pubsub topics list

 

클라우드 저장소 통지 생성하기

새로운 객체가 클라우드 저장소 업로드 버킷에 올라오면 촉발되게 한다.

gsutil notification create -t upload_notification -f json -e OBJECT_FINALIZE gs://${IV_BUCKET_NAME}
gsutil notification list gs://${IV_BUCKET_NAME}

 

 

배포용 클라우드 함수 준비하기

실습에서 사용되는 설정 파일은 config.json

함수는 index.js에 정의된다.

 

소스코드를 다운로드하여서 살펴보자.

gsutil -m cp -r gs://spls/gsp138/cloud-functions-intelligentcontent-nodejs .
cd cloud-functions-intelligentcontent-nodejs

 

빅쿼리 데이터셋과 테이블 생성하기

비전 API를 사용한 결과를 빅쿼리에 저장할 예정. 데이터셋을 intelligentcontentfilter로, 테이블은 filtered_content로 명명한다. (그냥 config.json에 정의된 대로 생성하는 것에 불과)

export DATASET_ID=intelligentcontentfilter
export TABLE_NAME=filtered_content

bq --project_id ${PROJECT_ID} mk ${DATASET_ID}

bq --project_id ${PROJECT_ID} mk --schema intelligent_content_bq_schema.json -t ${DATASET_ID}.${TABLE_NAME}

#빅쿼리 테이블이 잘 생성되었나 확인
bq --project_id ${PROJECT_ID} show ${DATASET_ID}.${TABLE_NAME}

 

설정 파일의 placeholder를 실제 값으로 바꾸기

sed -i "s/\[PROJECT-ID\]/$PROJECT_ID/g" config.json
sed -i "s/\[FLAGGED_BUCKET_NAME\]/$FLAGGED_BUCKET_NAME/g" config.json
sed -i "s/\[FILTERED_BUCKET_NAME\]/$FILTERED_BUCKET_NAME/g" config.json
sed -i "s/\[DATASET_ID\]/$DATASET_ID/g" config.json
sed -i "s/\[TABLE_NAME\]/$TABLE_NAME/g" config.json

참고로 config.json파일은 다음과 같이 생겼다.

{
  "VISION_TOPIC": "projects/[PROJECT-ID]/topics/visionapiservice",
  "VIDEOINTELLIGENCE_TOPIC": "projects/[PROJECT-ID]/topics/videointelligenceservice",
  "BIGQUERY_TOPIC": "projects/[PROJECT-ID]/topics/bqinsert",
  "REJECTED_BUCKET": "[FLAGGED_BUCKET_NAME]",
  "RESULT_BUCKET": "[FILTERED_BUCKET_NAME]",
  "DATASET_ID": "[DATASET_ID]",
  "TABLE_NAME": "[TABLE_NAME]",
  "GCS_AUTH_BROWSER_URL_BASE": "https://storage.cloud.google.com/" ,
  "API_Constants": {
        "ADULT" : "adult",
        "VIOLENCE" : "violence",
        "SPOOF" : "spoof",
        "MEDICAL" : "medical"
  }
}

 

클라우드 함수 배포하기

함수 구현은 깃헙(https://github.com/GoogleCloudPlatform/cloud-functions-intelligentcontent-nodejs/blob/master/index.js)에 정의되어 있음.

 

# 클라우드 펍/섭에서 클라우드 저장소 통지 메시지를 받고, 이 메시지를 클라우드 펍/섭 메시지와 함께 다른 클라우드 함수를 호출하는 함수 배포
gcloud functions deploy GCStoPubsub --runtime nodejs10 --stage-bucket gs://${STAGING_BUCKET_NAME} --trigger-topic ${UPLOAD_NOTIFICATION_TOPIC} --entry-point GCStoPubsub

# 클라우드 펍/섭에서 메시지를 받아서 비전 API를 호출하고 이를 insertIntoBigQuert클라우드 함수로 메시지를 전달하는 함수 
gcloud functions deploy visionAPI --runtime nodejs10 --stage-bucket gs://${STAGING_BUCKET_NAME} --trigger-topic visionapiservice --entry-point visionAPI

# 클라우드 펍/섭에서 메시지를 받아서 비전 API를 호출하고 이를 insertIntoBigQuert클라우드 함수로 메시지를 전달하는 함수 
gcloud functions deploy videoIntelligenceAPI --runtime nodejs10 --stage-bucket gs://${STAGING_BUCKET_NAME} --trigger-topic videointelligenceservice --entry-point videoIntelligenceAPI --timeout 540

# 클라우드 펍/섭에서 메시지를 받아서 데이터를 빅쿼리 테이블로 넣기 위한 API를 호출하는 함수
gcloud functions deploy insertIntoBigQuery --runtime nodejs10 --stage-bucket gs://${STAGING_BUCKET_NAME} --trigger-topic bqinsert --entry-point insertIntoBigQuery

#배포된 함수 확인
gcloud beta functions list

 

전체 앱 동작 확인

클라우드 콘솔에서 저장소의 -upload가 붙은 버킷에 이미지/동영상 파일을 업로드해본다.

 

로그 동작 모니터링

클라우드 함수가 잘 실행되었는지 확인해보기

gcloud beta functions logs read --filter "finished with status" "GCStoPubsub" --limit 100
gcloud beta functions logs read --filter "finished with status" "insertIntoBigQuery" --limit 100

# sql.txt 파일 만들기. PLACEHOLDER 값 변경해야 함.
echo "
#standardSql

SELECT insertTimestamp,
  contentUrl,
  flattenedSafeSearch.flaggedType,
  flattenedSafeSearch.likelihood
FROM \`$PROJECT_ID.$DATASET_ID.$TABLE_NAME\`
CROSS JOIN UNNEST(safeSearch) AS flattenedSafeSearch
ORDER BY insertTimestamp DESC,
  contentUrl,
  flattenedSafeSearch.flaggedType
LIMIT 1000
" > sql.txt

bq --project_id ${PROJECT_ID} query < sql.txt

 

 

 

 

 

 

 

 

 

 

가끔 친구들 만나면 최근 C++(모던 C++)는 너무 다른 모습이어서 우리가 예전에 배웠던 C++가 아닌 다른 언어로 봐야한다는 농담을 나누곤 했다.

그런데 Reddit에도 비슷한 고민글이 올라왔는데, 답변들이 주옥같아서 정리 습관이 도졌다;

 

원 질문 링크: https://www.reddit.com/r/cpp/comments/nxwg0c/how_to_move_from_c_to_modern_c/

 

답변들에 소개된 모던 C++학습 자료들이다.

 

비야네의 빨간책(ToCpp) 읽어볼 것. 온라인에 내용이 공개되어있다.: https://isocpp.org/tour

스캇 메이어 옹의 EMC++

github에 올라온 새 기능들 소개한 레포: https://github.com/AnthonyCalandra/modern-cpp-features

 

C++ Weekly 구독 꾸욱

https://www.youtube.com/user/lefticus1/videos

 

MS가 제공하는 가이드 문서 읽기

https://docs.microsoft.com/en-us/cpp/cpp/welcome-back-to-cpp-modern-cpp?view=msvc-160 

https://www.youtube.com/watch?v=BezbcQIuCsY 

https://modernescpp.com/

https://en.cppreference.com/w/cpp/20

 

'2. 개발 > 2.1 C++' 카테고리의 다른 글

C++과 Modern C++  (0) 2021.06.13

+ Recent posts