| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- 패스트캠퍼스
- 국비지원
- KDT
- UXUIPrimary
- Java
- 환급챌린지
- baekjoon
- 오픈패스
- 국비지원교육
- JPA
- 국비지원취업
- 디자인교육
- 내일배움카드
- UXUI챌린지
- 백준
- UXUI기초정복
- mysql
- 디자인강의
- Spring
- API
- Be
- 오블완
- 디자인챌린지
- 백엔드개발자
- 티스토리챌린지
- 시스템설계
- 백엔드 부트캠프
- OPENPATH
- 부트캠프
- 오픈챌린지
- Today
- Total
군만두의 IT 개발 일지
[구글 클라우드 스터디잼] API Developer Learning Path 본문
목차
구글 클라우드 스터디잼에 참가하여 'API Developer Learning Path' 중 'Google Cloud 기초: Cloud Storage 및 Cloud SQL 시작하기' 실습을 위주로 학습한 내용을 정리했습니다.
1. 클라우드 컴퓨팅의 기초
1.1 클라우드 컴퓨팅의 5가지 특성
- 사람의 개입 없이 웹 인터페이스로 컴퓨팅 자원을 직접 확보함.
- 인터넷을 통해 어디서나 자원에 접근 가능함.
- 클라우드 제공업체가 거대한 리소스 풀을 보유하며, 물리적 위치를 신경 쓸 필요 없음.
- 필요할 때 빠르게 확장하고, 불필요하면 축소 가능함.
- 사용한 만큼만 비용을 지불함.
1.2 클라우드 서비스 모델
| 모델 | 관리 책임 | 특징 | Google Cloud 예시 |
| IaaS | 고객이 OS 이상 관리 | 가상 인프라 자원 제공 | Compute Engine |
| PaaS | 고객은 코드만 관리 | 인프라 추상화, 실사용량 과금 | App Engine |
| Serverless | 고객은 함수/컨테이너만 관리 | 서버 관리 불필요, 이벤트 기반 | Cloud Run, Cloud Run Functions |
| SaaS | 제공업체가 전부 관리 | 완성된 애플리케이션 제공 | Gmail, Google Docs |
이번 실습은 IaaS(Compute Engine) + 관리형 서비스(Cloud SQL, Cloud Storage)으로 진행했습니다.
1.3 Google Cloud 리소스 계층 구조
- Google Cloud는 리소스 → 프로젝트 → 폴더 → 조직 노드의 4단계 계층으로 구성됨.
- 리소스: VM, Cloud Storage 버킷, BigQuery 테이블 등 실제 자원
- 프로젝트: 모든 리소스가 속하는 기본 단위 (결제, API, 권한의 기준)
- 폴더: 부서나 팀 단위로 프로젝트를 그룹화
- 조직 노드: 회사 전체를 대표하는 최상위 노드
- 상위에서 정의한 정책은 하위 리소스로 자동 상속됨 → 권한 관리가 효율적임
프로젝트는 프로젝트 ID(전역 고유, 변경 불가), 프로젝트 이름(변경 가능), 프로젝트 번호(Google이 할당)의 3가지 식별자를 가짐. 실습에서 사용하는 $DEVSHELL_PROJECT_ID가 프로젝트 ID에 해당함.
1.4 리전(Region)과 영역(Zone)
- 리전: 독립적인 지리적 구역 (예:
us-central1,asia-northeast3) - 영역: 리전 내부의 배포 단위 (예:
us-central1-c) *한 리전은 보통 3개 이상의 영역으로 구성됨. - 리소스는 영역에 배포되며, 자연재해 등으로 한 영역에 장애가 나도 다른 영역의 복제본으로 가용성을 확보할 수 있음.
- 현재 Google Cloud는 40개 이상의 리전과 121개 이상의 영역을 운영 중임.
이번 실습에서bloghostVM과blog-dbCloud SQL을 모두 us-central1-c 영역에 배치한 이유는 클라이언트와 데이터베이스를 같은 영역에 두면 네트워크 지연 시간이 가장 짧아지기 때문임.
2. Google Cloud의 스토리지 옵션
2.1 5가지 주요 스토리지 제품
| 제품 | 데이터 유형 | 주 사용 사례 |
| Cloud Storage | 비정형 (객체) | 이미지, 동영상, 백업, 정적 파일 |
| Cloud SQL | 관계형 (트랜잭션) | MySQL/PostgreSQL/SQL Server 기반 OLTP |
| Spanner | 관계형 (글로벌 분산) | 전 세계 단위의 강한 일관성 트랜잭션 |
| Firestore | NoSQL 문서 | 모바일/웹 앱의 실시간 동기화 |
| Bigtable | NoSQL 와이드 컬럼 | 대규모 분석, 시계열, IoT 데이터 |
이번 실습에서는 Cloud Storage(이미지)와 Cloud SQL(관계형 DB) 두 가지를 함께 사용함.
2.2 Cloud Storage 핵심 개념
객체 스토리지란
- 파일 계층(파일 스토리지)이나 디스크 청크(블록 스토리지)가 아닌 '객체' 단위로 데이터를 관리하는 아키텍처임.
- 각 객체는 실제 데이터 + 메타데이터(생성일, 작성자, 권한 등) + 전역 고유 식별자(URL)로 구성됨.
- 고유 키가 URL 형식이므로 웹 기술과 자연스럽게 통합됨 → 이번 실습에서
<img src='...'>로 바로 이미지를 불러올 수 있는 이유임.
버킷(Bucket)의 특성
- Cloud Storage 파일은 버킷이라는 컨테이너로 조직됨.
- 버킷 이름은 전역적으로 고유해야 함. 실습에서는
$DEVSHELL_PROJECT_ID를 그대로 버킷 이름으로 사용함. - 버킷은 단일 리전 또는 멀티 리전(US/EU/ASIA)과 연결됨. 사용자에게 가까운 위치를 선택해 지연 시간을 줄임.
객체 불변성과 버전 관리
- Cloud Storage 객체는 변경 불가(immutable)하므로 수정하지 않고 새 버전을 생성함.
- 버전 관리(versioning)를 활성화하면 덮어쓰기/삭제 이력이 모두 보관되므로 복원 가능함.
- 비활성화 시 새 버전이 이전 버전을 완전히 덮어씀.
액세스 제어(IAM vs ACL)
| IAM | ACL(Access Control List) |
| 프로젝트/버킷 단위 권한 | 객체 단위의 세밀한 권한 |
| 대부분의 경우 IAM만으로 충분 | 특정 객체만 공개하는 등 세밀한 제어가 필요할 때 사용 |
| 역할이 상위에서 하위로 상속됨 | '범위(누가)'와 '권한(무엇을)'으로 구성됨 |
실습에서 gsutil acl ch -u allUsers:R 명령어로 특정 이미지 객체만 모두에게 읽기 권한을 부여한 부분이 ACL의 사용 예시임. 버킷 전체가 아니라 해당 객체 하나만 공개로 만든 것임.
수명 주기 관리(Lifecycle)
- 비용 최적화를 위해 자동 삭제/이동 규칙을 설정할 수 있음.
- 예: 365일 지난 객체 자동 삭제, 최신 3개 버전만 유지 등
2.3 Cloud SQL 핵심 개념
- MySQL, PostgreSQL, SQL Server를 완전 관리형으로 제공하는 서비스임.
- 백업, 복제, 패치, 장애 조치(failover)를 Google이 자동 처리함. → 개발자는 데이터 모델링과 쿼리에만 집중 가능함.
- 네트워크 보안 모델: 기본적으로 외부 접근이 차단됨. → 접속을 허용하려면 승인된 네트워크(Authorized Networks)에 클라이언트 IP를 등록해야 함.
3. 실습 아키텍처
이번 실습에서 구축하는 미니 블로그 시스템의 구조는 다음과 같습니다.
| 구성 요소 | 역할 | 위치 |
Compute Engine VM (bloghost) |
Apache + PHP 웹 서버 | us-central1-c |
Cloud SQL (blog-db) |
MySQL 데이터베이스 | us-central1-c |
| Cloud Storage 버킷 | 배너 이미지(정적 파일) 저장 | US 멀티 리전 |
요청 흐름: 사용자 브라우저 → bloghost VM의 Apache → (PHP가 Cloud SQL에 PDO로 연결) + (Cloud Storage 공개 URL로 이미지 로드) → 응답
4. 실습 진행 과정
4.1 Compute Engine VM 인스턴스 배포
웹 서버 역할을 할 bloghost VM을 생성했습니다. 설정은 다음과 같습니다.
| 항목 | 값 |
| 이름 | bloghost |
| 리전 / 영역 | us-central1 / us-central1-c |
| 머신 유형 | e2-standard-2 |
| OS 이미지 | Debian GNU/Linux 12 (bookworm) |
| 방화벽 | HTTP 트래픽 허용 |
시작 스크립트(Startup Script)를 통해 VM이 부팅될 때 자동으로 Apache, PHP, php-mysql 모듈을 설치합니다.
#!/bin/bash
apt-get install apache2 php php-mysql -y
service apache2 restart
VM을 여러 번 재배포하거나 오토스케일링으로 인스턴스를 늘릴 때, 매번 SSH로 들어가 패키지를 설치하는 것은 비효율적임. 시작 스크립트는 인프라를 코드로 관리하는 첫 단계임.


