Develop/DevOps

[Cloud OnBoard] 2 - 가상머신 및 스토리지 | [Cloud OnBoard] 2 - Virtual Machines and Storage

2019년 11월 26일 세종대학교에서 있었던 Google Cloud OnBoard에서 나누어준 자료집의 정리본입니다모듈2 가상머신 및 스토리지0. 추가 자료Google Compute Engine : https://cloud.google.com/compute/docsGoogle Cloud Platform VPC : https://cloud.google.com/compute/docs/vpcGoogle Cloud Stackdriver : https://cloud.google.com/stackdriver/docsGcloud 도구 가이드 : https://cloud.google.com/source-repositories/docsCloud Storage 개요 : https://cloud.google.com/sto..

[Cloud OnBoard] 2 - 가상머신 및 스토리지 | [Cloud OnBoard] 2 - Virtual Machines and Storage

728x90

2019년 11월 26일 세종대학교에서 있었던 Google Cloud OnBoard에서 나누어준 자료집의 정리본입니다


모듈2 가상머신 및 스토리지

0. 추가 자료

Google Compute Engine : https://cloud.google.com/compute/docs

Google Cloud Platform VPC : https://cloud.google.com/compute/docs/vpc

Google Cloud Stackdriver : https://cloud.google.com/stackdriver/docs

Gcloud 도구 가이드 : https://cloud.google.com/source-repositories/docs

Cloud Storage 개요 : https://cloud.google.com/storage

Google Cloud SQL 시작하기 : https://cloud.google.com/sql/docs/quickstart

Cloud Bigtable : https://cloud.google.com/stackdriver/docs

Cloud Spanner : https://cloud.google.com/spanner/docs

Cloud Datastore : https://cloud.google.com/datastore/docs

1. Virtual Private Cloud (VPC) 네트워크

  • 각 VPC 네트워크는 하나의 GCP 프로젝트에 포함
  • Cloud Platform 리소스를 프로비저닝하고 서로 연결하거나 격리할 수 있다.
  • VPC 네트워크는 글로벌 수준으로, 서브넷은 리전별 구성으로

2. Compute Engine

  • 관리형 가상머신 제공

    • 고성능 CPU, 대용량 메모리, 표준 및 공유 코어 머신 유형
    • 영구 디스크 (HD와 같은 느낌)
    • 표준, SSD, 로컬 SSD
    • 스냅샷
    • 다운타임없이 디스크 크기 조절
    • 인스턴스 메타데이터 및 시작 스크립트
  • 고객에게 유리한 가격 제시

    • 초단위 청구, 지속 사용 할인, 약정 사용 할인
    • 선점형 인스턴스
    • 추가 비용없이 스토리지 처리량 상향
    • 커스텀 머신 유형 : 필요한 하드웨어에 대해서만 지불
  • 수평확장 또는 수직 확장

    • 메모리 및 컴퓨팅 집약적 애플리케이션에 대규모 VM 사용
    • 탄력적인 확장형 애플리케이션에 자동 확장 사용

3. 중요한 VPC 기능

  • VCP 네트워크의 토폴로지 제어

    • 경로 테이블을 사용해 트래픽을 네트워크 안에서는 물론 서브넷 간에 전달
    • 방화벽을 사용해 네트워크 트래픽이 허용되는 항목을 제어
    • 공유 VPC를 사용해 네트워크 또는 개별 서브넷을 다른 GCP 프로젝트와 공유
    • VPC 피어링을 사용해 GCP 프로젝트의 네트워크의 상호연결
  • 전역 Cloud Load Balancing으로 전 세계에 단일 프런트 엔드로 제공되는 애플리케이션

    • 사용자가 단일 글로벌 Anycast IP 주소를 사용
    • Google 백본을 통해 가장 가까운 접속 지점에서 사용자에게로 트래픽 전달
    • 부하를 기준으로 백엔드 선택
    • 정상 백엔드만 트래픽 수신
    • 가동 준비가 필요 없음
  • Cloud DNS
    • 관리형 영역을 생성한 후 DNS 레코드를 추가, 편집, 삭제
    • RESTful API 또는 명령줄 인터페이스를 사용해 영역과 레코드를 프로그래매틱 방식으로 관리
  • Cloud CDN (Content Delivery Network)

    • 전세계에 분산된 Google의 에지 캐시를 사용하여 콘텐츠를 사용자에게 가깝게 캐싱
    • 다른 CDN의 사용을 원하는 경우 CDN Interconnect 사용
  • 다양한 상호 연결 옵션을 제공

    • VPN : VPN 터널을 통한 Gbps 단위의 연결 확보
    • 다이렉트 피어링 : 하이브리드 클라우드 워크로드를 위한 사용자와 Google간 비공개 연결
    • Dedicated Interconnect : Google 접속 지점에서 Google Cloud로 전달되는 프라이빗 클라우드 트래픽을 위한 N X 10G 전송 회로 연결
    • 이동통신사 피어링 : 서비스 제공업체의 대규모 파트너 네트워크를 통한 연결
    • Partner Interconnect : 지원되는 서비스 제공업체를 통한 온프레미스 네트워크 및 VPC 네트워크 간 연결
  • 부하 분산 옵션 제품군을 제공하는 Google VPC

 

글로벌 HTTP(S) 글로벌 SSL 프록시 글로벌 TCP 프록시 리전 리전 내부
부하를 기준으로한 Layer 7 부하 분산 부하를 기준으로 한 HTTPS외 SSL 트래픽의 Layer 4 부하 분산 SSL외 TCP 트래픽의 Layer 4 부하 분산 모든 트래픽(TCP, UDP)의 부하 분산 VPC내 트래픽의 부하 분산
각종 URL을 다양한 백엔드에 라우팅 할 수 있음 특정 포트 번호에서 지원됨 특정 포트번호에서 지원됨 모든 포트번호에서 지원됨 다중 계층 애플리케이션의 내부 계층에 사용

4. GCP - 스토리지

5. Cloud Storage

  • Cloud Storage의 특징

    • BLOB (binary large-object) 스토리지
    • 고성능 인터넷 규모 : 단순한 관리
    • 용량을 관리할 필요가 없음
    • 저장 데이터 암호화
    • 기본적으로 Google에서 엔드포인트로 전송 중인 데이터 암호화
    • 온라인 및 오프라인 가져오기 서비스 사용 가능
  • Cloud Storage 파일은 버킷으로 구성
  • Cloud Storage 등급 선택하기
  • Cloud Stoarge로 데이터를 가져오는 3가지 방법


    • 온라인 전송 : 명령줄 도구 또는 드래그인 드롭을 사용한 자체 관리형 사본
    • Storage Transfor Service : 일정에 따른 관리형 일괄 전송
    • Transfer Appliance : 데이터를 안전하게 전송하는, 랙 장착 가능한 어플라이언스
  • 다른 GCP 서비스와 함께 사용이 가능하다.

6. Cloud Bigtable

  • Cloud Bigtable의 특징


    • 관리형 NoSQL
    • 테라바이트 규모의 애플리케이션을 위한 완전 관리형 NoSQL, 광폭 열 데이터베이스 서비스
    • HBase API로 액세스
    • 빅데이터, Hadoop 에코시스템과 기본적으로 호환
    • 복제 스토리지
    • 가동 여부와 관계없이 상시 데이터 암호화
    • 역할 기반 ACL
    • google Analytics, Gmail등의 주요 애플리케이션 실행
  • Bigtable 액세스 패턴

    • Application API
      관리형 VM, HBase REST 서버, HBase 클라이언트를 사용하는 자바 서버와 같은 데이터 서비스 계층을 통해 Cloud Bigtable에서 데이터를 읽고 쓸 수 있다. 일반적으로 애플리케이션, 대시보드, 데이터 서비스에 데이터를 제공한다.
    • 스트리밍
      Cloud Dataflow Streaming, Spark Streaming, Storm과 같은 다양한 인기 스트림 처리 프레임워크를 통해 데이터를 스트리밍(이벤트별로 쓰기) 할 수 있다.
    • 일괄 처리
      Hadoop 맵 리듀스, Dataflow, Spark와 같은 일괄 프로세스를 통해 Cloud Bigtable에서 데이터를 읽고 쓸 수 있다. 요약 데이터 또는 새로 계산괸 데이터가 Cloud Bigtable 또는 다운스트림 데이터베이스에 다시 기록되는 경우가 많다.

 

7. Cloud SQL 및 Cloud Spanner

7-1. Cloud SQL

 

  • Cloud SQL의 특징

    • 관리형 RDBMS
    • MySQL및 PostgreSQL 데이터베이스를 서비스로 제공
    • 자동 복제
    • 관리형 백업
    • 수직 확장 (읽기 및 쓰기)
    • 수평 확장 (읽기)
    • Google 보안
  • 다른 GCP 서비스와 함께 사용 가능

    • Cloud SQL + App Engine
      표준 드라이버를 통해 Cloud SQL과 App Engine을 함께 사용할 수 있다.
      App Engine 애플리케이션을 따르도록 Cloud SQL인스턴스를 구성할 수 있다.
    • Cloud SQL + Compute Engine
      Compute Engine 인스턴스에서 외부 IP 주소를 사용하여 Cloud SQL 인스턴스에 액세스 하도록 승인할 수 있다.
      Cloud SQL 인스턴스를 선호 영역에 구성할 수 있다.
    • Cloud SQL + 외부 서비스
      Cloud SQL을 외부 애플리케이션 및 클라이언트와 함께 사용할 수 있다.
      표준 도구를 사용하여 데이터베이스를 관리할 수 있다.
      외부 읽기 복제본을 구성할 수 있다.

7-2. Cloud Spanner

 

  • 수평으로 확장 가능한 RDBMS
  • 자동 복제
  • 강력한 전역 일관성
  • 가용성이 높은 관리형 인스턴스
  • SQL (ANSI 2011, 확장 포함)

8. Cloud Datastore

 

 

  • 수평으로 확장 가능한 NoSQL DB
  • 애플리케이션 백엔드용으로 설계된 NoSQL
  • 완전 관리형 : 분산 아키텍처를 사용해 확장을 자동 관리
  • 내장형 중복 기능
  • ACID 트랜잭션 지원
  • 스키마 없는 액세스 : 기본 데이터 구조를 고려할 필요 없음
  • 로컬 개발 도구
  • 무료 일일 할당량 포함
  • RESTful 인터페이스를 통해 어디서나 액세스

9. 스토리지 옵션 비교

9-1. 기술 세부 정보

  Cloud Datastore Cloud Storage Cloud Bigtable Cloud SQL Cloud Spanner BigQuery
유형 NoSQL 문서 Blobstore NoSQL
광폭 열
OLTP용 관계형 SQL OLTP용 관계형 SQL OLAP용 관계형 SQL
트랜잭션 O X 단일 행 O O X
복잡한 쿼리 X X X O O O
용량 TB+ PB+ PB+ 10TB PB PB+
단위 크기 1MB/항목 -10MB/셀 -100MB/행 5TB/객체 DB엔진 결정 10.240MiB/행 10MB/행

9-2. 사용 사례

  Cloud Datastore Cloud Storage Cloud Bigtable Cloud SQL Cloud Spanner BigQuery
유형 NoSQL 문서 Blobstore NoSQL 광폭 열 OLTP용 관계형 SQL OLTP용 관계형 SQL OLAP용 관계형 SQL
권장용도 반구조화 애플리케이션 데이터, 내구성 높은 키-값 데이터 '플랫' 데이터, 집중적인 읽기 /쓰기, 이벤트, 분석 데이터 구조화 및 비구조화 바이너리 또는 객체 데이터 웹 프레임워크, 기존 애플리케이션 대규모 데이터 베이스 애플리케이션 (약 2TB이상) 대화형 쿼리, 오프라인 분석
사용사례 입문용, App Engine 애플리케이션 AdTech, 금융, IoT 데이터 이미지, 대용량 미디어 파일, 백업 사용자 인증 정보, 고객 주문 높은 I/O, 전역적인 일관성이 필요한 모든 경우 데이터 웨어하우스
단위크기 1MB/항목 -10MB/셀 -100MB/행 5TB/객체 DB엔진 결정 10.240MiB/행 10MB/행

This is a summary of the handout distributed at the Google Cloud OnBoard event held at Sejong University on November 26, 2019.


Module 2: Virtual Machines and Storage

0. Additional Resources

Google Compute Engine : https://cloud.google.com/compute/docs

Google Cloud Platform VPC : https://cloud.google.com/compute/docs/vpc

Google Cloud Stackdriver : https://cloud.google.com/stackdriver/docs

Gcloud Tool Guide : https://cloud.google.com/source-repositories/docs

Cloud Storage Overview : https://cloud.google.com/storage

Getting Started with Google Cloud SQL : https://cloud.google.com/sql/docs/quickstart

Cloud Bigtable : https://cloud.google.com/stackdriver/docs

Cloud Spanner : https://cloud.google.com/spanner/docs

Cloud Datastore : https://cloud.google.com/datastore/docs

1. Virtual Private Cloud (VPC) Network

  • Each VPC network belongs to a single GCP project
  • You can provision Cloud Platform resources and connect or isolate them from each other.
  • VPC networks are configured at the global level, while subnets are configured at the regional level

2. Compute Engine

  • Provides managed virtual machines

    • High-performance CPUs, large memory, standard and shared-core machine types
    • Persistent disks (similar to a hard drive)
    • Standard, SSD, Local SSD
    • Snapshots
    • Resize disks with no downtime
    • Instance metadata and startup scripts
  • Customer-friendly pricing

    • Per-second billing, sustained use discounts, committed use discounts
    • Preemptible instances
    • Higher storage throughput at no additional cost
    • Custom machine types: pay only for the hardware you need
  • Scale out or scale up

    • Use large VMs for memory and compute-intensive applications
    • Use autoscaling for elastic, scalable applications

3. Key VPC Features

  • Control the topology of VPC networks

    • Use route tables to forward traffic within the network as well as between subnets
    • Use firewalls to control what network traffic is allowed
    • Use Shared VPC to share a network or individual subnets with other GCP projects
    • Use VPC Peering to interconnect networks across GCP projects
  • Global Cloud Load Balancing provides applications served by a single frontend worldwide

    • Users use a single global Anycast IP address
    • Traffic is routed to the user from the nearest point of presence via the Google backbone
    • Backends are selected based on load
    • Only healthy backends receive traffic
    • No pre-warming required
  • Cloud DNS
    • Create managed zones, then add, edit, and delete DNS records
    • Programmatically manage zones and records using a RESTful API or command-line interface
  • Cloud CDN (Content Delivery Network)

    • Cache content close to users using Google's globally distributed edge caches
    • Use CDN Interconnect if you prefer to use another CDN
  • Offers a variety of interconnect options

    • VPN: Secure Gbps-level connectivity through VPN tunnels
    • Direct Peering: Private connection between you and Google for hybrid cloud workloads
    • Dedicated Interconnect: N x 10G transport circuits for private cloud traffic from a Google point of presence to Google Cloud
    • Carrier Peering: Connectivity through a service provider's extensive partner network
    • Partner Interconnect: Connectivity between on-premises networks and VPC networks through a supported service provider
  • Google VPC provides a suite of load balancing options

 

Global HTTP(S) Global SSL Proxy Global TCP Proxy Regional Regional Internal
Layer 7 load balancing based on load Layer 4 load balancing for non-HTTPS SSL traffic based on load Layer 4 load balancing for non-SSL TCP traffic Load balancing for all traffic (TCP, UDP) Load balancing for traffic within a VPC
Can route various URLs to different backends Supported on specific port numbers Supported on specific port numbers Supported on any port number Used for internal tiers of multi-tier applications

4. GCP - Storage

5. Cloud Storage

  • Features of Cloud Storage

    • BLOB (binary large-object) storage
    • High performance, internet scale: simple management
    • No need to manage capacity
    • Data at rest encryption
    • Data in transit encryption by default from Google to endpoints
    • Online and offline import services available
  • Cloud Storage files are organized into buckets
  • Choosing a Cloud Storage class
  • 3 ways to bring data into Cloud Storage


    • Online transfer: Self-managed copies using command-line tools or drag and drop
    • Storage Transfer Service: Managed batch transfers on a schedule
    • Transfer Appliance: A rackable appliance for securely transferring data
  • Can be used together with other GCP services

6. Cloud Bigtable

  • Features of Cloud Bigtable


    • Managed NoSQL
    • Fully managed NoSQL, wide-column database service for terabyte-scale applications
    • Access via HBase API
    • Natively compatible with big data and the Hadoop ecosystem
    • Replicated storage
    • Data encryption at all times, whether in use or not
    • Role-based ACLs
    • Powers key applications like Google Analytics, Gmail, and more
  • Bigtable access patterns

    • Application API
      You can read and write data in Cloud Bigtable through a data service layer such as managed VMs, an HBase REST server, or a Java server using an HBase client. This typically serves data to applications, dashboards, and data services.
    • Streaming
      You can stream data (write per event) through various popular stream processing frameworks such as Cloud Dataflow Streaming, Spark Streaming, and Storm.
    • Batch processing
      You can read and write data in Cloud Bigtable through batch processes such as Hadoop MapReduce, Dataflow, and Spark. Summary data or newly computed data is often written back to Cloud Bigtable or a downstream database.

 

7. Cloud SQL and Cloud Spanner

7-1. Cloud SQL

 

  • Features of Cloud SQL

    • Managed RDBMS
    • Offers MySQL and PostgreSQL databases as a service
    • Automatic replication
    • Managed backups
    • Vertical scaling (read and write)
    • Horizontal scaling (read)
    • Google security
  • Can be used with other GCP services

    • Cloud SQL + App Engine
      You can use Cloud SQL with App Engine through standard drivers.
      You can configure a Cloud SQL instance to follow an App Engine application.
    • Cloud SQL + Compute Engine
      You can authorize access to a Cloud SQL instance using the external IP address from a Compute Engine instance.
      You can configure a Cloud SQL instance in a preferred zone.
    • Cloud SQL + External Services
      You can use Cloud SQL with external applications and clients.
      You can manage databases using standard tools.
      You can configure external read replicas.

7-2. Cloud Spanner

 

  • Horizontally scalable RDBMS
  • Automatic replication
  • Strong global consistency
  • Highly available managed instances
  • SQL (ANSI 2011, with extensions)

8. Cloud Datastore

 

 

  • Horizontally scalable NoSQL DB
  • NoSQL designed for application backends
  • Fully managed: automatically handles scaling using a distributed architecture
  • Built-in redundancy
  • Supports ACID transactions
  • Schemaless access: no need to worry about the underlying data structure
  • Local development tools
  • Includes free daily quota
  • Accessible from anywhere via a RESTful interface

9. Comparing Storage Options

9-1. Technical Details

  Cloud Datastore Cloud Storage Cloud Bigtable Cloud SQL Cloud Spanner BigQuery
Type NoSQL Document Blobstore NoSQL
Wide-column
Relational SQL for OLTP Relational SQL for OLTP Relational SQL for OLAP
Transactions O X Single-row O O X
Complex queries X X X O O O
Capacity TB+ PB+ PB+ 10TB PB PB+
Unit size 1MB/entity -10MB/cell -100MB/row 5TB/object Determined by DB engine 10,240MiB/row 10MB/row

9-2. Use Cases

  Cloud Datastore Cloud Storage Cloud Bigtable Cloud SQL Cloud Spanner BigQuery
Type NoSQL Document Blobstore NoSQL Wide-column Relational SQL for OLTP Relational SQL for OLTP Relational SQL for OLAP
Best for Semi-structured application data, durable key-value data 'Flat' data, heavy read/write, event and analytics data Structured and unstructured binary or object data Web frameworks, existing applications Large-scale database applications (roughly 2TB+) Interactive queries, offline analytics
Use cases Getting started, App Engine applications AdTech, finance, IoT data Images, large media files, backups User credentials, customer orders Any case requiring high I/O and global consistency Data warehousing
Unit size 1MB/entity -10MB/cell -100MB/row 5TB/object Determined by DB engine 10,240MiB/row 10MB/row

댓글

Comments

Develop/DevOps

[Cloud OnBoard] 1 - Google Cloud Platform 소개 | [Cloud OnBoard] 1 - Introduction to Google Cloud Platform

2019년 11월 26일 세종대학교에서 있었던 Google Cloud OnBoard에서 나누어준 자료집의 정리본입니다모듈1 Google Cloud Platform 소개0. 추가 자료GCP를 선택해야하는 이유 : https://cloud.google.com/why-google/가격 책정 철학 : https://cloud.google.com/pricing/philosophy데이터 센터 : https://www.google.com/about/datacentersGoogle Cloud Platform 제품 개요 : https://cloud.google.com/productsGoogle Cloud Platform 솔루션 : https://cloud.google.com/solutionsGoogle Cloud Pla..

[Cloud OnBoard] 1 - Google Cloud Platform 소개 | [Cloud OnBoard] 1 - Introduction to Google Cloud Platform

728x90

2019년 11월 26일 세종대학교에서 있었던 Google Cloud OnBoard에서 나누어준 자료집의 정리본입니다


모듈1 Google Cloud Platform 소개

0. 추가 자료

GCP를 선택해야하는 이유 : https://cloud.google.com/why-google/

가격 책정 철학 : https://cloud.google.com/pricing/philosophy

데이터 센터 : https://www.google.com/about/datacenters

Google Cloud Platform 제품 개요 : https://cloud.google.com/products

Google Cloud Platform 솔루션 : https://cloud.google.com/solutions

Google Cloud Platform 보안 : https://cloud.google.com/security

권한 구성 : https://cloud.google.com/docs/permissions-overview

Identity And Access Management (IAM) : https://cloud.google.com/iam/

