Sociable Unit Test vs Integration Test

테스트하고자 하는 객체가 다른 객체에 의존하고 있으면 그것은 단위 테스트가 아닌가? Sociable Unit Test와 Integeration Test는 궁극적으로 테스트의 목표가 다르다. Integration Test는 2개이상의 모듈이 있을 때, 각 모듈의 정확성보다는 제대로 협력하는지를 테스트한다. 따라서 Integration Test는 모든 경우를 모두 테스트할 필요는 없다. Sociable Unit Test는 모든 경우의 수에 제대로 동작하는지 테스트를 한다. 종속되는 대상을 이미 테스트하고 있다면, 굳이 독립적인 테스트를 만들 필요가 없다. 이미 종속되는 테스트를 완료했으며, 만약 너가 TDD를 하고있다면 테스트를 실패하는 원인을 찾기 어렵다는 점도 없을 것이다....

2024-09-15 · 1 min · 81 words

snake case 필드를 camel case로 역직렬화 하기

목표 아래와 같이 snake case로 필드가 존재하는 json을 camel case로 역직렬화 하는 방법이 필요했다. { "first_name": "Jackie", "last_name": "Chan" } 방법1: @JsonProperty 사용 @JsonProperty 어노테이션을 사용하면, 해당 필드와 매핑되는 json 프로퍼티의 이름을 지정할 수 있다. public class UserWithPropertyNames { @JsonProperty("first_name") private String firstName; @JsonProperty("last_name") private String lastName; // standard getters and setters } 방법2: @JsonNaming 사용 @JsonNaming을 클래스 위에 명시하면 현재 클래스의 역직렬화 이름 전략을 설정할 수 있다. 아래와 같이 명시하면 클래스의 필드를 json의 snake case로 찾아서 매핑한다....

2024-09-15 · 1 min · 98 words

setter 메서드로 변경 추적이 되지 않는 문제 해결

Room room = Room.builder() .id(1L) .game(game) .tags(tags) .build(); room.join(user); roomRepository.save(room); 위와 같은 코드가 있는데 roomRepository.getById(1L) 해도 user가 비어있다. @Transactional어노테이션을 붙이니 해결이 됐는데 원인을 모르겠다. 현재 추정: 트랜잭션과 변경 감지 roomRepository.save()를 호출하면 트랜잭션을 기준으로 저장되는 것으로 추정된다. 따라서 위의 코드는 @Transactional 이 없기 때문에 트랜잭션에 모아둔 커밋이 없기 때문에 단순하게 Room Entity 자체만 저장이 되는것같다. (users는 연관관계의 주인이 아니기때문에 저장되지 않는다.) JpaRepository의 코드를 보기로 했다. JpaRepository의 기본 구현체는 SimpleJpaRepository 로 이 부분에 save 메서드가 구현되어 있었다....

2024-09-15 · 1 min · 175 words

Routing

목표 SvelteKit의 라우팅 방법을 이해한다. SvelteKit의 라우팅 SvelteKit은 파일 시스템 기반으로 라우트를 구성한다. 원하는 URL 경로와 일치하는 디렉토리를 코드에 정의하면 된다. src/routes: root 경로 src/routes/: /about 경로의 라우팅 src/routes/blog/[slug]: slug라는 파라미터를 받으면서, /blogs/[slug] 경로의 라우팅 파라미터를 받으려면 동적 라우팅이 필요한데, prerender=true 에서는 사용할 수 없다. SvelteKit이 아닌 https://github.com/jorgegorka/svelte-router 같은 별도의 라우터를 사용해야된다. 모든 route 디렉토리에는 하나 이상의 route 파일이 필요하다. 이는 + prefix로 구분한다. +page, +error, +layout 등 +page +page.svelte 해당 경로의 페이지를 정의한다....

2024-09-15 · 1 min · 142 words

RestAssured로 Rest docs 사용하기

MockMvc로 사용중인 Spring rest docs를 RestAssured로 바꿔보자. 의존 추가 testImplementation 'org.springframework.restdocs:spring-restdocs-restassured' 테스트 코드 private RequestSpecification spec; @BeforeEach public void setUp(RestDocumentationContextProvider restDocumentation) { this.spec = new RequestSpecBuilder() .addFilter(documentationConfiguration(restDocumentation)) .build(); } body 내용을 예쁘게 표시하고 싶다면 아래와 같이 구성하면된다. @BeforeEach protected void setUp(final RestDocumentationContextProvider restDocumentation) throws Exception { this.specification = new RequestSpecBuilder() .addFilter(documentationConfiguration(restDocumentation).operationPreprocessors() .withResponseDefaults(prettyPrint())) .build() ; rest api 호출 RestAssured.given(this.spec) .accept("application/json") .filter(document("index")) .when().get("/") .then().assertThat().statusCode(is(200)); 필드 설명을 추가하고 싶다면 아래와 같이 필터를 지정하면 된다....

2024-09-15 · 1 min · 86 words

REST DOCS가 빌드 시 자동 생성되도록 gradle build 수정하기

의존 추가 없이 구현이 가능했다. asciidoctor에서 최종 문서가 저장되는 위치를 설정하는 방법이 적혀있어서 참고했다. outputDir를 통해 자신이 원히는 경로를 지정할 수 있다. jar 파일을 만들기 전에 build/resources/main/static/docs 경로에 rest docs 파일을 추가하여 수동으로 문서를 커밋하지 않아도 빌드시에 만들어지도록 구현했다. // build.gradle asciidoctor { attributes 'snippets': snippetsDir inputs.dir snippetsDir outputDir "build/resources/main/static/docs" dependsOn test } bootJar { dependsOn asciidoctor } 참고 자료 https://asciidoctor.github.io/asciidoctor-gradle-plugin/development-3.x/user-guide/

2024-09-15 · 1 min · 61 words

ResourceBundleMessageSource 파헤치기

목표 ResourceBundleMessageSource가 다국어 값을 가져오는 과정을 이해한다. ResourceBundleMessageSource에 기본 Locale을 설정하는 방법을 이해한다. ResourceBundleMessageSource Spring Boot에서 다국어를 처리할 때 기본적으로 사용하는 MessageSource 인터페이스의 구현체 액세스한 ResourceBundle 인스턴스와 각 메시지에 대해 생성한 MessageFormat을 캐싱한다. MessageSource Spring에서 만든 메시지를 매개 변수화 및 i18n화 할 때 사용하는 전략 인터페이스 아래 3가지의 메소드가 존재한다. ResourceBundle Java에서 만든 Locale 별로 리소스(예: 문자열)가 필요한 경우 이를 번들로 묶어서 관리해주는 클래스 이를 상속해서 property file로부터 각 Locale 별로 문자열을 관리하는 PropertyResourBundle도 존재한다....

2024-09-15 · 1 min · 161 words

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