Period d-day를 구해야하는 로직에 Period class의 between 메서드를 사용했다. LocalDate start = LocalDate.of(2023, 1, 1); LocalDate end = LocalDate.of(2023, 8, 9); Period between = Period.between(start, end); int days = between.getDays(); log.info("days={}", days); //days=8 실제로 start 와 end의 날짜는 220일 차이가 나지만 getDays()의 결과는 8이 나온다. Period 클래스는 년, 월, 일 을 모두 이용해서 기간을 나타낸다. LocalDate start = LocalDate.of(2023, 1, 1); Loc..
외부 설정 외부설정이란? 하나의 애플리케이션을 여러 환경에서 실행해야 할 때가 있다. 대표적으로 개발자들이 사용하는 개발 환경, 실제 운영 서버와 같은 데이터로 테스트를 진행하는 테스트 서버, 실제 고객에게 서비스하는 운영 환경이 있다. 각각 환경에 따라서 서로 다른 설정값을 사용한다. 각 환경에 같은 코드를 사용하면서 다른 설정을 하기 위한 방법이 외부에서 설정값을 주입해주는 방법이다. 유지보수하기 좋은 애플리케이션 개발의 가장 기본 원칙은 변하는 것과 변하지 않는 것을 분리하는 것이다. 외부 설정을 통해 각 환경에 따라 변하는 외부 설정값은 분리하고, 변하지 않는 코드와 빌드 결과물은 유지했다. 빌드 과정을 줄이고, 환경에 따른 유연성을 확보할 수 있다. 외부설정방법 OS 환경 변수 : OS에서 지원..
프록시 기술의 한계 JDK 동적 프록시와 CGLIB를 사용해서 AOP 프록시를 만드는 방법에는 각각 장단점이 있다. JDK 동적 프록시는 인터페이스가 필수이고, 인터페이스를 기반으로 프록시를 생성한다. CGLIB는 구체 클래스를 기반으로 프록시를 생성한다. 물론 인터페이스가 없고 구체 클래스만 있는 경우에는 CGLIB를 사용해야 한다. 인터페이스가 있는 경우에는 JDK 동적 프록시나 CGLIB 둘중에 하나를 선택할 수 있다. ProxyFactory에 proxyTargetClass 옵션에 따라서 둘중 하나를 선택해서 프록시를 만들 수 있다. proxyTargetClass = false JDK 동적 프록시를 사용해서 인터페이스 기반 프록시 생성 proxyTargetCalss = true [default] C..
TypeHandler란 Mybatis가 PreparedStatement에 파라미터를 셋팅하거나 ResultSet에서 값을 가져올 때마다 적절한 Java Type으로 변환하기 위해 TypeHandler를 사용한다. Mybatis에는 default TypeHandler 들이 있다. https://mybatis.org/mybatis-3/configuration.html#typeHandlers mybatis – MyBatis 3 | Configuration Configuration The MyBatis configuration contains settings and properties that have a dramatic effect on how MyBatis behaves. The high level stru..
김영한님 스프링 고급편 강의를 듣고 정리.. AOP 소개 핵심 기능과 부가 기능 분리 부가기능의 문제점 부가 기능을 적용할 때 아주 많은 반복이 필요하다. 부가 기능이 여러 곳에 퍼져서 중복 코드를 만들어낸다. 부가 기능을 변경할 때 중복 때문에 많은 수정이 필요하다 부가 기능의 적용 대상을 변경할 때 많은 수정이 필요하다. 부가 기능을 핵심 기능에서 분리하고 한 곳에서 관리하도록 했다. 그 부가 기능과 부가 기능을 어디에 적용할 지 선택하는 기능을 합해서 하나의 모듈로 만들었는데, 이를 바로 애스펙트(aspect)이다. 이것이 바로 @Aspect 이다. 그리고 스프링이 제공하는 어드바이저도 어드바이스(부가 기능)과 포인트컷(적용 대상)을 가지고 있어서 개념상 하나의 애스펙트이다. 이렇게 애스펙트를 사용..
docker image 어플리케이션을 실행되기 위한 코드와 그 종속성 있는 것들을 패키징한 단위 읽기 전용 템플릿 container없이 존재 가능 컴퓨팅 자원 필요 없음 docker container docker image를 실행시키면 docker container docker image의 인스턴스 docer image 없이 존재할 수 없음 하나의 docker image로 여러개의 컨테이너를 만들 수 있음 컴퓨팅 자원 필요 pod k8s에서 배포 가능한 가장 작은 단위 pod는 하나 이상의 container그룹 파드 vs 컨테이너 컨테이너는 애플리케이션을 말한다. 완전한 애플리케이션일 수도 있고, 일부 기능일 수도 있다. 일부 기능이라면 여러개의 컨테이너가 모여서 파드를 구성한다. 완전한 기능이라면 하나..
SOLID 원칙은 객체지향 프로그래밍에서 지켜야 할 5대 설계원칙을 말한다. 1. SRP (Single Responsibility Principe : 단일책임의 원칙) SRP는 작성된 클래스는 하나의 기능만 가지며 클래스가 제공하는 모든 서비스는 그 하나의 책임을 수행하는데 집중되어 있어야 한다는 원칙이다. 이는 어떤 변화에 의해 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 함을 의미한다. SRP원리를 적용하면 무엇보다 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있다. 뿐만 아니라 책임을 적절히 분배함으로써 코드의 가독성 향상, 유지보수 용이라는 이점까지 누릴 수 있으며 객체지향 원리의 대전제 격인 OCP뿐만 아니라 다른 원리들을 적용하는 기초가..
문자열을 추가하는 연산에서 StringBuilder가 String보다 성능이 좋다. 왜 그런지 알아보자. String은 immutable하기 때문이다. 불변하기 때문이다. String a = "a"; a = "a" + "b"; 이렇게 a 를 + 연산을 이용하여 문자열을 합치면 a 인스턴스를 "a" -> "ab"로 변경하는 것이 아니라 "ab"라는 새로운 문자열을 string pool에 새로 생성한 뒤 참조하게 해준다. 그 뒤 이전 "a" 문자열은 가비키 컬렉션 대상이 된다. 따라서 String 클래스를 사용하면 더욱 많은 시간과 메모리가 사용된다. 더보기 StringBuilder, StringBuffer가 문자열 연산에서 더 좋은 이유? String 클래스는 연산이 수행될 때마다 두 문자열을 모두 읽어 ..