Cloud SDK 설치 및 빠른 시작 : https://cloud.google.com/sdk/#Quick_Start

gcloud 도구 가이드 : https://cloud.google.com/sdk/gcloud

1. GCP의 특징

  • 고객 상황에 알맞은 서비스를 제공하는 GCP 컴퓨팅 아키텍처
  • 전세계 134개의 접속 지점과 13개의 해저 케이블에 투자했다
    전 세계적인 서비스에 GCP는 적합하다.
  • GCP의 구성은 Region과 Zone으로 구성되어있다.
    멀티 리전 : 미국 - 한국
    리전 : europe-west2
    Zone : europe-west2-a, europe-west2-b, europe-west2-c
    현재 발표된 Region의 수
  • google은 환경보호에 앞장선다.
    • 2007년부터 탄소 중립성 100%를 유지하고있다.
    • 전세계적으로 재생 에너지를 가장 많이 구매하는 기업 중 하나이다.
    • ISO 14001 인증을 획득한 가장 최초의 데이터 센서이다.
  • Google은 고객에게 유리한 가격 조건을 제시한다.
    • 분단위 증가분 결제 - 컴퓨팅, 데이터 처리, 기타 서비스
    • 지속 사용 할인 - 가상 머신을 한달에 25%이상 사용하는 경우 자동으로 적용
    • 약정 사용 할인 - 장기간 워크로드가 꾸준할 경우 비용 할인
    • 선점형 사용 할인 - 일시 중단될 수 있는 워크로드에 대한 비용 할인
    • 커스텀 VM 인스턴스 유형 - 애플리케이션에 필요한 리소스에만 지불
  • 개방형 API 및 오픈소스
  • 보안
  • GCP의 서비스

2. CGP 리소스 계층 구조

2-1. 리소스 계층 구조 수준에 따라 신뢰 경계정의

  • 조직 구조에 따라 리소스를 그룹화
  • 계층 구조 수준에 따라 신뢰 경계 및 리소스 격리가 설정

2-2. 모든 GCP 서비스는 프로젝트와 연결

  • 리소스 및 할당량 사용량 추적
  • 결제를 사용설정
  • 권한 및 사용자 인증 정보를 관리
  • 서비스 및 API를 사용 설정

2-3. 프로젝트에 사용되는 3가지 식별 속성

프로젝트 ID 전역에서 고유 사용자가 선택 변경 불가능
프로젝트 ID 전역에서 고유 사용자가 선택 변경 불가능
프로젝트 이름 고유할 필요 없음 사용자가 선택 변경 불가능
프로젝트 번호 전역에서 고유 GCP 에서 선택 변경 불가능

2-4. GCP의 폴더관리

  • 폴더로 한 조직내의 여러 프로젝트를 그룹화 할 수 있다.
  • 폴더에는 프로젝트나 다른 폴더 또는 이 두가지가 모두 포함될 수 있다.
  • 폴더를 사용해 정책을 할당할 수 있다.

2-5. 조직노드로 프로젝트 정리

2-6. IAM 리소스 계층 구조 예시

  • 정책이 리소스에 설정 : 각 정책은 역할 및 역할 구성원 집합을 명시
  • 상위 정책이 리소스에 상속 : 리소스 정책은 상위 리소스와 현재 리소스의 합집합 이다.
  • 덜 제한적인 상위정책이 더 제한적인 리소스 정책을 재 정의

3. Identity and Access Management (IAM)

3-1. GCP IAM에서 정의하는 요소 3가지

  • 누가
    1. Google 계정 Cloud ID 사용자 : test@gamil.com , test@example.com
    2. 서비스 계정 : test@project_id.iam.gserviceaccount.com
    3. google 그룹 : test@googlegroups.com
    4. cloudID 또는 G Suite 도메인 : example.com
  • 무엇을
    IAM의 역할은 관련된 권한의 모음이다. 서비스 리소스 등에 대해 인스턴스 관리자 역할을 한다.
  • 어느 리소스에
    계층 구조의 특정 항목에 대한 역할을 부여받은 사용자가 IAM이다.

3-2. IAM의 3가지 역할

  • 기본 역할
    • 프로젝트의 모든 GCP 서비스에 적용된다. [모든 리소스에]
    • 세분화 되지 않은 고정된 액세스 수준을 제공한다.
      소유자 구성원 초대 / 구성원 삭제 / 프로젝트 삭제 / 기타 ...
      편집자 애플리케이션 배포 / 코드 수정 / 서비스 구성 / 기타 ...
      뷰어 읽기 전용 액세스
      결제 관리자 결제 관리 / 관리자 추가 및 삭제
      한 프로젝트에 여러 소유자, 편집자, 뷰어, 결제 관리자가 있을 수 있다.
  • 사전정의 역할
    • 프로젝트의 모든 GCP 서비스에 적용된다. [이 프로젝트, 폴더 or 조직의 Gompute Engine 리소스에]
    • 특정 서비스에 보다 세분화된 권한을 제공한다.
  • 커스텀 역할
    • IAM 커스텀 역할 권한 집합을 정확하게 정의할 수 있다.

3-3. 서비스 계정

  • 프로젝트에서 서버간 상호작용에 사용되는 ID 제공
  • 서비스간 인증에 사용
  • 리소스에서 사용하는 권한을 제어하는데 사용 : 이를 통해 애플리케이션이 인증된 최종 사용자 대신 작업을 수행할 수 있음
  • 이메일 주소로 식별
    PROJECT_NUMBER-compute@developer.gserviceaccount.com
    PROJECT_ID@appspot.gserviceaccount.com
  • 서비스 계정과 IAM
    • 키를 사용해 서비스 계정에 인증 : google에서 Compute Engine 및 App Engine의 키 관리
    • 서비스 계정에 사전 정의 또는 커스텀 IAM 역할 할당 가능

4. Cloud ID

  • 무엇으로 GCP 관리 사용자를 관리하나요?
    • Gmail 계정 및 Google 그룹스
    • G Suite 도메인의 사용자 및 그룹
    • Cloud ID 도메인의 사용자 및 그룹
  • 다른 기업 디렉터리가 있는 경우

5. Google Cloud Platform 과의 상호작용

5-1. GCP와 상호작용하는 4가지 방법

  • Cloud Platform Console : 웹 사용자 인터페이스
    • 모든 프로젝트 데이터에 대한 중앙 관리형 콘솔
    • 개발자 도구 : Cloud Sourc Repositories (github 같은 것), Cloud shell, Test Lab (모바일 앱 테스트)
    • 제품 API에 액세스
    • 프로젝트 관리 및 생성
  • Cloud Shell 및 Cloud SDK : 명령줄 인터페이스
    • SDK에 Cloud Platfrom 제품 및 서비스를 위한 CLI 도구 포함 : gcloud, gwutil(Cloud Storage), bq(BigQuery)
    • Docker 이미지로 제공
    • Cloud Shell을 통해 제공 : Compute Engine 인스턴스에서 실행되는 Cloud SDK의 컨테이너형 버전
  • Cloud Console Mobile App : iOS및 Android
    • 가상 머신 및 데이터베이스 인스턴스 관리
    • Google App Engine에서 앱 관리
    • 결제 관리
    • 맞춤 설정 가능한 대시보드로 프로젝트 시각화
  • REST 기반 API : 커스텀 애플리케이션
    • 제품 및 서비스에 프로그래매틱 액세스 : 일반적으로 JSON을 교환방식으로 사용 , 인증 및 승인에 OAuth 2.0 사용
    • Google Cloud Platform Console을 통해 사용 설정
    • 지출을 관리할 수 있도록 대부분의 API에 일일 할당량 및 요금(한도)이 적용됨 : 요청에 따라 할당 및 요금 상향 조정 가능

5-2. API 탐색기

 

  • 브라우저를 사용하여 간편하게 Google API를 사용해볼 수 있는 대화형 도구
  • 사용가능한 API 및 버전을 신속하게 탐색
  • 각 API에서 사용 가능한 메서드 및 지원되는 매개 변수를 인라인 문서로 확인
  • 실시간으로 메서드 요청을 실행하고 응답 확인
  • 손쉽게 인증 및 승인된 API 호출 작성

5-3. Cloud 클라이언트 라이브러리

 

  • 커뮤니티에서 소유하며 직접 개발한 클라이언트 라이브러리
  • 예시 : Google API 클라이언트 라이브러리
    • 오픈 소스, 자동 생성, 다양한 언어 지원
      (Java, Python, Javascript, PHP, .NET, GO, Node.js, Ruby, Objective-C, Dart)

This is a summary of the materials distributed at the Google Cloud OnBoard event held at Sejong University on November 26, 2019.


Module 1: Introduction to Google Cloud Platform

0. Additional Resources

Why choose GCP: https://cloud.google.com/why-google/

Pricing philosophy: https://cloud.google.com/pricing/philosophy

Data centers: https://www.google.com/about/datacenters

Google Cloud Platform product overview: https://cloud.google.com/products

Google Cloud Platform solutions: https://cloud.google.com/solutions

Google Cloud Platform security: https://cloud.google.com/security

Permission configuration: https://cloud.google.com/docs/permissions-overview

Identity And Access Management (IAM): https://cloud.google.com/iam/

Cloud SDK installation and quickstart: https://cloud.google.com/sdk/#Quick_Start

gcloud tool guide: https://cloud.google.com/sdk/gcloud

1. Features of GCP

  • GCP computing architecture that provides services tailored to customer needs
  • Google has invested in 134 points of presence worldwide and 13 submarine cables.
    GCP is well-suited for global-scale services.
  • GCP is structured with Regions and Zones.
    Multi-region: US - Korea
    Region: europe-west2
    Zone: europe-west2-a, europe-west2-b, europe-west2-c
    Number of currently announced Regions
  • Google leads the way in environmental protection.
    • Has maintained 100% carbon neutrality since 2007.
    • One of the largest purchasers of renewable energy in the world.
    • The first data center to obtain ISO 14001 certification.
  • Google offers customer-friendly pricing.
    • Per-minute billing increments - compute, data processing, and other services
    • Sustained use discounts - automatically applied when virtual machines are used more than 25% of the month
    • Committed use discounts - cost discounts for long-term, steady workloads
    • Preemptible use discounts - cost discounts for workloads that can be interrupted
    • Custom VM instance types - pay only for the resources your application needs
  • Open APIs and open source
  • Security
  • GCP services

2. GCP Resource Hierarchy

2-1. Defining Trust Boundaries by Resource Hierarchy Level

  • Group resources according to organizational structure
  • Trust boundaries and resource isolation are set according to hierarchy level

2-2. All GCP Services Are Associated with Projects

  • Track resource and quota usage
  • Enable billing
  • Manage permissions and user credentials
  • Enable services and APIs

2-3. Three Identifying Attributes Used for Projects

Project ID Globally unique Chosen by user Immutable
Project ID Globally unique Chosen by user Immutable
Project name Does not need to be unique Chosen by user Immutable
Project number Globally unique Assigned by GCP Immutable

2-4. Folder Management in GCP

  • Folders can be used to group multiple projects within an organization.
  • Folders can contain projects, other folders, or both.
  • Folders can be used to assign policies.

2-5. Organizing Projects with Organization Nodes

2-6. IAM Resource Hierarchy Example

  • Policies are set on resources: Each policy specifies a set of roles and role members.
  • Parent policies are inherited by resources: A resource policy is the union of the parent resource and the current resource.
  • A less restrictive parent policy overrides a more restrictive resource policy.

3. Identity and Access Management (IAM)

3-1. Three Elements Defined in GCP IAM

  • Who
    1. Google account or Cloud ID user: test@gamil.com, test@example.com
    2. Service account: test@project_id.iam.gserviceaccount.com
    3. Google group: test@googlegroups.com
    4. Cloud ID or G Suite domain: example.com
  • What
    IAM roles are a collection of related permissions. They act as instance administrator roles for service resources, etc.
  • Which resource
    IAM is about users who are granted roles on specific items in the hierarchy.

3-2. Three Types of IAM Roles

  • Basic roles
    • Applied to all GCP services in a project. [To all resources]
    • Provides fixed, coarse-grained access levels.
      Owner Invite members / Remove members / Delete project / etc.
      Editor Deploy applications / Modify code / Configure services / etc.
      Viewer Read-only access
      Billing Administrator Manage billing / Add and remove administrators
      A project can have multiple owners, editors, viewers, and billing administrators.
  • Predefined roles
    • Applied to all GCP services in a project. [To Compute Engine resources in this project, folder, or organization]
    • Provides more fine-grained permissions for specific services.
  • Custom roles
    • You can precisely define a set of IAM custom role permissions.

3-3. Service Accounts

  • Provides identity for server-to-server interactions within a project
  • Used for authentication between services
  • Used to control permissions used by resources: This allows applications to perform actions on behalf of authenticated end users
  • Identified by email address
    PROJECT_NUMBER-compute@developer.gserviceaccount.com
    PROJECT_ID@appspot.gserviceaccount.com
  • Service accounts and IAM
    • Authenticate to service accounts using keys: Google manages keys for Compute Engine and App Engine
    • Predefined or custom IAM roles can be assigned to service accounts

4. Cloud ID

  • What do you use to manage GCP admin users?
    • Gmail accounts and Google Groups
    • Users and groups from a G Suite domain
    • Users and groups from a Cloud ID domain
  • If you have another corporate directory

5. Interacting with Google Cloud Platform

5-1. Four Ways to Interact with GCP

  • Cloud Platform Console: Web user interface
    • Centralized console for all project data
    • Developer tools: Cloud Source Repositories (like GitHub), Cloud Shell, Test Lab (mobile app testing)
    • Access to product APIs
    • Project management and creation
  • Cloud Shell and Cloud SDK: Command-line interface
    • SDK includes CLI tools for Cloud Platform products and services: gcloud, gsutil (Cloud Storage), bq (BigQuery)
    • Available as a Docker image
    • Available through Cloud Shell: A containerized version of Cloud SDK running on a Compute Engine instance
  • Cloud Console Mobile App: iOS and Android
    • Manage virtual machines and database instances
    • Manage apps on Google App Engine
    • Manage billing
    • Visualize projects with customizable dashboards
  • REST-based API: Custom applications
    • Programmatic access to products and services: Typically uses JSON as the exchange format, uses OAuth 2.0 for authentication and authorization
    • Enabled through the Google Cloud Platform Console
    • Most APIs have daily quotas and rates (limits) applied to help manage spending: Quotas and rates can be increased upon request

5-2. API Explorer

 

  • An interactive tool that lets you easily try out Google APIs using your browser
  • Quickly explore available APIs and versions
  • View available methods and supported parameters for each API with inline documentation
  • Execute method requests in real time and view responses
  • Easily create authenticated and authorized API calls

5-3. Cloud Client Libraries

 

  • Community-owned and community-developed client libraries
  • Example: Google API client libraries
    • Open source, auto-generated, supports multiple languages
      (Java, Python, Javascript, PHP, .NET, GO, Node.js, Ruby, Objective-C, Dart)

댓글

Comments

Develop/Springboot

springboot - application.yml 설정 | springboot - application.yml Configuration

[oauth2 google 관련 yml]spring: security: oauth2: client: registration: google : client : client-id : [GCP 발급 ID] clientSecret: [GCP 발급 Secret key] accessTokenUri: https://www.googleapis.com/o/oauth2/token userAuthorizationUri: https://accounts.google.com/o/oauth2/auth clientAuthenticationScheme: form ..

springboot - application.yml 설정 | springboot - application.yml Configuration

728x90

[oauth2 google 관련 yml]

spring:
  security:
    oauth2:
      client:
        registration:
         google :
          client :
            client-id : [GCP 발급 ID]
            clientSecret: [GCP 발급 Secret key]
            accessTokenUri: https://www.googleapis.com/o/oauth2/token
            userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
            clientAuthenticationScheme: form
            provider: github
            scope:
              - email
              - profile
          resource:
            userInfoUri: https://www.googleapis.com/oauth2/v2/userinfo

 client-id의 끝은 .apps.googleusercontent.com 이다.

 

[jpa및 db설정 관련 yml]

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://[서버 url]/[DB 스키마]?serverTimezone=UTC&characterEncoding=UTF-8
    username: root
    password:

  jpa:
    show-sql: true
    hibernate:
      format_sql: true
      ddl-auto: create
 
 logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          trace

 

[security관련 yml]

security:
  basic:
    enabled: false # security 기본 인증 옵션 제거

 

[내가 임의로 설정하는 yml]

test-propertiy:
  id: jyami
  secret: ajkflhjaskfhldfahjklfbdn

사용법

@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "test-property")
public class TokenConfig {
    private String id;
    private String secret;
}

[OAuth2 Google-related yml]

spring:
  security:
    oauth2:
      client:
        registration:
         google :
          client :
            client-id : [GCP issued ID]
            clientSecret: [GCP issued Secret key]
            accessTokenUri: https://www.googleapis.com/o/oauth2/token
            userAuthorizationUri: https://accounts.google.com/o/oauth2/auth
            clientAuthenticationScheme: form
            provider: github
            scope:
              - email
              - profile
          resource:
            userInfoUri: https://www.googleapis.com/oauth2/v2/userinfo

 The client-id ends with .apps.googleusercontent.com.

 

[JPA and DB configuration-related yml]

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://[server url]/[DB schema]?serverTimezone=UTC&characterEncoding=UTF-8
    username: root
    password:

  jpa:
    show-sql: true
    hibernate:
      format_sql: true
      ddl-auto: create
 
 logging:
  level:
    org:
      hibernate:
        SQL: DEBUG
        type:
          trace

 

[Security-related yml]

security:
  basic:
    enabled: false # Remove default security authentication option

 

[Custom yml I set myself]

test-propertiy:
  id: jyami
  secret: ajkflhjaskfhldfahjklfbdn

Usage

@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "test-property")
public class TokenConfig {
    private String id;
    private String secret;
}

댓글

Comments

Daily/Code Fest

DevFest on Campus 2019 - 기획단의 후기! | DevFest on Campus 2019 - A Review from the Planning Team!

1. 인트로2019년 11월 16일 DevFest on Campus 2019가 드디어 끝났다!!!! https://festa.io/events/654/ DevFest on Campus 2019 | Festa!Festa에서 당신이 찾는 이벤트를 만나보세요.festa.ioGDG Campus에서 DSC Korea로 먼저 요청이 오면서 행사 규모가 점점 커졌던 행사였습니다. 초반만 해도 200을 생각했었는데, 판이 점점 커져서 약 500명 정도의 인원이 DevFest on Campus로 모였습니다 DSC Lead님들 GDG Campus Organizer분들 모두 고생했던 행사였던 만큼 강의 퀄리티, 행사 만족도 모두 높았던 행사여서 개인적으로도 앞으로 어떤 활동을 해야 할지 느끼는 바가 많았습니다. 발표자와 ..

DevFest on Campus 2019 - 기획단의 후기! | DevFest on Campus 2019 - A Review from the Planning Team!

728x90

1. 인트로

2019년 11월 16일 DevFest on Campus 2019가 드디어 끝났다!!!! 

 

https://festa.io/events/654/

 

DevFest on Campus 2019 | Festa!

Festa에서 당신이 찾는 이벤트를 만나보세요.

festa.io

GDG Campus에서 DSC Korea로 먼저 요청이 오면서 행사 규모가 점점 커졌던 행사였습니다. 초반만 해도 200을 생각했었는데, 판이 점점 커져서 약 500명 정도의 인원이 DevFest on Campus로 모였습니다

 

DSC Lead님들 GDG Campus Organizer분들 모두 고생했던 행사였던 만큼 강의 퀄리티, 행사 만족도 모두 높았던 행사여서 개인적으로도 앞으로 어떤 활동을 해야 할지 느끼는 바가 많았습니다. 발표자와 장소 쪽을 맡으면서 고생도 많았지만, 그래도 이번 기회에 좋은 사람들을 알게 되고 스스로도 성장할 수 있는 기회였어서 제 기회를 제가 만든 기분?!  행복하네요★

 

2. 장소 - 이화여대 아산공학관

이번 DevFest on Campus의 장소는 이화여대로 결정이 되었습니다

초기 기획을 할 때 Campus라는 특성에 맞게 대학교 대관을 알아보다가 교수님이 긍정적으로 답변해주셔서 저희학교로 결정이 났는데요

이번 대관, 이화여대 후원으로 진행하면서 주관 대표라는 명목으로 교수님, 학과사무실, 소프트웨어 중심대학 사무실, 여러 학교 부처에도 전화를 돌리면서 엄청 귀찮게 했었는데요. 학교 선생님들 네 접니다.. 학교 선생님들 이제 끝났으니 귀찮은 학생이었던 저를 당분간 안 보셔도 됩니다!!ㅋㅋㅋㅠ

현수막 때문에 전날 갑자기 업체 부르고 난리였는데 흑흑...

 

장소를 저희학교로 하다 보니 책임감이 생기면서 힘들었는데, 그래도 마지막이 좋으니까 다 좋았던 기억으로 남더라고요. 무엇보다도 교수님 소프트웨어 중심대학 선생님과 더 끈끈한 관계를 맺게 되어서 이화여대 컴퓨터공학과 내에 DSC Ewha의 입지를 키울 수 있는 기회로 만들어서 Lead로서 의미 있던 행사였습니다 :)

 

3. 세미나 - 발표자 초청

발표자에 정말 엄청난 분들이 많았는데, 청중으로 갔어도 엄청 좋았을 것 같아요. 행사 신경쓰고, 왔다 갔다 하다 보니 저는 유경수 님의 웹 초보도 할 수 있는 WebVR/AR with aframe, 박재성 님의 의식적인 연습으로 TDD, 리팩토링, 클린 코드 연습하기 세션밖에 못 들어서 아쉬웠습니다ㅠㅠ

 

