9-값 타입

값 타입 3가지 기본값 타입 자바 기본 타입(int, double) 래퍼 클래스(Integer) String 임베디드 타입 컬렉션 값 타입 기본값 타입 값 타입은 다른 엔티티와 공유하면 안 된다. 임베디드 타입(복합 값 타입) 임베디드 타입을 사용하려면 다음 2가지 어노테이션이 필요하다. 참고로 둘 중 하나는 생략해도 된다. @Embeddable: 값 타입을 정의하는 곳에 표시 @Embedded: 값 타입을 사용하는 곳에 표시 임베디드 타입은 기본 생성자가 필수다. 임베디드 타입과 테이블 매핑 잘 설계한 ORM 애프리케이션은 매핑한 테이블의 수보다 클래스의 수가 더 많다....

2025-02-10 · 3 min · 485 words

멀티 모듈 사용시 JaCoCo 구성

배경 멀티 모듈을 사용하는 maven 프로젝트가 있다. A, B 모듈이 존재하고, B 모듈이 A 모듈을 의존하고 있다. B 모듈에서 실행한 테스트들이 A 모듈 코드의 테스트 커버리지를 채우지 못하는 문제가 SonarQube에서 발생했다. 싱글 모듈에서 SonarQube가 테스트 커버리지를 측정하는 방법 SonarQube는 직접 테스트 커버리지 측정을 지원하지 않는다. 다른 툴을 이용해서 테스트 커버리지 분석 보고서를 생성하고, SonarQube에게 보고서의 위치를 알려줘서 커버리지를 출력하도록 한다. Java 프로젝트는 일반적으로 JaCoCo를 사용해서 보고서를 생성한다. maven의 JaCoCo 플러그인을 이용해서 보고서를 생성한다....

2025-02-04 · 2 min · 357 words

Spring log4j2 적용기

log4j vs logback vs log4j2 를 비교 해보고 log4j2를 사용해보기로 결정했다. Spring Framwork에 log4j2를 적용한 과정을 정리해본다. 의존 중복 처음에 log4j2 의존을 아래와 같이 추가해서 실행하니 에러가 발생했다. SLF4J가 여러 개 바인딩 되어서 발생한 문제였다. implementation 'org.springframework.boot:spring-boot-starter-log4j2:2.6.3' Spring Boot에 로깅 모듈을 제외 시켜서 해결할 수 있다. implementation('org.springframework.boot:spring-boot-starter-data-jpa:2.6.2') { exclude module: "spring-boot-starter-logging" } 멀티 프로필 Spring Boot에서는 Logback처럼 프로필 별 xml 자동 감지가 안된다. properties 파일을 통해서 사용할 로깅 xml파일을 지정해줘야 된다....

2025-02-01 · 1 min · 184 words

Logging

System.out.println("*********제발 나와라*********"); 위 코드 한 줄은 아마 개발을 해본 대부분은 시도 해본 디버깅 방법일 것이다. 필자도 한 때 많이 이용한 방법이다. 특별한 기술이 없어도 내가 작성한 코드가 어떻게 흘러가는지, 어디까지 동작하는지 확인할 수 있다. 점차 IDE 사용법에 익숙해지면 알게 되는 좀 더 쉬운 디버깅 방법으로는 디버거가 있다. 디버거를 사용하면 특정 코드 라인에 도달했을 때, 각 변수의 주소, 값 등을 확인할 수 있어 디버깅할 때 용이하다. 하지만 이런 방법들은 한계가 있다....

2025-02-01 · 5 min · 917 words

Docker 네트워크

목표 도커 네트워크가 무엇인지 이해한다. 도커 네트워크 타입에 무엇이 있는지 이해한다. Docker Network Docker는 컨테이너 간, 호스트, 외부 네트워크와 통신을 하기위한 네트워크 시스템을 포함하고 있다. Docker Network 타입 bridge 컨테이너 끼리 서로 연결하고 외부 네트워크와 분리하는 네트워크 동일한 bridge 네트워크 내의 컨테이너는 IP 주소 또는 컨테이너 이름을 사용해서 통신할 수 있다. 컨테이너와 호스트 사이에 소프트웨어 기반의 bridge를 만들어준다. 기본적으로 아웃바운드 트래픽은 허용하지만, 인바운드 트래픽은 허용하지 않는다. port publish 를 통해서 특정 포트로의 인바운드 트래픽을 허용해준다....

2025-02-01 · 2 min · 394 words

Docker Stack 알아보기

