파일 이름에서 확장자 분리

splitext 함수를 호출하고 마지막 요소가 확장자가 된다. import os ext = os.path.splitext(full_filename)[-1] 참고 자료 https://wikidocs.net/39

2024-09-15 · 1 min · 15 words

파라미터로 넘어오는 값 확인하기

MyList myList = mock(MyList.class); ArgumentCaptor<String> valueCapture = ArgumentCaptor.forClass(String.class); doNothing().when(myList).add(any(Integer.class), valueCapture.capture()); myList.add(0, "captured"); assertEquals("captured", valueCapture.getValue()); https://www.baeldung.com/mockito-void-methods

2024-09-15 · 1 min · 15 words

파드에 환경 변수로 데이터 넘겨주기

목표 디플로이먼트를 이용해서 파드를 생성할 때, 파드에서 필요한 데이터를 환경 변수로 설정되도록 하여 넘겨주고자 한다. 파드에 넘겨줄 데이터를 클러스터에서 어떻게 관리할지도 고민해본다. ConfigMap 클러스터 내에 기밀이 아닌 데이터를 저장하는 데 사용하는 API 오브젝트다. 파드는 ConfigMap을 환경 변수, 파라미터 볼류의 구성 파일로 사용할 수 있다. 아래와 같이 명령어로 바로 ConfigMap을 만들 수도 있고, yaml 파일을 이요해서 만들 수도 있다. kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm apiVersion: v1 kind: ConfigMap metadata: creationTimestamp: 2022-02-18T19:14:38Z name: special-config namespace: default resourceVersion: "651" uid: dadce046-d673-11e5-8cd0-68f728db1985 data: special....

2024-09-15 · 2 min · 299 words

특정 필드가 없는 도큐먼트 조회 쿼리

목표 특정 필드가 없는 도큐먼트 조회 쿼리 작성법을 이해한다. exists exists 쿼리를 통해서 필드를 존재하는 도큐먼트를 필터링할 수 있다. GET /_search { "query": { "exists": { "field": "user" } } } 아래 예시와 같이 must_not을 통해 필드가 없는 도큐먼트도 조회가 가능하다. GET /_search { "query": { "bool": { "must_not": { "exists": { "field": "your_field" } } } } } 참고 자료 https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html https://stackoverflow.com/questions/29357148/how-to-filter-out-fields-that-do-not-exist-in-elastic-search

2024-09-15 · 1 min · 63 words

특정 포트를 사용하고 있는 프로세스 찾기

lsof -i :포트번호 참고 자료 https://sas-study.tistory.com/281

2024-09-15 · 1 min · 6 words

특정 패키지에 있는 클래스들의 빈 생성자 전부 호출하기