포토존에서 찰칵!! 찰칵!! 머리띠 관종 트랙 A 담당자

발표자 담당을 맡으면서 메일을 엄청 보냈는데요 다들 친절하게 피드백주셔서 너무 감사했습니다

직접 만나서 얘기도 많이 하고싶었는데 트랙 A에서 계속 담당해서 있다 보니 그럴 기회가 없었네요ㅠㅠ

그리고 세션을 듣다보니, 한 번쯤은 저도 발표자로 나서고 싶더라고요! 꼭 다음에는!!!ㅎㅎ

 

3-1. 유경수 - 웹초보도 할 수 있는 Web VR/AR with aframe

작년에 이화여대 게임동아리 King에서 cardboard VR 방탈출 게임을 개발했던 기억 때문에 열심히 들었던 세션이었는데, 와 진짜 재밌었습니다!! 유니티로 VR요소 하나하나 스크립팅하고, 위치에 재질에 이벤트 클릭 raycast 하나하나 개발해서 결과물을 만들었을 때가 생각났네요. 그런데 웹이라니! 그것도 HTML과 비슷한 방식으로 만들어진다니!! 웹을 좋아하는  저에게 딱이었습니다.

 

만약 이 세션을 먼저 알았으면 졸프로 Web VR/AR을 했을지도 몰라요...ㅠㅠ 

여느때와 같이 세션 필기 노트입니다! 그런데 오늘은 세션 정리도 해보려고 해요 궁금한 분들은 클릭!!!

 

더보기

●  민정 피셜 색깔

VR : 존재하지 않는 가상공간 
AR : 증강현실
{VR AR} = XR

보통은 Unity나 Unreal 엔진을 이용해 C#이나 C++로 개발을 하지만, 유경수 님은 웹 개발자로 시작했기에 조금 거부감이 느껴졌다. > 그렇게 발견한 게 Javascript API

 

Javascript API는 브라우저를 통해 XR을 구현할 수 있었다. (웹 개발자들은 친숙한 JS!!)

> 근데 위기 공부하니까 deprecate 되었다 함

> 알고 보니 Javscript API -> Web XR로 용어를 변경

 

Aframe = Web XR Device API + Three.js (렌더링)

 

Aframe의 장점

1. visual Inspector (Unity의 Scene window와 비슷한 개념인 듯!)
   모델을 마우스로 줄이거나 크게 할 수 있다! (경수님은 이전에 숫자 하나하나 대입하면서 비교했다 한다.)

2. 렌더링이 자동으로 된다!

    Entity Component Architecture

3. 무엇보다 코드가 HTML과 비슷하게 이루어져 있다!

   마치 부트스트랩 쓰는 것처럼 속성을 지정해줘서 반가웠다

4. Modeling 적용 가능

코드를 보면 Cube와 같은 간단한 컴포넌트만 가능한가? NO

3D 모델러가 작업한 결과물도 HTML 태그 형식으로 만들 수 있다 : Gltf 파일을 지원한다

이때 Animation도 적용이 가능하며, Animation은 3D 모델 자체가 가진 Animation과 JS에서 조작하는 것 둘 다 가능하다.

 

Aframe의 단점

1. 고사양(100MB도 안된다)이면 구동이 어렵다.

2. 공간 배치가 어렵다 > solution : visual inspector

 

Aframe으로 JSON파일에서 자동 모델링하기 - Event로의 상호작용

Entity : Componet의 집합 (Vue js의 템플릿 구조와 비슷했음)

Component를 어떻게 섞냐에 따라 요소 1개 1개가 그려진다. > DOM 구조가 아니라 컴포넌트 단위로 렌더 되는 듯

이때 Entity는 HTML 태그 형식으로 그대로 표현이 가능하다! : 진짜 Vue js <template> 이거 같았음

JS에서도 마찬가지로 getDocumentId() 등의 HTML 표현이 가능하기 때문에, 이벤트를 넣는 것 역시 가능하다. (click 이벤트 시 텍스트 작성 등등의 이벤트, or xyz값을 수치로 받아서 event 구현!) 

JS를 사용해서 이벤트 구현이 가능하니 Unity처럼 총알이 타 다다다 발사되는 것도 구현이 가능!!

 

경수님은 학교 축제 소개 페이지를 만드셨다 하셨음!

AR은 Location Based AR과 Marker Based AR이 있었다 : Marker를 이용해서 부스의 스탬프를 구현!

이때 Marker방식은 특이한 게 QR과 Marker 둘 다 준비해야 한다는 점!

 

AR과 HTML의 호환으로 컴포넌트 재사용성 good 그러나 내가 정리한 단점 외에도 단점이 뚜렷하다 

(경수님 ppt에 적혀있는데 안 적음 가장 기억나는 건 무조건 https로 해야 해서 SSL을 붙여야 한다는 점)

 

마무리

추가로 Aframe을 사용하더라도 기본적인 3D에 대한 이해가 필요하다!

그렇지만 HTML 포맷의 AR/VR이기 때문에 빠르게 습득해서 구현하고 싶다면 추천!!

 

--개인적으로 드린 질문--

 

Q. 슬라이드 지나간 사진 중에 VR 장비를 찬 걸 보았다 혹시 오큘러스 빌드가 되는 것인가?

A. 그건 그냥 cardboard 장비였다. 웹에서 cardboard 모드로 설정한 후, 카드보드용 VR 장비를 낀 것!

 

Q. Raycast 구현 쪽이 궁금하다. 유니티에서는 일정 반경 안에 들었을 때 Raycast를 통한 클릭이 가능하게 활성화되는데, 아까 좌표 얘기를 하신 얘기를 생각했을 때 설마 xyz 좌표를 하나하나 설정하면서 비교하는걸 Raycast로 대체하는 건가?

A. 아니다 Raycast 기능도 제공을 하고 있다!! 처음에 xyz좌표 하나하나 지정해야 하는 줄 알았는데 아니었다!

세션을 정리하고 보니 엄청 뿌듯하네요!! 해커톤이나 프런트엔드 중심 토이 프로젝트를 하게 되면 Aframe의 사용도 고려해봐야겠습니다! 아니면 DSC관련 프로젝트로 하나 혼자 만들어버리거나

 

3-2. 박재성 - 의식적인 연습으로 TDD, 리팩토링, 클린 코드 연습하기

발표자분들을 섭외하면서 아무래도 스프링 공부를 하고 클린코드 테스트 코드 공부를 하다 보니 정말 정말로!! 뵙고 싶었던 자바지기님인 박재성 님께 개인적으로 요청을 드렸는데 흔쾌히 수락해주시고, 재성님의 세미나를 들을 수 있어서 자기 계발에 정말로 큰 도움이 되었습니다 :)

처음에 의식적인 연습에 대해 말씀하실 때 음,, 추상적이라고 생각했는데 뒤로 가면 갈수록 더 상세히 구체적으로 공부 방법론을 제시해주는 게 너무 도움이 되었습니다.

 

아무래도 코드를 하다 보면 내 코드가 정말 깔끔한가?라는 생각이 들 때가 많아요. 그리고 대부분이 구현만 되는 코드를 짜면 되지라고 생각을 하는데 재성님이 대학생들에게 그런 방식의 공부가 정말 옳은가?라는 메시지를 주고 떠나신 것 같아서 , 참여자분들에게, 이화여대 학생들에게, 저에게 정말로 좋았던 세미나였습니다.

 

세션 정리 내용입니다!! 궁금하다면 클릭!! 아니 꼭 클릭!! 진짜 너무 좋았던 세미나라 공유하고 싶네요

더보기

●  민정 피셜 색깔

"요즘 개발자의 수요가 증가합니다. 그러나 학생들은 취업난, 회사는 개발자 인력부족 문제는 무엇일까요?"

회사에서 원하는 개발자

1) 클린 코드로 유지보수가 좋은 코드를 짜는 개발자 (여기서 클린 코드란 TDD 리팩토링에 중점)

2) 협업능력이 좋은 개발자

3) 주도적으로 문제를 찾고 근본적 문제를 해결하는 개발자

 

의식적인 연습이란?

[재성님 강조 부분]

1) 컴포트 존을 벗어나라 (편한 상태를 깨트리고 더 어려운 걸 도전하기!)

2) 명확하고 구체적인 목표 세우기

3) 피드백 주기 (내 생각엔 코드 리뷰 이야기인 것 같다)

[ppt 글씨 부분]

4) 효과적인 훈련기법이 수립된 기술을 연마한다.

5) 개인이 온전히 집중하고 '의식적'으로 행동한다

6) 효과적인 심적 표상을 만들어내는 한편 심적 표상에 의존한다

7) 기존에 습득한 기술의 특정 부분을 집중적으로 개선함으로써 발전시키고 수정하는 과정을 수반한다.

1. 단위 테스트

나의 API를 테스트한다 : 내 API가 Input Output에 따라 명확한 코드로 이루어져 있는 잘 동작하는 코드인가?

- 자바 String 클래스의 다양한 메서드를 사용해보고 단위 테스트로 확인한다.

- 자바 ArrayList에 데이터를 추가, 수정, 삭제한다.

단위 테스트가 잘 짜여 있다면 API의 사용법을 익힐 수 있다.

 

단위 테스트를 해야 하는 것

내가 구현하는 메서드 중 Input과 Output이 명확한 클래스나 메소드

> 대학생 눈높이 : 알고리즘!!

알고리즘을 학습할 때 알고리즘의 구현을 단위 테스트로 검증해본다!

Input, Output이 명확해서 단위 테스트를 연습하는데 효과적이다.

2. TDD

1. 회사 프로젝트 말고 토이 프로젝트를 활용하기
2. 웹 모바일 UI나 DB에 의존관계가 없는 요구사항으로 연습한다 > 순수 Java Project 말씀하시는 듯

Test를 짠다 > 이후에 해당하는 메서드를 만든다!! (production 코드를 나중에 만든다)

TDD는 복잡도가 너무 높은 건 좋지 않다!

3. 리팩토링 연습

3-1. 메서드 분리

이때 중요한 건 테스트 코드는 변경하지 말고 테스트 대상 코드(프로덕션 코드)를 개선하는 것!!

어디서부터 해야 할지 막막하다!

 

메서드 분리의 중요점 : 메서드가 1가지 역할만 하게 하는 게 좋다 (추상적, 정성적인 기준)

 > 정량적이고 측정 가능한 방법으로!!

 

[예시 : 문자열 덧셈기]

 

정량적인 방법 수치화

1. 인덴트 즉 들여 쓰기는 1단계만 한다 -> 이를 위해 메서드를 분리하게 된다. (대표적으로는 for안의 if문)

2. else를 쓰지 않는다 -> return을 사용해서 if만을 사용한다.

3. 메서드가 한 가지 일만 하도록 구현한다 -> parsing로직과 sum로직을 분리하셨음!

4. 로컬 변수가 정말 필요할까? -> 줄이는 것도 효과적이다! 

 

compose method 패턴

메서드(함수)의 의도가 잘 드러나도록 동등한 수준의 작업을 여러 개로 나눈다.

즉, 추상화 레벨을 똑같이 한다!

이때 외부 개발자는 public만 본다. public을 봤을 때 직관적으로 읽히면 ㅇㅋ! : 프로그램 로직 한눈에 볼 수 있다.

return sum(toInt(split(text))) : text를 split 해서 int로 바꾸고 sum 한다! 

 

리팩토링 관점

- 클린 코드를 만드는 경험이 중요한 것!

- 기능을 변경하지 않고 코드의 구조만 바뀌는 것이다

- 리팩토링 후 테스트가 너무 힘들다 : but 테스트 코드가 있으면 빠른 피드백이 가능하다 (fast 핑퐁!)

 

의식적인 공부 : 한 번에 모든 원칙보단 한번에 한 가지 명확하고 구체적인 목표 가지기!

ex ) 메서드의 라인수 줄이기 15 -> 10 

 

3-2. 클래스 분리

예외사항 throw 관련 클래스 분리

모든 원시 값과 문자열을 포장한다!

 

클래스 분리를 위한 원칙

1. 일급 컬렉션

2. 3개 이상의 인스턴스 변수 가진 클래스 쓰지 않기

 

3-3. 의존 관계 추가를 통한 난이도 높이기

웹, 모바일, UI, DB와 같은 의존관계를 추가한다.

이때! 테스트하기 쉬운 것과 어려운 것을 불리하는 역량 즉 센스가 있어야 한다!

 

3-4. 더 어려운 단계

1. 컴파일 에러 최소화 하기

2. ATDD기반으로 응용 애플리케이션 개발하기

3. 레거시 애플리케이션에 테스트 코드 추가하기 (제일 어렵다)

 

--개인적으로 물어본 질문--

 

Q. 게터, 세터를 쓰지 말라고 하셨는데 게터는 쓸 수도 있지 않은가? 그래서 저는 lombok의 @Data를 경계하라는 의미를 내 포한 건가?라는 생각이 들었다

A. 재성님이 구현한 로또게임 코드를 보여주심!

게터 세터를 쓰지 말라는 것은 A라는 클래스의 기능은 A클래스 안의 메서드로 해결하길 권장한다는 점에서 이야기한 것이다! 만약 게터를 쓴다면 A클래스 안에서 해결해야 하는 기능을 B클래스에서 getter로 불러와서 고치고 검증하는 코드가 될 것이다.

모든 원시 값을 포장하라고 했던 거 기억나는가? 로또 번호는 Integer이지만 번호를 가리키는 LottoNumber라는 클래스를 만들고, 해당 클래스 안에서 1~45까지의 숫자인지 검증하는 로직 등 정말 LottoNumber라고 확신할 수 있는 객체를 만드는 게 질문의 대답이 될 것 같다.

 

Q. 클린 코드 공부를 하다 보니까 나도 모르게 알고리즘 짤 때 Enum을 사용하고 그 안에 Abstract method를 구현하기도 하고, 알고리즘 짜다가 갑자기 변수명을 고민하고, 변수명이 길어지는 이상한 짓을 하고 있다. 조언 부탁드린다.

A. 그걸 의식적으로 연습해라!!! 그건 당연히 분리해야 하는 영역이다! 좋은 개발 습관이지만 취업에는 치명적이니 꼭 분리해야 한다!! 근데 정말 좋은 자세이다. 내가 추천하는 건 의식적으로 목표를 잡을 때 
1단계 정말 빠르게! 알고리즘만 생각해서 풀기 > 2단계 그렇게 짠 알고리즘을 리팩토링 해서 클린 코드로 바꾸기!

이렇게 공부한다면 본인의 실력에 도움이 될 것이다.

특히 요즘 클린코드 테스트 코드와 관련해서 있던 고민(알고리즘과 관련)을 재성님 옆에 붙어서 귀찮게 질문을 드렸는데 '의식적인 연습'이란 가르침 너무 감사했습니다!! 

 

4. 후원사 부스

후원사 부스가 들어가니 원래는 저의 학업 공간이었던 학교가 정말 행사장이 된 분위기가 들더군요.

그리고 오랜만에 보는 반가운 얼굴들 때문에 기억에 남습니다.

 

수철님이 먼저 나서서 후원해주시겠다고 얘기해주신 이노베이션 아카데미, 딱 지금 1년 전 스마일게이트 윈터 데브 캠프로 인연을 맺었는데 오랜만에 봐서 너무 좋았던 스마일게이트 식구분들!! 그리고 오픈 핵, 중국 해커톤 멘토로 항상 저한테 많은 도움을 주시는 Common Computer 민현 님까지 후원도 해주시고 너무 감사했습니다 :)

 

스마일게이트 서버 개발 캠프를 문의하느라 학생들이 몰려있었는데, 면접관 두분이 직접 상담을 해주고 계시니까 역시 학생들의 입장에서 생각해주시는 캠프장님의 모습이 멋졌습니다!! 혹시 서버개발캠프 관련 여쭤보고 있으신 점 있으면 연락 주세요. 선착순으로 스마일게이트 블루투스 키보드 이벤트도 진행했는데 저희 DSC Ewha 멤버 중 한 분도 알차게 가져가셨어요!!ㅋㅋ

 

그리고 WTM!! WTM은 따로 글을 쓰고 싶은 게 있어서 오늘은 패스~!

 

그리고 이노베이션 아카데미는 워후... 안 그래도 5000명 돌파했다는 소식에 놀랐는데, 지나다니면서도 학생들이 나 원래 이거 지원하려고 했는데! 이런 말을 지나가면서 스쳐들으니까 확실히 홍보를 엄청 잘하셨구나 싶었습니다!

 

그리고 커먼 컴퓨터 부스!! 아니ㅋㅋㅋ 오픈핵 때문에 커먼컴퓨터 가방부터 굿즈 스티커 다 있는데 직원분들이 또 가져가라고 더 챙겨주시고 AFAN 유저라고 하니까 invest도 해주시더라고요!

AFAN은 커먼 컴퓨터에서 만든 리워드형 SNS입니다. Invest와 Crush On을 이용해서 유저들끼리 서로의 포스팅에 가치를 매기고 내가 invest 한 사람이 AFAN을 이용한 광고 등으로 수익을 얻을 경우엔 나는 가치 있는 사람에게 invest 했다는 value가 있어서 일정 수익을 같이 얻을 수 있습니다! 

https://apps.apple.com/kr/app/afan/id1434385630

 

‎aFan

‎* 팬들을 위한 새로운 소셜 미디어 내가 좋아하는 크리에이터와 친구들에게 쉽게 다가가 보세요. * 단순 팔로잉을 넘어 팬이 되어보세요! 누구나 내가 좋아하는 크리에이터의 팬이 될 수 있습니다. 가장 먼저 팬이 되어 창작자를 성장시켜주세요. 때로는 크러쉬온 기능을 통해 포스트에 하트를 보내주세요! * 나의 팬들만을 위한 크러쉬온 크러쉬온을 통해 팬들에게 받은 사랑을 아낌없이 돌려주세요. aFan - 팬과 크리에이터가 함께 성장하는 플랫폼

apps.apple.com

5. DevFest on Campus 굿즈

크으 후원사 부스의 스티커부터 짱짱한 Devfest 스탭 후드, 반팔, 배지, 목도리~! 아주 짱짱해요!! 특히 우리 스티커에 있는 코린이 너무 귀엽지 않나요! 굿즈 열심히 제작해주신 두리님께 감사를ㅎㅎㅎ

6. 코드 랩 & 액티비티

사실 코드 랩을 많이 못갔어요 세션장에만 있다보니까 스태프분들 놔두고 혼자 코드랩을 할 수가 없어서..ㅠㅠ 

코드랩 콘텐츠 기획은 대학생 관련 행사라면 하나 정도는 있으면 좋겠다는 생각이 들었습니다. 얼마 전에 DSC Ewha에서 했던 코드 랩도 반응이 좋았고, 또 열어달라는 요청이 있었거든요.

처음에 GDG Campus랑 DSC랑 회의할 때 대학생들이 생각보다 코딩하는걸 막막해하고, 직접 구현해보는 시간을 가져봤으면 좋겠다는 말을 했었는데 이렇게 현실화가 되었습니다!! 다들 만족하셨겠죠?

 

이대 무선랜 문제가 있었다 들었는데,, 어음,, 학교 측에서 대규모 다운로드가 힘들 수 있다고 사전에 말씀하셨고 토요일이라 증설을 못하는 상황이었습니다ㅠㅠ 불편했을 텐데 현장 분들이 잘 해결해주셨을 거라 생각합니다..!

 

그리고 액티비티!! 크으 한결님이 나만의 시간표 만들기 웹을 직접 만들어 주셨어요! 저도 하고 싶었는데 아쉽네요

 

7. DSC와 GDG Campus

사실 DevFest의 가장 큰 장점은 여러 사람들을 만날 수 있는 거라고 생각합니다. 이번 행사에서 그동안 저는 DSC Lead 님들 그리고 DSC Ewha만 만났었는데, 다른 학교 DSC 멤버분들도 만날 수 있어서 좋았습니다.

사진도 왕창 찍고 친해지고! 이번 DevFest를 기념하면서 잘 마무리했습니다!

 

무엇보다도 GDG Campus 오거나이저 분들 우리 DSC Lead분들 다들 너무 고생했고, 스태프, 코드 랩 튜터 참가자 홍보까지 이화여대 안에서 DSC 활동을 활발하게 해주는 우리 DSC Ewha 멤버들에게도 감사했습니다.

 

항상 열일하는 DSC Lead들!!! 그래서 우리 제주도 날짜 언제임
♥DSC EWHA♥
Track A 사람들과 GDG!!! 3번째 사진ㅋㅋㅋ 몸으로 말해요 DSC GDG!!
마지막으로 단체사진

8. 이화여대 내 반응

처음에는 사실 걱정이 앞섰습니다. 저희 학교에서 주최를 하면 벗들에게 도움이 되는 부분이고 정말 좋은 행사지만, 혹시라도 문제가 생기면 앞장서서 책임을 져야 했으니까요.

그런데 행사를 마치고, 에브리타임에 들어갔는데 DevFest관련 글이 하나 있더라고요

그거보고 사실 눈물이 핑돌았어요ㅋㅋㅋ 

 

엄청 동기부여가 됐다고 했다는 글이었는데, 댓글에서 현업에서 오래 일한 베테랑 발표자분들도 좋았지만 현재 학부생인데 커리어 탄탄히 쌓은 분을 보고 용기를 얻고 전공 공부를 더 열심히 해야겠다고 결심하는 내용이었습니다

그러면서 아래 댓글에 DSC 아니었으면 이 행사 주최도 못했을 텐데 학교에서 열어줘서 고맙다는 댓글 때문에 힘나더라고요. 

 