목표 Docker Stack이 무엇인지 이해한다. Docker Stack의 사용법을 이해한다. Docker Stack 이란 Docker Swarm 은 Docker 컨테이너를 클러스터링하고 스케줄링하기 위한 컨테이너 오케스트레이션 툴이다. Docker Stack 은 기본적으로 Docker Swarm을 통해 실행된다. Docker Stack을 사용하면 Swarm에 분산된 컨테이너인 여러 서비스를 논리적으로 배포하고 그룹화할 수 있다. vs Docker Compose Docker Compose는 단일 노드에서 실행되는 컨테이너를 관리하기 위한 용도이고, Docker Stack은 Docker Swarm 모드로 실행되는 멀티 노드 환경에서 컨테이너를 관리하긴 위한 용도이다. 공통점 docker-compose....

2025-02-01 · 1 min · 158 words

SSO 이해하기

목표 SSO(Single sign-on)가 무엇인지 이해한다. SSO와 OAuth, SAML의 관계를 이해한다. SSO란 SSO: 하나의 자격 증명으로 여러 애플리케이션과 웹사이트에 인증할 수 있는 인증 방법이다. 예시: 구글 로그인으로 Gmail, YouTube 등 인증 가능 일반적인 SSO 흐름 사용자가 접근하려는 애플리케이션 또는 웹사이트(SP)를 접속한다. SP는 사용자 인증 요청의 일부로 사용자에 대한 일부 정보(이메일 등)가 포함된 토큰을 SSO 시스템과 같은 IdP에 보낸다. IdP는 사용자가 이미 인증되었는지 확인하며, 인증된 경우 사용자에게 SP 애플리케이션에 대한 액세스 권한을 부여하고 5단계로 건너뛴다....

2025-01-25 · 1 min · 179 words

8-프록시와 연관관계 관리

프록시 지연 로딩: 엔티티가 실제 사용될 때까지 데이터베이스 조회를 지연하는 방법 지연 로딩 기능을 사용하려면 실제 엔티티 객체 대신 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요한데 이것을 프록시 객체라 한다. JPA 표준 명세는 지연로딩의 구현 방법을 JPA 구현체에 위임했다. 하이버네이트는 지연 로딩을 지원하기 위해 프록시를 사용하는 방법과 바이트코드를 수정하는 두 가지 방법을 제공한다. 프록시 기초 엔티티를 직접 조회하면 조회한 엔티티를 실제 사용하든 사용하지 않든 데이터베이스를 조회하게 된다. Member member = em....

2025-01-24 · 4 min · 821 words

Docker 빌드 캐시

목표 Docker 빌드 시 캐시가 사용되는 방법을 이해한다. 레이어 Docker가 빌드될 때 캐시가 동작하는 방법을 이해하기 전에 먼저 Docker 이미지의 레이어가 무엇인지 이해해야 된다. 하나의 이미지는 여러 개의 레이어로 구성된다. 각 레이어는 Dockerfile에 있는 각 명령어의 빌드 결과다. 각 레이어는 이전 레이어과의 차이값을 나타내고 있다. 아래 Dockerfile이 있으면 그림과 같이 각 명령어의 결과가 하나의 레이어가 된다고 볼 수 있다. # syntax=docker/dockerfile:1 FROM ubuntu:latest RUN apt-get update && apt-get install -y build-essentials COPY main....

2025-01-21 · 1 min · 192 words

Cache Stampede

목표 Cache Stampede가 무엇인지 이해한다. Cache Stampede를 해결하기 위해 적용할 수 있는 방법을 이해한다. Cache Stampede 란? server side cache는 자주 바뀌지 않는 데이터에 대해서 데이터베이스 읽기 동작을 최소화 하기위해 캐싱한다. redis를 사용한다고 하면, redis로 데이터를 조회한 후 존재하지 않는다면 데이터베이스로 조회를 하고, 이를 redis에 저장한다. 이런 경우 일반적으로 캐시에 TTL(만료 기간)을 설정해둔다. 이 경우 트래픽이 1000rps 인 서비스에서 redis의 데이터가 TTL 만료가 되었다고 했을 때, 1초동안 redis에 캐싱을 하지 못 한다면 1초 동안 1000개의 요청이 모두 데이터베이스를 조회하면서 데이터베이스에 부하를 줄 수 있다....

2025-01-17 · 1 min · 202 words

3-Vue 3 기초

