전역 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.
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
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
Google account or Cloud ID user: test@gamil.com, test@example.com
Service account: test@project_id.iam.gserviceaccount.com
Google group: test@googlegroups.com
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
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에서 계속 담당해서 있다 보니 그럴 기회가 없었네요ㅠㅠ
그리고 세션을 듣다보니, 한 번쯤은 저도 발표자로 나서고 싶더라고요! 꼭 다음에는!!!ㅎㅎ
3-1. 유경수 - 웹초보도 할 수 있는 Web VR/AR with aframe
작년에 이화여대 게임동아리 King에서 cardboard VR 방탈출 게임을 개발했던 기억 때문에 열심히 들었던 세션이었는데, 와 진짜 재밌었습니다!! 유니티로 VR요소 하나하나 스크립팅하고, 위치에 재질에 이벤트 클릭 raycast 하나하나 개발해서 결과물을 만들었을 때가 생각났네요. 그런데 웹이라니! 그것도 HTML과 비슷한 방식으로 만들어진다니!! 웹을 좋아하는 저에게 딱이었습니다.
만약 이 세션을 먼저 알았으면 졸프로 Web VR/AR을 했을지도 몰라요...ㅠㅠ
여느때와 같이 세션 필기 노트입니다! 그런데 오늘은 세션 정리도 해보려고 해요 궁금한 분들은 클릭!!!
보통은 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가 있어서 일정 수익을 같이 얻을 수 있습니다!
크으 후원사 부스의 스티커부터 짱짱한 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 2019finally came to an end!!!!
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!!!
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.
"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!
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...
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에서 제공하는 여러 프로덕트들을 간략하게나마 설명을 들을 수 있어서 좋았습니니다.
세션에 대한 정보, 그리고 쇼케이스나 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를 기업에 도입할 때 도움을 줄 수 있도록 각종 참가자들의 명함 이벤트나, 설문을 진행하는 모습을 볼 수 있었는데요. 여러 부스를 다니면서 설문을 진행하면 그 부스와 관련된 기념품이나, 경품 응모를 진행할 수 있었습니다.
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.
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.
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
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.
DevFest Seoul 2019 Staff 후기 | DevFest Seoul 2019 Staff Review
쟈 미
728x90
DevFest Campus Korea 2019 준비로 교수님과 면담하고 다같이 행아웃 회의하고 그랬는데 정작 제가 DevFest를 안가봐서 이번에 DevFest Seoul 스탭으로 지원을 하게되었습니다! 사실 너무 속셈이 보이는 지원서였어서ㅋㅋ 더 적합한 분들을 선별하느라 떨어질 수도 있겠다 싶었는데 합격 메일이 와서 열심히 즐기다 왔습니다!
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
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!!!
평소에 Spring Data JPA 를 썼는데, 김영한님은 JPA 자체를 강의하시더라구요.
김영한님 강의 바탕으로 Spring Data JPA로 강의 소스를 테스트해보고 개념을 기록하기 위해 포스팅을 하게되었습니다.
고급 매핑
1. 상속관계 매핑
관계형 데이터베이스는 상속 관계X
슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사
상속관계 매핑: 객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 매핑
슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법
각각 테이블로 변환 -> 조인 전략
통합 테이블로 변환 -> 단일 테이블 전략
서브타입 테이블로 변환 -> 구현 클래스마다 테이블 전략
테이블은 여러개의 모델링이 나오지만, 객체는 상속관계라는 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("엔플라잉");
}
}
@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{ ... }
매핑 정보만 받는 슈퍼 클래스로 하고싶다면
extends 로 클래스 설정하기
@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.
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:
Convert to separate tables -> Joined strategy
Convert to a single table -> Single table strategy
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("엔플라잉");
}
}
@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:
Set up the class with extends
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{...}
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);
}
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 사용) => 프록시로 넘어올지, 원래 객체 타입으로 넘어올지 모른다
프록시 클래스 확인 방법 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
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. 프록시와 즉시로딩 주의
가급적 지연 로딩만 사용(특히 실무에서) 만약 관련 링크객체가 N개면 N개만큼 Join이 발생해서 나간다.
즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
즉시로딩을 JPQL에서 N+1 문제를 일으킨다.
@ManyToOne, @OneToOne은 기본이 즉시로딩 -> LAZY로 설정 (X To One 시리즈)
@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개의 쿼리가 나간다.)
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는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이것을 고아 객체 제거라 한다. 이 기능을 사용해서 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제 된다.
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);
}
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
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
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.
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
Use lazy loading as much as possible (especially in production) If there are N related linked objects, N joins will be executed.
Applying eager loading can cause unexpected SQL queries
Eager loading causes the N+1 problem in JPQL
@ManyToOne and @OneToOne default to eager loading -> Set them to LAZY (the X-To-One series)
@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); //양방향 위해 추가함!
}
}
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.
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