1. 특정 패키지에 있는 클래스 가져오기 이전에 학습했던 System Class Loader를 이용하면 특정 패키지에 있는 모든 클래스를 가지고 올 수 있다. private Set<Class<?>> findAllClassesUsingClassLoader(String packageName) { final InputStream stream = ClassLoader.getSystemClassLoader() .getResourceAsStream(packageName.replaceAll("[.]", "/")); final BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(stream))); return reader.lines() .filter(line -> line.endsWith(".class")) .map(line -> getClass(line, packageName)) .collect(Collectors.toSet()); } private Class<?> getClass(String className, String packageName) { final String classPath = packageName + "." + className.substring(0, className.lastIndexOf('.')); try { return Class....

2024-09-15 · 1 min · 201 words

특정 파드 로그 확인하기

목표 특정 파드에 발생하는 로그를 실시간으로 확인한다. 특정 파드가 재시작 되었을 때 이전 인스턴스의 로그를 확인한다. 방법 기본적으로 kubectl logs <파드 id> 로 파드의 로그를 확인할 수 있다. -f 옵션은 follow의 약자로 로그가 스트리밍 되는 옵션이다. kubectl logs -f <파드 id> 에러 등으로 인해 파드가 재시작되었다면, 재시작 원인을 분석하기 위해 이전 인스턴스의 로그를 확인할 필요도 있다. -p: previous의 약자 kubectl logs -p <파드 id> 참고 자료 https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#logs https://stackoverflow.com/questions/39454962/kubectl-logs-continuously https://www.digitalocean.com/community/questions/how-to-check-the-logs-of-running-and-crashed-pods-in-kubernetes

2024-09-15 · 1 min · 69 words

특정 컬럼에 null이 아닌 row의 개수 구하기

sum(case when [session.id](http://session.id/) is null then 0 else 1 end) case 키워드를 이용하면 된다. 참고 자료 https://www.sqlshack.com/working-with-sql-null-values/

2024-09-15 · 1 min · 17 words

특정 주기마다 실행되는 메서드

Spring task라는 내장된 기능 통해 특정 메서드를 주기적으로 실행하는 것이 가능하다. 스케쥴링 지원 활성화 Configuration에 @EnableScheduling 어노테이션을 추가하면 활성화된다. @Configuration @EnableScheduling public class SpringConfig { ... } fixed 방식 fixed 방식에는 2가지가 있다. fixedDelay: 작업이 종료된 시간부터 지정된(ms단위) 시간 뒤에 재실행. fixedRate: 작업이 시작된 시간부터 지정된(ms단위) 시간 뒤에 재실행. @Scheduled(fixedDelay = 1000) public void scheduleFixedDelayTask() { System.out.println( "Fixed delay task - " + System.currentTimeMillis() / 1000); } @Scheduled(fixedRate = 1000) public void scheduleFixedRateTask() { System....

2024-09-15 · 1 min · 181 words

특정 문자열로 시작하는 값 조회

방법 CONCAT을 이용해야 된다. SELECT * FROM TABLE_NAME WHERE COLUMN_NAME LIKE CONCAT(‘%’, #{searchKeyword}) 참고 자료 https://dongram.tistory.com/12

2024-09-15 · 1 min · 16 words

특정 메소드가 호출된 횟수 검증

Mockito.verify(utilClass, Mockito.times(1)).method(); https://stackoverflow.com/questions/57775074/mockito-veify-is-giving-wrong-invocation-count

2024-09-15 · 1 min · 3 words

특정 디렉토리의 하위 디렉토리 검색

os.walk() 함수를 사용하면 된다. import os for (path, dir, files) in os.walk("c:/"): for filename in files: ext = os.path.splitext(filename)[-1] if ext == '.py': print("%s/%s" % (path, filename)) 참고 자료 https://wikidocs.net/39

2024-09-15 · 1 min · 30 words

특정 디렉토리의 파일 리스트

import os os.listdir(dirname) 참고 자료 https://wikidocs.net/39

2024-09-15 · 1 min · 6 words

특정 디렉토리에 있는 전체 파일 가져오기

Files.walk 메소드는 현재 입력받은 경로로부터 파일 트리를 전부 탐색해서 stream 으로 반환한다. Files.walk(Paths.get("folder")) .filter(Files::isRegularFile) .forEach(System.out::println); folder\file1.txt folder\file2.txt folder\subfolder\file3.txt folder\subfolder\file4.txt 현재 디렉토리에 있는 파일만 가져올 경우는 list() 메소드를 사용하면 된다. Files.list(Paths.get("folder")) .filter(Files::isRegularFile) .forEach(System.out::println); folder\file1.txt folder\file2.txt https://stackoverflow.com/questions/1844688/how-to-read-all-files-in-a-folder-from-java https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html

2024-09-15 · 1 min · 36 words

특정 경로에 파일이 존재하는 경우에 따른 분기 처리

문법 [ {parameter} {FILE 경로} ] parameter -e: 파일이 존재하면 true 리턴 -f: regular file이 존재하면 true 리턴 -r: 읽기 권한이 있는 파일이 존재하면 true 리턴 -w: 쓰기 권한이 있는 파일이 존재하면 true 리턴 -x: 실행 권한이 있는 파일이 존재하면 true 리턴 -d: 디렉토리가 존재하면 true 리턴 예시 FILE="$1" if [ -f "$FILE" ]; then echo "File $FILE exist." else echo "File $FILE does not exist" >&2 fi 참고 자료 https://www....

2024-09-15 · 1 min · 71 words

특정 Endpoint만 Interceptor를 거치도록 구현

아래와 같이 인터셉터를 추가할 때 addPathPatterns 를 통해 일부 경로에 대해서만 인터셉터를 처리할 수 있다. @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AdminAccessInterceptor(administratorService)) .addPathPatterns("/api/games/**", "/api/tags/**", "/api/sliders/**", "/api/admins/**"); } } 하지만 WAS가 HTTP를 받았을 때 항상 IP가 웹 서버(NGINX)의 IP로 인식되는 문제가 있었다. 문제 해결 WAS는 중간에 있는 리버스 프록시의 IP를 인식하는 문제가 있었다. 보통 요청을 보낸 Client의 IP 를 확인하기 위해서 X-Forwarded-For 헤더를 사용한다고 한다....

2024-09-15 · 1 min · 186 words

트랜잭션 스크립트 패턴 vs 도메인 모델 패턴

배경 팀 코드를 읽어보게 되었는데, 트랜잭션 스크립트 패턴에 가까운 형태를 취하고 있었다. 지금까지 도메인 모델 패턴을 사용해온 입장에서는 상당히 절차지향 적이고 유지보수하기 힘들어보였는데, 이 두 가지 패턴이 어떤 장단점이 있는지 비교해본다. 개인적인 견해는 강조 표시로 표기했다. 트랜잭션 스크립트 패턴 프레젠테이션 레이어에서 오게되는 단일 요청별로 처리되는 메서드가 각각 존재하는 패턴이다. 비즈니스 로직을 처리하는 하나의 기능을 스크립트라고 표현한다. 일반적으로 유스케이스 하나당 하나의 클래스를 가진다. class BuyProductBO { List<Product> getProducts(string filter) { /* some database query */ } void putInCart(int productId, int amount) { ....

2024-09-15 · 2 min · 317 words

트랜잭션 관련 주의점

배경 @Transactional을 붙여놓은 테스트에서 XXXRepository로 저장한 데이터들이 Awaitility 사용시에만 조회되지 않는 이슈가 있었다. Awaitility.await().pollInterval(100, TimeUnit.MILLISECONDS).until({ XXXRepository.listByIds(ids) }) { it.size == 5 } 원인 Awaitility는 기본적으로 별도의 스레드로 동작하기 때문에 위와 같은 예시에서는 같은 트랜잭션으로 묶이지 않는다. 테스트와 같은 스레드에서 동작하기를 원한다면 pollInSameThread()를 사용해야 된다. Awaitility.with().pollInSameThread().await().atMost(1000, TimeUnit.MILLISECONDS).until { XXXRepository.listByIds(ids).size == 5 } 참고 자료 https://github.com/awaitility/awaitility/wiki/Usage#thread-handling

2024-09-15 · 1 min · 54 words

통합 테스트에서 사용되는 패턴

이 글은 아래 글을 한국어로 정리한 것이다. https://medium.com/swlh/usual-production-patterns-applied-to-integration-tests-50a941f0b04a Basics: build, operate, check 모든 통합테스트는 build, operate, check 단계를 가진다. build: 테스트 시나리오를 준비하는 단계. 일반적으로 데이터에비스에 데이터를 추가한다. operate: 테스트할 API나 객체의 메서드를 호출한다. check: 실행한 API나 메서드의 결과가 예상한대로 동작했는지 확인한다. build 단계: 데이터 추가 build 단계에 테스트 시나리오를 위해 데이터베이스에 데이터를 추가해야된다. 데이터를 추가하는 방법으로는 3가지가 있다. 테스트 중인 시스템의 API 호출 순수 SQL 사용 Repository Layer 사용 테스트 중인 시스템의 API 호출 이는 안티패턴이 될 수 있다....

2024-09-15 · 2 min · 343 words

통합 테스트에 @Transactional을 붙이면 안되는 이유

배경 통합 테스트중에 DB에 추가된 데이터를 제거하기 위해서 @Transactional을 사용하는 경우가 있다. 이럴 경우 버그가 있어 실패해야될 테스트가 통과되어버리는 문제가 발생할 수 있다. @SpringBootTest @Transactional internal class CartItemsControllerTests { ... @Test fun getAllCartItems() { val cart = Cart() cart.addProduct(product, 3) cartsRepository.save(cart) mockMvc.perform(get("/carts/{id}/items", cart.id)) .andExpect(status().isOk) .andExpect(jsonPath("$.[*].id").value(hasItem(cart.items[0].id.toString()))) .andExpect(jsonPath("$.[*].product.id").value(hasItem(product.id.toString()))) .andExpect(jsonPath("$.[*].product.name").value(hasItem(product.name))) .andExpect(jsonPath("$.[*].quantity").value(3)) } } 이유 서비스에 @Transactional이 붙어있지 않아서 실패되어야할 요청이 통과되어버린다. lazy loading이 동작하지 않아서 실패해야 되는 경우에도 통과 되어버린다. 변경 탐지가 동작하지 않아서 실패해야 되는 경우에도 통과 되어버린다....

2024-09-15 · 1 min · 107 words