대학교 새내기 20살 때부터 멋사로 개발을 시작하면서, 사실 주변에 학점을 챙기는 친구는 많았지만, 같이 콘퍼런스를 간다거나 해커톤을 같이 나가는 친구가 없어서 항상 고민이었습니다. 그런데 저 글을 보니 DSC 활동을 학교 내에 개발을 좋아하는 벗들을 더 많이 이끌어 내고 서로 협업할 메이트를 찾는 활동으로 만들면 좋겠다는 생각이 들었습니다.

 

특히나 이번 행사 참여자 성비가 1:1이었대요. 사실 오픈 핵, 멋사, junction x seoul 어느 행사나 해커톤을 가도 여성 개발자는 소수였고, 발표자도 마찬가지였어요. 그래서 그런지 이번 DevFest가 저에게 엄청 크게 다가왔네요

 

9. 마무리

열심히 홍보를 했더니 지인분들이 많이 와주시고, 발표자로도 나서 주셨는데 생각만큼 많이 못 챙겨드린 것 같아서 죄송했습니다. 오픈 핵 사람들하고도 멋사 언니들하고도 사진 찍고 오랜만에 얘기도 하고 싶었는데 아쉬워요. 

 

다음 DSC 활동도 으쌰 으쌰 하겠습니다!

장장 2개월간의 DevFest 기획단 후기 끝!!!!

이제 기획단 아니야 다시 개발자로 돌아갈래! 당장 이번 주 네이버 핵 데이 어쩌지...

 

 

 

 

1. Intro

On November 16, 2019, DevFest on Campus 2019 finally came to an end!!!! 

 

https://festa.io/events/654/

 

DevFest on Campus 2019 | Festa!

Find the events you're looking for on Festa.

festa.io

It started with GDG Campus reaching out to DSC Korea first, and the event kept growing bigger and bigger. In the beginning, we were thinking around 200 people, but it snowballed and about 500 people gathered for DevFest on Campus.

 

Since all the DSC Leads and GDG Campus Organizers worked so hard on this event, both the session quality and overall satisfaction were really high. Personally, it gave me a lot to think about in terms of what kind of activities I should pursue going forward. I had a tough time handling the speakers and venue, but through it all, I got to meet great people and it was a chance for me to grow — like I created my own opportunity?! I'm happy★

 

2. Venue - Ewha Womans University Asan Engineering Building

The venue for this DevFest on Campus was decided to be Ewha Womans University.

During the initial planning, we were looking into university venues to match the "Campus" theme, and our professor responded positively, so we ended up going with our school.

While organizing the venue booking and Ewha sponsorship, I called professors, department offices, the Software-Centered University office, and various school departments under the title of "lead organizer" — I must've been such a nuisance. Dear school staff, yes it's me.. Now that it's all over, you won't have to deal with this annoying student for a while!! lol 😭

We had to call the banner company last minute the day before — it was chaos...

 

Having the event at our school came with a lot of pressure and it was tough, but since it ended well, it all turned into good memories. Above all, I was able to build a closer relationship with the professor and the Software-Centered University staff, which became an opportunity to strengthen DSC Ewha's presence within the Ewha Computer Science department — so as a Lead, it was a truly meaningful event :)

 

3. Seminars - Inviting Speakers

We had so many amazing speakers — I think it would've been fantastic even just attending as an audience member. I was busy managing the event and running back and forth, so I could only attend Kyungsoo Yoo's "Web VR/AR with aframe Even for Web Beginners" and Jaesung Park's "Practicing TDD, Refactoring, and Clean Code Through Deliberate Practice" sessions, which was a bummer ㅠㅠ

 

Snap snap at the photo zone!! The attention-loving headband-wearing Track A manager

As the person in charge of speakers, I sent out a ton of emails, and everyone was so kind with their feedback — I'm really grateful.

I wanted to meet them in person and chat more, but I was stuck managing Track A the whole time so I didn't get the chance ㅠㅠ

And after listening to the sessions, I really wanted to be a speaker myself someday! Definitely next time!! haha

 

3-1. Kyungsoo Yoo - Web VR/AR with aframe Even for Web Beginners

I paid extra attention to this session because I had memories of developing a cardboard VR escape room game at Ewha's gaming club "King" the year before — and wow, it was really fun!! It reminded me of when I was scripting every VR element one by one in Unity, setting up materials, event click raycasts, and building the final product piece by piece. But on the web! And it's built in a way similar to HTML!! It was perfect for someone like me who loves web development.

 

If I had known about this session earlier, I might have done Web VR/AR for my graduation project... ㅠㅠ 

As always, here are my session notes! But today I'm also going to try summarizing the session — click if you're curious!!!

 

더보기

●  Minjeong's personal color-coded notes

VR: A virtual space that doesn't exist 
AR: Augmented Reality
{VR AR} = XR

Normally you'd develop with C# or C++ using Unity or Unreal engine, but since Kyungsoo started as a web developer, he felt a bit of resistance. > That's how he discovered the Javascript API.

 

The Javascript API allowed implementing XR through the browser. (JS, which web developers are familiar with!!)

> But then — crisis — he found out it was deprecated.

> Turns out Javascript API -> the term was just changed to Web XR.

 

Aframe = Web XR Device API + Three.js (rendering)

 

Advantages of Aframe

1. Visual Inspector (Seems similar to Unity's Scene window!)
   You can resize models with your mouse! (Kyungsoo said he used to plug in numbers one by one to compare before.)

2. Rendering happens automatically!

    Entity Component Architecture

3. Best of all, the code structure is similar to HTML!

   It felt familiar, like using Bootstrap where you just specify attributes.

4. Supports 3D Modeling

Looking at the code, can you only use simple components like Cube? NO

You can also use 3D modeler output in HTML tag format: it supports Gltf files.

Animations can also be applied — both the 3D model's built-in animations and JS-controlled animations are possible.

 

Disadvantages of Aframe

1. High-spec content (even under 100MB) can be difficult to run.

2. Spatial arrangement is difficult > solution: Visual Inspector

 

Auto-modeling from JSON files with Aframe - Interaction through Events

Entity: A collection of Components (Felt similar to Vue.js template structure)

Depending on how you mix Components, each element is drawn. > It seems to render in component units rather than DOM structure.

Entities can be expressed directly in HTML tag format!: It really looked like Vue.js <template>

In JS as well, HTML expressions like getDocumentId() are possible, so adding events is also doable. (Events like writing text on click, or implementing events by receiving xyz values as numbers!) 

Since you can implement events using JS, you can even build things like bullets firing rat-a-tat-tat like in Unity!!

 

Kyungsoo said he built a school festival introduction page!

For AR, there was Location Based AR and Marker Based AR: He used markers to implement booth stamps!

The interesting thing about the Marker approach is that you need to prepare both a QR code and a Marker!

 

The compatibility between AR and HTML means great component reusability, but there are clear disadvantages beyond what I've noted.

(They were listed in Kyungsoo's slides but I didn't write them down — the most memorable one is that it must use HTTPS, so you need to set up SSL.)

 

Wrap-up

Additionally, even when using Aframe, a basic understanding of 3D is necessary!

But since it's AR/VR in HTML format, it's recommended if you want to pick it up quickly and build something!!

 

--Personal question I asked--

 

Q. In one of the slides that went by, I saw someone wearing VR equipment — does it support Oculus builds?

A. That was just a cardboard device. You set it to cardboard mode on the web, then put on the cardboard VR headset!

 

Q. I'm curious about the Raycast implementation. In Unity, clicking is enabled through Raycast when you're within a certain radius — considering what you said earlier about coordinates, does that mean you replace manually setting and comparing xyz coordinates with Raycast?

A. No, Raycast functionality is provided as well!! At first I thought you'd have to set xyz coordinates one by one, but that wasn't the case!

After summarizing the session, I feel so proud!! If I ever do a hackathon or a frontend-focused toy project, I should definitely consider using Aframe! Or maybe I'll just build one on my own as a DSC-related project.

 

3-2. Jaesung Park - Practicing TDD, Refactoring, and Clean Code Through Deliberate Practice

While recruiting speakers, since I'd been studying Spring and clean code and test code, I really, truly!! wanted to meet Javajigi (Jaesung Park), so I personally reached out to him. He gladly accepted, and being able to attend his seminar was a huge help for my personal development :)

At first, when he talked about deliberate practice, I thought hmm, that's pretty abstract — but as the talk went on, he provided increasingly detailed and specific study methodologies, which was super helpful.

 

When you code, you often wonder "is my code really clean?" And most people think "as long as it works, that's fine" — but I feel like Jaesung left college students with the message of "is that approach to studying really the right one?" It was a truly great seminar for the attendees, for Ewha students, and for me personally.

 

Here's the session summary!! Click if you're curious!! No, you MUST click!! This seminar was so good that I just have to share it.

더보기

●  Minjeong's personal color-coded notes

"The demand for developers is increasing these days. But students face job shortages, and companies face developer shortages — what's the problem?"

What companies want in a developer

1) A developer who writes clean, maintainable code (Here, clean code focuses on TDD and refactoring)

2) A developer with good collaboration skills

3) A developer who proactively identifies problems and solves root causes

 

What is Deliberate Practice?

[Points Jaesung emphasized]

1) Get out of your comfort zone (Break out of what's comfortable and challenge yourself with harder things!)

2) Set clear and specific goals

3) Provide feedback (I think this is about code reviews)

[From the slides]

4) Practice skills for which effective training techniques have been established.

5) The individual focuses fully and acts 'deliberately.'

6) Creates effective mental representations while relying on them.

7) Involves the process of advancing and modifying by intensively improving specific aspects of previously acquired skills.

1. Unit Testing

Test your own API: Is my API well-functioning code with clear input/output?

- Try out various methods of Java's String class and verify them with unit tests.

- Add, modify, and delete data in Java ArrayList.

If unit tests are well-written, you can learn how to use the API.

 

What should be unit tested

Classes or methods with clear Input and Output among the methods you implement

> For college students: Algorithms!!

When learning algorithms, verify your algorithm implementation with unit tests!

Since input and output are clear, it's effective for practicing unit testing.

2. TDD

1. Use toy projects, not company projects.
2. Practice with requirements that have no dependencies on web, mobile UI, or DB > I think he means pure Java projects.

Write the test first > then create the corresponding method!! (Production code comes later.)

TDD isn't great when complexity is too high!

3. Refactoring Practice

3-1. Method Separation

The important thing here is: don't change the test code — improve the target code (production code)!!

Where do I even start? It feels overwhelming!

 

Key point of method separation: It's best if a method does only one thing (abstract, qualitative criteria)

 > Use quantitative and measurable approaches!!

 

[Example: String Calculator]

 

Quantitative approach

1. Keep indentation to only 1 level -> This forces you to separate methods. (A classic example is an if inside a for loop.)

2. Don't use else -> Use return so you only need if statements.

3. Make methods do only one thing -> He separated the parsing logic from the sum logic!

4. Do you really need local variables? -> Reducing them is also effective! 

 

Compose Method Pattern

Break down a method (function) into multiple tasks at the same level of abstraction so the intent is clear.

In other words, keep the abstraction levels equal!

External developers only see the public methods. If it reads intuitively when looking at the public method, that's good!: You can see the program logic at a glance.

return sum(toInt(split(text))) : Split the text, convert to int, and sum! 

 

Refactoring Perspective

- The experience of creating clean code is what matters!

- Only the code structure changes, not the functionality.

- Testing after refactoring is really tough: but with test code, fast feedback is possible (fast ping-pong!)

 

Deliberate study: Rather than all principles at once, have one clear and specific goal at a time!

ex) Reduce method line count from 15 -> 10 

 

3-2. Class Separation

Class separation for exception throw handling

Wrap all primitive values and strings!

 

Principles for class separation

1. First-class collections

2. Don't use classes with more than 3 instance variables

 

3-3. Increasing Difficulty by Adding Dependencies

Add dependencies like web, mobile, UI, and DB.

The key here! You need the sense — the ability to distinguish what's easy to test from what's hard to test!

 

3-4. Even More Advanced Levels

1. Minimize compile errors

2. Develop applications based on ATDD

3. Adding test code to legacy applications (the hardest)

 

--Personal questions I asked--

 

Q. You said not to use getters and setters, but aren't there cases where getters are fine? So I was thinking, did you mean something like "be cautious of Lombok's @Data"?

A. Jaesung showed us his Lotto game code!

The point about not using getters and setters is that class A's functionality should be handled within class A's own methods! If you use a getter, you'd end up pulling data from class A into class B via getter, then fixing and validating it there.

Remember when he said to wrap all primitive values? A lotto number is an Integer, but you create a class called LottoNumber, and within that class you put validation logic like checking if the number is between 1 and 45 — creating an object you can truly be confident is a LottoNumber. I think that answers your question.

 

Q. While studying clean code, I find myself unconsciously using Enums with abstract methods when writing algorithms, and I suddenly start agonizing over variable names, and the names keep getting longer — I'm doing these weird things. Any advice?

A. Practice that deliberately!!! That's absolutely something you should separate! It's a good development habit, but it can be fatal for job interviews, so you definitely need to separate the two!! But it really is a great attitude. What I recommend is setting deliberate goals: 
Step 1: Solve it really fast! Focus only on the algorithm > Step 2: Refactor that algorithm into clean code!

Studying this way will help improve your skills.

Especially regarding the concerns I'd been having about clean code and test code (related to algorithms), I stuck by Jaesung's side and pestered him with questions — I'm so grateful for the lesson on 'deliberate practice'!! 

 

4. Sponsor Booths

Once the sponsor booths were set up, my school — which is normally just where I study — really felt like an actual event venue.

It's also memorable because I got to see so many familiar faces I hadn't seen in a while.

 

Innovation Academy, where Sucheol stepped up and offered to sponsor us first; the Smilegate folks, who I first connected with exactly a year ago through the Smilegate Winter Dev Camp — it was so great to see them again after so long!! And Minhyun from Common Computer, who always helps me out so much as a mentor at Open Hack and China hackathons — thank you so much for sponsoring as well :)

 

Students were crowding around to ask about the Smilegate Server Development Camp, and the two interviewers were personally giving consultations — it was really cool to see the camp director always thinking from the students' perspective!! If you have any questions about the Server Dev Camp, feel free to reach out. They also had a first-come-first-served Smilegate Bluetooth keyboard giveaway, and one of our DSC Ewha members snagged one too!! lol

 

And then WTM!! I have something separate I want to write about WTM, so I'll skip it for today~!

 

And Innovation Academy was like... wow. I was already surprised to hear they'd surpassed 5,000 applicants, and as I walked around, I kept overhearing students say things like "I was actually planning to apply for this!" So they clearly did an amazing job with promotion!

 

And the Common Computer booth!! Seriously lol, I already had all the Common Computer bags and sticker goodies from Open Hack, but the staff kept giving me more stuff, and when I said I was an AFAN user, they even gave me an invest!

AFAN is a reward-based SNS made by Common Computer. Using Invest and Crush On, users can assign value to each other's posts, and if someone I invested in earns revenue through AFAN ads and such, I get a share of the profits because I had the value of having invested in a worthy person! 

https://apps.apple.com/kr/app/afan/id1434385630

 

‎aFan

‎* A new social media for fans — easily connect with your favorite creators and friends. * Go beyond just following — become a fan! Anyone can become a fan of their favorite creator. Be the first to become a fan and help creators grow. Sometimes, send hearts to posts through the Crush On feature! * Crush On just for my fans — give back the love you've received from fans generously through Crush On. aFan — a platform where fans and creators grow together

apps.apple.com

5. DevFest on Campus Goodies

Heck yeah — from sponsor booth stickers to the awesome DevFest staff hoodies, t-shirts, badges, and scarves~! Everything was top-notch!! Especially, isn't the little Korin character on our stickers just the cutest? Big thanks to Duri for working so hard on the merch!! haha

6. Codelabs & Activities

To be honest, I couldn't attend many codelabs. Since I was stationed at the session hall the whole time, I couldn't just leave the staff behind and go do a codelab by myself..ㅠㅠ 

I thought that if it's a university-related event, having at least one codelab content would be great. The codelab we held at DSC Ewha recently got great responses, and there were requests to hold another one.

When we first had meetings with GDG Campus and DSC, I mentioned that university students find coding more daunting than expected and that it'd be nice to give them hands-on implementation time — and it actually came to life!! I hope everyone was satisfied!

 

I heard there were issues with Ewha's Wi-Fi.. um.. the school had warned us in advance that large-scale downloads might be difficult, and since it was a Saturday, they couldn't add more capacity ㅠㅠ It must have been inconvenient, but I trust the on-site team handled it well..!

 

And the activities!! Hangyeol personally built a "Create Your Own Schedule" web app! I wanted to try it too — what a shame I couldn't.

 

7. DSC and GDG Campus

Honestly, I think the biggest advantage of DevFest is getting to meet so many people. At this event, I had previously only met the DSC Leads and DSC Ewha members, but it was great to also meet DSC members from other universities.

We took tons of photos and got to know each other! We wrapped things up nicely while celebrating this DevFest!

 

Above all, huge shoutout to the GDG Campus organizers and all our DSC Leads for working so hard, and I'm grateful to our DSC Ewha members for actively contributing within Ewha — from staffing and codelab tutoring to participant outreach.

 

DSC Leads always working hard!!! So when are we going to Jeju?
♥DSC EWHA♥
Track A crew and GDG!!! The 3rd photo lol — charades spelling out DSC GDG!!
And finally, the group photo

8. Reactions at Ewha Womans University

At first, I was honestly more worried than anything. Hosting it at our school would benefit our fellow students and it was truly a great event, but if anything went wrong, I'd have to take responsibility.

But after the event ended, I checked Everytime and found a post about DevFest.

I actually teared up a little when I saw it lol 

 

The post said it was incredibly motivating. In the comments, people wrote that while the veteran speakers with years of industry experience were great, seeing a current undergrad who'd built a solid career gave them courage and made them determined to study their major harder.

And then there was a comment below saying that this event wouldn't have been possible without DSC, and thanking the school for hosting it — that really gave me energy. 

 

Ever since I started coding through LikeLion as a 20-year-old college freshman, I had plenty of friends who focused on their GPA, but I never had friends to go to conferences with or participate in hackathons together, and that always bothered me. But seeing that post made me think it'd be great to turn DSC activities into something that draws out more dev-loving students on campus and helps them find collaborators to work with.

 

Especially since I heard the gender ratio of attendees at this event was 1:1. Whether it was Open Hack, LikeLion, Junction X Seoul, or any other event or hackathon, female developers were always a minority — and the same went for speakers. So this DevFest really hit differently for me.

 

9. Wrapping Up

Thanks to all the promotion, a lot of people I know came out and even volunteered as speakers, but I feel bad that I couldn't take better care of everyone. I wish I could've taken photos and caught up with the Open Hack crew and my LikeLion seniors. 

 

I'll keep pushing forward with our next DSC activities!

And that's a wrap on the 2-month-long DevFest planning team review!!!!

I'm done being on the planning team — I want to go back to being a developer! But what am I going to do about Naver Hack Day this week...

 

 

 

 

댓글

Comments

Daily/Code Fest

2019 google cloud summit 후기 | 2019 Google Cloud Summit Review

11월 6일 코엑스에서 Google Cloud Summit이 열렸는데요.DSC Korea 소속으로 티켓을 받아서 갔다왔습니다. 원래는 AWS만 사용하는 유저였는데, DSC 활동을 하면서 google product에 대한 얘기를 많이 듣게 되다보니 GCP에 대해 모를 수가 없더군요.근데 요즘 행사 준비로 바빠 공부할 시간이 부족해서 GCP가 있다는 것만 알고, 간단하게 google API를 사용할 때만 써봤었는데, 이번 Google Cloud Summit을 갔다오면서 GCP에서 제공하는 여러 프로덕트들을 간략하게나마 설명을 들을 수 있어서 좋았습니니다.그러면 후기 시작할까요? 0. google cloud summit 웹[Google Cloud Summit 홈페이지]https://inthecloud.wit..

2019 google cloud summit 후기 | 2019 Google Cloud Summit Review

728x90

11월 6일 코엑스에서 Google Cloud Summit이 열렸는데요.

DSC Korea 소속으로 티켓을 받아서 갔다왔습니다.

 

원래는 AWS만 사용하는 유저였는데, DSC 활동을 하면서 google product에 대한 얘기를 많이 듣게 되다보니 GCP에 대해 모를 수가 없더군요.

근데 요즘 행사 준비로 바빠 공부할 시간이 부족해서 GCP가 있다는 것만 알고, 간단하게 google API를 사용할 때만 써봤었는데, 이번 Google Cloud Summit을 갔다오면서 GCP에서 제공하는 여러 프로덕트들을 간략하게나마 설명을 들을 수 있어서 좋았습니니다.

그러면 후기 시작할까요?

 

0. google cloud summit 웹

[Google Cloud Summit 홈페이지]

https://inthecloud.withgoogle.com/summit-sel-19/agenda.html

 

Google Cloud Summit

 

inthecloud.withgoogle.com

세션에 대한 정보, 그리고 쇼케이스나 DevZone에 대한 모든 정보를 담고 있었습니다. 저는 주로 연사 세션과 DevZone에 많이 있었는데요. 공식 홈페이지 웹 뿐만이 아니라 참가자들이 자신의 코드를 입력해서 들어가는 웹을 이용해서 행사 정보를 한눈에 알 수 있었습니다.

 

 

 

다음과 같이 행사에 대한 모든 정보를 참가자들이 쉽게 알 수 있게 도와주는 웹이었습니다 :) 