4.2 Cloud Storage 버킷 생성 및 객체 업로드
콘솔 UI 대신 Cloud Shell의 gcloud storage 명령어를 사용합니다. 자동화 관점에서 CLI가 훨씬 강력합니다.
# 1. 위치 환경 변수 설정
export LOCATION=US
# 2. 프로젝트 ID와 동일한 이름으로 버킷 생성 (전역 고유성 확보)
gcloud storage buckets create -l $LOCATION gs://$DEVSHELL_PROJECT_ID
# 3. Google이 제공한 샘플 배너 이미지를 로컬로 다운로드
gcloud storage cp gs://cloud-training/gcpfci/my-excellent-blog.png my-excellent-blog.png
# 4. 내 버킷으로 업로드
gcloud storage cp my-excellent-blog.png gs://$DEVSHELL_PROJECT_ID/my-excellent-blog.png
# 5. 해당 객체만 모든 사용자에게 읽기 권한 부여 (ACL 변경)
gsutil acl ch -u allUsers:R gs://$DEVSHELL_PROJECT_ID/my-excellent-blog.png
$DEVSHELL_PROJECT_ID란? Cloud Shell 환경에 자동으로 주입되는 환경 변수임. 현재 활성화된 프로젝트 ID가 담겨 있어서 별도로 입력하지 않아도 명령어에서 바로 사용할 수 있음.