Vue 3 기초 Vue를 프로젝트에 포함하는 방법 2가지 CDN으로 부터 Vue 라이브러리를 Script에 포함하는 방법 라이브러리를 호스트 서버에 저장해둘 필요가 없기 때문에 네트워크 트래픽을 줄일 수 있다. 한번 브라우저에 내려오고 나면 대부분 디스크 캐시에 저장되어 재활용되기 때문에 매우 빠른 속도를 보여준다. npm/yarn을 이용하여 Vue 패키지를 설치하여 사용하는 방법 라이브러리의 의존성 관리를 자동으로 해준다. 라이브러리와 애플리케이션 코드를 하나 혹은 사용자가 설정한 청크의 개수로 컴파일하여 브라우저에 전달할 수 있다. 브라우저에서는 컴파일된 코드만 캐시하고 나면 서버로 추가적으로 받을 파일이 없으므로 굉장히 빠른 속도를 보여준다....

2025-01-17 · 9 min · 1780 words

12-아키텍처 스타일 정하기

도메인이 왕이다 육각형 스타일과 같은 도메인 중심의 아키텍처 스타일은 DDD의 조력자라고 말할 수 있다. 경험이 여왕이다 우리가 과거에 했던 일에 편안함을 느낀다면 무언가를 바꿀 필요가 없다. 육각형 아키텍처에 대한 확신이 없다면 지금 만들고 있는 애플리케이션의 작은 모듈에 먼저 시도해 보자. 그때그때 다르다 정답은 없다.

2025-01-14 · 1 min · 44 words

HTTP Redirect 시 Authorization 헤더 사라지는 현상

배경 어떤 구성원의 프로필 사진을 조회할 수 있는 API가 있다. 해당 API는 구성원의 프로필 사진 URL을 구해서, 302 응답을 내려준다. (Location 헤더에 프로필 사진 URL) 해당 API는 Authorization 헤더를 참조해 인증/인가 작업을 거친다. 프로필 사진 URL에 접근할 때도 Authorization 헤더가 필요하다. 프로필 사진 조회 API와 프로필 사진 URL의 호스트는 다르다. API를 호출해보니 리다이렉트는 되었지만 프로필 사진 URL 조회 시에 인증 실패가 발생한다. 원인 Postman이나 curl 명령어 등 대부분의 HTTP 클라이언트에서는 다른 호스트로 리다이렉트 될 때 Authorization 헤더는 유지하지 않고 요청을 보낸다....

2025-01-14 · 1 min · 126 words

7-고급 매핑

상속 관계 매핑 관계형 데이터베이스에는 객체지향 언어에서 다루는 상속이라는 개념이 없다. 슈퍼타입 서브타입 논리 모델을 실제 물리 모델인 테이블로 구현하는 방법 3가지 조인 전략: 모두 테이블로 만들고 조회할 때 조인을 사용한다. 단일 테이블 전략: 테이블을 하나만 사용해서 통합한다. 구현 클래스마다 테이블 전략: 서브 타입마다 하나의 테이블을 만든다. 조인 전략 엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략 주의 점: 타입을 구분하기 위한 컬럼이 추가 되어야 한다....

2025-01-14 · 6 min · 1248 words

3-컨테이너를 다루는 표준 아키텍처, 쿠버네티스

쿠버네티스 이해하기 쿠버네티스는 컨테이너 오케스트레이션을 위한 솔루션이다. 오케스트레이션: 복잡한 단계를 관리하고 요소들의 유기적인 관계를 미리 정의해 손쉽게 사용하도록 서비스를 제공하는 것 다수의 컨테이너를 유기적으로 연결, 실행, 종료할 뿐만 아니라 상태를 추적하고 보존하는 등 컨테이너를 안정적으로 사용할 수 있게 만들어준다. 쿠버네티스 구성 요소 간 통신 마스터 노드 kubectl: 쿠버네티스 클러스터에 명령을 내리는 역할을 한다. 다른 구성 요소들과 다르게 바로 실행되는 멍령 형태인 바이너리로 배포되기 때문에 마스터 노드에 있을 필요는 없지만, 통상적으로 API 서버와 주로 통신하므로 이 책에서는 API 서버가 위치한 마스터 노드에 구성했다....

2025-01-14 · 13 min · 2759 words

10-아키텍처 경계 강제하기

