Hyeon9mak / WIL

학습한 내용을 정리하자!
22 stars 3 forks source link

지식파편

너무너무 좋은 아티클 모음

BDDMockito 를 사용할 때 primitive type 에 대해서는 any() 를 사용할 수 없다.

만약 정수형일 경우?

  1. anyInt() 를 사용한다.
  2. 혹은 타입을 Integer 로 변환한다.

gradlew 명령어는 sudo 로 만들어진 파일 편집 권한이 없다.

만약 sudo 명령을 통해 관리자 권한으로 파일, 디렉토리를 생성한 경우 ./gradlew 명령어를 통해 이를 편집할 수 없다.

$ ./gradlew clean build

(clean 명령어를 통해 .build 디렉토리를 제거할 수 없음.)

때문에 만약 아래와 같이 sudo ./gradlew build 명령어 등을 통해서 디렉토리를 개설한 경우, 수동으로 디렉토리와 파일들을 제거해주어야 한다.

$ sudo ./gradlew clean build

$ sudo rm -rf ...


argocd helm chart 에 주석을 달면 안된다.

argocd helm chart 를 이용한 spring batch parameter 관리 중 아래와 같이 주석을 달아두었었다.

{{=sprig.date("20060102", sprig.dateModify("+9h", sprig.now()))}} # 금일

그러자 아래와 같이 sql syntax 에러가 발생했다.

PSQLException: ERROR: invalid input syntax for type timestamp: \"20240321 # 전 일 \"

argocd helm chart 파일은 주석 기호를 구분하지 못하고 곧이 곧대로 문자열을 기입한다.

@ConfigurationProperties 를 통해 환경변수를 불러올 때 간혹 실패하는 경우

@ConstructorBinding  
@ConfigurationProperties(prefix = "aws.s3")  
data class AwsS3Properties(  
  val bucket: Bucket,  
  val mockS3: MockS3 = MockS3(),  
) {  
  data class Bucket(  
    val name: String,  
    val cloudFrontBaseUrl: String  
  )  

  data class MockS3(  
    val port: Int = 8111,  
    val mockObjectDirectory: String = "s3"  
  )  
}
@ConfigurationProperties(prefix = "aws.s3")  
data class AwsS3Properties(  
  val bucket: Bucket,  
  val mockS3: MockS3 = MockS3(),  
) {  
  data class Bucket(  
    val name: String,  
    val cloudFrontBaseUrl: String  
  )  

  data class MockS3(  
    val port: Int = 8111,  
    val mockObjectDirectory: String = "s3"  
  )  
}

추가 내용은 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0.0-M2-Release-Notes 참고.

성능 부하 발생 명령어

$ systemctl
$ amazon-linux-extras install -y epel
$ yum install -y stress-ng
$ stress-ng --cpu 1 --cpu-load 70% --timeout 10m --metrics --times --verify
# CPU 정보 확인
$ cat /proc/cpuinfo | grep name

# 메모리 용량 확인
$ cat /proc/meminfo | grep MemTotal

# 프라이빗 IP 주소 확인
$ ip -br -c addr show eth0

# 퍼블릭 IP 주소 확인
$ curl ipinfo.io/ip

# 스토리지 (EBS 볼륨 확인)
$ lsblk
$ df -hT -t xfs

PostgreSQL major upgrade 시 챙겨야할 주의점

When upgrading major versions pg_upgrade does not copy existing statistics over to the new version of the DB. It is recommended to run VACUUM ANALYZE or at least ANALYZE after pg_upgrade.

RDB 테이블 정규화는 왜 중요한가?

intellij 에서 gradle 프로젝트를 정상적으로 찾지 못할 때

ES 몇 가지..

query IN (null)

sub query NOT IN

모듈별 코드 옮기기 트러블 슈팅

겪은 문제

원인

해결방법

presignedURL

mongo db and search

@Transactional(propagation = Propagation.REQUIRES_NEW)`

spring actuator

@Component class CustomInfoContributor : InfoContributor {

override fun contribute(builder: Info.Builder) { builder.withDetail("info", "OK") } }


## ConstructorBinding
```kotlin
@ConstructorBinding  
@ConfigurationProperties("work-book")

https://codingdog.tistory.com/entry/spring-boot-constructorbinding-%EC%83%9D%EC%84%B1%EC%9E%90%EB%A1%9C-binding%EC%9D%84-%EC%8B%9C%ED%82%A8%EB%8B%A4

제네릭 공변성과 반공변성

Redis 도입을 통[[hyeon9mak/wil/지식파편]]한 성능 개선

서비스의 성능은 여러 단계로 확인할 수 있다.

nGrinder를 이용해 테스트를 진행한다.

테스트 시나리오 대상

가장 중요한 것은 어떤 성능을 중점적으로 측정할 것인가?
사용자 트래픽이 많은 파트, 가장 중요한 파트를 측정하는게 효율적이다. 경쟁사이트 또는 유사 사이트의 성능을 조사해서 지표로 삼는 것도 좋다. 즉, 자기 서비스에 대한 이해가 우선 되어야 한다.