4.3 Cloud SQL 인스턴스 생성
| 항목 | 값 |
| 엔진 | MySQL |
| 버전 사전 설정 | 샌드박스 (학습/실습용 저비용 구성) |
| 인스턴스 ID | blog-db |
| 리전 / 영역 | us-central1 / us-central1-c (단일 영역) |
| 비밀번호 | Passw0rd1! |
| 보안 | 암호화되지 않은 네트워크 트래픽 허용 (실습용) |
인스턴스 생성 후 다음 두 가지를 추가로 설정함.
- 사용자 추가:
blogdbuser/Passw0rd1! - 승인된 네트워크 추가:
web front end라는 이름으로 bloghost VM의 외부 IP + /32를 등록 (단일 IP만 허용한다는 의미)
/32인 이유는? CIDR 표기법에서 /32는 단 하나의 IPv4 주소를 의미함. "오직 이 IP 한 대에서만 접속을 허용한다"는 가장 좁은 범위의 화이트리스트임. 보안의 기본 원칙인 최소 권한(Principle of Least Privilege)을 따른 것임.



4.4 PHP 애플리케이션에서 Cloud SQL 연결
bloghost VM에 SSH로 접속하여 /var/www/html/index.php를 작성합니다. PDO(PHP Data Objects)를 통한 MySQL 연결이 핵심입니다.
<?php
$dbserver = "CLOUDSQLIP"; // Cloud SQL 인스턴스의 공개 IP
$dbuser = "blogdbuser";
$dbpassword = "DBPASSWORD"; // 실제 운영에서는 Secret Manager 사용
try {
// PDO 객체로 MySQL 연결
$conn = new PDO("mysql:host=$dbserver;dbname=mysql", $dbuser, $dbpassword);
// 에러 발생 시 예외를 던지도록 설정
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
} catch(PDOException $e) {
echo "Database connection failed:: " . $e->getMessage();
}
?>
실제 서비스에서는 DB 비밀번호를 소스 코드에 평문으로 넣어선 안 됨. Google Cloud는 이를 위해 Secret Manager를 제공하며, 환경 변수나 IAM 기반 인증(예: Cloud SQL Auth Proxy)을 사용하는 것이 권장됨.
설정 후 Apache를 재시작하고 브라우저에서 http://[VM 외부 IP]/index.php로 접속하면 Connected successfully 메시지를 확인할 수 있습니다.


