Skip to content
Beside the Wheel
Search
Cancel
GitHub
LinkedIn
Select theme
Dark
Light
Auto
글
(57)
공부
(4)
코드 까보기, 오픈소스 기여해보기
데브옵스(네트워크) 스터디 후기
eBPF로 서버 성능 Profiling하는 법: Pyroscope의 구현 살펴보기
Downtime 없는 Spot Instance 클러스터 구축 과정
독후감
(33)
과학
(1)
니콜라 테슬라 평전
사회
(2)
능력주의와 불평등
그의 운명에 대한 아주 개인적인 생각
산문
(3)
보통의 존재
새는 날아가면서 뒤돌아보지 않는다.
시지프 신화 – 부조리에 관한 시론
소설
(11)
수레바퀴 아래서
멋진 신세계
데미안
말테의 수기
구토
인간실격
젊은 베르테르의 슬픔
노르웨이의 숲
삼국지
황야의 이리
고래
인문
(5)
지성적 회심
담론
효율성
미쳤다는 것은 정체성이 될 수 있을까?
영향에 대한 불안
자기계발
(5)
홀로 성장하는 시대는 끝났다
C의 유전자
네 명의 완벽주의자
세상에서 가장 긴 행복 탐구 보고서
학습하는 조직
전공
(3)
IT 엔지니어를 위한 네트워크 입문
코드로 인프라 관리하기 2판
데브옵스 엔지니어를 위한 실전 관찰가능성 엔지니어링
철학
(3)
지극히 인간적인 삶에 대하여
아리스토텔레스 수사학
사마의 평전
발표
(4)
Git hook으로 Repository README에 파일트리 넣기
2023 DSM 컨퍼런스 - 좋은 프로젝트에 대한 고찰
DSM DevOps 분야 설명회
Xquare 관련 컨테이너 기술 설명회
생각들
(7)
2023년에 쓴 일기장
변화에 대하여
비구조적인 회고에 대하여
의식의 영역에 대하여
국카스텐
짧은 생각들
소유냐 존재냐
회고
(9)
2022.03-04 대덕소마고 입학소감/다짐
2022.05-08 프로젝트와 인간관계
2022.09-2023.02 불안과 판단
2023.03-07 DMS 리더 회고
2023.08-11 나는 누구인가?
2023.12 더 많은 걸 배우기 위한 경험
2024.03-04 3학년으로서 근황
2024.05-07 나름 알찬 3학년
2024.08-12 첫 회사
TIL
(810)
DevOps
(272)
AWS
(77)
Analytics
(5)
Athena
EMR
Glue
Kinesis
Lake Formation
Computing
(15)
Auto Scaling
(5)
ASG Lifecycle Hook
Auto Scaling
Auto Scaling termination policies
Scaling cooldowns
State Change Event
EC2
(6)
EC2
EC2 Fleet
Elastic Fabric Adapter
Instance Store
RI와 Saving plan
Spot Instance
ECS
Elastic Beanstalk
Fargate
Lambda
Database
(6)
Aurora
DynamoDB
EFS
RDS
RDS proxy
Redshift
Management and governance
(4)
CloudFormation
CloudTrail
CloudWatch
LogGroup
Netwoking
(20)
elb
(3)
Application LoadBalancer components
Connection Draining
ELB
security
(3)
NACLs
Security Groups
WAF
Bastion Host
CloudFront
Direct Connect Gateway
EC2 Instance Connect Endpoint
ENI
Global Accelerator
NAT gateway & NAT instance
Route53
Transit Gateway
VPC
VPC endpoint
VPC Mapping Service
VPN
VPN Options
Security
(9)
AWS Managed Microsoft AD
Cognito
Conformance Packs & Security Hub
IAM
KMS
KMS Datakey
MalformedPolicyDocument
Microsoft Active Directory
WAF & Firewall Manager & Shield Advanced
Storage
(11)
EBS
(3)
EBS
EBS gp2 vs gp3
EBS vs Instance Store
AppSync
DayaSync
EFS
FSx
S3
S3 Glacier Vault Lock
Snow Famliy
Storage Gateway
API Gateway
AWS cloud computing
AWS Organization
Region과 Zone
SAA 오답노트
SAA 요약
Well Architected
Container
(22)
CNI
(3)
Calico
CNI
Install Calico
Docker
(15)
Docker Image Layer
dockersock 권한에러
DockerSwarm
exec user process caused exec format error
Overlay Network
Private registry 구축
Prune
README
가상화와 컨테이너
도커 네트워크
도커 네트워크 명령어
도커 명령어
도커 스토리지
도커 아키텍처
도커 안에서 도커 사용하기
cAdvisor
Container Orchestration
ContainerRuntime
Docker와 PID1
DR
(2)
DR strategies
Fail over와 서버 이중화
IaC
(12)
Terraform
(7)
aws 서버 네트워크 구축
Terraform
Terraform import와 Terraforming
Terraform taint
Terraform with AWS
Terraform 키워드
Terratest
Ansible
Cobbler
Configuration Drift
Phoenix Server
Understanding Ansible, Terraform, Puppet, Chef, and Salt
Kubernetes
(102)
EKS
(13)
Add IAM to RBAC
Amazon VPC CNI
AWS Load Balancer Controller
EBS CSI driver
EKS ALB
EKS Control Plane
EKS kubecofig
EKS Network BestPractice
EKS Spot Instances with Karpenter
EKS 인증과정
IP addresse prefix
NLB IP mode
Node not Ready
Network
(11)
DNS
(4)
CoreDNS
DNS in k8s
External DNS
ServiceDNS
Debugging DNS Resolution
eBPF
HTTPProxy
IPVS
NetworkPolicy
Network Troubleshooting
Node and Pod Network Layout
Service Mesh
(9)
istio
(9)
Dry run
gateway log debug 하는 법
Istio Arcitecture
Istio authorization
Istio Configuration Profiles
Istioctl
Istio RBAC
Resource Annotations & Labels
ServiceEntry
tools
(19)
ArgoCD
(5)
ApplicationSets
Apps of Apps
ArgoCD 설치
Config Management Plugins
Health Check
helm
(3)
Chart Development Tips
Helm
Values Files
Karpenter
(2)
Karpenter
Karpenter best practices
Kyverno
(2)
Kyverno
Usecases
GoCD
Install Cilium
K8s Metric API
MetalLB
node shell
Node Termination Handler
OPA Gatekeeper
개념
(31)
Node Scheduling
(3)
Assigning Pods to Nodes
cordon, drain
Taints and Tolerations
object
(15)
Annotation
CRD
Deployments
Deployment Status
Deployment Strategy
Events
ingress
Labels and Selectors
Pod
Pod Readiness and Probes
Pod 생성과정
PV & PVC
RollingUpdate
Service와 port
StatefulSets
Volume
(2)
attachdetach controller
CSIDriver
CNI Specification
Disruption Budget
Endpoints
etcd
HPA와 VPA
K8s의 도커런타임 사용중단
Kubeproxy
NodePort와 ServicePort와 targetPort
Workloads
가상 IP와 서비스 프록시
사이드카 패턴
실습
(15)
Auth
(5)
Authenticating
k8s 클러스터 root CA를 통한 사용자 인증
OIDC Authentication with Dex
Security Context for a Pod or Container
Token Webhook with Guard
10 most common mistakes using kubernetes
Cert manager
End user RBAC
K8s를 위한 SpringBoot 개발
kubectl context
minukube 시작하기
NetworkPolicy Cilium example
Pulling images from ECR on Kubernetes
SpringBoot 서비스를 위한 Kubernetes 설정
환경변수 설정
K8s Architecture
Kubernetes
Kubernetes Overview Diagrams
MetalLB
Monitoring
(24)
datadog
(5)
datadog
DatadogAnomalydetectionAlgorithms
datadog APM 기능 사용하기
datadog 아키텍처
helmChart로 Agent 설치
elk
(4)
Elastic Search
ElasticSearch 검색 명령어
ELK Stack
Logstash
grafana
(2)
Granafa agent
Pyroscope Distributor and Ingester
loki
(1)
Loki Canary
prometheus
(5)
kiali with prometheus
prometheus
prometheus agent mode
prometheus glossary
prometheus storage
thanos
(2)
Rule
Thanos
DeepFlow
DeepFlow 논문 요약
Grok exporter
SLO, SLI, SLA
telemetry
Proxy
(15)
envoy
(3)
Envoy
LDS
xDS configuration
nginx
(9)
location block
nginx certbot
nginx docker
NGINX Ingress Basic Auth
nginx 명령어
nginx 설정
sites available
SSL passthrough
리버스 프록시
Contour
Contour CRD 설치
Reverse Proxy vs. Ingress Controller vs. API Gateway
tools
(14)
Clium
CUE
Dex
Dex K8s Authenticator
GPG
jenkins
Keycloak
minio
Mortar
OpenHistorian
openssl로 pemKey 만들고 접속하기
Packer
tar
Vault
CI/CD파이프라인
Cloud Agnostic Design
Platform Engineering
데브옵스
Network
(59)
error
(1)
Context deadline exceeded
L1 network access layer
(8)
CRC
Ethernet과 TokenRing
L2 스위치와 STP
MTU
NIC
데이터링크 제어(DLC)
매체 접근 제어(MAC)
아날로그, 디지털 신호와 전송
L2 internet layer
(15)
라우터
(4)
ECMP
라우터
라우팅 알고리즘
멀티캐스트 라우팅
CIDR
ICMP
IP
IPAM
IPSec
IP 데이터그램과 단편화
NAT
PacketTracer 네트워크 구성
secondary IP
서브넷
정보기기운용기능사 실기
L3 transport layer
(6)
4계층 장비
SO_REUSEADDR
SSH config
Sticky Session과 Session Clustering
TCP와 UDP
전송계층 프로토콜
L4 appplication layer
(13)
http
(3)
HTTP
HTTP Options
keep alive
tls
(3)
SNI
TLS
TLS 인증서 발급 절차를 이해해보자
ACME
CDN
DHCP
DNS 레코드유형
FTP Active, Passive mode
java로 간단한 socket 프로그램만들기
SMTP의 보안 시스템
VPN
(3)
firezone
VPN
Wireguard와 Firezone
개념
(5)
가상화 기술
네트워크
네트워크 보안
네트워크 침해
이중화
bandwidth
Exponential Backoff And Jitter
OSI 7Layer
Switch
vTAP
WebRTC
로드밸런서
브라우저에 url을 입력하면 어떤일이 생길까?
OS
(127)
Embedded
(6)
Audio Codec
Cramfs
I2C
시리얼 통신
임베디드 리눅스 프로그래밍 수업 정리
임베디드 시스템
linux
(102)
Authority
(3)
chattr과 chown
chmod
사용자 관리
BPF
(12)
BCC
BPF
BPF communicates with userspace
BPF ring buffer
BPF System Call
BPF 프로그램 타입
BTF
libbpf
libbpf helper 함수
XDP
메모리 로딩
서브프로그램
Disk & Dir
(9)
Linux 디렉토리 구조
LVM
od
RAID
Symbolic Link
백업
파일 관리 명령어
파일 시스템
파일 종류
ELF
(2)
ELF
SEC()
ETC
(10)
linux 표준 에러 코드
mail
man
Perf
PMU
Redirection와 FD
Runlevel
set
X window
명령어들
Kernel
(19)
Block I/O
CPU Load Average
entropy
vmlinux
동기화와 lock
디버깅
메모리 관리와 캐시
모듈과 장치 관리
스케줄러 소스 분석
시스템 콜과 인터럽트
유저모드와 커널모드
이식성
커널 개념
커널 모듈
타이머
파일시스템
프로세스 관리
프로세스 스케줄러
프로세스 주소 공간
Memory
(2)
Swap메모리
VSS, RSS, PSS, USS
Network
(17)
DNS
(2)
bind로 DNS 서버 정의하기
DNS 서버
주요명령어
(4)
arp
ifconfig
ping과 netstat
route로 라우팅 테이블 확인하기
DERP
Domain-based Split Tunnels
ip_forward와 rp_filter
IP masquerading
iptables
iptables 방화벽 설정
namespace와 cgroup
Netfilter
network namespaces
ufw
Virtual Networking Interface
Process
(8)
cgroup
Deamon process
httpd
pipe
signal
top
프로세스 관리
환경변수와 프로세스
Shell
(3)
bash_profile과 bashrc
shell
zshrc
System call
(10)
epoll
file 관련 systemcall
fork와 exec
ioctl
mmap
perf event
rlimit
thread 관련 systemcall
wait과 waitpid
리눅스 시스템 프로그래밍 프로젝트
kprobe와 kretprobe
Linux Package
Linux 배포판
Linux 부팅 과정
Linux 특징 및 관련용어
Stack trace와 kallsyms
쉘 단축키
memory
(2)
Memory Mapping
페이지 교체 알고리즘
process
(6)
TAS
교착상태와 스케줄링
생산자 소비자 문제
임계영역과 상호배제
프로세스의 개념
프로세스의 관리
VM
(2)
VMware Fusion NAT config
VMware Fusion Ubuntu 디스크 용량 늘리기
window
(1)
Active Directory Domain Services
보안
(1)
엑세스 제어
CPU 아키텍처
c언어 컴파일과정
디스크 시스템
반도체 8대 공정
운영체제 유형
유저, 커널레벨 스레드
파일 시스템
개발
(55)
AI
(18)
Vector Search
(3)
Distance Metrics
Index-realated chians
Vector Search
실습
(3)
CNN, RNN
MNIST 숫자 판별
배, 자동차, 비행기 분류하기
자연어 처리
(1)
BERT
CNN
Document Question Answering
DropOut
Keras
Optimizer
RAG
RNN
선형회귀
임베딩
퍼셉트론
활성화함수
App
(2)
React Native
(2)
New Architecture
React Native
SEO
(2)
sitemap
Web Vitals
Tools
(20)
Git
(9)
Flow
(2)
GitFlow
GithubFlow
hooks
(3)
githook을 위한 perl command
GitHub hooks
파일트리 자동생성
GitLab
git reflog
Selfhosted Runner
자동커밋
vi
(3)
vim
vim 단축키
vi 단축키
Airflow
Firefox 상단 탭 없애는 법
GTM
Intellij Profiling tools
Makefile
mermaid 문법
Spark
Tridactyl
암호화
(5)
AES&IV
Certificate formats
Cipher
DB 암호화
Keytool
테스팅
(1)
테스팅 용어
authn과 authz
FineGrained와 CoarseGrained
Nightly build
turborepo
소프트웨어 공학
압축 알고리즘
자막 파일 포맷
데이터베이스
(60)
DB설계
(8)
DBMS와 RDBMS
데이터모델링
무결성 제약조건
분산데이터베이스
스키마
정규화와 반정규화
테이블분할
트랜잭션 ACID와 격리수준
MQ
(4)
Docker로 Kafka 실행
RabbitMQ
Spring with Kafka
메시지큐
NoSQL
(16)
MongoDB
(8)
Atlas Search
BinData
MongoDB
MongoDB Aggregation
MongoDB Document로 POJO 상속받기
MongoDB 스키마설계 고려사항
MongoDB 유저관리
MongoDB 쿼리
PostgreSQL
(2)
PostgreSQL
PostgreSQL명령어
redis
(2)
Redis
Spring Redis Phantomkey
Cassandra
Memcached VS Redis
NoSQL 데이터유형
NoSQL에는 ACID가 없다고?
SQL 쿼리
(23)
최적화
(3)
DB 커넥션 풀
옵티마이저
조인 수행원리
쿼리종류
(5)
DCL
DDL
DML
Procedural/Nonprocedural DML
TCL
Alias
FK옵션
GROUP BY와 HAVING절
GROUPING SETS와 GROUPING
INNER JOIN과 OUTER JOIN
ON절
ORDER BY절
ROLLUP과 CUBE
SELECT쿼리 실행순서
계층형 질의
서브쿼리
윈도우 함수
제약조건
집계함수
집합연산자
Change Date Capture
ClickHouse
Column, Row기반 DB
Data Lake와 Warehouse
MySQL Replication
OLAP
pgbouncer
Postgresql Transaction Wraparound
Two Phase commit
서버
(72)
netty
(5)
HashedWheelTimer
netty server 예제
netty 메시지 전송 흐름
netty의 thread 모델
webFlux와 netty
node.js
(3)
module.exports와 exports
puppeteer
v8과 libuv
Spring
(62)
AOP
(8)
트랜잭션
(3)
TransactionAttributeSource
트랜잭션
트랜잭션 전파
AdviceAnnotation
Pointcut
ProxyFactoryBean
Spring AOP
Spring에서 aspectj weaving사용하기
Event
(2)
ApplicationEventPublisher
@TransactionalEventListener
JPA
(27)
JPQL
(2)
FetchJoin
경로표현식
QuerydslJpa
(8)
fetchResults가 deprecated된 이유
Paging
Projection
QuerydslJpa와 QClass
QuerydslPredicateExecutor
기본문법
동적쿼리
벌크연산
캐싱
(3)
1차캐시
2차캐시
영속성 컨텍스트
Cascade
@GeneratedValue 코드보기
GenerateValue Column에 값을 넣는다면
Hibernate dialect
Hibernate 쿼리실행순서
Id로 연관관계 객체 저장
JDBC Object Mapping Fundamentalsentity
JPA
N+1 문제
OrphanRemoval
Persistable
ReadOnlyQuery 최적화
벌크연산
트랜잭션 전파 설정
SpringSecurity
(2)
CORS
CSRF
Validation
(2)
@GroupSequence
@Valid와 @Validated
Web MVC
(2)
Request 처리과정
SpringServletContainerInitializer
WebFlux
(7)
R2DBC
(2)
R2DBC
R2DBC 사용
@Controller
RouterFunctions
WebClient
WebFilter
WebFlux
기본원리
(9)
@Autowired 빈 주입 스캔 원리
@ComponentScan
Ioc와 DI
Programmatic과 Declarative
Reflection과 직렬화
등록된 빈 목록 출력하기
빈
선점 잠금과 비선점 잠금
싱글톤
AOT
@Cacheable
Spring 6.0과 Spring Boot 3.0
WAS
(2)
tomcat 구성요소
웹서버와 WAS
아키텍처 및 방법론
(46)
API 아키텍처
(4)
GraphQL
REST
RPC
SOAP
DDD
(5)
DDD
DDD의 아키텍처
도메인영역
이벤트 스토밍
컨트랙트
MSA
(8)
MSA의 장단점
메시지 브로커
사가 패턴
사가 편성
시맨틱 버저닝
통신
트랜잭션 격리
트랜잭션 로그 테일링 패턴
객체지향
(2)
SOLID
응집도와 결합도
디자인패턴
(25)
1. 생성패턴
(5)
빌더 패턴
싱글톤 패턴
추상팩토리 패턴
팩토리메소드 패턴
프로토타입 패턴
2. 구조패턴
(7)
데코레이터 패턴
브릿지 패턴
어댑터 패턴
컴포짓 패턴
퍼사드 패턴
프록시 패턴
플라이웨이트 패턴
3. 행위패턴
(11)
메멘토 패턴
방문자 패턴
상태 패턴
옵저버 패턴
이터레이터 패턴
인터프리터 패턴
전략 패턴
중재자 패턴
책임연쇄 패턴
커맨드 패턴
템플릿메소드 패턴
디자인패턴
위임 패턴(Delegate Pattern)
CQRS
HexagonalArchitecture
알고리즘
(15)
자료구조
(3)
LSM Tree
Trie
세그먼트트리
2020 중등부 정올 2차
N Queen
Range GCD
가장 가까운 두 점
담금질 기법
볼록 껍질과 회전하는 캘리퍼스
오일러 경로 테크닉
왜판원순회
외판원순회
직사각형 스위핑
최소외접원
코드포스 문제모음
언어
(80)
Go
(11)
BSON
Command line argument, flag
defer와 panic
GC
gomod와 gosum
Go에서 하기 쉬운 실수
pprof
slice
toolchain
고루틴 스케줄링
메모리 관리
Java
(20)
JVM
(8)
Heap 영역 구조와 GC
Java Bytecode
jcmd
JVM 구성요소
Permanent to Metaspace
Runtime Data Area
TLAB과 PLAB
메모리누수
Thread
(4)
Thread 상태
@Volatile
wait()과 notifyAll()
가상스레드
Inner static class
JAR과 WAR
JAVA
JDKProxy와 CGLibProxy
JLink & JDeps
record
예외와 에러
제네릭과 variance
JavaScript
(7)
Iterator
Lexical Scope와 Closure
Promise
useEffect 안에서 setInterval 사용하기
절대경로 설정
프로토타입
화살표 함수
Kotlin
(20)
변수
(3)
List와 MutableList
Nullable
val과 var
클래스
(8)
@JvmField
@JvmStatic
Object
Sealed Class, interface
생성자
코틀린에서의 Static
클래스 상속
필드와 접근자 메서드
함수
(1)
기본인자
Collections
field 상속
InlineFuntion과 Reified
Label
Sequences
람다 표현식
범위 지정 함수
제네릭과 variance
Rust
(19)
ffi
(3)
extern
FFI
repr
메모리 참조
(5)
Rc 타입과 Weak 타입
temporary value is freed
Unwrap
소유권과 Lifetime
스마트 포인터 활용
스레드
(3)
Condvar
동시성
멀티 스레드 웹 서버 만들기
예외처리
(1)
Anyhow
String
Trait
구조체 impl
조건문과 반복문
클로저
타입과 변수
함수와 메서드
CustomAnnotation
자바<?>와 코틀린<*>
직렬화 serialVersionUID
코드
(24)
TestCode
(5)
Kotlin
(4)
Kotest
Kotest Assertions
Kotest Specs
Mockk
Mock과 Spy
비동기
(15)
coroutine
(8)
thread
(1)
공유객체 스레드 동기화
Channel
Coroutine CPS
Coroutine Delay
Coroutine Dispatcher
Coroutine Scope, Context
Integration
코루틴
reactor
(3)
Callback과 Futures
Reactor
Reactor Pattern과 event loop
cold stream과 hot stream
Coroutine vs Reactor
Flow
netty 사례연구
빌드
(4)
Gradle
(4)
DependencyHandler
Git action gradle caching
Gradle LifeCycle
멀티모듈
GitHub
LinkedIn
Select theme
Dark
Light
Auto
태그: 서버
총 72개의 글이 있습니다.
@Cacheable
spring
2024. 5. 22.
This method-level annotation lets Spring Boot know that the return value of the annotated method can be cached. Each time a method marked with this @Cacheable is called, the caching behavior will be applied. In particular, Spring Boot will check whether the method has been already invoked for the given arguments. This involves looking for a key, which is generated using the method parameters by de
AdviceAnnotation
aop
2024. 5. 22.
AOP란 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 한다. AOP를 사용하면 기존 코드를 수정하지 않고 기존 코드에 동작을 추가할 수 있다. AOP를 지정하기 위해선 AOP 동작을 메서드에 작성해야한다. 아래 어노테이션들을 이용해서 메서드의 실행 시점을 지정할 수 있다. Advice Annotation Annotation설명@Before핵심관심사 시작 전에 실행@After메서드가 끝난 후 실행 (성공여부 상관 X)@AfterThrowing메서드 실행이 예외를 throw하여 종료될 때 실행@AfterReturning메서드 실행이 정상적으로 반환될 때 실행@Around핵심관심사의 메서드 실행 전 후로 실행 (성공여부
Pointcut
aop
2024. 5. 22.
Pointcut은 Advice가 부가 기능을 제공할 대상을 특정하는 정규표현식이다. 즉, AOP를 적용할 대상을 정한다. 포인트컷에는 다양한 명시자를 이용할 수 있는데, 각 명시자마다 어떤 범위에서 Target을 정할지 어떤 것을 기준으로 할지 등의 의미가 조금씩 다르다. 아래 영어로 된 PointCut 명시자 설명이 있으니, 참고하면 좋을 것 같다. 명시자설명executionfor matching method execution join points, this is the primary pointcut designator you will use when working with Spring AOPwithinlimits matchi
ProxyFactoryBean
aop
2024. 5. 22.
스프링은 서비스 추상화를 프록시 기술에도 동일하게 적용한다. 따라서 스프림은 일관된 방법으로 프록시를 만들 수 있게 도와주는 추상 레이어를 제공한다. ProxyFactoryBean은 프록시를 생성해서 빈 오브젝트로 등록하게 해주는 팩토리 빈이다. ProxyFactoryBean은 순수하게 프록시를 생성하는 작업만을 담당하고 프록시를 통해 제공해줄 부가기능은 별도의 빈에 둘 수 있다. ProxyFactoryBean이 생성하는 프록시에서 사용할 부가기능은 MethodInterceptor 인터페이스를 구현해서 만든다. MethodInterceptor는 InvocationHanler와 비슷하지만 한가지 다른점이 있다. InvocationHandler의 invoke() 메소드는 오브젝트에 대한 정보를 제공하지 않는다.
Spring AOP
aop
2024. 5. 22.
AOP란 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 한다. 여기서 Aspect(관점)이란 흩어진 관심사들을 하나로 모듈화 한 것을 의미한다. 객체 지항 프로그래밍(OOP)에서는 주요 관심사에 따라 클래스를 분할한다. 이 클래스들은 보통 SRP(Single Responsibility Principle)에 따라 하나의 책임만을 갖게 설계된다. 하지만 클래스를 설계하다보면 로깅, 보안, 트랜잭션 등 여러 클래스에서 공통적으로 사용하는 부가 기능들이 생긴다. 이들은 주요 비즈니스 로직은 아니지만, 반복적으로 여러 곳에서 쓰이는 데 이를 흩어진 관심사(Cross Cutting Concerns)라고 한다. AOP 없이 흩어진 관심사를 처리하면 다음과 같은 문제가 발생한다.
Spring에서 aspectj weaving사용하기
aop
2024. 5. 22.
Spring은 객체지향적으로 AOP 기술을 구현하기 위해 프록시 패턴의 관점을 선택했다. 이러한 패턴의 추상적인 관점을 구체화하기 위해, Java에서 기본적으로 제공해주고 있는 JDK Dynamic Proxy(프록시 패턴의 관점의 구현체)를 기반으로 추상적인 AOP 기술을 객체 모듈화하여 설계하였다. 또한 Spring은 성숙한 AOP 기술을 제공해주기 위해 Spring 2.0 부터 @AspectJ애노테이션 방식을 지원하였고, Aspect를 구현하는데 있어 AspectJ5 라이브러리에 포함된 일부 애노테이션을 사용할 수 있다. AspectJ의 강력한 AOP 기술을 Spring에서 쉽게 구현할 수 있기 때문에 개발자는 비즈니스 개발에 보다 집중할 수 있다. 물론, @AspectJ 애노테이션 방식을 통해 구현된
TransactionAttributeSource
트랜잭션
2024. 5. 22.
위 두개의 클래스는 모두 TransactionAttributeSource 인터페이스의 구현체이다 TransactionAttributeSource는 TransactionInterceptor의 메타 데이터 검색에 사용되는 전략 인터페이스인데, 트렌잭션의 메타데이터나 속성을 소싱하는 역할을 한다. public interface TransactionAttributeSource { default boolean isCandidateClass(Class&x3C;?targetClass) { return true; } @Nullable TransactionAttribute getTransactionAttribute(Method method, @Nullable Class&x3C;?targetClass); }
트랜잭션
트랜잭션
2024. 5. 22.
포괄적인 트랜잭션 지원은 Spring Framework를 사용하는 가장 강력한 이유 중 하나이다. Spring Framework는 다음과 같은 이점을 제공하는 트랜잭션 관리를 위한 일관된 추상화를 제공한다. JTA(Java Transaction API), JDBC, Hibernate 및 JPA(Java Persistence API)와 같은 다양한 트랜잭션 API에서 일관된 프로그래밍 모델 선언적 트랜잭션 관리 지원 프로그래밍 방식 트랜잭션 관리 지원 Spring의 데이터 접근 추상화와의 뛰어난 통합 이전의 Transaction 지원 모델… Spring Transaction 지원 모델에 대해 알아보기 전에, 이전의 Transaction 처리 방식에 대해 알아보자. 전통적인 Java EE 개발자는 트랜잭션
트랜잭션 전파
트랜잭션
2024. 5. 22.
트랜잭션 전파란 트랜잭션 경계에서 이미 진행 중인 트랜잭션이 있을 때 또는 없을 때 어떻게 동작할 것인가를 결정하는 방식을 말한다. 1. PROPAGATION_REQUIRED 가장 많이 사용되는 트랜잭션 속성이다. 진행 중인 트랜잭션이 없으면 새로 시작하고, 이미 시작된 트랜잭션이 있으면 이에 참여한다. DefaultTransactionDefinition의 트랜잭션 전파 속성은 바로 이 PROPAGATION_REQUIRED이다. 2. PROPAGATION_REQUIRED_NEW 항상 새로운 트랜잭션을 시작한다. 즉. 앞에서 시작된 트랜잭션이 있든 없든 상관없이 새로운 트랜잭션을 만들어서 독자적으로 동작하게 한다. 3. PROPAGATION_NOT_SUPPORTED 트랜잭션이 없이 동작하도록 만들
AOT
spring
2024. 5. 22.
Spring AOT 엔진은 빌드 시 스프링 애플리케이션을 분석하고 최적화하는 도구이다. 또한 AOT 엔진은 GraalVM Native Configuration이 필요로 하는 reflection configuration을 생성해준다. 이것은 Spring native 실행 파일로 컴파일 하는데 사용되고 이후에 애플리케이션의 시작 시간과 메모리 사용량을 줄일 수 있게 한다. 그러한 변환은 Maven과 Gradle 스프링 AOT 플러그인에 의해 수행된다. AOT 엔진은 최적화된 애플리케이션 컨텍스트와 애플리케이션을 위해 특별히 제작된 스프링 팩토리(Spring Boot 뒤의 플러그인 시스템)를 생성하기 위해 빌드 시 조건을 평가한다. 이를 통해 아래와 같은 효과를 볼 수 있다. 런타임시 필요한 스프링 인프라가
@TransactionalEventListener
event
2024. 5. 22.
Event를 사용할 때 기본적으로 사용하는 @EventListener는 event를 publishing 하는 코드 시점에 바로 publishing*한다. 하지만 우리가 퍼블리싱하는 event는 대부분 메인 작업이 아닌 서브의 작업이 많고 비동기로 진행해도 되는 경우도 많다. 다른 도메인 로직인 경우도 있다. 이럴 경우 조금 애매해지기도 한다. 아래 예를 보자. 아래코드는 @Transactional로 메서드가 하나의 트랜잭션으로 묶여있다. 이 메서드를 실행했을때, 1번과 2번이 정상적으로 마무리되고 3번이 발생하는 도중에 예외처리가 발생하면 어떻게 될까? 3번이 실패했으면 같은 트랜잭션으로 묶여있는 1번도 함께 롤백될 것이다. 하지만 2번은 발행된 이벤트를 listen하는 별도의 구현체가 이후의 동작을 수
ApplicationEventPublisher
event
2024. 5. 22.
ApplicationEventPublisher는 Spring의 ApplicationContext가 상속하는 인터페이스 중 하나이다. 옵저버 패턴의 구현체로 이벤트 프로그래밍에 필요한 기능을 제공해준다. 이벤트 기반의 방법을 사용하면, 서비스간 강결합 문제를 해결힐 수 있다. 1. ApplicationEvent를 상속하는 이벤트 클래스 만들기 --1:403F53"org.springframework.context.ApplicationEvent; public class MyEvent extends ApplicationEvent { private int data; public MyEvent(Object source) { super(source); } public MyEvent
@GeneratedValue 코드보기
jpa
2024. 5. 22.
GeneratedValue는 jakarta에 정의되어있고, Id에 새로운 값을 자동으로 생성해줄 전략을 지정하기 위한 어노테이션이다. @Target({METHOD, FIELD})@Retention(RUNTIME) public @interface GeneratedValue { / * (Optional) The primary key generation strategy * that the persistence provider must use to * generate the annotated entity primary key. */ GenerationType strategy() default AUTO; / * (Optional) The name of t
Cascade
jpa
2024. 5. 22.
cascade 옵션은 jpa를 사용할때 @OneToMany나 @ManyToOne에 옵션으로 줄 수 있는 값이다. cacade 옵션을 사용하면 부모 엔티티에 상태 변화가 생길 때 그 엔티티와 연관되어있는 엔티티에도 상태 변화를 전이시킬 수 있다. 즉, 자식 엔티티의 생명주기를 관리할 수 있다. cascade 타입의 종류 PERSIST 부모 엔티티를 저장하면 자식 엔티티까지 함께 저장한다. 다시말해, 명시적으로 부모엔티티와 연관관계를 가진 자식 엔티티 영속화시킬때 따로 명시할 필요 없이 부모.자식 = 자식 인스턴스 과 같이 적으면 자식 엔티티도 데이터베이스에 자동으로 저장된다. MERGE 데이터베이스에서 가져온 부모 객체를 통해 자식 엔티티의 정보를 수정하여 병합했을때 변경 결과가 자식 엔티티에 반
GenerateValue Column에 값을 넣는다면
jpa
2024. 5. 22.
Hexagonal architecture를 사용해서 구현하다 문제가 생겼다. 해당 프로젝트에선 기본 PK로 UUID를 사용했고, 새로 생성한 도메인 모델은 id 값을 UUID(0, 0)으로 설정해서 사용했다. (여기서 중요하진 않지만 생성 전략은 IdentifierGenerator로 TimeBasedUUID를 생성할 수 있도록 직접 정의된 상태였다.) UUID(0, 0)으로 설정해주다 보니 기존에는 새 insert문을 날려야하는 경우 isNew가 Persistable 기본 전략에 따라 false로 들어갔고, merge가 호출되었다. 여기에서 알아봤던 것 처럼 영속성 컨텍스트에 등록되지 않은 객체에 대해 merge를 호출하면, 어떤 update문(혹은 insert문)을 날려야하는지를 알아야 하기 때문에 sel
Hibernate dialect
jpa
2024. 5. 22.
하이버네이트가 데이터베이스와 통신을 하기 위해 사용하는 언어를 Dialect라고 한다. 모든 데이터베이스에는 각자의 고유한 SQL언어가 있는데, 관계형 데이터베이스끼리 형태나 문법이 어느정도 비슷하긴 하지만, 완전히 똑같지는 않다. 예를 들어 Oracle 쿼리 구문과 MySQL 쿼리구문은 다르다. 하지만, 하이버네이트는 한 데이터베이스관리시스템(DBMS)에 국한되지않고, 다양한 DBMS에 사용 가능하다. 즉 내부적으로 각자 다른 방법으로 처리하고 있는 것이다. 그렇기 때문에특정 벤더(DBMS)에 종속적이지 않고, 얼마든지 대체가능하다. JPA에서는 아래와 같이 Dialect라는 추상화된 언어 클래스를 제공하고 각 벤더에 맞는 구현체를 제공하고 있다. spring: datasource:
Hibernate 쿼리실행순서
jpa
2024. 5. 22.
OrphanRemovalAction AbstractEntityInsertAction EntityUpdateAction QueuedOperationCollectionAction CollectionRemoveAction CollectionUpdateAction CollectionRecreateAction EntityDeleteAction performExecutions protected void performExecutions(EventSource session) Execute all SQL (and second-level cache updates) in a special order so that foreign-key constraints cannot be violated: Inserts, in the o
Id로 연관관계 객체 저장
jpa
2024. 5. 22.
다대일 연관관계를 맺고 있는 Member와 Team이라는 엔티티가 있다고 하자. @Getter@NoArgsConstructor(access = AccessLevel.PROTECTED)@Entitypublic class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "team_id") private Team team; public Member(Team team) { this.team = team; }} @Getter@NoArgsConstructor(acce
JDBC Object Mapping Fundamentalsentity
jpa
2024. 5. 22.
스프링 데이터가 객체를 매핑할 떄 담당하는 핵심 역할은 도메인 객체 인스턴스를 생성하고, 여기에 저장소 네이티브 데이터 구조를 매핑하는 일이다. 여기에는 두 가지의 핵심적인 단계가 있다. 노출된 생성자중 하나로 인스턴스 생성하기. 나머지 프로퍼티 채우기. 엔티티(Entity) 생성 Spring Data JDBC에서 엔티티 객체를 생성하는 알고리즘은 3가지이다. 기본 생성자가 있는 경우 기본생성자를 사용한다. 다른 생성자가 존재해도 무시하고 우선적으로 기본생성자를 사용한다. 매개변수가 존재하는 생성자가 하나만 존재한다면 해당 생성자를 사용한다. 매개변수가 존재하는 생성자가 여러개 있으면 @PersistenceConstructor 어노테이션이 적용된 생성자를 사용한다. 만약 @PersistenceCons
JPA
jpa
2024. 5. 22.
JPA는 자바의 ORM(Object-Relational Mapping) 기술의 표준으로, 객체와 테이블을 매핑해 패러다임의 불일치를 개발자 대신 해결하는 기술이다. 객체는 객체대로 생성하고, 데이터베이스는 데이터베이스에 맞게 설계할 수 있도록 해준다. Repository interface JPA는 Repository라는 interface를 통해 지속성 저장소에 대한 데이터 액세스 계층을 구현하는 데 필요한 상용구 코드의 양을 크게 줄일 수 있도록 해준다. Repository를 상속받은 하위 인터페이스의 종류로는 CrudRepository, PagingAndSortingRepository, JpaRepository 등이 있고 각 인터페이스가 적절한 기본 메서드를 지정하고 있다. //ex) CrudReposit
FetchJoin
jpql
2024. 5. 22.
fetch join은 JPQL에서 성능 최적화를 위해 제공하는 기능이다. 페치 조인은 연관된 엔티티나 컬렉션을 한 번에 같이 조회해준다. 일반적으로 연관관계가 맺어진 엔티티를 조회할때, N+1문제를 해결하기 위해서 FetchType.LAZY를 사용하는 경우가 있다. 하지만 두 엔티티를 모두 조회해야하는 경우엔 두개의 쿼리를 날려야하기 때문에 N+1문제가 동일하게 발생한다. 이럴 때 fetch join을 사용하면 하나의 쿼리로 두 엔티티를 한 번에 조회할 수 있다. 1:N 조인에서 fetch join을 사용하면 결과의 갯수가 늘어날 수 있다.(‘1’쪽에서 조회해야하는 엔티티의 총 갯수가 아닌, ‘1’쪽의 엔티티 갯수만큼의 결과가 조회된다.) 이 경우 JPQL의 DISTINCT를 사용해서 결과의 갯수를 줄일
경로표현식
jpql
2024. 5. 22.
자바에서 인스턴스화된 객체로 클래스의 변수나 메서드에 접근할 때 .을 이용해 접근하는 것 처럼, jpql 쿼리에서 .으로 객체의 값에 점을 찍어 객체 그래프를 탐색하는 것을 경로 표현식이라고 한다. 경로 유형별 동작 상태 필드(State Field) 상태 필드는 일반적인 값을 저장하기 위한 필드이다. 즉, int, varchar등의 자료형을 가지는 기본적인 데이터를 저장한다. 상태필드는 더 나아갈 경로가 존재하지 않으므로 jpql에서 부가적인 조인 등의 탐색 또한 일어나지 않는다. 연관 필드(Association field) 연관 필드는 연관관계가 맺어진 외래 테이블의 값을 위한 필드이다. 단일 값 연관 필드와 컬렉션 값 연관 필드로 나뉜다. 단일 값 연관 필드 @ManyToOne, @OneToOne
N+1 문제
jpa
2024. 5. 22.
어떤 엔티티를 조회할때, 그 엔티티의 하위 엔티티들을 가져오기 위해 별도의 쿼리가 실행되는 것을 N+1 문제라고 한다. N+1 문제는 DB 조회 성능에 악영향을 끼치기 때문에 JPA 사용시 꼭 주의해야 한다. 예를 들어 아래와 같은 두 엔티티가 있다고 해보자. @Entitypublic class User { @Id @Column(name = "user_id") private Long id; @OneToMany(mappedBy = "user") private List&x3C;Orderorders = new ArrayList&x3C;>();} @Entitypublic class Order { @Id @Column(name = "order_id") private L
OrphanRemoval
jpa
2024. 5. 22.
cascade 옵션을 사용하면 부모 엔티티에 상태 변화가 생길 때 그 엔티티와 연관되어있는 엔티티에도 상태 변화를 전이시킬 수 있다. 그러나 cascade 옵션을 사용한다고 해서 부모 엔티티에서 자식 엔티티의 생명주기를 완전히 통제할 수 있는 것은 아니다. cascade의 REMOVE 옵션은, 부모 엔티티를 삭제했을때 그 엔티티를 참조하고 있는 자식 엔티티(해당 부모 엔티티를 Foreign Key로 가지고있는 엔티티)도 함께 삭제해준다. 하지만 부모 엔티티에서 자식 엔티티를 삭제했을때에는 그 참조를 끊어줄 뿐, 그 자식 엔티티를 같이 삭제해주진 않는다. (심지어 FK에 NotNull 제약조건을 걸어놨으면 아무 변화도 생기지 않는다) 그럴 때 사용할 수 있는 것이 OrphanRemoval이다
Persistable
jpa
2024. 5. 22.
CrudRepository의 기본 구현인 SimpleJpaRepositoryy의 save 메서드는 이렇게 구현되어있다. // SimpleJpaRepository의 save method @Transactional @Override public &x3C;S extends T> S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } S save(S entity) { Assert.
Paging
querydsljpa
2024. 5. 22.
Querydsl에서 페이징하는 방법을 알아보자. Page는 인터페이스이기 떄문에, Page를 반환하기 위해선 Page를 구현한 구체클래스를 생성해야한다. 그렇기 때문에 아래 코드에선 스프링 데이터에 있는 PageImpl 클래스를 사용하여 return 하도록 한다. fetchResults()를 사용하여 total count쿼리와 결과 리스트를 한 코드로 조회하도록 할 수도 있지만, fetchResults()와 fetchCount()가 특정 상황에서 제대로 동작하지 않는 이슈때문에 depercated 되었으므로 따로 count를 조회하여 반환하는 방식을 택했다. 원하는 컬럼을 Dto로 만들어서 조건에 따라 조회한 후 반환하는 예제 코드이다. public Page&x3C;MemberTeamDto> sear
Projection
querydsljpa
2024. 5. 22.
Projection은 엔티티를 그냥 그대로 가지고 오지 않고, 필요한 정보만 추출해오는 것을 의미한다. Querydsl 에서는 프로젝션 대상이 하나면 명확한 타입을 지정할 수 있지만 프로젝션 대상이 둘 이상이라면 Tuple 이나 DTO 로 조회해야 한다. 순수 JPA에서의 Projection @Test void projectionWithJpa() { //given //when List&x3C;MemberDtoresults = em.createQuery( "select new com.study.querydsl.dto.MemberDto(m.username, m.age)" +
QuerydslJpa와 QClass
querydsljpa
2024. 5. 22.
Spring Data JPA가 기본적으로 제공해주는 CRUD 메서드 및 쿼리 메서드 기능을 사용하더라도 원하는 조건의 데이터를 수집하기 위해선 JPQL을 작성해야한다.JPQL로 간단한 로직을 작성하는데는 큰 문제가 없지만, 복잡한 로직의 경우 쿼리 문자열이 상당히 길어진다. 또, 정적 쿼리인 경우엔 어플리케이션 로딩 시점에 JPQL 문자열의 오타나 문법적인 오류를 발견할 수 있지만, 그 외는 런타임 시점에서 에러가 발생한다는 문제가 있다. 이러한 문제를 해결하기 위한 프레임워크가 바로 QueryDSL-jpa이다. QueryDSL을 사용하면 문자가 아닌 코드로 쿼리를 작성할 수 있기 때문에 컴파일 시점에 문법 오류를 쉽게 확인할 수 있고, 타입 안정성(type-safe)을 지키면서 동적인 쿼리를 편리하게
QuerydslPredicateExecutor
querydsljpa
2024. 5. 22.
QuerydslPredicateExecutor는 스프링 데이터에서 제공하는 Querydsl 기능이다. (공식 문서) public interface QuerydslPredicateExecutor&x3C;T{ Optional&x3C;TfindById(Predicate predicate); Iterable&x3C;TfindAll(Predicate predicate); long count(Predicate predicate); boolean exists(Predicate predicate); // … more functionality omitted.} { Optional findById(Predicate predicate); Iterable findAll(Pre
fetchResults가 deprecated된 이유
querydsljpa
2024. 5. 22.
공식 Docs 설명 fetchResults() : Get the projection in QueryResults form. Make sure to use fetch() instead if you do not rely on the QueryResults.getOffset() or QueryResults.getLimit(), because it will be more performant. Also, count queries cannot be properly generated for all dialects. For example: in JPA count queries can’t be generated for queries that have multiple group by expressions or a havin
기본문법
querydsljpa
2024. 5. 22.
엔티티 조회 @Test public void searchWithQuerydsl() { //given Member findMember = queryFactory .select(member) .from(member) .where(member.username.eq("member1")) .fetchOne(); //when //then assertEquals("member1", findMember.getUsername()); } Querydsl에서는 Q클래스 인스턴스를 사용해 쿼리를 작성할 수 있다. 기본 인스턴스를 static i
동적쿼리
querydsljpa
2024. 5. 22.
Querydsl에서 동적인 쿼리를 생성해보자. 동적쿼리를 작성하는 방법은 1. BooleanBuilder를 작성하는 방법2. Where 절과 Predicate를 이용하는 방법3. Where 절과 피라미터로 Predicate 를 상속한 BooleanExpression을 사용하는 방법 총 세가지가 있다. 그렇다면 세가지 방법을 모두 비교해보자. 모든 코드에서 MemberSearchCondition를 파라미터로 받아 username, teamName, ageGoe, ageLoe를 조건으로 걸어 조회하고, 값이 null인경우 where절에 적용하지 않도록 했다. @Getter@NoArgsConstructorpublic class MemberSearchCondition { private String userna
벌크연산
querydsljpa
2024. 5. 22.
JPA에서 벌크 연산이란, 여러 건(대량의 데이터)을 한 번에 수정하거나 삭제하는 것을 뜻한다. 자세한 설명이나 사용시 주의사항에 대해 더 알고싶다면 위의 하이퍼링크를 참고하길 바란다. 사실 Querydsl에서 따로 특별하게 벌크 연산을 생성하는 방법은 따로 없고, Where 조건에 여러 튜플이 해당할 수 있는 조건을 넣는다면 벌크 연산이 수행된다. @Testvoid bulkUpdate(){ //given //when long count = queryFactory .update(member) .set(member.username, "미성년자") .where(member.age.lt(20)) .execute();
ReadOnlyQuery 최적화
jpa
2024. 5. 22.
JPA의 영속성 컨텍스트는 변경 감지를 위해 스냅샷 인스턴스를 보관하는 특징이 있다. 하지만 엔티티를 단순 조회하는 경우에는 컨텍스트에 있는 엔티티를 다시 꺼내오거나 수정할 필요가 없기 때문에 스냅샷 인스턴스를 저장하는 것이 메모리적으로 낭비이다. 이럴 경우 아래의 방법으로 메모리 사용량을 최적화할 수 있다. 스칼라 타입으로 조회 스칼라 타입은 영속성 컨텍스트가 관리하지 않기 떄문에, 엔티티가 아닌 스칼라 타입으로 조회하면 읽기 전용 쿼리에서 메모리를 절약할 수 있다. SELECT u.id, u.name, u.age FROM user u 읽기 전용 쿼리 힌트 사용 하이버네이트 전용 힌트인 org.hibernate.readOnly를 사용하면 엔티티를 읽기 전용으로 조회할 수 있다. 읽기 전용이므로
벌크연산
jpa
2024. 5. 22.
JPA에서 벌크 연산이란, 여러 건(대량의 데이터)을 한 번에 수정하거나 삭제하는 것을 뜻한다. 벌크 연산은 executeUpdate() 메소드를 사용하고, 해당 메서드는 영향을 받은 엔티티 건수를 반환한다. //재고가 10개 이하인 상품의 가격을 10% 증가하는 벌크 연산 String queryString = "update Product p" + "set p.price = p.price * 1.1" + "where p.stockAmount &x3C; :stockAmount"; int resultCount = em.createQuery(queryString) .setParameter("stockAmount", 10) .exe
1차캐시
캐싱
2024. 5. 22.
캐시란 무엇일까? Cache는 간단히 말해서 나중의 요청에 대한 결과를 미리 저장했다가 빠르게 사용하는 것이다. 컴퓨터에서 중요한 메인 데이터들은 전원이 꺼져도 저장되는 SSD, HDD 등의 Secondary Memory에 저장된다. Secondary Memory에 저장된 데이터들은 장기적으로 안정적이게 저장될 수 있지만, 기술 한계상 데이터를 IO 하는 속도가 느리다. 그렇기 때문에 컴퓨터에서는 데이터 처리에 바로 필요한 데이터를 Main Memory인 RAM에 끌어놓거나, CPU에서 빠르게 접근할 수 있는 CPU Registers, Cache Memory의 형태로 저장하여 더 빠르고 쉽게 접근할 수 있도록 한다. 애플리케이션 서버(Spring JPA?)가 DB에 접근할 때를 예로 들어보면, DB에 연결
2차캐시
캐싱
2024. 5. 22.
애플리케이션에서 공유하는 캐시를 JPA는 공유 캐시(Shared Cache)또는 2차 캐시 (Second Level Cache, L2 Cache)라 부른다. 분산 캐시나 클러스터링 환경의 캐시는 애플리케이션보다 더 오래 유지 될 수도 있다. 2차 캐시를 적절히 활용하면 데이터베이스 조회 횟수를 획기적으로 줄일 수 있다. 1차캐시는 못하고 2차캐시는 할 수 있는 것 1차캐시는 영속성 컨텍스트에서 관리되는 캐시로, 트랜잭션이 시작하고 종료할 때 까지만 유지된다. 그렇기 때문에 같은 트랜잭션에서 한 엔티티를 여러번 가져와야할때 효과를 볼 수 있다. 하지만 만약에 여러 유저가 한 엔티티의 정보를 필요로 한다면 어떨까? 여러 요청들에서 공통적으로 같은 엔티티의 데이터가 필요한 경우에는, 1차캐시가 효용을 미치지 못한
영속성 컨텍스트
캐싱
2024. 5. 22.
영속성 컨텍스트랑 말 그대로 엔티티를 영속화(영구저장) 시켜주는 환경이다. 애플리케이션과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스(1차캐시) 역할을 한다. 엔티티 매니저를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다. 영속성 컨텍스트는 엔티티 매니저를 생성할 때 하나 만들어지고, 엔티티 매니저를 통해 영속성 컨텍스트에 접근하고 관리할 수 있다. 영속성 컨텍스트는 엔티티를 여러가지 상태로 저장한다. 엔티티의 생명주기 비영속(new/transient): 영속성 컨텍스트와 전혀 관계가 없는 상태 영속(managed): 영속성 컨텍스트에 저장된 상태 준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태 삭제(removed): 삭제
트랜잭션 전파 설정
jpa
2024. 5. 22.
Spring에서 사용하는 어노테이션 @Transactional은 해당 메서드를 하나의 트랜잭션 안에서 진행할 수 있도록 만들어주는 역할을 한다. 이때 트랜잭션 내부에서 트랜잭션을 또 호출한다면 스프링에서는 어떻게 처리하고 있을까? 새로운 트랜잭션이 생성될 수도 있고, 이미 트랜잭션이 있다면 부모 트랜잭션에 합류할 수도 있을 것이다. 진행되고 있는 트랜잭션에서 다른 트랜잭션이 호출될 때 어떻게 처리할지 정하는 것을 ‘트랜잭션의 전파 설정’이라고 부른다. 전파 설정 옵션 트랜잭션의 전파 설정은 @Transactional의 옵션 propagation을 통해 설정할 수 있다. 각 옵션은 아래와 같다. REQUIRED (default) 부모 트랜잭션이 존재한다면 부모 트랜잭션으로 합류하고, 부모 트랜잭션이 없다면 새
CORS
springsecurity
2024. 5. 22.
CORS란Cross-Origin Resource Sharing, 교차 출처 리소스 공유의 약자이다. 서로 출처가 다른 웹 애플리케이션에서 자원을 공유하는 것을 말한다. 보안상의 이유로 브라우저에서는 이 교차 출처 요청을 제한하는 경우가 많다. (포스트맨은 개발 도구이기 때문에 CORS에 신경쓰지 않는다.) Spring Security에서도 기본적으로 CORS가 제한되어있다. 이때 특정 도메인, 또는 전체 도메인에서의 요청을 허용하려면 아래와 같이 설정해주면 된다. @Beanpublic class SecurityFilterChain filterChain(HttpSecurity: httpSecurity) { return httpSecurity .cors().and() // cors 설정을
CSRF
springsecurity
2024. 5. 22.
CSRF(Cross site Request forgery)는 웹 애플리케이션의 취약점 중 하나로, 이용자가 의도하지 않은 요청을 통한 공격을 의미한다. 즉, 인터넷 사용자가 자신의 의지와 무관하게 공격자가 의도한 특정 행위를 웹사이트의 요청하도록 하여 간접적으로 해킹하도록 하는 것이다. 따라서, 스프링 시큐리티는 CSRF 공격을 방지하기 위한 기능을 가지고있다. @EnableWebSecurity 어노테이션을 붙이면 Referrer 검증, CSRF Token 사용 등의 기능이 활성화된다. 각 기능에 대해 간단하게 알아보자 Referrer 검증 서버단에서 request의 referrer을 확인하여 domain이 일치하는지 검증하는 방법이다. Spring Security CSRF Token 임의의 토큰을
Spring 6.0과 Spring Boot 3.0
spring
2024. 5. 22.
Spring 6.0에서 달라지는 점 Java 17기반으로 변경 일부 Java EE API 지원 종료 (javax등) XML이 점차적으로 Spring에서는 사라지게 될 것 RPC 지원 종료 새로운 AOT 엔진 도입 @Inject 같은 JSR에서 지원하던 어노테이션들이 jakarta.annotation 패키지의 어노테이션으로 변경 HttpMethod가 enum에서 class로 변경 Jakarta EE 9+로의 마이그레이션으로 인한 변경 Hibernate ORM 5.6.x 버전부터 hibernate-core-jakarta 사용 javax.persistence에서 jakarta.persistence로 변경 Tomcat 10, Jetty 11, Undertow 2.2.14 (undert
@GroupSequence
validation
2024. 5. 22.
보통 WebRequest를 받을때, null이거나 비어있는 등의 유효하지 않은 값을 미리 걸러내기 위해 Sprign validation을 사용한다. 설정해둔 @NotNull, @Size, @Pattern 등 조건에 부합하지 못하면 MethodArgumentNotValidException이 발생하고, 이 에러를 적절히 처리하여 반환하는 방식이 많이 사용된다. 하지만 한 필드에 여러 검증을 넣게 되면, 그 검증에 순서가 부여되지 않아 무작위로 먼저 걸리는 조건의 에러가 반환된다. 그렇다면 이 에러 처리의 순서를 정해줘야 한다면 어떻게 해야할까? 즉, Null 체크를 먼저하고, 그다음 Size를 체크하고, 그다음 Pattern을 체크하는 방식으로 흐름을 지정하려면 어떻게 해야할까? 그런 경우 @GroupSeque
@Valid와 @Validated
validation
2024. 5. 22.
@Valid는 JSR-303 표준 스펙(자바 진영 스펙)으로써 빈 검증기(Bean Validator)를 이용해 객체의 제약 조건을 검증하도록 지시하는 어노테이션이다. JSR 표준의 빈 검증 기술의 특징은 객체의 필드에 달린 어노테이션으로 편리하게 검증을 한다는 것이다. Spring에서는 일종의 어댑터인 LocalValidatorFactoryBean이 제약 조건 검증을 처리한다. 이를 이용하려면 LocalValidatorFactoryBean을 빈으로 등록해야 하는데, SpringBoot에서는 아래의 의존성만 추가해주면 해당 기능들이 자동 설정된다. //
@Controller
webflux
2024. 5. 22.
@Controller로 webFlux를 사용해보자. 프로젝트 생성 스프링부트 프로젝트를 생성하여 build.gradle에 Dependencies를 설정한다. 필요한 의존성과, webflux 의존성을 설정해준다. implementation 'org.springframework.boot:spring-boot-starter-webflux' Flux 반환 유형 Flux는 Reactive Streams의 Publisher를 구현한 N개 요소의 스트림을 표현하는 Reactor 클래스이다. 기본적으로 text/plain으로 응답이 반환되지만, Server-Sent Event나 JSON Stream으로 반환할 수도 있다. Flux의 반환 유형은 클라이언트가 헤더에 응답 유형을 어떻게 설정하느냐에 따라 달라진다. 아래같은
R2DBC
r2dbc
2024. 5. 22.
R2DBC는 Reactive Relational Database Connectivity의 줄임말이다. R2DBC는 관계형 데이터베이스 접근을 위해 구현해야 할 리액티브 API를 선언하는 스펙이다. JDBC는 완전한 블로킹 API이었고, RDBMS는 NoSQL에 비해 자체 리액티브 클라이언트를 가지고 있는 경우가 적어서 비동기 통신을 하기 힘들었다. 반면에 R2DBC는 Non-Blocking 관계형 데이터베이스 드라이버와 잘 동작하도록 하는 것을 목적으로 만들어졌다. 쿼리를 소켓에 기록하고 스레드는 응답이 수신될 때까지 다른 작업을 계속 처리하여 리소스 오버헤드를 줄이는 방식으로 적은 스레드, 하드웨어 리소스로 동시 처리를 제어할 수 있도록 한다. 하지만, R2DBC는 개념적으로 쉬운 것을 목표로 하므로, 기
R2DBC 사용
r2dbc
2024. 5. 22.
R2DBC를 사용하기 위해서는 의존성을 먼저 추가해주어야 한다. 데이터베이스에 맞는 R2DBC driver와 그 구현체의 의존성을 추가해주자. implementation("org.springframework.boot:spring-boot-starter-webflux")implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")implementation("com.github.jasync-sql:jasync-r2dbc-mysql:2.0.8") 그리고 yml 설정을 해준다. spring: r2dbc: url: r2dbc:pool:mysql://localhost:3306/test username: user password: u
RouterFunctions
webflux
2024. 5. 22.
RouterFunctions로 webFlux를 사용해보자. 기본적인 원리와 방식은 @Controller에서 모두 설명하였으며 같은 기능의 코드를 테스트할 것이기 때문에 해당 글을 먼저 보고 오는 것을 추천한다. 우선 GET(”/“)으로 Flux의 “Hello World”를 반환하는 Routing을 정의한다. @Componentpublic class HelloHandler { RouterFunction&x3C;ServerResponseroutes() { return route(GET("/"), req -> ok().body(Flux.just("Hello", "World!"), String.class)); } } routes() { return rou
WebClient
webflux
2024. 5. 22.
외부 서비스와 HTTP로 통신해야 하는 경우 가장 흔한 방법은 RestTemplate을 사용하는 것이다. RestTemplate은 Spring 애플리케이션에서 가장 일반적인 웹 클라이언트지만 블로킹 API이므로 리액티브 기반의 애플리케이션에서 성능을 떨어트리는 원인이 될 수 있다. 대신 Spring5에서 추가된 WebClient를 사용하면 reactive 기반의 비동기-논블로킹 통신을 구현할 수 있다. webClient .get() .uri("/users/" + userId) .retrieve(); 기본 요청 방법 http method는 webClient의 get, post, put, head 등의 메서드로 지정해준다. query parameter query p
WebFilter
webflux
2024. 5. 22.
WebFilter는 Spring WebMVC의 Filter에 대응되는 클래스이다. WebFilter는 Spring Web package에 있는 클래스이고, WebFlux를 사용할 때만 동작한다. RequestContextWebFilter --1:403F53"org.springframework.web.server.ServerWebExchange--1:403F53"org.springframework.web.server.WebFilter--1:403F53"org.springframework.web.server.WebFilterChain--1:403F53"reactor.core.publisher.Mono class RequestContextWebFilter( private val requestContext:
WebFlux
webflux
2024. 5. 22.
Spring WebFlux는 논블로킹(Non-Blocking) 런타임에서 리액티브 프로그래밍을 할 수 있도록 하는 새로운 Web 프레임워크이다. Spring 5에서 추가되었다. 지금까지 Spring MVC는 서블릿 컨테이너에 Servlet API를 기반으로 한 프레임워크이었지만, Spring WebFlux는 Servlet API를 사용하지 않고 Reactive Streams와 그 구현체인 Reactor를 기반으로 한 새로운 HTTP API로 구현되어 있다. 런타임으로서 Netty, Undertow(서블릿 컨테이너가 아닌 방향)와 같은 WAS로 NonBlocking을 사용할 수 있다. 또한 Servlet 3.1에서 도입된 NonBlocking API를 사용하여 Tomcat, Jetty 구현체를 사용할 수도
Request 처리과정
webmvc
2024. 5. 22.
Spring Web MVC 에서 HTTP Request를 처리하는 핵심 클래스는 DispatcherServlet이란 클래스이다. 아 DispatcherServlet은 MVC 아키텍처로 구성된 프레젠테이션 계층을 만들 수 있도록 설계되어 있다. 서버가 브라우저 등의 HTTP 클라이언트로부터 요청을 받아 처리 후 응답하기까지의 과정을 알아보자. 1. DispatcherServlet의 요청 접수 자바 서버의 서블릿 컨테이너는 HTTP 프로토콜을 통해 들어오는 요청을 DispatcherServlet에 전달해준다. (이때, URL이나 확장자를 설정해주면 일부 요펑만 매핑되도록 설정할 수도 있다.) DispatcherServlet은 요청을 제일 먼저 받아 원하는 전처리 동작을 수행한 후 다음 클래스에게 일부
SpringServletContainerInitializer
webmvc
2024. 5. 22.
ServletContainerInitializer(in org.springframework.web) is the interface which allows a library/runtime to be notified of a web application’s startup phase and perform any required programmatic registration of servlets, filters, and listeners in response to it. The spring also has an implementation for it. That is ServletContainerInitializer, When you started a spring apllication, it will be loade
@Autowired 빈 주입 스캔 원리
기본원리
2024. 5. 22.
// AutowiredAnnotationBeanPostProcessorbuildAutowiringMetadata // Autowiring을 해야하는지 여부를 확인하고, 주입 메타데이터를 반환하는 함수 private InjectionMetadata buildAutowiringMetadata(Class&x3C;?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; // Autowired 어노테이션을 가지고 있지 않은 클래스는 Empty를 반환한다. } List&x3C;InjectionMetadata.Inje
@ComponentScan
기본원리
2024. 5. 22.
@ComponentScan은 객체를 패키지에서 Scan하여 빈으로 등록해주는 어노테이션이다. 보통은 @Component나 @Service, @Application등의 지정된 어노테이션을 가지고 있는 객체를 경로의 전체 패키지에서 탐색하여 등록하지만 Scan할 패키지나 어노테이션, 조건 등을 custom하여 마음대로 지정할 수도 있다. 기본적인 어노테이션들은 @SpringBootApplication에 달려있는 @ComponentScan에 의해 빈으로 등록된다. @Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentSc
Ioc와 DI
기본원리
2024. 5. 22.
🍃 제어의 역전 IoC (Inversion of Control) 기존에는 클라이언트 구현 객체가 스스로 필요한 서버 구현 객체를 생성하고, 연결하고, 실행하는 프로그램. 즉, 구현 객체가 프로그램의 제어 흐름을 조정하는 프로그램이 많았다. 하지만 이런 방식은 코드의 재사용성과 유지보수성이 낮다. 하지만 그와 반대로 프로그램에 대한 제어 권한을 외부에서 가지고 있는 것을 제어의 역전(Ioc)이라고 한다. IoC는 객체지향성을 잃지 않고 유지보수성이 높은 코드를 만들 수 있게 해준다. (+ 프레임워크는 작성된 코드를 제어하고 대신 실행해주는 역할을 한다. Spring도 이와 같은 프레임워크의 일종이다.) IoC의 장점 애플리케이션 코드의 양을 줄일 수 있다. 클래스 간의 결합을 느슨하게 한다. 애플리케이
Programmatic과 Declarative
기본원리
2024. 5. 22.
사실은 Spring에 관련된 개념은 아니지만, 스프링을 공부하면서 헷갈렸던 부분이라 정리해본다. 또한, 스프링을 공부할때 알면 더 많은 것을 이해하는데 도움이 될 것이다. 어느날, Spring의 공식 Docs의 트랜잭션 부분을 보면서 이러한 부분을 발견하게 되었다. Declarative Transaction ManagementMost Spring Framework users choose declarative transaction management. This option has the least impact on application code and, hence, is most consistent with the ideals of a non-invasive lightweight container.The S
Reflection과 직렬화
기본원리
2024. 5. 22.
Reflection은 런타임에 동적으로 클래스들의 정보를 알아내고, 실행할 수 있는 것을 말한다. Reflection은 프로그래머가 데이터를 보여주고, 다른 포맷의 데이터를 처리하고, 통신을 위해 serialization(직렬화)을 수행하고, bundling을 하기 위해 일반 소프트웨어 라이브러리를 만들도록 도와준다. java와 같은 객체지향 프로그래밍언어에서 Reflection을 사용하면 컴파일 타임에 인터페이스, 필드, 메소드의 이름을 알지 못해도 실행중에 접글할 수 있다. 또, 멤버 접근 가능성 규칙을 무시하여 private 필드의 값을 변경할 수 있다. 직렬화 jackson은 java.lang reflection 라이브러리를 사용한다. 기본생성자가 있는 경우에는 _constructor.newInsta
등록된 빈 목록 출력하기
기본원리
2024. 5. 22.
Spring에서는 애플리케이션을 구성하는 몇몇 클래스들을 싱글톤으로 관리할 수 있도록 ‘빈’을 등록한다. 해당 객체는 애플리케이션 실행 과정에서 주요한 정보를 설정하거나, 로직을 수행하는 역할을 수행한다. 빈은 자바 애플리케이션을 실행하여 Spring이 initializing 된 후에 스캔을 통해 컨텍스트에 등록되는데, 이렇게 등록된 빈의 목록을 출력하려면 아래와 같은 코드를 작성하여 클래스 경로 내에 넣어주면 된다. //in java@Componentpublic class BeanListPrinter implements CommandLineRunner { private ApplicationContext ac; BeanListPrinter(ApplicationContext ac) {
빈
기본원리
2024. 5. 22.
스프링 컨테이너(Spring Container) 스프링에서 DI를 이용하여 애플리케이션을 구성하는 여러 빈(Bean)들의 생명주기(Lifecycle)와 애플리케이션의 서비스 실행 등을 관리하며 생성된 인스턴스들에게 기능을 제공하는 것을 부르는 말이다. 프로그래머의 개입 없이도 컨테이너에 설정된 내용에 따라 빈을 알아서 참조하고 관리한다. 대표적으론 BeanFactory와 ApplicationContext 가 있다. BeanFactory 스프링 컨테이너의 최상위 인터페이스로서, 스프링 빈을 관리하고 조회하는 역할을 담당힌디. getBean() 을 제공한다. 지금까지 우리가 사용했던 대부분의 기능은 BeanFactory가 제공하는 기능이다. ApplicationContext BeanFactory 기능을 모두 상
선점 잠금과 비선점 잠금
기본원리
2024. 5. 22.
운영자 스레드와 고객 스레드는 같은 주문 애그리거트를 나타내는 다른 객체를 구하게 된다. 운영자 스레드와 고객 스레드는 개념적으로 동일한 애그리거트이지만 물리적으로 서로 다른 애그리거트 객체를 사용한다. 위 그림과 같은 상황에서 두 스레드는 각각 트랜잭션을 커밋할 때 수정한 내용을 DB에 반영하는데, 상태가 서로 충돌되기 때문에 애그리거트의 일관성이 깨진다. 이 순서의 문제점은 운영자는 기존 배송지 정보를 이용해서 배송 상태로 변경했는데 그 사이 고객은 배송지 정보를 변경했다는 점이다. 즉 애그리거트의 일관성이 깨지는 것이다. 이런 문제가 발생하지 않도록 하려면 다음 두 가지 중 하나를 해야한다. 운영자 배송지 정보를 조회하고 상태를 변경하는 동안 고객이 애그리거트를 수정하지 못하게 막는다. 운영자가 배
싱글톤
기본원리
2024. 5. 22.
웹 애플리케이션은 보통 여러 고객이 요청을 동시에 보내는데, 이럴 때 마다 새로운 객체를 생성해서 반환하는 것은 메모리 낭비가 너무 심하다. 그래서 고안된 것이 생성된 하나의 객체를 공유해서 사용하도록 설계한 ‘싱글톤 패턴’이다. 싱글톤 패턴은 이미 만들어진 객체를 재사용하기 때문에 객체를 생성하는 데 메모리와 시간을 쓰지 않아도 되니 아주 효율적이다! 하지만 싱글톤 패턴도 단점이 있다. 싱글톤 패턴의 문제점 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다. 의존관계상 클라이언트가 구체 클래스에 의존한다. DIP를 위반한다. 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다. 테스트하기 어렵다. 내부 속성을 변경하거나 초기화 하기 어렵다. private 생성자로 자식 클래스를 만들기
tomcat 구성요소
was
2024. 5. 22.
tomcat-Catalina Catalina는 Tomcat의 서블릿 컨테이너 이름이다. 자바 서블릿을 호스팅 하는 환경. tomcat-Coyote 톰캣에 TCP를 통한 프로토콜을 지원한다. Coyote가 HTTP요청을 받으면 Catalina 서블릿 컨테이너에서 요청중에서 java웹 어플리케이션을 해석하는데, jsp에 관한 요청 일땐 Jasper가 처리한다. tomcat-Jasper Jasper는 실제 JSP페이지의 요청을 처리하는 서블릿 엔진이다. Jasper는 JSP 파일을 구문 분석하여 Java 코드로 컴파일한다. 런타임에 Jasper는 JSP 파일에 대한 변경 사항을 감지하고 재컴파일한다. Catalina is Tomcat’s servlet container. Catalina implements Sun
웹서버와 WAS
was
2024. 5. 22.
웹 서버(Web Server) 웹 서버란 HTTP 프로토콜을 기반으로 클라이언트가 웹 브라우저에서 어떠한 요청을 하면 그 요청을 받아 정적 컨텐츠를 제공하는 서버이다. 정적 컨텐츠란 단순 HTML 문서, CSS, 이미지, 파일 등 즉시 응답 가능한 컨텐츠이다. 이때 웹 서버가 정적 컨텐츠가 아닌 동적 컨텐츠를 요청받으면 WAS에게 해당 요청을 넘겨주고, WAS에서 처리한 결과를 클라이언트에게 전달하는 역할도 해준다. 이러한 웹 서버에는 Apache, NginX등이 있다. WAS(Web Application Server) WAS란 DB 조회 혹은 다양한 로직 처리를 요구하는 동적 컨텐츠를 제공하기 위해 만들어진 Application 서버이다. HTTP 프로토콜을 기반으로 사용자 컴퓨터나 장치에 애플리케이션을
HashedWheelTimer
netty
2024. 5. 22.
Timers are important for failure recovery, rate based flow control, scheduling algorithms, controlling packet lifetime in networks. And Efficient timer algorithms are required to reduce the overall interrupt overhead Timer maintenance high if Processor interrupted every clock tick Fine granularity timers are used outstanding timers is high Model &x26; Performance Measure Therefore, we will lo
netty server 예제
netty
2024. 5. 22.
클라이언트의 입력을 그대로 응답으로 돌려주는 서버를 Netty 프레임워크로 구현하고 이해해보자. 메인 클래스 class EchoServer { private val allChannels: ChannelGroup = DefaultChannelGroup("server", GlobalEventExecutor.INSTANCE) private var bossEventLoopGroup: EventLoopGroup? = null private var workerEventLoopGroup: EventLoopGroup? = null fun startServer() { // (1) bossEventLoopGroup = NioEventLoopGroup(1, DefaultThr
netty 메시지 전송 흐름
netty
2024. 5. 22.
Channel을 통해 메시지 전송을 요청한다. Channel channel = ...channel.writeAndFlush(message); Channel은 ChannelPipeline으로 메시지를 전달한다. ChannelPipeline은 기본적으로 TailContext와 HeadContext를 가진다. (Pipeine의 시작과 끝이라 할 수 있다.) Tail과 Head 사이에는 사용자가 등록한 ChannelHandlerContext가 체인 구조로 연결되고, 전달된 메시지가 체인을 따라 Outbound 방향으로 흘러간다. ChannelPipeline이 메시지가 각각의 Handler를 거칠 때 마다, Handler에게 바인딩된 EventExecutor 쓰레드와 현재 메시지 전송을 요청하고 있는
netty의 thread 모델
netty
2024. 5. 22.
이벤트 루프란 이벤트를 실행하기 위한 무한루프 스레드를 말한다. 위의 그림과 같이 객체에서 발생한 이벤트는 이벤트 큐에 입력되고 이벤트 루프는 이벤트 큐에 입력된 이벤트가 있을 때 해당 이벤트를 꺼내서 이벤트를 실행한다. 이것이 이벤트 루프의 기본 개념이다. 이벤트 루프는 지원하는 스레드 종류에 따라서 단일 스레드 이벤트 루프와 다중 스레드 이벤트 루프로 나뉜다. 이것을 reactor pattern이라 부르기도 한다. single thread event loop 현재는 다중 코어나 CPU를 장착한 시스템이 일반적이므로 최신 애플리케이션은 시스템 리소스를 효율적으로 활용하기 위해 정교한 멀티스레딩 기법을 이용하는 경우가 많다. 자바 초창기의 멀티스레딩 체계는 동시 작업 단위를 실행하기 위해 필요할 때마다 새
webFlux와 netty
netty
2024. 5. 22.
Spring MVC는 기본적으로 블럭킹이고 동기방식을 사용한다. 비동기 처리 기능이 스프링 프레임워크 3에서 추가되어 지원된다고 하지만, 서블릿은 응답을 기다리는 동안 pool의 스레드들은 여전히 지연시킬 수 있기 때문에 전체 stack이 reactive 해야 하는 요구를 충족시킬 수 없다. 이러한 요구사항에 맞추어 스프링 프레임워크5에 도입된 대안적인 모듈이 바로 WebFlux이고, 웹 요청을 reactive 하게 다루는 데에 초점이 맞추어져 있다. 기존의 서블릿 기반의 Spring Boot는 Tomcat을 기반으로 동작한다. 반면 Spring Boot WebFlux는 여러 가지를 고를 수 있는데, Default로 Netty를 사용한다. Netty를 사용하는 이유는 tomcat은 요청 당 하나의 스레드가
module.exports와 exports
nodejs
2024. 5. 22.
모듈이란 관련된 코드들을 하나의 코드 단위로 캡슐화 하는 것을 말한다. greeting.js 라는 파일이 있다. 이 파일은 두개의 함수를 포함하고 있다. greetings.jssayHelloInEnglish = function() { return "Hello";}; sayHelloInSpanish = function() { return "Hola";}; 모듈 추출하기(exporting) gretting.js의 코드를 다른 파일에서 사용해보자. 우선 외부에서 사용할 함수에 아래와 같이 export 설정을 해주어야 한다. greetings.jsexports.sayHelloInEnglish = function() { return "HELLO";};exports.sayHelloInSpanish = fun
puppeteer
nodejs
2024. 5. 22.
Puppeteer는 Headless Chrome 혹은 Chromium 를 제어하도록 도와주는 라이브러리이다. Puppeteer는 Node 6 이상 에서 동작하며, Chrome 혹은 Chromium의 DevTools 프로토콜을 통해 각 Chrome 혹은 Chromium의 API를 제어한다. Headless Browser Headless Browser는 일반적으로 사용자가 사용하는 GUI 에서 동작하는 것이 아닌 CLI(Command Line interface) 에서 작동하는 브라우저이다. 백그라운드에서 동작하며, 일반적인 브라우저와 같이 웹페이지에 접속하여 HTML, CSS로 DOM Tree와 CSSOM Tree를 만들고, JS 엔진을 구동한다. 유일한 차이점은 만든 화면을 사용자에게 보여주지 않는다는 점이다
v8과 libuv
nodejs
2024. 5. 22.
Node.js는 js 코드를 V8 엔진으로 해석하여 실행하고, 비동기 작업을 libUV에게 위임하여 논 블로킹 I/O를 지원한다. 각 요소의 구체적인 동작 방식에 대해 알아보자. V8 V8은 구글이 C++로 개발한 자바스크립트 엔진으로 JS 코드 기계어로 해석하여 OS가 실행할 수 있는 상태로 만들어준다. JIT(Just-In-Time) 방식으로 코드를 해석한다. GC를 위해 메모리 영역을 Heap(New space, Old space), Stack으로 나누어 관리한다. libUV libUV는 운영체제의 커널을 추상화하여 C++로 작성된 Wrapping 라이브러리이다. Node.js는 기본적으로 libUV 위에서 동작하며, node 인스턴스가 뜰 때, libuv에는 워커 쓰