또한, Google Cloud Summit에서 진행하는 여러 쇼케이스나 세션, 부스를 방문하면 summit point를 지급해주었는데요. 이 summit point를 Google 관련 굿즈와 바꿀 수 있는 cloud shop이 준비되어있었습니다 :)

그래서 포인트 탭을 이용해서 현재까지 누적된 포인트를 확인할 수 있었습니다.

 

위 사진처럼 장소 각종 트랙부터 시작해서, 파트너 부스, 쇼 케이스, 포토존, cloud shop, 미팅룸 등 참가자들이 행사를 잘 즐길 수 있도록 만반의 준비를 한 것이 인상적이었습니다.

특히나 참가자들이 세션을 듣고난 후에 발표자들에게 질문을 할 수 잇는 장소가 따로 마련되어있는점에서 기획단의 배려를 알 수 있었습니다.

 

 

1. 아젠다

 

위에 있는 웹에도 나와있는 아젠다이지만, 저희 DSC Lead들끼리 제목만 저장해서 원하는 세션만을 골라서 들었습니다!

 

가장 큰 벽면에 붙어있던 행사 요약

 

2. 행사장 분위기

등록대

코엑스에 입장을 하는 순간부터 구글특유의 4가지 색깔이 눈에 띄었습니다 :)

아무래도 큰 행사다 보니까 준비를 많이 한게 보이더라구요. 부스 퀄리티부터 현수막 크기, 각종 info인원 배치 등 세심한 배려가 인상깊었습니다

 

 

등록을 하면, 제 소속과 관련된 명찰과 행사에 참여한 각종 부스에 대한 팸플릿을 담아서 받을 수 있었습니다.

그런데 동시에 너무 많은 행사와 세션이 진행되서 사전에 조금 행사를 알아보고 갔으면 알차게 즐길 수 있었을텐데 라는 생각이 들어서 아쉬웠습니다.

 

한눈에 보는 Summit 행사장

행사장에는 GCP와 관련된 여러 부스가 있었는데, 아무래도 Google Cloud Summit 행사의 파트너 부스인 것 같았습니다.

GCP를 기업에 도입할 때 도움을 줄 수 있도록 각종 참가자들의 명함 이벤트나, 설문을 진행하는 모습을 볼 수 있었는데요. 여러 부스를 다니면서 설문을 진행하면 그 부스와 관련된 기념품이나, 경품 응모를 진행할 수 있었습니다.

 

기념사진 짠!!!

3. 세미나

[cloud summit 녹화 영상]

https://cloudonair.withgoogle.com/events/summit-sel-19-livestream

 

Cloud Summit Seoul 생중계

11월 6일 진행된 Google Cloud Summit Seoul을 다시보기로 만나보세요.

cloudonair.withgoogle.com

 

 

저는 거의 이 행사를 세션으로만 보낸 것 같아요

부스를 둘러보기엔 아직 대학생 신분이라서 입력이 어려운 폼도 있었고, 실습에 대한 사전신청도 안했어서 자리 하나 잡고 GCP와 세션을 들었습니다!!

 

제가 들은 세션은 이렇게 5 가지 였는데 각각을 정리해보았습니다.

그리고 여느때와 같이 세션 필기!!

 

 

그리고 점심식사때 점심을 먹으면서 듣는 것도 있었는데,, 유연님하고 같이 먹을 때 밥먹는데 집중해버렸습니다. 

4. DevZone 이벤트

저는 주로 이번 행사를 DSC Lead분들과 함께 즐겼습니다. 근데, 저희를 초대해주신 나연님과 나연님을 도와주시는 GDG분들이 맡아서하는 곳이 바로 이 DevZone이었어요! 그래서 거의 여기에 상주했던것 같아요

DevZone에서 GDG DSC 다같이 찰칵!!

 

Summit point와는 별개로 DevZone에서의 3가지 프로그램을 완수하면, 행사에 온 참가자들과 네트워킹을 할 수 있는 Dev Party의 초대권에 응모가 됩니다!

 

DevZone에 가면 무료로 주는 콜라, 맥주, 팝콘이 있었는데 저희 DSC Lead님들하고 짠!! 흐흐 너무 좋아요

DevZone의 콜라 맥주 쿠폰과 클라우드님의 출현ㅋㅋㅋ
혼란을 틈타 맥주 파티중인 DSC!!

4-1. Qwiklabs Zone

Qwiklabs Zone은 1개월 무료 엑세스 쿠폰으로 직접 실습을 진행해볼 수 있는 공간입니다.

여기에 가면 Qwiklabs 1개월 액세스 쿠폰을 주셨는데요, 주변에 GDG Cloud 운영진분들이 실습을 도와주려고 기다리고 계시기도하고, 일단 쿠폰을 준다고하니까 무조껀 했습니다!ㅎㅎ

 

킥랩 주소 : https://www.qwiklabs.com/?locale=ko

 

Qwiklabs - Hands-On Cloud Training

Qwiklabs provides real cloud environments that help developers and IT professionals learn cloud platforms and software, such as Firebase, Kubernetes and more.

www.qwiklabs.com

4-2. Presentation Zone

GDG/GCP 커뮤니티 소개, 스터디 잼 꿀팁 방출과 GCP 자격증에 관한 Q&A 미니 세션이 진행되는 공간이었습니다!

GCP OX퀴즈랑 경품 추첨을 봤는데요, 이외에도 GDG 설명 등여러 PT를 진행한 것으로 알고 있습니다.

경품추첨에서 하다하다 안나와서 결국은 가위바위보로 결정했는데 아으,,, 막판에 져서 아쉽네요ㅋㅋ

 

4-3. Play Zone

Play Zone은 클라우드 아케이드 게임을 즐길 수 있는 공간입니다.

GCP의 간단한 커맨드를 게임기로 구현해서 게임을 진행하는 곳이었는데요! 

문제를 해결하고 아래처럼 CORRECT 라는 문자가 뜰 때 성취감은 크으,, 아무리 생각해도 잘 만들었어요!!

5. 기념품

저번 DevFest Seoul도 그렇고 이번 summit도 그렇고 GDG관련 행사를 다니다보면 굿즈가 늘어나는 것 같아요!!

 

먼저 기본적으로 연사 세미나를 들으면, 이름표 뒤에 있던 응모권을 1점부터 5점까지 세미나 만족도 조사 박스에 넣으면 summit 행사 마지막에 있는 경품 추천이벤트에 참여할 수 있었습니다.

 

하지만, 경품추천을 원하지 않는 경우에는 이름표를 반납하고, 양털조끼를 기념품으로 받을 수 있었습니다 :)

그리고 행사 막바지에 summit point를 바꿔서 google cloud 방석도 받고! 갈때는 양손 무겁게 갔습니다. 만약 summit point가 더 많았더라면 13인치 노트북파우치나 담요로 바꿨을텐데ㅎㅎ 너무 세미나만 들으면서 시간을 보냈는지, 포인트가 모자라서 아쉬웠습니다

 

그래도 메가존에서 받은 맨투맨! 기본 기념품 양털조끼(센스굿!!) cloud point로 받은 방석! mongoDB에서 받은 수첩까지 양손 가득 무겁게 좋아요><

기념품 다같이 받고 남은 DSC Lead님들끼리 기념사진 찰칵!

6. DevParty

DevZone 이벤트를 3개다 수행해서 DevParty 초대권을 얻었습니다! DSC Lead, GDG분들하고 같이 저녁을 먹었는데, 행사 규모가 확실히 대단하더군요! 참석자들에게 이벤트를 하셔서 사진도 많이 찍고, 밥도 맛있게 먹고 오늘 행사를 마무리 했습니다 :)

 

GDG DSC 다같이 기념사진 찰칵!! 클라우드님 씹덕사..★

7. 마무리

Google Cloud Summit을 갔다오니 GCP 자격증에도 관심이 생기고, 얼마전에 들은 얘기로는 GCP가 요즘 클라우드 시장에서 급성장을 하는 이유중에 하나가 BigQuery를 기업에서 많이 사용하기 때문이라고 하셔서 궁금해졌습니다!

 

이전에 어떤 개발자님에게 듣기로 하나하나 섬세하게 조정하기는 AWS가 제격인데, UI/UX나 직관적으로 환경을 세팅이라는 점에서는 GCP가 강점을 갖고있다고 했던게 생각나더라구요.

오늘 여러 세미나를 들으면서 GCP가 제공하는 여러 기능들에 대해서 얕지만 넓게 귀동냥을 할 수 있어서 좋았습니다.

 

그러면 Google Cloud Summit 후기는 여기까지 끝!

 

The Google Cloud Summit was held at COEX on November 6th.

I got a ticket through DSC Korea and went to check it out.

 

I was originally an AWS-only user, but since I started my DSC activities, I kept hearing so much about Google products that I couldn't help but learn about GCP.

But lately I've been so busy preparing for events that I didn't have time to study, so I only knew GCP existed and had only used it briefly for Google APIs. Going to this Google Cloud Summit was great because I got to hear brief explanations about the various products GCP offers.

So shall we get this recap started?

 

0. Google Cloud Summit Website

[Google Cloud Summit Homepage]

https://inthecloud.withgoogle.com/summit-sel-19/agenda.html

 

Google Cloud Summit

 

inthecloud.withgoogle.com

It had all the information about sessions, showcases, and the DevZone. I mostly spent my time at speaker sessions and the DevZone. In addition to the official website, there was also a web app where attendees could enter their personal code to get an at-a-glance view of all the event info.

 

 

 

It was a web app that helped attendees easily find all the information about the event like this :) 

Also, Google Cloud Summit gave out summit points when you visited various showcases, sessions, and booths. There was a cloud shop where you could exchange these summit points for Google-related merchandise :)

So you could check your accumulated points using the points tab.

 

As shown in the photos above, it was impressive how thoroughly they prepared everything—from venue tracks, partner booths, showcases, photo zones, the cloud shop, to meeting rooms—so that attendees could fully enjoy the event.

I especially appreciated that they had a dedicated space where attendees could ask speakers questions after sessions, which really showed the organizers' thoughtfulness.

 

 

1. Agenda

 

The agenda was also available on the website mentioned above, but we DSC Leads saved just the titles and picked the sessions we wanted to attend!

 

Event summary on the largest wall

 

2. Venue Atmosphere

Registration desk

From the moment I entered COEX, Google's signature four colors caught my eye :)

Since it was such a big event, you could tell they put a lot of effort into the preparations. The booth quality, banner sizes, and the placement of info staff throughout—the attention to detail was really impressive.

 

 

Upon registration, I received a name badge with my affiliation and a bag containing pamphlets about the various booths at the event.

However, there were so many events and sessions happening simultaneously that I wished I had researched the event beforehand so I could have enjoyed it more fully—that was a bit of a regret.

 

Summit venue at a glance

The venue had various booths related to GCP, which seemed to be partner booths for the Google Cloud Summit event.

You could see them running business card events and surveys to help companies adopt GCP. By visiting different booths and completing surveys, you could get booth-related souvenirs or enter prize drawings.

 

Commemorative photo, cheese!!!

3. Seminars

[Cloud Summit Recorded Videos]

https://cloudonair.withgoogle.com/events/summit-sel-19-livestream

 

Cloud Summit Seoul Live Stream

Watch the replay of Google Cloud Summit Seoul held on November 6th.

cloudonair.withgoogle.com

 

 

I think I spent almost the entire event attending sessions.

Since I'm still a college student, some of the booth forms were hard to fill out, and I hadn't pre-registered for any hands-on labs, so I just grabbed a seat and attended GCP sessions!!

 

I attended 5 sessions in total, and here's a summary of each one.

And as always, session notes!!

 

 

There was also a lunchtime session where you could eat and listen at the same time, but I was eating with Yuyeon and ended up just focusing on the food. 

4. DevZone Events

I mostly enjoyed this event with fellow DSC Leads. But the person who invited us, Nayeon, and the GDG members helping her were in charge of this very DevZone! So I ended up hanging out here most of the time.

GDG and DSC together at the DevZone, say cheese!!

 

Separate from the summit points, if you completed all 3 programs at the DevZone, you could enter a drawing for an invitation to the Dev Party—a networking event with other attendees!

 

The DevZone had free cola, beer, and popcorn, and we DSC Leads cheered together!! Hehe, it was so great.

DevZone cola and beer coupons, plus Cloud mascot appearance lol
DSC having a sneaky beer party in the midst of it all!!

4-1. Qwiklabs Zone

The Qwiklabs Zone was a space where you could do hands-on labs with a 1-month free access coupon.

When you went there, they gave you a Qwiklabs 1-month access coupon. GDG Cloud organizers were standing by to help with the labs, and since they were giving out coupons, I absolutely had to do it! haha

 

Qwiklabs URL: https://www.qwiklabs.com/?locale=ko

 

Qwiklabs - Hands-On Cloud Training

Qwiklabs provides real cloud environments that help developers and IT professionals learn cloud platforms and software, such as Firebase, Kubernetes and more.

www.qwiklabs.com

4-2. Presentation Zone

This was a space where mini sessions were held, including GDG/GCP community introductions, Study Jam tips, and Q&A about GCP certifications!

I watched the GCP O/X quiz and prize drawing. I also know they had several other presentations including GDG introductions.

During the prize drawing, nobody was getting picked for so long that they ended up deciding by rock-paper-scissors. Ugh,,, I lost at the very end, so that was disappointing lol

 

4-3. Play Zone

The Play Zone was a space where you could enjoy cloud arcade games.

They had simple GCP commands implemented as arcade games that you could play! 

The sense of achievement when you solved a problem and saw CORRECT pop up like below was amazing,, no matter how I think about it, they did a great job with this!!

5. Souvenirs

Between the last DevFest Seoul and this summit, going to GDG-related events seems to keep growing my swag collection!!

 

First, when you attended speaker seminars, you could drop the raffle ticket from the back of your name badge into a satisfaction survey box (rated 1 to 5 points), which entered you into the prize drawing at the end of the summit.

 

However, if you didn't want to enter the prize drawing, you could return your name badge and receive a fleece vest as a souvenir instead :)

And toward the end of the event, I exchanged my summit points for a Google Cloud cushion! I left with both hands full. If I had more summit points, I would've gotten a 13-inch laptop sleeve or a blanket haha. I spent too much time just attending seminars, so I didn't have enough points—that was a bummer.

 

Still, the sweatshirt from Megazone! The basic souvenir fleece vest (great taste!!) the cushion from cloud points! And a notebook from MongoDB—I'm happy leaving with both hands full of goodies ><

Group photo with the remaining DSC Leads after getting our souvenirs!

6. DevParty

I completed all 3 DevZone events and earned a Dev Party invitation! I had dinner with DSC Leads and GDG members, and the scale of the event was truly impressive! They had activities for the attendees, so I took lots of photos, enjoyed delicious food, and wrapped up the day's event :)

 

GDG and DSC group photo together!! Cloud mascot being adorable..★

7. Wrapping Up

After attending the Google Cloud Summit, I became interested in GCP certifications too. I also heard recently that one of the reasons GCP is rapidly growing in the cloud market is because many companies use BigQuery, which made me curious!

 

I remember a developer once told me that AWS is the way to go for fine-grained control, but GCP has its strengths in terms of UI/UX and intuitive environment setup.

It was great to attend various seminars today and get a broad (if shallow) introduction to the many features GCP offers.

 

And that wraps up my Google Cloud Summit recap!

 

댓글

Comments

Daily/Code Fest

DevFest Seoul 2019 Staff 후기 | DevFest Seoul 2019 Staff Review

DevFest Campus Korea 2019 준비로 교수님과 면담하고 다같이 행아웃 회의하고 그랬는데 정작 제가 DevFest를 안가봐서 이번에 DevFest Seoul 스탭으로 지원을 하게되었습니다! 사실 너무 속셈이 보이는 지원서였어서ㅋㅋ 더 적합한 분들을 선별하느라 떨어질 수도 있겠다 싶었는데 합격 메일이 와서 열심히 즐기다 왔습니다! 어쨌든, 진짜진짜! 한 줄 후기는 가길 잘했다!! DSC에게는 Free ticket이 주어졌는데, 요즘 시험기간이라 DSC Ewha 대부분이 못가셔서 아쉽네요.저는 왠지 모르게 시험이 없는 양아치로 살고있네요ㅎㅎㅎ... 요즘들어 수업도 많이 째고 학교 때려친기분 후기 시작합니다!! 사진 이쁘게 찍어주신 기훈님 감사합니다 :) 스태프스태프들은 9시에 모여서 다같이 ..

DevFest Seoul 2019 Staff 후기 | DevFest Seoul 2019 Staff Review

728x90

DevFest Campus Korea 2019 준비로 교수님과 면담하고 다같이 행아웃 회의하고 그랬는데 정작 제가 DevFest를 안가봐서 이번에 DevFest Seoul 스탭으로 지원을 하게되었습니다! 사실 너무 속셈이 보이는 지원서였어서ㅋㅋ 더 적합한 분들을 선별하느라 떨어질 수도 있겠다 싶었는데 합격 메일이 와서 열심히 즐기다 왔습니다!

 

 

어쨌든, 진짜진짜! 한 줄 후기는 가길 잘했다!!

 

DSC에게는 Free ticket이 주어졌는데, 요즘 시험기간이라 DSC Ewha 대부분이 못가셔서 아쉽네요.

저는 왠지 모르게 시험이 없는 양아치로 살고있네요ㅎㅎㅎ... 요즘들어 수업도 많이 째고 학교 때려친기분

 

후기 시작합니다!! 

사진 이쁘게 찍어주신 기훈님 감사합니다 :)

 

스태프

스태프들은 9시에 모여서 다같이 부스 설치하고, 소품을 준비했습니다. 파주에서 세종대까지 가려고 6:30에 일어났어요..

GDG 행사를 여러번 다녀보신 분들끼리는 그래도 안면이 있으시던데 저는 이번이 처음이라서 낯가리고 있었어요...ㅎㅎ 근데 다른분들이 먼저 말도 걸어주셔서 어떻게 어떻게 적응했네요

 

스태프 활동을 하면서 제일 자극이 됐던건 미림여고 분들이었어요. 어린나이인데도 개발행사에 이렇게 관심갖고 저보다 빨리 취직이라니.. 그리고 여고다보니까 여성개발자 네트워크가 기본적으로 생성되는 환경이라서 부럽기도 했습니다.

 

이번 DevFest Seoul 2019 컨셉은 할로윈이라서! 스탭분들 모두 할로윈 머리띠로 표시하고 다녔습니다!

스태프티도 너무 마음에 들어서 사진을 왕창 찍었네요 

 

 

인스타 스토리에 올렸던 사진!! GDG 스태프 티 입고 찰칵

 

일정표

행사가 시작되고 저는 Track B에서 스태프로 있었습니다! 스태프로 있으면서 세션도 듣고 좋았어요..ㅎㅎ 

 

Activity

입장시 주어지는 손목 티켓과 행사 안내 팜플렛입니다!!
저기 보이는 9개 빙고를 완성하면 DevFest 목도리를 받았는데요 

keynote전에 저는 호다닥 완성해서 받았습니다!!

 

Activity1 - PullRequest 미션

정말 인상깊었던 미션이었습니다!! PR을 모르는 사람이어도 손쉽게 README 읽으면서 충분히 할 수 있었습니다

(git bash 없이 할 수 있는 PR이라니 이벤트를 생각하신 분 진짜 아이디어 뱅크에요!!)

사람들이 PR을 날려서 Accept 됐을 경우, github.io 페이지에서 자신의 PR이 반영된 내용을 볼 수 있게 해주시다니!! 

진짜 개발자스러운 미션이라서 인상깊었습니다

 

나중에 DSC 행사열면 저도 써먹어야겠어요...ㅋㅋ

 

[github 레포지토리 링크] : https://github.com/GDG-Seoul/DevFest-Seoul-2019-guestbook

[github.io 링크] : https://gdg-seoul.github.io/DevFest-Seoul-2019-guestbook/

제가 남긴 PR도 이렇게 뿅!! 나타났네요! 급하게 하지말고 이미지도 신경써서 넣을껄!!

 

Activity2 - 후원사 부스

여기있는 후원사 부스에서 요구하는 미션을 수행하고 도장을 쾅쾅 받았습니다!

스프링 공부를 하다보니 우아한형제들 회사에 관심이 많은데, 덕분에 신입 채용관련해서 여쭤보기도 했습니다.

스태프로 가서 제 사리사욕을 더 채웠네요ㅋㅋㅋ

그리고 Women Techmakers 쪽 부스는 아무래도 DSC Ewha 차기 활동을 생각해서 제 소개를 드리고 연락 방법도 물어보고 했습니다!! WTM쪽에 관심이있었는데 이번 기회에 오거나이저 분들을 만나뵐 수 있어서 운이 좋았네요

 

그리고 무엇보다도 스티커!!! 행사 굿즈 모으는거 너무 좋아요ㅠㅠ 부스에서 열심히 줍줍하고 다녔습니다ㅋㅋ

 

Activity 3 - 포토존 / New Friend()

포토존에서 옆에있는 박스의 할로윈 물품을 들고 인증샤샤샷!! 

그리고 New Friend()라는 미션의 조건에서 할로윈 분장을 한 스태프와 사진을 찍으면 도장 받는게 있어서 돌아다니다가 사진찍히고 그랬네요ㅋㅋㅋ 

 

세미나

이번에도 역시 세미나엔 아이패드죠!! 

강의를 들으면서 slide에 없는 발표자님의 말을 적으려고 했는데, 음... 공부를 많이 해야겠구나를 다시한번!!

왜 세상에 있는 개발자들은 저빼고 다들 똑똑한걸까요ㅋㅋㅋ

 