경계와 의존성 가장 안쪽 계층에는 도메인 엔티티가 있다. 애플리케이션 계층은 애프리케이션 서비스 안에 유스케이스를 구현하기 위해 도메인 엔티티에 접근한다. 어댑터는 인커밍 포트를 통해 서비스에 접근하고, 반대로 서비스는 아웃고잉 포트를 통해 어댑터에 접근한다. 설정 계층은 어댑터와 서비스 객체를 생성할 팩터리를 포함하고 있고, 의존성 주입 메커니즘을 제공한다. 접근 제한자 package-private 제한자: 패키지 내에 있는 클래스들은 서로 접근 가능하지만, 패키지 바깥에서는 접근할 수 없다. 모듈의 진입점으로 활용될 클래스들만 골라서 public으로 만들면, 의존성이 잘못된 방향을 가리켜서 의존성 규칙을 위반할 위험이 줄어든다....

2025-01-14 · 2 min · 359 words

11-의식적으로 지름길 사용하기

왜 지름길은 깨진 창문 같을까? 품질이 떨어진 코드에서 작업할 때 더 낮은 품질의 코드를 추가하기가 쉽다. 코딩 규칙을 많이 어긴 코드에서 작업할 때 또 다른 규칙을 어기기도 쉽다. 지름길을 많이 사용한 코드에서 작업할 때 또 다른 지름길을 추가하기도 쉽다. 유스케이스 간 모델 공유하기 유스케이스마다 다른 입출력 모델을 가져야 한다. 유스케이스가 입출력 모델을 공유하는 것은 단일 책임 원칙에서 이야기하는 ‘변경할 이유’를 공유하는 것이다. 유스케이스 간 입출력 모델을 공유한느 것은 유스케이스들이 기능적으로 묶여 있을 때 유요하다....

2025-01-07 · 2 min · 369 words

9-애플리케이션 조립하기

왜 조립까지 신경 써야 할까? 아키텍처에 대해 중립적이고 인스턴스 생성을 위해 모든 클래스에대한 의존성을 가지는 설정 컴포넌트(configuration component)가 있어야 한다. 이유: 코드 의존성이 올바른 방향을 가리키게 하기 위해 부수효과: 클래스가 필요로 하는 모든 객체를 생성자로 전달 수 있다면 실제 객체 대신 목으로 전달할 수 있고, 이렇게 되면 격리된 단위 테스트를 생성하기 쉬워진다. 설정 컴포넌트의 역할: 우리가 제공한 조각들로 애플리케이션을 조립 설정 파일이나 커맨드라인 파라미터 등과 같은 설정 파라미터의 소스에도 접근할 수 있어야 한다....

2025-01-02 · 2 min · 373 words

10-애노테이션과 리플렉션

애노테이션 선언과 적용 애노테이션 적용 코틀린에서 @Deprecated 애노테이션은 대신할 수 있는 패턴을 제시할 수 있다. @Deprecated("Use new(index) instead.", ReplaceWith("new(index)")) fun deprecated(index: Int) { println("deprecated: index") } fun new(index: Int) { println("new: $index") } 애노테이션의 인자로는 원시 타입의 값, 문자열, enum, 클래스 참조, 다른 애노테이션 클래스, 그리고 지금까지 말한 요소들로 이뤄진 배열이 들어갈 수 있다. 클래스 애노테이션 인자로 지정할 때는 @MyAnnotation(MyClass::class) 처럼 ::class를 클래스 이름 뒤에 넣어야 한다. 다른 애노테이션을 인자로 지정할 때는 인자로 들어가는 애노테이션의 이름 앞에 @를 넣지 말아야된다....

2025-01-02 · 4 min · 743 words

7-아키텍처 요소 테스트하기

테스트 피라미드 단위 테스트: 피라미드의 토대 일반적으로 하나의 클래스를 인스턴스화하고 해당 클래스의 인터페이스를 통해 기능들을 테스트한다. 만약 테스트 중인 클래스가 다른 클래스에 의존한다면 의존되는 클래스들은 인스턴스화하지 않고 테스트하는 동안 필요한 작업들을 흉내 내는 목으로 대체한다. 통합 테스트: 여러 유닛을 인스턴스화하고 시작점이 되는 클래스의 인터페이스로 데이터를 보낸 후 유닛들의 네트워크가 기대한대로 잘 동작하는지 검증한다. 이 책에서 정의한 통합 테스트에서는 두 계층 간의 경계를 걸쳐서 테스트할 수 있기 때문에 객체 네트워크가 와넞ㄴ하지 않거나 어떤 시점에는 목을 대상으로 수행해야 한다....

2024-12-18 · 3 min · 452 words