본문 바로가기

소프트웨어-이야기/프로그래밍 언어와 프레임워크

Java14. Record Keyword java 14 이전 버전에서는 데이터 클래스를 생성하려면, 여러 보일러 플레이트 코드가 필요하다. 다음 샘플처럼 hashcode, equals, toString 함수를 추가해줘야한다. public class Person { private final String name; private final String address; public Person(String name, String address) { this.name = name; this.address = address; } @Override public int hashCode() { return Objects.hash(name, address); } @Override public boolean equals(Object obj) { if (this ..
Spring과 의존성 주입 (DI) 의존은 변경에 의해 영향을 받는 관계를 의미한다. DI는 의존하는 객체를 직접 생성하는 대신 의존 객체를 전달받는 방법을 말한다. 의존성 주입 위치별 특징 의존성을 주입하는 방법은 크게 3가지이다. 1. Constructor Injection 클래스를 생성할 때, 모든 의존성 객체를 주입하기 때문에 NPE 문제를 방지할 수 있다. final 인자를 사용할 수 있기 때문에 불변성을 유지할 수 있다. 반면, 여러 객체를 의존하고 있는 경우 의존성 객체를 주입하는 코드가 복잡해지고 이해하기 어려워진다. 그러나 여러 객체를 의존한다는 것은 SRP (단일 책임 원칙)을 위배하는 것이기 때문에 베드스멜인 상황이다. 의도적으로 의존 객체를 줄여야한다는 위기의식을 줄 수 있기 때문에 권장되는 방식이다. 2. Sette..
Hibernate Query Plan Cache란? JPQL 쿼리 혹은 Criteria 쿼리는 AST(Abstract Syntax Tree)으로 파싱된다. 그래야 하이버네이트가 SQL문을 실행할 수 있다. 이와 같은 쿼리 컴파일 시간을 단축시키기 위해 하이버네이트는 Query Plan Cache를 사용한다. 네이티브 쿼리인 경우, 하이버네이트에서 파라미터와 반환 타입에 대한 정보를 추출하여 ParameterMetadata에 저장한다. 모든 실행마다 하이버네이트는 Cache를 확인하여 Query Plan이 있는지 확인한다. 없는 경우에만 Query Plan을 새로 생성한 후, 향후 재사용을 위해 캐시에 값을 저장한다. Query Plan Cache 설정 Query Plan Cache는 두가지 속성으로 설정할 수 있다. hibernate.query.plan_..
Domain services vs Application services 본 글에서는 도메인 서비스에 대해서 정리하고자 한다. 도메인 서비스와 애플리케이션 서비스의 차이점, 도메인 서비스를 사용할 때의 이점에 대해서도 설명하고자 한다. 1. Domain services와 Application services의 차이점 도메인 서비스는 entity와 VO에 자연스럽게 맞지 않는 도메인 지식을 제공하는 경우가 있다. 하지만 도메인 서비스를 도입하는 또다른 이유가 있다. 이는 도메인 모델 격리 (isolation)과 관련있다. Domain Service, Application Service는 entity, VO를 상위에서 다루는 stateless한 클래스를 의미한다. 이렇게 보면 둘은 꽤 유사해 보인다. 그러나 도메인 서비스는 도메인 로직을 갖고 있지만, 애플리케이션 서비스는 그렇지..
Hibernate-type-52 - Entity에 Postgresql Jsonb 타입 선언하기 Note Hibernate는 Postgresql의 Jsonb 타입을 지원하지 않는다. Jsonb 타입을 엔터티의 속성으로 적용하고 싶은 경우 hibernate-types-52 오픈 소스를 적용하거나, Hibernate의 UserType을 사용하여 커스텀한 Jsonb 타입을 구현해야한다. Code (1) 의존성 추가하기 dependencies { compile('com.vladmihalcea:hibernate-types-52:2.10.0') } (2) Entity Class에 TypeDef 어노테이션 선언하기 (3) 프로퍼티에 jsonb Type, Column 어노테이션 선언하기 (4-1) 샘플 - JsonBinary 타입 선언하기 @Entity(name = "Event") @Table(name = "ev..
[Django] Django에서 MultiProccess 사용 시 주의사항 Django에서는 하나의 프로세스에서 하나의 커넥션을 맺는 것을 가정하고 있다. 그러나 Python에서는 프로세스를 사용하는 경우, 자식 프로세스에서 부모 프로세스의 자원을 복제한다. 때문에 Django에서 멀티프로세스를 사용하는 경우, 위와 같은 처리 때문에 오류가 발생하기 쉽다. 해당 문제의 대표적인 해결안으로는 자식 프로세스 시작 시, 모든 커넥션을 닫아주는 방법이 있다. def close_service_connections(): # close db connections, they will be recreated automatically db.connections.close_all() # close ES connection, needs to be manually recreated connection..
(Django) Django에서 Thread를 다룰 때 주의할 점 💡한줄 요약 Django 스크립트에서 Thread를 사용하는 경우, Thread가 종료될 때 명시적으로 DB Connection을 닫아주는 것이 좋다. Djagno에서 Thread를 사용할 때, DB Connection이 관리되는 방식 Django에서 DB에 접근하는 Thread를 사용하는 경우, Thread마다 새로운 DB Connection을 생성된다. Django는 request가 종료될때, request_finished signal을 발생시켜 지난 DB Connection들을 모두 닫는다. ( 참고 - DB Connection을 관리하는 방법 ) 즉, Thread에서 만들어진 DB Connnecion은 Thread를 실행시킨 메인 프로세스가 종료될 때 닫힌다. import threading fro..
(Celery) 트랜잭션이 커밋된 이후에 Celery Task 전송하기 트랜잭션 안에서 Celery Task가 호출되는 경우, 트랜잭션이 커밋되기 전에 Task가 실행될 수 있다. 이 때, Task가 커밋되지 않은 데이터를 참조하는 경우, 오류가 발생할 수 있다. 위와 같은 상황의 예시와 이를 회피하는 방법에 대해서 정리해보고자 한다. 문제상황 아래의 코드는 회원가입을 처리하는 가상의 코드이다. from django.db import transaction from coupon.util import create_welcome_coupon from mileage.util import create_welcome_mileage @transaction.atomic() def create_user(user_data): user = User.objects.create(**user_dat..