세션 필기내용 - 알아듣진 못하지만 끄적끄적..
세션 필기내용 - 알아듣진 못하지만 끄적끄적..

제가 가장 흥미로웠던 세미나는 CleanCode였습니다!!

아무래도 지금 CleanCode 스터디를 계속 하고있고, 변수명 정하기, 좀 더 객체지향적으로 코드 짜기, indent 없애기 등 중요한 요소라고 생각을 하기 때문이었습니다.

저는 AI 관련은 아니지만, AI쪽 코드는 아무래도 분기가 많아서 코드가 어지러울텐데 확실한 예제를 들어주시면서 쉽게 설명을 해주시니 이해가 잘가더라구요!!

그리고 이전에 오픈핵에서 python 으로 크롤링 코드를 짜면서, 계속 for문안에 for문, if안에 또 if 이런 패턴이 계속 나왔는데, dictionary로 그걸 깔끔하게 정리해버리시길래 왜 저런 생각을 못했을까 싶었습니다.

 

 

반면에 가장 반성하게 되는 세미나는 MSA 였습니다.

발표자님이 정말 설명을 잘하셨는데, 처음 듣는 용어가 너무 많다고 느껴졌습니다. 

서버 공부한다고 그러면서 쿠버네티스 해야지 해야지만 하고 제쳐뒀었거든요.

근데 쿠버네티스 뿐만아니라 발표자님이 언급하시는 cloud 서비스들 역시도 모르는게 너무 많아서ㅠㅠ

공부를 열심히하자! 결심쓰!

 

굿즈

집에 도착해서 스티커, 각종 쿠폰 목록을 보는데 세상 뿌듯♥

DevFest Seoul을 이렇게 알차게 준비하신 오거나이저분들께 너무 감사했습니다.

 

마무리

이후엔 스태프들끼리 회식!!! 네..ㅎㅎ 후원사쪽 전화받다가 막차 끊겼어요

이렇게 블로그 포스팅까지 완료하니까 진짜 잘 갔다온 기분이네요

스태프 일하면서 만나게된 여러 인연들을 또 보고싶네요! GDG, DSC 활동을 적극적으로 하고 다니는걸로!!

 

 

그래서 11/16에 있는 DevFest Campus Korea 도 열심히 준비할 예정입니다!!

세종대학교만큼 큰 장소가 아니라서 걱정되는데ㅠㅠ 잘해야죠!!!

 

그러면 오늘은 여기까지 끗!!

GDG Seoul Facebook : https://www.facebook.com/groups/gdgseoul/

GDG Campus Korea Facebook : https://www.facebook.com/gdgcampus/

GDG DevFest Korea Facebook : https://www.facebook.com/devfest.seoul.2019/

DSC Korea Facebook Group : https://www.facebook.com/groups/dsckorea/

 

보안 확인 필요

메뉴를 열려면 alt + / 키 조합을 누르세요

www.facebook.com

 

보안 확인 필요

메뉴를 열려면 alt + / 키 조합을 누르세요

www.facebook.com

 

GDG Campus Korea

GDG Campus Korea. 좋아하는 사람 912명 · 이야기하고 있는 사람들 28명. Google Developers Group Campus Korea 챕터 입니다! 반갑습니다~

www.facebook.com

 

보안 확인 필요

메뉴를 열려면 alt + / 키 조합을 누르세요

www.facebook.com

 

I'd been meeting with my professor and having group Hangouts meetings to prepare for DevFest Campus Korea 2019, but I realized I'd never actually been to a DevFest myself, so I applied to be a staff member for DevFest Seoul! Honestly, my application was so transparently self-serving lol, I thought they might reject me in favor of more qualified people, but I got the acceptance email and had a blast!

 

 

Anyway, for real for real! My one-line review is: So glad I went!!

 

DSC members got free tickets, but since it's exam season, most of DSC Ewha couldn't make it, which was a bummer.

Somehow I'm living like a rebel with no exams lol... I've been skipping a lot of classes lately and it feels like I've dropped out

 

Let's get this review started!! 

Thanks to Kihoon for taking such great photos :)

 

Staff

The staff gathered at 9 AM to set up booths and prepare props together. I had to wake up at 6:30 to get from Paju to Sejong University..

People who'd been to multiple GDG events already knew each other, but since this was my first time, I was being shy... haha But other people came up and talked to me first, so I managed to warm up somehow.

 

The most inspiring thing about being on staff was meeting the students from Mirim Girls' High School. Despite being so young, they were so passionate about dev events and getting jobs before me.. And since it's an all-girls school, they naturally have a women-in-tech network built in, which I was honestly envious of.

 

The theme for DevFest Seoul 2019 was Halloween! So all the staff wore Halloween headbands to identify themselves!

I loved the staff t-shirt so much that I took a ton of photos 

 

 

Photos I posted on my Instagram story!! Posing in the GDG staff tee

 

Schedule

Once the event started, I was stationed at Track B as staff! It was nice being able to listen to the sessions while working as staff..haha 

 

Activity

These are the wristband tickets and event pamphlets given at entry!!
If you completed the 9-square bingo shown there, you'd get a DevFest scarf 

I rushed to complete it before the keynote and got mine!!

 

Activity 1 - Pull Request Mission

This was such an impressive mission!! Even people who didn't know what a PR was could easily do it just by reading the README

(A PR you can do without git bash?! Whoever came up with this event idea is a genius!!)

When people sent PRs and they got accepted, they could see their PR reflected on the github.io page!! 

It was so impressive because it was such a developer-like mission

 

I should totally steal this idea when we host DSC events later... lol

 

[GitHub Repository Link] : https://github.com/GDG-Seoul/DevFest-Seoul-2019-guestbook

[github.io Link] : https://gdg-seoul.github.io/DevFest-Seoul-2019-guestbook/

My PR showed up just like that!! I should've taken my time and added a proper image instead of rushing!!

 

Activity 2 - Sponsor Booths

I completed missions at the sponsor booths and collected stamps!

Since I've been studying Spring, I'm really interested in Woowa Brothers (Baemin), so I got to ask them about entry-level hiring too.

I went as staff but ended up serving my own interests more lol

And for the Women Techmakers booth, I introduced myself and asked about ways to connect, thinking about future DSC Ewha activities!! I'd been interested in WTM, so I was lucky to meet the organizers this time.

 

And most importantly, STICKERS!!! I love collecting event goodies so much ㅠㅠ I went around collecting everything I could from the booths lol

 

Activity 3 - Photo Zone / New Friend()

Grabbed some Halloween props from the box next to the photo zone and snapped a pic!! 

And there was a mission called New Friend() where you could get a stamp by taking a photo with a staff member in Halloween costume, so I kept getting pulled into photos while walking around lol 

 

Sessions

Of course, I brought my iPad for the sessions as always!! 

I tried to jot down things the speakers said that weren't on the slides, but... it reminded me once again that I need to study a lot more!!

Why is every developer in the world smart except me lol

 

Session notes - couldn't understand everything but scribbled away..
Session notes - couldn't understand everything but scribbled away..

The session I found most interesting was the one on Clean Code!!

It's because I've been doing a Clean Code study group, and I think things like naming variables, writing more object-oriented code, and reducing indentation are really important elements.

I'm not in the AI field myself, but AI code tends to have a lot of branching which makes it messy — the speaker gave such clear examples and explained things so well that it was easy to follow!!

And previously at an open hack event, while writing crawling code in Python, I kept running into patterns of for loops inside for loops and if statements inside if statements — but the speaker cleaned all that up using a dictionary, and I was like, why didn't I think of that?

 

 

On the other hand, the session that made me reflect the most was the one on MSA.

The speaker explained things really well, but I felt like there were way too many terms I was hearing for the first time. 

I kept saying I should learn Kubernetes while studying server stuff, but I kept putting it off.

And it wasn't just Kubernetes — there were so many cloud services the speaker mentioned that I didn't know about ㅠㅠ

I need to study harder! Resolution made!

 

Goodies

When I got home and looked at all the stickers and various coupons, I felt so satisfied♥

I was so grateful to the organizers who put together such an amazing DevFest Seoul.

 

Wrapping Up

Afterwards, the staff went out for dinner together!!! Yeah..haha I was on the phone with a sponsor and missed the last train

Now that I've even finished this blog post, it really feels like the trip was worthwhile

I'd love to see all the people I met while working as staff again! Time to be more active in GDG and DSC!!

 

 

So I'm going to work hard preparing for DevFest Campus Korea on 11/16 too!!

The venue isn't as big as Sejong University so I'm worried ㅠㅠ but we gotta make it work!!!

 

That's all for today, bye!!

GDG Seoul Facebook : https://www.facebook.com/groups/gdgseoul/

GDG Campus Korea Facebook : https://www.facebook.com/gdgcampus/

GDG DevFest Korea Facebook : https://www.facebook.com/devfest.seoul.2019/

DSC Korea Facebook Group : https://www.facebook.com/groups/dsckorea/

 

Security Check Required

Press alt + / to open the menu

www.facebook.com

 

Security Check Required

Press alt + / to open the menu

www.facebook.com

 

GDG Campus Korea

GDG Campus Korea. 912 likes · 28 people talking about this. This is the Google Developers Group Campus Korea chapter! Nice to meet you~

www.facebook.com

 

Security Check Required

Press alt + / to open the menu

www.facebook.com

 

댓글

Comments

Develop/Springboot

[JPA] 고급매핑 - 상속 관계 , 매핑 정보 상속 | [JPA] Advanced Mapping - Inheritance Relationships, Mapped Superclass

인프런에서 에서 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 듣고 쓴 정리 글입니다.https://www.inflearn.com/course/ORM-JPA-Basic 자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 서버 데이터베이스 프레임워크 및 라이브러리 프로그래밍 언어 서비스 개발 Java JPA 스프링 데이터 JPA 온라인 강의www.inflearn.com평소에 Spring Data JPA 를 썼는데, 김영한님은 JPA 자체를 강의하시더라구요.김영한님 강의 바탕으로 Spring Data ..

[JPA] 고급매핑 - 상속 관계 , 매핑 정보 상속 | [JPA] Advanced Mapping - Inheritance Relationships, Mapped Superclass

728x90

인프런에서 에서 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 듣고 쓴 정리 글입니다.

https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 서버 데이터베이스 프레임워크 및 라이브러리 프로그래밍 언어 서비스 개발 Java JPA 스프링 데이터 JPA 온라인 강의

www.inflearn.com

평소에 Spring Data JPA 를 썼는데, 김영한님은 JPA 자체를 강의하시더라구요.

김영한님 강의 바탕으로 Spring Data JPA로 강의 소스를 테스트해보고 개념을 기록하기 위해 포스팅을 하게되었습니다.



고급 매핑

1. 상속관계 매핑

  • 관계형 데이터베이스는 상속 관계X
  • 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사
  • 상속관계 매핑: 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑
  • 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법
    1. 각각 테이블로 변환 -> 조인 전략
    2. 통합 테이블로 변환 -> 단일 테이블 전략
    3. 서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략

테이블은 여러개의 모델링이 나오지만, 객체는 상속관계라는 1개의 개념이다.

객체관계는 같지만 DB설계를 다르게 할 수 있음

  • 관계형 데이터베이스는 상속 관계 X
  • 슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사
  • 상속관계 매핑 : 객체의 상속, 구조와 DB의 슈퍼타입 서브타입 관계를 매핑
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorColumn
@Getter
public abstract class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Book")
public class Book extends Item {
    private String author;
    private String isbn;