4.5 Cloud Storage 객체를 웹페이지에 통합
앞서 ACL로 공개해둔 이미지의 URL을 index.php에 추가합니다.
<img src='https://storage.googleapis.com/[버킷명]/my-excellent-blog.png'>
<h1>Welcome to my excellent blog</h1>
Apache 재시작 후 페이지를 새로고침하면 배너 이미지가 정상 표시됩니다. 이때 이미지는 VM의 디스크가 아니라 Cloud Storage에서 직접 서빙되고 있습니다.
아키텍처 관점: 정적 파일(이미지, CSS, JS)을 VM 디스크가 아닌 객체 스토리지에 분리하면, ① VM 디스크 용량을 절약하고 ② CDN과 연동하기 쉬우며 ③ VM이 여러 대로 늘어나도 모든 인스턴스가 동일한 파일을 참조할 수 있음. Stateless 웹 서버를 만드는 출발점임.

5. 트러블슈팅: 승인된 네트워크에 잘못된 IP를 입력
실습 도중 가장 헷갈렸던 부분입니다. Cloud SQL의 승인된 네트워크에 DB 인스턴스 자신의 공개 IP를 입력하는 실수를 했습니다.
- 승인된 네트워크는 이 DB에 접속해 올 클라이언트의 IP를 등록하는 곳임.
- DB 입장에서 외부에서 들어오는 요청의 출발지 IP를 화이트리스트에 추가해야 함.
- DB 자기 자신의 IP를 등록하는 것은 의미가 없음. "누가 누구에게 접속하는가"를 명확히 머릿속에 그리지 못하여 발생한 실수임.
6. 정리
- 관심사의 분리: 컴퓨팅(VM), 관계형 데이터(Cloud SQL), 정적 파일(Cloud Storage)을 각각 적합한 서비스에 위임함.
- 관리형 서비스의 가치: MySQL을 VM에 직접 설치하지 않고 Cloud SQL을 사용함으로써 백업/패치/복제를 위임함.
- 네트워크 보안의 기본: 승인된 네트워크와 /32 CIDR로 최소 권한 원칙을 실천함.
- 객체 스토리지의 사용 패턴: ACL로 객체 단위 공개 권한을 부여하고, URL 형태의 고유 식별자를 그대로
<img>태그에 사용함.
| 전통적인 방식 | 이번 실습 방식 |
| 한 서버에 Apache + MySQL + 정적 파일을 모두 배치 | 역할별로 서비스를 분리 |
| 스케일 아웃이 어려움 (DB와 파일이 한 서버에 묶임) | 각 계층을 독립적으로 확장 가능 |
| 장애 시 전체 서비스 중단 | 장애 영역이 분리되어 가용성 향상 |
| 백업/패치를 직접 관리 | 관리형 서비스에 위임 |
이 글은 '2026 구글 클라우드 스터디잼'에서 학습한 내용을 바탕으로 작성되었습니다.
'학습일지' 카테고리의 다른 글
| [구글 클라우드 스터디잼] Prompt Design in Vertex AI (0) | 2026.05.16 |
|---|---|
| [코드트리 후기] 코딩테스트 준비, 갭체크부터 청약 통장 1회차 시작하기 (0) | 2026.05.11 |
| [스터디13] 10. gRPC 시작하기 (0) | 2026.03.13 |
| [스터디13] 09. 웹서비스 배포하기 (0) | 2026.03.08 |
| [스터디13] 07. 사용자 인터페이스 설계하기 (0) | 2026.02.20 |