성능 목표

성능 목표를 지정하는 방법은 여러가지가 있지만, CU 강의에서 제시해주신 방법은 크게 3가지

  1. DAU (1일 사용자 수)
  2. 피크 시간대 집중률 (최대 트래픽 / 평소 트래픽)
  3. 1명당 1일 평균 요청 수

3가지가 모두 합쳐져서 Throughput: 1일 평균 rps ~ 1일 최대 rps가 만들어진다.

계산 방법은 아래와 같다.

java reflection

getMethods()

상속한 메서드를 포함해서, 접근제한자가 public 인 메서드들만 가져온다.

Class<?> animalCLass = Student.class;
Method[] methods = animalClass.getMethods();

"toString", "getName", "getAge", 
"wait", "wait", "wait", "equals", "hashCode",
"getClass", "notify", "notifyAll"

별별 거 다 가져온다.

getDeclaredMethods()

상속한 메서드를 제외하고, 접근제한자에 관계없이 직접 코드로 선언된 메서드들을 가져온다.

Class<?> animalClass = Student.class;
Method[] methods = animalClass.getDeclaredMethods();

"getAge", "toString", "getName"

getConstructor, getDeclaredConstructor도 마찬가지.

LogBack JPA query 설정

logback.xml 설정에서 JPA query는 application.yml 프로필의 hibernate 옵션 설정을 따른다.

Querydsl 은 insert query 를 지원하지 않는다.

Spring Data Envers 는 navtive query 를 대상으로 동작하지 않는다.

성능 테스트 및 하드웨어 스펙 조절

enum 에 없는 타입이 전달 되었을 때 예외를 발생시키지 않고 기본 enum 을 선택하게 할 수 있는 방법

@JsonEnumDefaultValue 을 이용한다.

json 은 정규표현식 사용이 어렵다.

{} 를 이용한 depth 가 깊기 때문에 정규표현식 활용이 어렵다. json parser 라이브러리를 적극 활용하자. 대부분 readTree 를 통해 해결 가능하다.

캐싱할 땐 항상 중복주의

해싱을 하기 때문에 같은 데이터도 별개 id 로 저장될 수 있다.

CPU 가 기하급수적으로 튈 때

request dto no args constructor 왜 안됨?

intellij settings > Build, Execution, Deployment > Build Tools > Gradle 메뉴의 Build and Run 설정을 Gradle 로 변경

Redis 공부

JPA Bulk delete

Request header is too large

https://goateedev.tistory.com/126

CDC 가 추적하지 않는 것

CDC 는 truncate 를 추적하지 않는다.

디버깅이 너무 오래걸릴 때

AWS VPC

VPC

Subnet

Availability Zone (AZ, 가용 영역)

Security Group (SG, 보안 그룹)

Querydsl 에서 Projections.constructor 표현식에 nullable 한 인자 전달하기

java.lang.NullPointerException: Parameter specified as non-null is null: method com.kidsworld.main.domain.dto.PaperSubDto.<init>, parameter linkType
  1. groupBy 절로 묶어서 Map 으로 가져와서 일일히 매핑한다.
  2. 별개 DTO 를 만들어서 @QueryProjection 을 붙인다.

1번 방법의 경우 간단한 테이블에서는 문제가 해결된다. 그러나 1:N:N 으로 2depth 이상 계위가 들어가는 구조에서는 상당히 복잡하다. 때문에 엔티티가 붙는게 조금 껄끄럽지만, @QueryProjection 를 사용해서 문제 해결했음.

AWS Gateway API

No Constructor" Deserializer module

New module -- jackson-module-no-ctor-deser -- now included in jackson-modules-base -- added to support a very specific use case of POJOs that do not have either:

  1. No-arguments ("default") constructor, nor
  2. @JsonCreator annotated constructor or factory method

in which case module can force instantiation of values without using any constructor, using JDK-internal implementation (included to support JDK serialization itself). Note that this module may stop functioning in future, but appears to work at least until JDK 14.

jackson 라이브러리 2.13 버전부터는 default 생성자 없이도 @RequestBody 어노테이션을 이용하는 request DTO 생성이 가능하다. 언제 지원이 끊길지는 알 수 없으나, JDK 14 버전까지는 잘 동작하는 중.

AutoConfigureTestDatabase

포트어댑터 패턴에서 집중해야 하는 것은 코드 재사용성이 아니라, 어댑터 모양에 알맞는 포트는 무엇이든 끼울 수 있다는 뜻의, 결국 포트의 규격만 맞춰서 어떻게 구현하든 상관없는, 다른 유스케이스에서 사용하는 혹은 다른 의존체의 모양을 신경쓸 필요 없이 나의 유스케이스에만 맞춰서 코드를 작성하면 되는 격리성에 집중해야하는거 아닐까?