    @Builder
    public Book(String name, int price, String author, String isbn) {
        super(name, price);
        this.author = author;
        this.isbn = isbn;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Album")
public class Album extends Item{
    private String artist;

    @Builder
    public Album(String name, int price, String artist) {
        super(name, price);
        this.artist = artist;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Movie")
public class Movie extends Item {
    private String actor;
    private String director;

    @Builder
    public Movie(String name, int price, String actor, String director) {
        super(name, price);
        this.actor = actor;
        this.director = director;
    }
}

[Repository 코드]

public interface ItemRepository<T extends Item> extends JpaRepository<T, Long> {}
public interface BookRepository extends JpaRepository<Book, Long> {}
public interface AlbumRepository extends JpaRepository<Album, Long> {}
public interface MovieRepository extends JpaRepository<Movie, Long> {}

이때 ItemRepository extends 를 꼭 기억하자!! [abstract class jpaRepository 상속법]

ItemRepository만 사용해도 Book, Album, Movie를 모두 가져올 수 있다. (type casting 사용해서)

[테스트 코드]

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ItemTest {

    @Autowired
    ItemRepository itemRepository;

    @Autowired
    EntityManager entityManager;

    @Before
    public void setUp() throws Exception {
        Movie movie = Movie.builder()
                .actor("맷데이먼")
                .director("리들리스콧")
                .name("마션")
                .price(10000)
                .build();

        Book book = Book.builder()
                .author("조영호")
                .isbn("isbn")
                .name("객체지향의 사실과 오해")
                .price(10000)
                .build();

        Album album = Album.builder()
                .artist("엔플라잉")
                .name("야호")
                .price(30000)
                .build();

        itemRepository.save(movie);
        itemRepository.save(book);
        itemRepository.save(album);

        entityManager.clear();
    }

    @Test
    public void Item의_서브클래스_객체들_casting으로_가져오기() {
        Movie movie = (Movie) itemRepository.findAll().get(0);
        Book book = (Book) itemRepository.findAll().get(1);
        Album album = (Album) itemRepository.findAll().get(2);

        assertThat(movie.getName()).isEqualTo("마션");
        assertThat(book.getName()).isEqualTo("객체지향의 사실과 오해");
        assertThat(album.getArtist()).isEqualTo("엔플라잉");

    }
}

1-0. 주요 어노테이션

  • @Inheritance(strategy = InheritanceType.XXX) = default: SINGLE_TABLE
    • JOINED : 조인 전략
    • SINGLE_TABLE : 단일 테이블 전략
    • TABLE_PER_CLASS : 구현 클래스마다 테이블 전략
  • @DiscriminatorColumn(name = "DTYPE") = default: DTYPE DTYPE이라는 Column이 super class의 table에 생기고,
    DTYPE의 값은 sub class의 이름으로 지정된다. SingleTable 전략에서 없어도 DTYPE 이생성되기도 하는데, 그래도 운영상 써주자
  • @DiscriminatorValue("XXX") = default: classname

[예시]

@Inheritance(strategy = InheritanceType.JOIN)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{}

@DiscriminatorValue("ALBUM_TYPE")
public class Album extends Item{}

@DiscriminatorValue("BOOK_TYPE")
public class Book extends Item{}

@DiscriminatorValue("MOVIE_TYPE")
public class Movie extends Item{}

DB 설계를 바꿨는데도 코드를 많이 수정하지 않아도 된다!! : JPA의 큰 장점!!

Join이 성능이 안나오네 -> singletable로 고치자!!
: query를 사용하면 코드를 많이 바꿔야함 근데 JPA사용하면 바꾸는게 엄청 쉽다.

1-1. 조인전략

데이터를 가져올 때 JOIN을 이용해서 가져온다.

insert는 두번 ITEAM ALBUM

select는 PK, FK를 이용해서 JOIN해서 가져온다.

abstract class에는 type을 컬럼을 두어서 구분한다.

@Inheritance(strategy = InheritanceType.JOIN)
@DiscriminatorColumn
public abstract class Item{}

1-1-1. 장점

  • 테이블 정규화
  • 외래 키 참조 무결성 제약조건 활용 가능
  • 저장공간 효율화

1-1-2. 단점

  • 조회시 조인을 많이 사용, 성능 저하
  • 조회 쿼리가 복잡함
  • 데이터 저장시 INSERT SQL 2번 호출

조인 성능이 생각보다 치명적이진 않고, 오히려 저장공간이 더 효율적일 수도 있음

그래도 단일 테이블 전략과 비교했을 때 단점이다!

조인이 정규화도 되고 객체랑도 잘 맞고 설계 입장에서 잘 맞아 떨어진다.

1-2. 단일 테이블 전략 - 기본 전략

subclass 의 모든 멤버변수를 테이블의 컬럼으로 가져온다.

insert도 한번에 되고, select도 한번에 되니까 아무래도 성능이 나오지!

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item{}

1-2-1. 장점

  • 조인이 필요 없으므로 일반적으로 조회 성능이 빠름
  • 조회 쿼리가 단순함

1-2-2. 단점

  • 자식 엔티티가 매핑한 컬럼은 모두 null 허용
  • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있고 상황에 따라서 조회 성능이 오히려 느려질 수 있다. NULL 조건이 데이터 무결성 입장에서 애매하다. ALBUM 저장하면 > Book, Movie 관련 column이 모두 null이 되어야한다. 조회 성능을 문제시 하려면 임계점을 넘어야하는데 보통은 없음

1-3. 구현 클래스마다 테이블 전략

subclass 자체를 테이블로 만든다 + superclass의 멤버변수도 포함해서!

superclass를 아예 없애버리고, table을 subclass 기준으로 만든 후,
superclass의 멤버변수도 같이 포함하게 한다.

Item table 자체가 존재하지 않고, Movie, Book, Album table만 존재한다.

@DiscriminatorColumn의 의미가 없다! (없어도 된다.)

단순하게 값을 넣고 뺄 때는 좋은데, 이외의 경우에는 세 개 테이블을 모두 찾아봐서 쿼리가 복잡하게 나간다.

ex ) Item id가 5번이라고 할 때!

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item{}

이 전략은 데이터베이스 설계자와 ORM 전문가 둘 다 싫어하는 전략임!

1-3-1. 장점

  • 서브 타입을 명확하게 구분해서 처리할 때 효과적
  • Not Null 제약조건 사용가능

1-3-2. 단점

  • 여러 자식 테이블을 함께 조회할 때 성능이 느림 (UNION SQL)
  • 자식 테이블을 통합해서 쿼리하기 어려움

2. @MappedSuperclass - 매핑 정보 상속

  • 공통 매핑 정보가 필요할 때 사용한다. (ex : baseTimeEntity 같은 것)

위에서 말한 상속 관계 매핑에서 테이블까지 고민하기 싫음.
DB는 따로 쓰되, 객체입장에서 속성만 상속 받아서 쓰고 싶을때!

@MappedSuperclass
public abstract class BaseEntity {
    private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifedBy;
    private LocalDateTime lastModifiedDate;
}

@Entity
public class Member extends BaseEntity{ ... }

@Entity
public class Team extends BaseEntity{ ... }

매핑 정보만 받는 슈퍼 클래스로 하고싶다면

  1. extends 로 클래스 설정하기
  2. @MappedSuperclass 어노테이션 추가하기.

그냥 속성을 같이 쓰고 싶을 때 사용한다!!

@Column(name = "CREATED_BY") // 이런식으로 column 설정도 충분히 가능하다.
private String createdBy;

JPA의 이벤트 기능으로 아예 어노테이션으로 시간, auth 정보를 편리하게 만들어 버릴 수 있다.

  • 상속관계 매핑 X
  • 엔티티X, 테이블과 매핑X (@Entity 안붙였다.)
  • 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공
  • 조회, 검색 불가(em.find(BaseEntity)불가) em.find(BaseEntity.class, 1L); 불가능
  • 직접 생성해서 사용할 일이 없으므로 추상 클래스 권장
  • 테이블과 관계 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할
  • 주로 등록일, 수정일, 등록자, 수정자 같은 전체 엔티티에서 공통으로 적용하는 정보를 모을 때 사용
  • 참고 : @Entity 클래스는 엔티티나 @MappedSuperclass로 지정한 클래스만 상속가능하다.
@MappedSuperclass //매핑 정보 상속
public abstract class BaseEntity{...}

@Entity //상속 관계 매핑
public abstract class Item extends BaseEntity{...}

@Entity
public class Album extends Item{...}

This is a summary post written after taking Kim Young-han's Java ORM Standard JPA Programming - Basics course on Inflearn.

https://www.inflearn.com/course/ORM-JPA-Basic

 

Java ORM Standard JPA Programming - Basics - Inflearn

For those who are new to JPA or use JPA in practice but lack foundational theory — build a solid understanding of JPA basics so that even beginners can confidently use JPA in real-world projects. Beginner Web Development Server Database Frameworks & Libraries Programming Languages Service Development Java JPA Spring Data JPA Online Course

www.inflearn.com

I've been using Spring Data JPA, but Kim Young-han actually teaches JPA itself.

Based on his lectures, I'm writing this post to document concepts while testing the course source code with Spring Data JPA.



Advanced Mapping

1. Inheritance Mapping

  • Relational databases do NOT have inheritance
  • The supertype-subtype modeling technique is similar to object inheritance
  • Inheritance mapping: Mapping between object inheritance structure and DB supertype-subtype relationships
  • Ways to implement a supertype-subtype logical model into a physical model:
    1. Convert to separate tables -> Joined strategy
    2. Convert to a single table -> Single table strategy
    3. Convert to subtype tables -> Table-per-class strategy

Tables can result in multiple modeling approaches, but on the object side, there's only one concept: inheritance.

The object relationships stay the same, but the DB design can vary.

  • Relational databases do NOT have inheritance
  • The supertype-subtype modeling technique is similar to object inheritance
  • Inheritance mapping: Mapping between object inheritance/structure and DB supertype-subtype relationships
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorColumn
@Getter
public abstract class Item {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int price;

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Book")
public class Book extends Item {
    private String author;
    private String isbn;

    @Builder
    public Book(String name, int price, String author, String isbn) {
        super(name, price);
        this.author = author;
        this.isbn = isbn;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Album")
public class Album extends Item{
    private String artist;

    @Builder
    public Album(String name, int price, String artist) {
        super(name, price);
        this.artist = artist;
    }
}

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("Movie")
public class Movie extends Item {
    private String actor;
    private String director;

    @Builder
    public Movie(String name, int price, String actor, String director) {
        super(name, price);
        this.actor = actor;
        this.director = director;
    }
}

[Repository Code]

public interface ItemRepository<T extends Item> extends JpaRepository<T, Long> {}
public interface BookRepository extends JpaRepository<Book, Long> {}
public interface AlbumRepository extends JpaRepository<Album, Long> {}
public interface MovieRepository extends JpaRepository<Movie, Long> {}

Make sure to remember the ItemRepository extends part!! [How to extend JpaRepository for an abstract class]

You can retrieve Book, Album, and Movie all through ItemRepository alone. (using type casting)

[Test Code]

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ItemTest {

    @Autowired
    ItemRepository itemRepository;

    @Autowired
    EntityManager entityManager;

    @Before
    public void setUp() throws Exception {
        Movie movie = Movie.builder()
                .actor("맷데이먼")
                .director("리들리스콧")
                .name("마션")
                .price(10000)
                .build();

        Book book = Book.builder()
                .author("조영호")
                .isbn("isbn")
                .name("객체지향의 사실과 오해")
                .price(10000)
                .build();

        Album album = Album.builder()
                .artist("엔플라잉")
                .name("야호")
                .price(30000)
                .build();

        itemRepository.save(movie);
        itemRepository.save(book);
        itemRepository.save(album);

        entityManager.clear();
    }

    @Test
    public void Item의_서브클래스_객체들_casting으로_가져오기() {
        Movie movie = (Movie) itemRepository.findAll().get(0);
        Book book = (Book) itemRepository.findAll().get(1);
        Album album = (Album) itemRepository.findAll().get(2);

        assertThat(movie.getName()).isEqualTo("마션");
        assertThat(book.getName()).isEqualTo("객체지향의 사실과 오해");
        assertThat(album.getArtist()).isEqualTo("엔플라잉");

    }
}

1-0. Key Annotations

  • @Inheritance(strategy = InheritanceType.XXX) = default: SINGLE_TABLE
    • JOINED: Joined strategy
    • SINGLE_TABLE: Single table strategy
    • TABLE_PER_CLASS: Table-per-class strategy
  • @DiscriminatorColumn(name = "DTYPE") = default: DTYPE A column called DTYPE is created in the superclass table,
    and the DTYPE value is set to the subclass name. In the SingleTable strategy, DTYPE may be generated even without this annotation, but you should still include it for production use.
  • @DiscriminatorValue("XXX") = default: classname

[Example]

@Inheritance(strategy = InheritanceType.JOIN)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item{}

@DiscriminatorValue("ALBUM_TYPE")
public class Album extends Item{}

@DiscriminatorValue("BOOK_TYPE")
public class Book extends Item{}

@DiscriminatorValue("MOVIE_TYPE")
public class Movie extends Item{}

Even when the DB design changes, you barely need to modify the code!! This is a huge advantage of JPA!!

Join performance isn't cutting it -> Let's switch to single table!!
With raw queries, you'd have to change a lot of code, but with JPA it's super easy to switch.

1-1. Joined Strategy

When fetching data, it uses JOINs to retrieve it.

Insert happens twice — once for ITEM, once for ALBUM.

Select uses PK and FK to JOIN and fetch the data.

The abstract class has a type column to distinguish between subtypes.

@Inheritance(strategy = InheritanceType.JOIN)
@DiscriminatorColumn
public abstract class Item{}

1-1-1. Pros

  • Table normalization
  • Can leverage foreign key referential integrity constraints
  • Efficient storage space

1-1-2. Cons

  • Heavy use of joins during queries, potential performance degradation
  • Complex query statements
  • INSERT SQL is called twice when saving data

Join performance isn't as fatal as you might think, and it can actually be more storage-efficient.

Still, these are disadvantages compared to the single table strategy!

Joins provide normalization, align well with objects, and fit nicely from a design perspective.

1-2. Single Table Strategy - Default Strategy

All member variables of subclasses become columns in a single table.

Insert happens in one shot, select happens in one shot — so naturally the performance is better!

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item{}

1-2-1. Pros

  • No joins needed, so query performance is generally fast
  • Simple query statements

1-2-2. Cons

  • All columns mapped by child entities must allow null
  • Since everything is stored in a single table, the table can get large and in some cases query performance may actually get slower. NULL conditions are awkward from a data integrity standpoint. When you save an ALBUM > all Book and Movie related columns must be null. For query performance to become a real problem, you'd need to cross a threshold, which usually doesn't happen.

1-3. Table-per-Class Strategy

Each subclass becomes its own table — including the superclass's member variables!

The superclass table is completely eliminated, tables are created based on subclasses,
and they include the superclass's member variables as well.

The Item table itself doesn't exist — only Movie, Book, and Album tables exist.

@DiscriminatorColumn has no meaning here! (You don't need it.)

It's fine for simple inserts and retrieves, but for anything else, it has to search all three tables resulting in complex queries.

e.g.) When the Item id is 5!

@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Item{}

This is a strategy that both database designers and ORM experts dislike!

1-3-1. Pros

  • Effective when you need to clearly distinguish and handle subtypes
  • Can use NOT NULL constraints

1-3-2. Cons

  • Slow performance when querying multiple child tables together (UNION SQL)
  • Difficult to write unified queries across child tables

2. @MappedSuperclass - Inheriting Mapping Information

  • Used when common mapping information is needed. (e.g., something like BaseTimeEntity)

You don't want to think about table design like in inheritance mapping above.
You want the DB tables to be separate, but from the object perspective, you just want to inherit the attributes!

@MappedSuperclass
public abstract class BaseEntity {
    private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifedBy;
    private LocalDateTime lastModifiedDate;
}

@Entity
public class Member extends BaseEntity{ ... }

@Entity
public class Team extends BaseEntity{ ... }

If you want a superclass that only provides mapping information:

  1. Set up the class with extends
  2. Add the @MappedSuperclass annotation.

Use it when you simply want to share attributes!!

@Column(name = "CREATED_BY") // 이런식으로 column 설정도 충분히 가능하다.
private String createdBy;

With JPA's event features, you can conveniently create time and auth information using annotations alone.

  • NOT inheritance mapping
  • NOT an entity, NOT mapped to a table (@Entity is not applied.)
  • Only provides mapping information to child classes that inherit from the parent class
  • Cannot be queried or searched (em.find(BaseEntity) is not possible) em.find(BaseEntity.class, 1L); is not possible
  • Since you'll never instantiate it directly, abstract class is recommended
  • Has no relation to tables — it simply gathers mapping information commonly used by entities
  • Mainly used to collect information like created date, modified date, created by, modified by that applies commonly across all entities
  • Note: @Entity classes can only extend entities or classes annotated with @MappedSuperclass.
@MappedSuperclass //매핑 정보 상속
public abstract class BaseEntity{...}

@Entity //상속 관계 매핑
public abstract class Item extends BaseEntity{...}

@Entity
public class Album extends Item{...}

댓글

Comments

Develop/Springboot

[JPA] 프록시와 연관관계 관리 - 프록시, LAZY, EAGER , CASCADE, orphanRemoval | [JPA] Proxy and Association Management - Proxy, LAZY, EAGER, CASCADE, orphanRemoval

인프런에서 에서 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 듣고 쓴 정리 글입니다.https://www.inflearn.com/course/ORM-JPA-Basic 자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 서버 데이터베이스 프레임워크 및 라이브러리 프로그래밍 언어 서비스 개발 Java JPA 스프링 데이터 JPA 온라인 강의www.inflearn.com평소에 Spring Data JPA 를 썼는데, 김영한님은 JPA 자체를 강의하시더라구요.김영한님 강의 바탕으로 Spring Data ..

[JPA] 프록시와 연관관계 관리 - 프록시, LAZY, EAGER , CASCADE, orphanRemoval | [JPA] Proxy and Association Management - Proxy, LAZY, EAGER, CASCADE, orphanRemoval

728x90

인프런에서 에서 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편을 듣고 쓴 정리 글입니다.

https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 서버 데이터베이스 프레임워크 및 라이브러리 프로그래밍 언어 서비스 개발 Java JPA 스프링 데이터 JPA 온라인 강의

www.inflearn.com

평소에 Spring Data JPA 를 썼는데, 김영한님은 JPA 자체를 강의하시더라구요.

김영한님 강의 바탕으로 Spring Data JPA로 강의 소스를 테스트해보고 개념을 기록하기 위해 포스팅을 하게되었습니다.



프록시와 연관관계 관리

1. 프록시

Member를 조회할 때 Team도 함께 조회해야 할까?

  • Member 가져올 때 Team도 함께 출력
    • jpa에서 member가져올 때 team도 가져오면 좋다.
  • Member 가져올때 오로지 member만!
    • jpa에서 member가져올 때 team도 가져오면 안좋다!

1-1. 프록시 기초

  • em.find() : DB를 통해서 실제 엔티티 객체조회
  • em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회

DB의 쿼리가 안나가는데 조회가 되는 것

@Test
public void 멤버와조회할때_팀도함께_조회() {
    Member findMember = entityManager.find(Member.class, 1L);
    System.out.println("findMember.id = " + findMember.getId());
    System.out.println("findMember.username = " + findMember.getUsername());
    }
select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_, 
    team1_.member_id as member_i1_1_1_, 
    team1_.name as name2_1_1_ 
from 
    member member0_ 
left outer join 
    team team1_ 
        on member0_.team_id=team1_.member_id 
where member0_.member_id=?

자동적으로 Member를 조회하는데 Team도 join이 되서 같이 조회가된다.

@Test
public void 멤버만_조회() {
    Member findMember = entityManager.getReference(Member.class, 1L);
}

이 경우 select 쿼리가 안나간다!!

@Test
public void 멤버만_조회() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("findMember.id = " + findMember.getId());
    System.out.println("findMember.username = " + findMember.getUsername());
}

이 경우에는 select 쿼리가 나간다!

getReference() 를 호출하는 시점에는 DB에 Query를 호출하지 않는다.
이 값이 실제 사용되는 시점 (username)에 DB에 Query를 호출한다.

System.out.println("findMember = " + findMember.getClass());
findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$injSwDL2

이름이 Member가 아니다! HibernateProxy : 강제로 만든 가짜클래스이다 : 프록시 클래스

1-2. 프록시 특징

  • 실제 클래스를 상속 받아서 만들어짐
  • 실제 클래스와 겉 모양이 같다.
  • 사용하는 입장에서는 진짜 객체인지 프록시 객체인지는 구분하지 않고 사용하면 됨 (이론상)
  • 프록시 객체는 실제 객체의 참조(target)를 보관
  • 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출
em.getReference(Member.class, 1L); //프록시객체 가져온다.

getName() > Member target에 값이 없다 > 영속성 컨텍스트에 실제 값 가져오라 요청 > db가 그 값을 가져오고, Proxy객체에 진짜 객체를 연결시켜준다. 그래서 target.getName()으로 name을 가져온다.

영속성 컨텍스트에 초기화 요청 : 프록시에 값이 없을 때 DB에서 진짜 값을 달라.

1-3. 프록시 객체 매커니즘

  • 프록시 객체는 처음 사용할 때 한 번만 초기화
@Test
public void 프록시_테스트() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("1st = " + findMember.getUsername());
        //1st에서는 query가 나간다.
    System.out.println("2nd = " + findMember.getUsername());
        //2nd에서는 query가 나가지 않는다.
}
  • 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아님, 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근 가능
@Test
public void 프록시_테스트() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("before findMember = " + findMember.getClass());
    System.out.println("findMember.username = " + findMember.getUsername());
    System.out.println("after findMember = " + findMember.getClass());
}
before findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$EYDMo7wU
Hibernate: [select query]
findMember.username = member1
after findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$EYDMo7wU
  • 프록시 객체는 원본 엔티티를 상속 받음, 따라서 타입 체크시 주의해야함 (== 비교 실패, instance of 사용) => 프록시로 넘어올지, 원래 객체 타입으로 넘어올지 모른다
@Test
public void 프록시_엔티티상속_테스트() {
    Member member1 = Member.builder()
        .username("member1")
        .build();
    memberRepository.save(member1);

    Member member2 = Member.builder()
        .username("member2")
        .build();
    memberRepository.save(member1);

    entityManager.clear();

    Member m1 = entityManager.find(Member.class, member1.getId());
    Member m2 = entityManager.getReference(Member.class, member2.getId());

    System.out.println("m1 == m2 : " + (m1.getClass() == m2.getClass()));   // false
    System.out.println("m1 instanceof : " + (m1 instanceof Member));        // true
    System.out.println("m2 instanceof : " + (m2 instanceof Member));        // true
}
  • 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
@Test
public void 프록시_영속성_테스트() {
    Member member1 = Member.builder()
        .username("member1")
        .build();
    memberRepository.save(member1);

    entityManager.clear();

    Member m1 = entityManager.find(Member.class, member1.getId()); //영속성 상태
    System.out.println("m1 = " + m1.getClass());

    Member references = entityManager.getReference(Member.class, member1.getId());
    System.out.println("reference = " + references.getClass());
}
m1 = class com.jyami.jpalab.domain.Member
reference = class com.jyami.jpalab.domain.Member

멤버를 이미 1차 캐싱했는데 굳이 proxy로 가져오는게 의미가 없다.

JPA는 한 트랜잭션에서 같은거를 보장해준다.
한 영속성 컨텍스트에서 가져온거면 true.

System.out.println(m==reference) // true로 무조껀 만들어 줘야한다 : proxy가 아닌 실 값 가져옴

Member reference1 = entityManager.getReference(Member.class, member1.getId());
System.out.println("reference1 = " + reference1.getClass());

Member reference2 = entityManager.getReference(Member.class, member1.getId());
System.out.println("reference2 = " + reference2.getClass());

System.out.println("a == a" + (reference1 == reference2)); //true
reference1 = class com.jyami.jpalab.domain.Member$HibernateProxy$Xr6pfd5T
reference2 = class com.jyami.jpalab.domain.Member$HibernateProxy$Xr6pfd5T

같은 프록시 객체를 가져온다. a == a 를 보장해주어야 하기 때문이다.

Member refMember = entityManager.getReference(Member.class, member1.getId()); 
System.out.println("refMember = " + refMember.getClass());

Member findMember = entityManager.find(Member.class, member1.getId());
System.out.println("findMember = " + findMember.getClass());

System.out.println("a == a" + (refMember == findMember));
refMember = class com.jyami.jpalab.domain.Member$HibernateProxy$HbLZp8PQ
Hibernate: [select 쿼리] 
findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$HbLZp8PQ

find() 에서도 proxy가 반환된다!!

proxy를 한번 조회되면 em.find()에서 proxy를 반환해버린다! == 비교를 완료하려고

"프록시든 아니든 개발에 문제가 없게 하는게 중요하다."

  • 영속성 컨텍스트의 도움을 받을 수 있는 준영속 상태일 때, 프록시를 초기화
Member refMember = entityManager.getReference(Member.class, member1.getId()); //영속성 상태
System.out.println("refMember = " + refMember.getClass());

entityManager.detach(refMember); //영속성 컨텍스트 관리 안한다.
entityManager.close();

assertThatThrownBy(() -> {
    refMember.getUsername();
}).isInstanceOf(org.hibernate.LazyInitializationException.class);

에러 : could not initialize proxy - no Session

영속성 컨텍스트의 도움을 받지 못해서 proxy에 연결되었던 객체에 대한 target이 없어지는 듯

그래서 transaction 설정과 proxy 설정을 같게 하려고 한다~

1-4. 프록시 확인

  • 프록시 인스턴스의 초기화 여부 확인 persistenceUnitUtil.isLoaded(Object entity)
    System.out.println("isLoaded = " + entityManagerFactory.getPersistenceUnitUtil().isLoaded(refMember));
  • 프록시 클래스 확인 방법 entity.getClass().getName() 출력 (..javasist.. or HibernateProxy..)
    System.out.println("refMember = " + refMember.getClass()); //클래스 확인
    System.out.println(refMember.getUsername()); //강제 호출
  • 프록시 강제 초기화
    System.out.println("refMember = " + refMember.getClass());
    Hibernate.initialize(refMember); // 강제 초기화
  • 참고: JPA 표준은 강제 초기화 없음
    강제 호출: member.getName()

2. 즉시로딩과 지연로딩

2-1. 지연로딩 LAZY를 사용해서 프록시로 조회

멤버 클래스만 DB에서 조회한다.

@ManyToOne(fetch = FetchType.LAZY)  ///fecth 설정을 해준다.
@JoinColumn(name = "TEAM_ID")
private Team team;
@Test
public void 지연로딩() {
    Member member = memberRepository.findById(1L).get();
    assertThat(member.getUsername()).isEqualTo("MemberDefault");
    System.out.println("m = " + member.getTeam().getClass()); 
    //getTeam()은 프록시 가져오는 것
}
Hibernate: select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_ 
from 
    member member0_ 
where 
    member0_.member_id=?
m = class com.jyami.jpalab.domain.Team$HibernateProxy$gs0vf0Qv

멤버만 나가는 걸 알 수 있다!
그리고 Team은 proxy 객체를 가져온다.

System.out.println("team.name = " + member.getTeam().getName());
select 
    team0_.member_id as member_i1_1_0_, 
    team0_.name as name2_1_0_ 
from 
    team team0_ 
where 
    team0_.member_id=?

그래서 위와 같이 영속성 컨텍스트 초기화를 하게 될 때 그때 쿼리가 나간다.

  • Member에서 Team을 가져올 때 Lazy로 설정해두었기 때문에,
    Team 객체 안에는 프록시 객체를 넣어둔다.
    실제 team을 사용하는 시점에 영속성 컨텍스트 초기화를 한다.
  • BM 상에서 Member조회시 Team을 같이 조회하지 않을 때 LAZY를 사용하면!

2-2. 즉시로딩 EAGER를 사용해서 함께 조회

@ManyToOne(fetch = FetchType.EAGER)  ///fecth 설정을 해준다.
@JoinColumn(name = "TEAM_ID")
private Team team;
Hibernate: insert into team (member_id, name) values (null, ?)
Hibernate: insert into member (member_id, team_id, username) values (null, ?, ?)
Hibernate: select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_, 
    team1_.member_id as member_i1_1_1_, 
    team1_.name as name2_1_1_ 
from 
    member member0_ 
left outer join 
    team team1_ on member0_.team_id=team1_.member_id 
where 
    member0_.member_id=?
m = class com.jyami.jpalab.domain.Team

즉시 로딩이기 때문에 Proxy를 가져올 필요가 없어서
getClass() 를 했을 때 실제 객체가 나온다!

proxy를 가져오지 않으니까 영속성 컨텍스트 초기화를 해줄 필요가 없다.

BM 상에서 Mebmer를 쓸때 항상 Team도 조회할 경우!

JPA 구현체는 가능하면 조인을 사용해서 SQL 한번에 함께 조회

2-3. 프록시와 즉시로딩 주의

  1. 가급적 지연 로딩만 사용(특히 실무에서)
    만약 관련 링크객체가 N개면 N개만큼 Join이 발생해서 나간다.
  2. 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
  3. 즉시로딩을 JPQL에서 N+1 문제를 일으킨다.
  4. @ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정 (X To One 시리즈)
  5. @OneToMany, @ManyToMany는 기본이 지연 로딩

2-3-1. JPQL N+1 문제 preview

  @Test
  public void JPQL의_N_플러스_1_문제() {
      List<Member> members = entityManager.createQuery("select m from Member m", Member.class)
          .getResultList();
  }
  Hibernate: select 
      member0_.member_id as member_i1_0_, 
      member0_.team_id as team_id3_0_, 
      member0_.username as username2_0_ 
  from 
      member member0_
  Hibernate: select 
      team0_.member_id as member_i1_1_0_,
      team0_.name as name2_1_0_ 
     from 
     team team0_ 
     where 
         team0_.member_id=?
  • 쿼리가 두번나간다!!
  • JPQL : 1번째 파라미터가 sql query로 그대로 읽힌다. 따라서 쿼리대로 Member를 가져온다. 근데 Team이 즉시로딩이 되어있음! 즉시로딩이라 무조껀 그안에 값이 들어가 있어야 하기 때문에 Team도 가져온다. 따라서 Team 쿼리를 또 따로 보낸다.
  • 쿼리가 N+1 나간다
    • 1 : 처음에 내보낸 쿼리 (N개의 Member 리턴)
    • N : EAGER 설정이 되어있어 참조 객체를 가져오기 위한 추가 쿼리 (N개의 Member 각각의 Team 값을 채우기 위해 각 Team을 찾기위해 N개의 쿼리가 나간다.)
  • 이걸 LAZY로 잡으면 그냥 Member만 가져오고, Team은 proxy 객체라서 쿼리가 1개만 나가게된다.
  • 해결 기본은 fetchJoin : runtime에 동적으로 내가 원하는애들만 선택해서 가져온다. application안에서도 member만 가져올 때 / member + team 가져올때가 구분되기 때문에
    List<Member> members = entityManager.createQuery("select m from Member m join fecth m.team", Member.class).getResultList();
    이 한방 쿼리에 모든게 들어가 있다.

2-4. 지연 로딩 활용

지금은 굉장히 이론적이고, 실무에서는 그냥 다 LAZY로 해야한다.

  • Member와 Team은 자주 함께 사용 : 즉시로딩
  • Member와 Order는 가끔 사용 : 지연로딩
  • Order와 Product는 자주 함께 사용 : 즉시로딩

3. 영속성 전이: CASCADE

  • 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속성 상태로 만들고 싶을 때
  • 예 : 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
  • 영속성 전이는 연관관계를 매핑하는 것과는 아무 관련이 없음
  • 엔티티를 영속화할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐
@Entity
@NoArgsConstructor
@Getter
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    //cascade 옵션 : Parent를 저장할 때 child도 같이 저장하고 싶다.
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<Child> childList = new ArrayList<>();

    @Builder
    public Parent(String name) {
        this.name = name;
    }
}
@Entity
@Getter
@NoArgsConstructor
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn
    private Parent parent;

    @Builder
    public Child(String name, Parent parent) {
        this.name = name;
        this.parent = parent;
        parent.getChildList().add(this); //양방향 위해 추가함!
    }
}

[테스트 코드]

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ParentTest {
    @Autowired
    ParentRepository parentRepository;

    @Autowired
    ChildRepository childRepository;

    @Autowired
    EntityManager entityManager;

    @Before
    public void setUp() throws Exception {
        Parent parent = Parent.builder()
                .name("parent")
                .build();

        Child child1 = Child.builder()
                .parent(parent)
                .name("child1")
                .build();

        Child child2 = Child.builder()
                .parent(parent)
                .name("child2")
                .build();

        parentRepository.save(parent);

        entityManager.clear(); //영속성 컨텍스트 제거
    }

    @Test
    public void Parent만_저장해도_Child_저장되는지_확인(){
        Parent parent = parentRepository.findById(1L).get();
        for(Child child: parent.getChildList()){
            assertThat(child.getName()).startsWith("child");
        }
    }
}
Hibernate: insert into parent (id, name) values (null, ?)
Hibernate: insert into child (id, name, parent_id) values (null, ?, ?)
Hibernate: insert into child (id, name, parent_id) values (null, ?, ?)
---
Hibernate: select parent0_.id as id1_2_0_, parent0_.name as name2_2_0_ from parent parent0_ where parent0_.id=?
Hibernate: select childlist0_.parent_id as parent_i3_0_0_, childlist0_.id as id1_0_0_, childlist0_.id as id1_0_1_, childlist0_.name as name2_0_1_, childlist0_.parent_id as parent_i3_0_1_ from child childlist0_ where childlist0_.parent_id=?

심플하게 Parent를 저장할 때, Parent안에 있는 객체인 Child도 같이 저장할 때

3-1. CASCADE의 종류

