1월, 2021의 게시물 표시

Spring Boot Admin Server, Client config 설정하기

이미지
 Spring Boot로 많은 프로젝트를 진행하게 됩니다. 많은 모니터링 도구가 있지만, Spring Boot 어플리케이션을 쉽게 모니터링 할 수 있는 방법을 소개하려고 합니다.   코드 중심으로 살펴보겠습니다. 1. 어드민 서버 구축 1-1. 디펜던시 추가 dependencies { // https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-server implementation 'de.codecentric:spring-boot-admin-starter-server:2.5.4' } 1-2. 어드민 서버 설정 활성화 @SpringBootApplication @EnableAdminServer public class ServerApplication { public static void main (String[] args) { SpringApplication. run (ServerApplication. class, args) ; } } EnableAdminServer를 하면 됩니다. 2. 클라이언트 서버 설정  예제는 book-client, member-client 2가지 클라이언트, member-client가 2개의 인스턴스 실행으로 작성했습니다.  2-1 디펜던시 추가 dependencies { // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web implementation 'org.springframework.boot:spring-boot-starter-web:2.5.4' // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-actuator implementation 'org.spring...

자바 스프링 설정값 사용하기

이미지
자바에서 스프링 설정 읽는 두가지 방법을 설명하겠습니다. 자바 설정을 통하여 읽어 올 수 있습니다. @Configuration @PropertySource ( "classpath:filename.properties" ) 파일에 include를 정의하여 읽어 올 수 있습니다. 스프링부트에서 기본적으로 applicaion.*를 설정 파일을 읽어오도록 되어 있습니다. 스프링부트 > 설정 파일 예시 *.yml 파일에서 읽을 파일 목록 정의하기 spring : profiles : include : - env - datasource - redis application-env.yml 파일에 설정 정의 env : api : host : localhost.withccm 정의된 설정값 사용하기 import org.springframework.beans.factory.annotation. Autowired ; import org.springframework.beans.factory.annotation. Value ; import org.springframework.context.annotation. Configuration ; import org.springframework.core.env.Environment ; @Value ( "${env.api.host}" ) private String apiHost ; @Autowired private Environment env ; public String getApiHost () { return env .getProperty( "env.api.host" ) ; } @Value 어노테이션을 통하여 정의된 사용할 값을 할당하여 사용합니다. 읽어야할 설정이 많은 경우 일일히 정의해야 하기 때문에 선언 부분이 길어질 수 있습니다. 또는 스프링 환경인 Environment 를 주입 받아, getProperty 함수를 호출하여 사...

MySQL PK 중복 (duplicate key ) 해결 방법

데이터베이스에 데이터를 입력하다보면 pk가 중복되어 오류(duplicate key)가 발생하는 경우가 있습니다. 이런 경우를 방지하기 위해서 조회를 해보고 없으면 신규 인서트(삽입), 있으면 무시하거나 업데이트 하도록 종종 개발할 때가 있습니다. 어플리케이션에서 조회하고 다음 쿼리를 호출하게 되는 경우 동시성 문제가 발생할 수 있어요. 그리고 조회해서 쿼리를 또 사용할 경우 네트워크 비용이 발생하는 단점이 있습니다. (성능이 좋지 못함) 동시성 문제란 여러 스레드나 프로세스에서 동일한 데이터를 접근할때 발생할 수 있고, 이때 데이터가 실제 데이터와 다른현상이 발생합니다. 예를들어 a, b 스레드에서 데이터를 조회하여 빈 값을 획득한경우 신규 데이터 인서트를 a와 b에서 실행하게 될때(순사적으로 실행되었다고 가정), b의 인서트를 실행할때 이미 a가 인서트 완료했기 때문에 오류가 발생합니다.  위의 문제를 쿼리를 통해 간단히 해결할 수 있습니다. user_log : 사용자로그 테이블  - userNo : 사용자번호 (PK) - lastLogAt : 마지막활동기록 PK중복인 경우 업데이트 (단건) INSERT INTO user_log SET userNo = 123, lastLogAt = 202101201043 ON DUPLICATE KEY UPDATE lastLogAt = 202101201043 INSERT INTO user_log (userNo, lastLogAt) VALUES (123, 202101201043) ON DUPLICATE KEY UPDATE lastLogAt = 202101201043 mybatis <insert id ="insert" parameterType ="map" > INSERT INTO user_log SET userNo = #{userNo}, lastLogAt = #{lastLogAt} ON DUPLICATE ...

자바 스프링 MVC에서 LocalDateTime 타입으로 파라미터 받기

웹에서 전달한 파라미터를 서버에서 문자열(String) 타입이 아닌 자바 시간 타입을 받으면 서버에서 별도의 문자열 포맷딩을 할 필요없이 사용할 수 있습니다. 웹 클라이언트에서 전달하는 코드 const startDate = moment ( '2021-01-13' , 'YYYY-MM-DD' ). startOf ( 'day' ). format ( 'YYYY-MM-DDTHH:mm:sszz' ) console . log (startDate) // //2021-01-13T00:00:00 axios. get ( "http://localhost/search?startDate" + startDate). then ((response) => { console . log (response) }) 위의 예시는 날짜기준 조회 예시입니다. 날짜 단위로 조회하기 위해 startOf 함수를 사용하여 시간을 0으로 변경하였다. 자바 스프링 MVC import org.springframework.format.annotation. DateTimeFormat ; // 클래스정의 생략 @GetMapping ( "/search" ) public void getSearch ( @DateTimeFormat (iso = DateTimeFormat .ISO. DATE_TIME ) @RequestParam LocalDateTime startDate) { // action } LocalDateTime의 타입으로 데이터를 받으려면, DateTiemFormat을 정의해주면 됩니다.