Request Parameter 기본값 지정하기

@RequestParam 어노테이션을 이용해서 지정할 수 있다. defaultValue라는 속성에 자신이 원하는 기본값을 지정해주면 된다. @GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam(defaultValue = "test") String id) { return "ID: " + id; } 참고 자료 https://www.baeldung.com/spring-request-param

2024-09-15 · 1 min · 32 words

request body로 enum 값 받기

목표 사용자가 request body로 string 값을 보냈을 때, enum으로 자동으로 매핑시켜서 컨트롤러 파라미터로 넘어오기를 원한다. Spring 기본 처리 Spring MVC에서는 StringToEnumConverterFactory 클래스가 String을 Enum 객체로 변환하려고 시도한다. 이 때, Enum.valueOf() 메소드를 통해서 변환을 시도한다. 이 때 일치하는 Enum 타입이 없다면, ConversionFailedException이 발생한다. Custom Converter 사용하기 Converter 인터페이스를 이용해서 변환을 커스텀 할 수도 있다. public class StringToEnumConverter<T extends Enum<?>> implements Converter<String, T> { private final Class<T> type; public StringToEnumConverter(Class<T> type) { this....

2024-09-15 · 1 min · 88 words

Repository를 사용하여 데이터 개수 제한하기

top이나 first를 사용하면된다. 따로 개수를 표기하지 않으면 1개의 데이터만 가져온다. User findFirstByOrderByLastnameAsc(); User findTopByOrderByAgeDesc(); Page<User> queryFirst10ByLastname(String lastname, Pageable pageable); Slice<User> findTop3ByLastname(String lastname, Pageable pageable); List<User> findFirst10ByLastname(String lastname, Sort sort); List<User> findTop10ByLastname(String lastname, Pageable pageable); 참고 자료 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.limit-query-result

2024-09-15 · 1 min · 37 words

Redis 서버 구성하기

설치 및 구성 redis-server를 실행한다. $ sudo apt update $ sudo apt install redis-server redis-server가 서비스 환경으로 구동될 수 있도록 설정 supervised systemd $ sudo systemctl restart redis.service 외부에서 접근 가능하도록 수정 bind 0.0.0.0 $ sudo systemctl restart redis 패스워드 설정 requirepass ${내가 원하는 패스워드} $ sudo systemctl restart redis 확인 참고 자료 https://xerar.tistory.com/80 https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04 https://infoscoco.com/92

2024-09-15 · 1 min · 56 words

Redis Transaction

목표 redis를 이용한 작업 중에서 원자적으로 동작해야되는 로직이 필요했다. 이를 위해 redis에서 transaction을 사용하는 방법을 이해한다. 방법 Redis에서 MULTI가 트랜잭션의 시작을 나타내고 EXEC가 트랜잭션의 커밋, DISCARD가 롤백을 나타낸다. RedisTemplate 자체애도 multi(), exec()가 있지만, 각 커맨드가 같은 connection에서 실행된다는 보장이 없다. 이를 위해 SessionCallback 인터페이스로 하나의 커넥션에서 수행할 연산을 전달한다. //execute a transaction List<Object> txResults = redisTemplate.execute(new SessionCallback<List<Object>>() { public List<Object> execute(RedisOperations operations) throws DataAccessException { operations.multi(); operations.opsForSet().add("key", "value1"); // This will contain the results of all operations in the transaction return operations....

2024-09-15 · 1 min · 97 words

Redis Lock 사용하기

목표 Distributed Lock의 목적을 이해한다. Spring Integration을 이용해서 Redis Lock을 사용해본다. Distributed Lock 자바에서 제공하고 있는 Lock은 하나의 프로세스에서 생성되는 여러 스레드에서 공유 자원에 접근할 때, 스레드간 동기화를 위해서 사용한다. 따라서, 여러 프로세스가 공유 자원을 상호 배타적으로 사용하기 위해서는 자바의 Lock으로는 처리가 불가능하다. 이를 가능하게 해주는 락이 distributed lock이다. Spring integration에서 구현할 수 있는 distributed lock에는 대표적으로 JDBC와 redis를 이용하는 방법이 있다. Spring Integration을 이용한 Redis Lock 사용해보기 의존성 추가 <dependency> <groupId>org....

2024-09-15 · 2 min · 280 words

Redirection( , )과 Pipe( ) 차이

Redirection은 (>의 경우) 왼쪽 프로그램의 출력을 오른쪽으로 지정한다. 파일 등으로 지정할 수 있다. pipe는 왼쪽 프로그램의 output을 오른쪽 프로그램의 input으로 사용한다.

2024-09-15 · 1 min · 21 words

Record Lock

목표 record lock이 무엇인지 이해한다. 목적 index에 걸리는 락 SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE이고 c1에 대해서 인덱스가 걸려있는 경우에, 다른 트랜잭션에서 t.c1 = 10 인 값을 수정하지 않도록 막아야된다. UPDATE 쿼리를 수행할 때 c1 같은 secondary index로 조건을 건다면, innoDB에서 secondary index로 PK를 찾고, PK를 통해서 행을 조회하므로, c1 = 10과 그에 해당하는 모든 PK에 record lock이 걸린다. 참고 자료 https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-record-locks

2024-09-15 · 1 min · 66 words

README

도서 ‘교보문고 > 컴퓨터/IT 베스트 셀러’ 중 백엔드 개발자와 관련된 도서(2024.08.13 기준 출판한지 6개월 이상된 책만 필터링) 이미 읽은 책은 제외 가상 면접 사례로 배우는 대규모 시스템 설계 기초: https://product.kyobobook.co.kr/detail/S000001033116 가상 면접 사례로 배우는 대규모 시스템 설계 기초 2: https://product.kyobobook.co.kr/detail/S000211656186 그림과 작동 원리로 쉽게 이해하는 AWS 구조와 서비스: https://product.kyobobook.co.kr/detail/S000200882352 만들면서 배우는 클린 아키텍처: https://product.kyobobook.co.kr/detail/S000001766486 카프카 핵심 가이드: https://product.kyobobook.co.kr/detail/S000201464167 자바 ORM 표준 JPA 프로그래밍: https://product.kyobobook.co.kr/detail/S000000935744 HTTP 완벽 가이드: https://product.kyobobook.co.kr/detail/S000001033001 도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지: https://product....

2024-09-15 · 1 min · 117 words

range() 역순으로 사용하기

range(start, stop, step) 라는 정의를 사용하면 된다. step이 다음 숫자로 이동하는 변화량이다. range(5, -1, -1) 참고 자료 https://stackoverflow.com/questions/7286365/print-a-list-in-reverse-order-with-range/21714738

2024-09-15 · 1 min · 18 words

QueryDSL 시작하기

상황에 따라 쿼리문이 동적으로 변하는 기능이 필요했다. 이 기회에 QueryDSL을 사용해서 이를 구현해보고자 한다. 의존성 추가 QueryDSL을 사용하기 위해서는 의존성을 추가할 뿐만의 아니라 약간의 설정이 필요하다. QueryDSL은 프로젝트 내에 있는 Entity들을 스캔하여 JPAAnnotationProcessor 을 통해 Q 클래스를 생성한다. Q 클래스를 통해 엔티티의 필드 값을 통한 쿼리문을 쉽게 작성할 수 있게 해준다. @Entity 같은 JPA 관련 어노테이션을 탐지할 수 있도록 하기위해서 ‘javax.persistence-api’, ‘javax.annotation-api’를 함께 annotationProcessor에 추가해준다. sourceSets 부분은 개발환경에서 Q 클래스에 접근할 수 있도록 하기위해 설정해주는 부분이다....

2024-09-15 · 2 min · 340 words

Python 기초 문법

참고자료: 점프 투 파이썬 숫자형 출력 print("asdf") 조건문 if if a > 1: print("a is greater than 1") 반복문 for for a in [1, 2, 3]: print(a) 반복문 while while i < 3: i=i+1 print(i) 함수 def add(a, b): return a+b add(3,4) 제곱 a ** b 나누기 7 / 4 나눗셈 몫 7 // 4 문자열 문자열 표현 4가지 "Hello World" 'Python is fun' """Life is too short, You need python""" '''Life is too short, You need python''' 문자열 연결 >>> head = "Python" >>> tail = " is fun!...

2024-09-15 · 20 min · 4181 words

PropertySourcesPlaceholderConfigurer

배경 Spring Boot의 자동-구성을 사용하지 않으니 @Value("\${...}") 어노테이션으로 property가 가져와지지 않았다. 원인 PropertySourcesPlaceholderConfigurer: bean 정의 프로퍼티 값이나 @Value를 Spring 내 Environment와 PropertySource의 집합으로 처리해주는 클래스이다. Spring Boot로 실행시에는 자동-구성으로 bean으로 등록된다. Environment: 현재 실행 중인 Spring 애플리케이션의 환경을 나타내는 인터페이스. 가지고 있는 데이터로 profile과 properties로 나눌 수 있다. profile: 특정 프로필이 활성화 된 경우에만 bean이 등록되도록 사용할 수 있다. properties: properties 파일, JVM 시스템 properties, 시스템 환경 변수 등을 출처로 가져온다....

2024-09-15 · 1 min · 174 words

property vs function

배경 코틀린 스터디 중에 커스텀 접근자(프로퍼티)와 함수를 언제 사용하면 좋을지 고민하는 시간을 가졌다. 코틀린 공식 문서 코틀린 공식 문서의 코딩 컨벤션에서는 아래의 경우 프로퍼티를 사용하는 것을 권장하고 있다. 예외를 던지지 않는다. 계산이 복잡하지 않다. (또는 최초 실행 결과가 캐시된다) 객체의 상태가 변경되지 않는 경우 호출에 대해 동일한 결과를 반환한다. 내 생각 프로퍼티를 객체의 상태를 표현하는 용도로 사용하는 것이 가장 적절하다는 생각이 들었다. 코틀린 공식 문서에서 제공하고 있는 가이드가 객체의 상태를 표현할 때만 사용한다면 위배되지 않는다....

2024-09-15 · 1 min · 78 words

properties에 비밀 번호 남는 문제 해결

현재는 일단 properties에 비밀번호를 입력하지 않고 실행시 아래와 같이 실행하도록 구현해뒀다 java -jar -Dspring.datasource.password=abcd1234 abc.jar 환경 변수를 이용하는 방법도 있다. https://stackoverflow.com/questions/37404703/spring-boot-how-to-hide-passwords-in-properties-file

2024-09-15 · 1 min · 21 words

Progressive JPEG 파일 저장

https://www.notion.so/85433ee030e7453b86ef84f399faa415 여기에서 이어지는 내용이다. JPEG파일을 Progressive JPEG로 저장되도록 구현하려고 했다. ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("jpg").next(); JPEGImageWriteParam imageWriteParam = new JPEGImageWriteParam(null); imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); imageWriteParam.setCompressionQuality(0.4f); imageWriteParam.setProgressiveMode(ImageWriteParam.MODE_DEFAULT); imageWriter.setOutput(imageOutputStream); image = ImageIO.read(file); IIOImage iioImage = new IIOImage(image, null, null); imageWriter.write(null, iioImage, imageWriteParam); 위 코드와 같이 setProgressiveMode() 메서드를 사용하면 쉽게 설정이 가능하다. 참고 자료 https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=kkforgg&logNo=221499435383 https://stackoverflow.com/questions/34178759/how-to-use-cfimage-to-save-image-as-progressive-jpg

2024-09-15 · 1 min · 49 words

proejct property 설정하여 Spring boot profile 설정하기

위의 방법으로 gradle을 실행시킬 때 project property를 설정할 수 있다. SPRING_PROFILES_ACTIVE=local ./gradlew build sonarqube --info 위의 방법으로 gradle 빌드할 때 spring의 프로필을 설정할 수 있다. 참고 자료 https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties https://stackoverflow.com/questions/23367507/how-to-pass-system-property-to-gradle-task

2024-09-15 · 1 min · 29 words

PriorityQueue에 이미 추가된 객체의 값을 수정하기

결론부터 생각해보면 당연하지만 코딩테스트 문제를 풀다가 실수한 내용이라 기록해본다. 이미 PriorityQueue에 추가된 값을 수정해도, 자동으로 heapify가 진행되지 않는다. 어떻게 해결했는가 PriorityQueue에 있는 값을 계속해서 수정해야 되는 경우가 있어서 soft delete 방법을 응용해서 해결했다. 값을 수정해야 되는 객체를 soft delete 시킨다. 해당 객체에서 값을 수정한 결과를 새로 인스턴스로 만들어 PriorityQueue에 추가한다. PriorityQueue에서 pop했을 때, deleted된 객체는 무시해버린다. 참고 자료 https://stackoverflow.com/questions/1871253/updating-java-priorityqueue-when-its-elements-change-priority

2024-09-15 · 1 min · 59 words

POST vs PUT vs PATCH

이를 이해하기 위해서는 멱등성이라는 개념을 알아야된다. 멱등성은 동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니는지를 나타내는 성질이다. 대표적으로 GET, PUT, DELETE가 멱등성을 가지고, POST, PATCH는 멱등성을 가지지 않는다. PUT의 경우에는 요청의 body 내용을 그대로 리소스를 교체하게 되지만, PATCH는 사이드 이펙트가 있는 업데이트다. https://junroot.github.io/programming/REST/#http-메서드를-사용하여-요청의-의미를-가지게-하기

2024-09-15 · 1 min · 49 words

Pointcut Designators

목표 pointcut을 표현할 수 있는 pointcut designators를 알아본다. this, target this: 현재 호출되는 joinpoint의 위치를 제한할 때 사용 target: 메서드를 호출하는 대상 객체를 제한할 때 사용 @Pointcut("target(com.baeldung.pointcutadvice.dao.BarDao)") @Pointcut("this(com.baeldung.pointcutadvice.dao.FooDao)") args 호출하는 메서드의 파라미터를 제한할 때 사용 메서드 명이 find로 시작하고, Long 타입 파라미터 하나만 있는 경우 @Pointcut("execution(* *..find*(Long))") 메서드 명이 find로 시작하고, 파라미터 개수는 상관없지만 첫 번째 파라미터가 Long인 경우 @Pointcut("execution(* *..find*(Long,..))") @target 호출된 객체의 클래스에 지정된 어노테이션이 있는 경우로 제한할 때 사용 @Pointcut("@target(org....

2024-09-15 · 1 min · 141 words