  • ALL : 모두 적용
  • PERSIST : 영속 - 저장할 때만 lifecycle을 맞출래
  • REMOVE : 삭제
  • MERGE : 병합
  • REFERESH : refresh
  • DETACH : detach

하나의 부모가 자식들을 관리할 때는 의미가 있다.
ex ) 게시판에 댓글, 첨부파일의 경로 등이 들어갈 때 : 의미 있음

그러나 여러 엔티티에서 관리한다면 쓰면 안된다.

소유자가 하나일 때는 써도 된다.

단일 엔티티에 완전히 종속적일 때 사용하자

Child와 Parent의 lifecycle이 완전히 비슷할 때 사용하자

4. 고아객체

  • 고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제 JPA는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이것을 고아 객체 제거라 한다. 이 기능을 사용해서 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제 된다.
  • orphanRemoval = true
    Parent parent1 = em.find(Parent.class, id);
    parent1.getChildren().remove(0);
    // 자식 엔티티를 컬렉션에서 제거
    DELETE FROM CHILD WHERE ID = ?
    연관관계가 끊어져버린 상태 > delete가 나간다.
    public class Parent{
        @OneToMany(mappedBy = "parent", orphanRemoval = true) // orphanRemoval 옵션 추가
        private List<Child> childList = new ArrayList<>();    
    }
  • 참조가 제거된 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능
  • 참조하는 곳이 하나일 때 사용해야함!!
  • 특정 엔티티가 개인 소유할 때 사용
  • @OneToOne, @OneToMany만 가능
  • 참고 : 개념적으로 부모를 제거하면 자식은 고아가된다.
    따라서 고아 객체 기능을 제거 기능을 활성화하면, 부모를 제거할 때 자식도 함께 제거된다.
    이것은 CascadeType.REMOVE 처럼 동작한다.

흠 근데 왜 난 안되지ㅠㅠ 물어봐야겠다.

5. 영속성 전이 + 고아 객체, 생명주기

public class Parent{
    @OneToMany(mappedBy = "parent", cascade = CascadeType=ALL, orphanRemoval = true)
    private List<Child> childList = new ArrayList<>();    
}
  • CasecadeType.ALL + orphanRemovel = true
  • 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거
  • 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다. 자식 repository가 필요 없어진다.
  • 도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용

This is a summary post written after taking Kim Young-han's Java ORM Standard JPA Programming - Basics course on Inflearn.

https://www.inflearn.com/course/ORM-JPA-Basic

 

Java ORM Standard JPA Programming - Basics - Inflearn

For those who are new to JPA or use JPA in practice but lack foundational theory — this course helps you build a solid understanding of JPA basics so that even beginners can confidently use JPA in real-world projects. Beginner Web Development Server Database Frameworks & Libraries Programming Languages Service Development Java JPA Spring Data JPA Online Course

www.inflearn.com

I've been using Spring Data JPA normally, but Kim Young-han actually teaches JPA itself.

Based on his lectures, I decided to write this post to test the course material with Spring Data JPA and document the concepts.



Proxy and Relationship Management

1. Proxy

When querying a Member, should we always fetch the Team together?

  • When fetching Member, also print Team together
    • It's good if JPA fetches Team when fetching Member.
  • When fetching Member, only fetch Member!
    • It's not good if JPA fetches Team when fetching Member!

1-1. Proxy Basics

  • em.find() : Retrieves the actual entity object through the DB
  • em.getReference() : Retrieves a fake (proxy) entity object that defers the database lookup

The query doesn't hit the DB, yet you can still retrieve the object.

@Test
public void 멤버와조회할때_팀도함께_조회() {
    Member findMember = entityManager.find(Member.class, 1L);
    System.out.println("findMember.id = " + findMember.getId());
    System.out.println("findMember.username = " + findMember.getUsername());
    }
select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_, 
    team1_.member_id as member_i1_1_1_, 
    team1_.name as name2_1_1_ 
from 
    member member0_ 
left outer join 
    team team1_ 
        on member0_.team_id=team1_.member_id 
where member0_.member_id=?

When querying Member, Team is automatically joined and fetched together.

@Test
public void 멤버만_조회() {
    Member findMember = entityManager.getReference(Member.class, 1L);
}

In this case, no select query is executed!!

@Test
public void 멤버만_조회() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("findMember.id = " + findMember.getId());
    System.out.println("findMember.username = " + findMember.getUsername());
}

In this case, the select query is executed!

At the point when getReference() is called, no query is sent to the DB.
The query is sent to the DB when the value is actually used (username).

System.out.println("findMember = " + findMember.getClass());
findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$injSwDL2

The name isn't Member! HibernateProxy: it's a forcibly created fake class — a proxy class

1-2. Proxy Characteristics

  • Created by inheriting the actual class
  • Looks the same as the actual class on the outside
  • From the user's perspective, you don't need to distinguish between the real object and the proxy object (in theory)
  • The proxy object holds a reference (target) to the actual object
  • When you call the proxy object, it delegates the call to the actual object's method
em.getReference(Member.class, 1L); //프록시객체 가져온다.

getName() > The Member target has no value > Requests the persistence context to fetch the actual value > The DB fetches that value and links the real object to the Proxy object. So it gets the name via target.getName().

Initialization request to the persistence context: when the proxy has no value, ask the DB for the real value.

1-3. Proxy Object Mechanism

  • The proxy object is initialized only once, on first use
@Test
public void 프록시_테스트() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("1st = " + findMember.getUsername());
        //1st에서는 query가 나간다.
    System.out.println("2nd = " + findMember.getUsername());
        //2nd에서는 query가 나가지 않는다.
}
  • When a proxy object is initialized, it doesn't turn into the actual entity — once initialized, you can access the actual entity through the proxy object
@Test
public void 프록시_테스트() {
    Member findMember = entityManager.getReference(Member.class, 1L);
    System.out.println("before findMember = " + findMember.getClass());
    System.out.println("findMember.username = " + findMember.getUsername());
    System.out.println("after findMember = " + findMember.getClass());
}
before findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$EYDMo7wU
Hibernate: [select query]
findMember.username = member1
after findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$EYDMo7wU
  • The proxy object inherits the original entity, so be careful with type checking (== comparison fails, use instanceof) => You never know if it'll come as a proxy or the original object type
@Test
public void 프록시_엔티티상속_테스트() {
    Member member1 = Member.builder()
        .username("member1")
        .build();
    memberRepository.save(member1);

    Member member2 = Member.builder()
        .username("member2")
        .build();
    memberRepository.save(member1);

    entityManager.clear();

    Member m1 = entityManager.find(Member.class, member1.getId());
    Member m2 = entityManager.getReference(Member.class, member2.getId());

    System.out.println("m1 == m2 : " + (m1.getClass() == m2.getClass()));   // false
    System.out.println("m1 instanceof : " + (m1 instanceof Member));        // true
    System.out.println("m2 instanceof : " + (m2 instanceof Member));        // true
}
  • If the entity being looked up already exists in the persistence context, calling em.getReference() returns the actual entity
@Test
public void 프록시_영속성_테스트() {
    Member member1 = Member.builder()
        .username("member1")
        .build();
    memberRepository.save(member1);

    entityManager.clear();

    Member m1 = entityManager.find(Member.class, member1.getId()); //영속성 상태
    System.out.println("m1 = " + m1.getClass());

    Member references = entityManager.getReference(Member.class, member1.getId());
    System.out.println("reference = " + references.getClass());
}
m1 = class com.jyami.jpalab.domain.Member
reference = class com.jyami.jpalab.domain.Member

If the member is already in the first-level cache, there's no point in fetching it as a proxy.

JPA guarantees identity within a single transaction.
If fetched from the same persistence context, it returns true.

System.out.println(m==reference) // must always return true: it fetches the real value, not a proxy

Member reference1 = entityManager.getReference(Member.class, member1.getId());
System.out.println("reference1 = " + reference1.getClass());

Member reference2 = entityManager.getReference(Member.class, member1.getId());
System.out.println("reference2 = " + reference2.getClass());

System.out.println("a == a" + (reference1 == reference2)); //true
reference1 = class com.jyami.jpalab.domain.Member$HibernateProxy$Xr6pfd5T
reference2 = class com.jyami.jpalab.domain.Member$HibernateProxy$Xr6pfd5T

It returns the same proxy object because it must guarantee a == a.

Member refMember = entityManager.getReference(Member.class, member1.getId()); 
System.out.println("refMember = " + refMember.getClass());

Member findMember = entityManager.find(Member.class, member1.getId());
System.out.println("findMember = " + findMember.getClass());

System.out.println("a == a" + (refMember == findMember));
refMember = class com.jyami.jpalab.domain.Member$HibernateProxy$HbLZp8PQ
Hibernate: [select 쿼리] 
findMember = class com.jyami.jpalab.domain.Member$HibernateProxy$HbLZp8PQ

Even find() returns a proxy!!

Once a proxy has been retrieved, em.find() returns the proxy too! This is to satisfy the == comparison.

"What matters is that it works correctly regardless of whether it's a proxy or not."

  • Initializing a proxy when in a detached state where the persistence context can no longer help
Member refMember = entityManager.getReference(Member.class, member1.getId()); //영속성 상태
System.out.println("refMember = " + refMember.getClass());

entityManager.detach(refMember); //영속성 컨텍스트 관리 안한다.
entityManager.close();

assertThatThrownBy(() -> {
    refMember.getUsername();
}).isInstanceOf(org.hibernate.LazyInitializationException.class);

Error: could not initialize proxy - no Session

Since the persistence context can no longer help, it seems like the target linked to the proxy object is lost.

That's why you want to align the transaction scope with the proxy scope~

1-4. Proxy Inspection

  • Check whether a proxy instance has been initialized: persistenceUnitUtil.isLoaded(Object entity)
    System.out.println("isLoaded = " + entityManagerFactory.getPersistenceUnitUtil().isLoaded(refMember));
  • How to check the proxy class: print entity.getClass().getName() (..javasist.. or HibernateProxy..)
    System.out.println("refMember = " + refMember.getClass()); //클래스 확인
    System.out.println(refMember.getUsername()); //강제 호출
  • Force initialize a proxy
    System.out.println("refMember = " + refMember.getClass());
    Hibernate.initialize(refMember); // 강제 초기화
  • Note: The JPA standard does not have forced initialization
    Forced invocation: member.getName()

2. Eager Loading and Lazy Loading

2-1. Using Lazy Loading (LAZY) to Fetch via Proxy

Only the Member class is fetched from the DB.

@ManyToOne(fetch = FetchType.LAZY)  ///fecth 설정을 해준다.
@JoinColumn(name = "TEAM_ID")
private Team team;
@Test
public void 지연로딩() {
    Member member = memberRepository.findById(1L).get();
    assertThat(member.getUsername()).isEqualTo("MemberDefault");
    System.out.println("m = " + member.getTeam().getClass()); 
    //getTeam()은 프록시 가져오는 것
}
Hibernate: select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_ 
from 
    member member0_ 
where 
    member0_.member_id=?
m = class com.jyami.jpalab.domain.Team$HibernateProxy$gs0vf0Qv

You can see that only Member is queried!
And Team returns a proxy object.

System.out.println("team.name = " + member.getTeam().getName());
select 
    team0_.member_id as member_i1_1_0_, 
    team0_.name as name2_1_0_ 
from 
    team team0_ 
where 
    team0_.member_id=?

So the query is only fired when the persistence context initialization happens, like above.

  • Since fetching Team from Member is set to Lazy,
    a proxy object is placed inside the Team object.
    The persistence context initialization happens at the point when Team is actually used.
  • When you don't need to fetch Team together when querying Member in your business model, use LAZY!

2-2. Using Eager Loading (EAGER) to Fetch Together

@ManyToOne(fetch = FetchType.EAGER)  ///fecth 설정을 해준다.
@JoinColumn(name = "TEAM_ID")
private Team team;
Hibernate: insert into team (member_id, name) values (null, ?)
Hibernate: insert into member (member_id, team_id, username) values (null, ?, ?)
Hibernate: select 
    member0_.member_id as member_i1_0_0_, 
    member0_.team_id as team_id3_0_0_, 
    member0_.username as username2_0_0_, 
    team1_.member_id as member_i1_1_1_, 
    team1_.name as name2_1_1_ 
from 
    member member0_ 
left outer join 
    team team1_ on member0_.team_id=team1_.member_id 
where 
    member0_.member_id=?
m = class com.jyami.jpalab.domain.Team

Since it's eager loading, there's no need to fetch a Proxy, so
when you call getClass(), the actual object is returned!

Since it doesn't fetch a proxy, there's no need for persistence context initialization.

Use this when you always need to fetch Team whenever you use Member in your business model!

The JPA implementation tries to use joins to fetch everything in a single SQL query

2-3. Cautions with Proxy and Eager Loading

  1. Use lazy loading as much as possible (especially in production)
    If there are N related linked objects, N joins will be executed.
  2. Applying eager loading can cause unexpected SQL queries
  3. Eager loading causes the N+1 problem in JPQL
  4. @ManyToOne and @OneToOne default to eager loading -> Set them to LAZY (the X-To-One series)
  5. @OneToMany and @ManyToMany default to lazy loading

2-3-1. JPQL N+1 Problem Preview

  @Test
  public void JPQL의_N_플러스_1_문제() {
      List<Member> members = entityManager.createQuery("select m from Member m", Member.class)
          .getResultList();
  }
  Hibernate: select 
      member0_.member_id as member_i1_0_, 
      member0_.team_id as team_id3_0_, 
      member0_.username as username2_0_ 
  from 
      member member0_
  Hibernate: select 
      team0_.member_id as member_i1_1_0_,
      team0_.name as name2_1_0_ 
     from 
     team team0_ 
     where 
         team0_.member_id=?
  • Two queries are fired!!
  • JPQL: The first parameter is read directly as an SQL query. So it fetches Member as the query specifies. But Team is set to eager loading! Since it's eager, the values must always be populated, so it fetches Team too. Therefore, it sends a separate query for Team.
  • N+1 queries are fired
    • 1: The initial query (returns N Members)
    • N: Additional queries to fetch referenced objects due to EAGER setting (N queries are fired to fill in each Team value for each of the N Members)
  • If you set this to LAZY, it just fetches Member, and since Team is a proxy object, only 1 query is fired.
  • The basic solution is fetch join: it dynamically selects and fetches only what you want at runtime. Since within the application there are times when you only need Member vs. times when you need Member + Team:
    List<Member> members = entityManager.createQuery("select m from Member m join fecth m.team", Member.class).getResultList();
    Everything is included in this single query.

2-4. Lazy Loading in Practice

This is all very theoretical for now — in practice, you should just use LAZY for everything.

  • Member and Team are frequently used together: Eager loading
  • Member and Order are occasionally used together: Lazy loading
  • Order and Product are frequently used together: Eager loading

3. Cascade (Persistence Propagation)

  • When making a specific entity persistent, you may want to make its associated entities persistent as well
  • Example: Saving child entities together when saving a parent entity
  • Cascade has nothing to do with mapping relationships
  • It simply provides the convenience of persisting associated entities together when persisting an entity
@Entity
@NoArgsConstructor
@Getter
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    //cascade 옵션 : Parent를 저장할 때 child도 같이 저장하고 싶다.
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
    private List<Child> childList = new ArrayList<>();

    @Builder
    public Parent(String name) {
        this.name = name;
    }
}
@Entity
@Getter
@NoArgsConstructor
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn
    private Parent parent;

    @Builder
    public Child(String name, Parent parent) {
        this.name = name;
        this.parent = parent;
        parent.getChildList().add(this); //양방향 위해 추가함!
    }
}

[Test Code]

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class ParentTest {
    @Autowired
    ParentRepository parentRepository;

    @Autowired
    ChildRepository childRepository;

    @Autowired
    EntityManager entityManager;

    @Before
    public void setUp() throws Exception {
        Parent parent = Parent.builder()
                .name("parent")
                .build();

        Child child1 = Child.builder()
                .parent(parent)
                .name("child1")
                .build();

        Child child2 = Child.builder()
                .parent(parent)
                .name("child2")
                .build();

        parentRepository.save(parent);

        entityManager.clear(); //영속성 컨텍스트 제거
    }

    @Test
    public void Parent만_저장해도_Child_저장되는지_확인(){
        Parent parent = parentRepository.findById(1L).get();
        for(Child child: parent.getChildList()){
            assertThat(child.getName()).startsWith("child");
        }
    }
}
Hibernate: insert into parent (id, name) values (null, ?)
Hibernate: insert into child (id, name, parent_id) values (null, ?, ?)
Hibernate: insert into child (id, name, parent_id) values (null, ?, ?)
---
Hibernate: select parent0_.id as id1_2_0_, parent0_.name as name2_2_0_ from parent parent0_ where parent0_.id=?
Hibernate: select childlist0_.parent_id as parent_i3_0_0_, childlist0_.id as id1_0_0_, childlist0_.id as id1_0_1_, childlist0_.name as name2_0_1_, childlist0_.parent_id as parent_i3_0_1_ from child childlist0_ where childlist0_.parent_id=?

Simply put, when saving a Parent, you also want to save the Child objects inside the Parent.

3-1. Types of CASCADE

  • ALL: Apply all
  • PERSIST: Persistence — only sync the lifecycle when saving
  • REMOVE: Delete
  • MERGE: Merge
  • REFERESH: Refresh
  • DETACH: Detach

It's meaningful when a single parent manages its children.
e.g.) When a board post has comments, attachment file paths, etc.: meaningful

However, you should NOT use it when multiple entities manage the same thing.

It's fine to use when there's a single owner.

Use it when something is completely dependent on a single entity.

Use it when the lifecycles of Child and Parent are completely aligned.

4. Orphan Objects

  • Orphan removal: Automatically deletes child entities whose relationship with the parent entity is severed. JPA provides a feature that automatically deletes child entities that are disconnected from their parent entity — this is called orphan removal. Using this feature, if you simply remove the reference to a child entity from the parent entity's collection, the child entity is automatically deleted.
  • orphanRemoval = true
    Parent parent1 = em.find(Parent.class, id);
    parent1.getChildren().remove(0);
    // 자식 엔티티를 컬렉션에서 제거
    DELETE FROM CHILD WHERE ID = ?
    The relationship is severed > a DELETE is executed.
    public class Parent{
        @OneToMany(mappedBy = "parent", orphanRemoval = true) // orphanRemoval 옵션 추가
        private List<Child> childList = new ArrayList<>();    
    }
  • It treats entities whose references have been removed as orphan objects that are not referenced anywhere else, and deletes them
  • Should only be used when there is exactly one place referencing it!!
  • Use when a specific entity has sole ownership
  • Only available for @OneToOne and @OneToMany
  • Note: Conceptually, when a parent is removed, the children become orphans.
    Therefore, when orphan removal is enabled, removing the parent also removes the children.
    This behaves like CascadeType.REMOVE.

Hmm, but why isn't it working for me 😭 I should ask about this.

5. Cascade + Orphan Removal, Lifecycle

public class Parent{
    @OneToMany(mappedBy = "parent", cascade = CascadeType=ALL, orphanRemoval = true)
    private List<Child> childList = new ArrayList<>();    
}
  • CascadeType.ALL + orphanRemoval = true
  • Entities that manage their own lifecycle use em.persist() to persist and em.remove() to remove
  • When both options are enabled, you can manage the child's lifecycle through the parent entity. The child repository becomes unnecessary.
  • Useful when implementing the Aggregate Root concept from Domain-Driven Design (DDD)

댓글

Comments