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...

Oauth jwt example

이미지
Oauth jwt API WEB 예제 샘플 코드 https://github.com/withccm/oauth-jwt-example API 서버와 WEB 클라이언트 oauth 로그인 인증 예제로 구성

리눅스 centos 프로세스 한번에 죽이기(kill)

이미지
서버를 직접 운영하다 보면 프로세스를 관리해야할 때가 있습니다. 이때 유용한 명령어를 소개 드립니다. 부모 데몬 확인방법 pstree -p | grep httpd httpd (아파치)는 찾고싶은 프로세스입니다. 프로세스 한번에 죽이기 pgrep httpd | xargs kill httpd라는 프로세스를 죽이고 싶을때 사용하면 됩니다.

자바스크립트 숫자 확인

자바스크립트에서 문자열 또는 변수가 숫자인지 아닌지 확인 방법입니다.  NaN은 Not a Number 의 약자입니다. isNaN은 Number에 포함된 함수 입니다. console . log ( isNaN ( 0 )) // false console . log ( isNaN ( '0' )) // false console . log ( isNaN ( '' )) // false console . log ( isNaN ( 1 )) // false console . log ( isNaN ( '1' )) // false console . log ( isNaN ( 'a' )) // true 논리 부정연산자 ! 를 붙이면 숫자인지 여부를 반환합니다. console . log (! isNaN ( 0 )) // true console . log (! isNaN ( '0' )) // true console . log (! isNaN ( '' )) // true console . log (! isNaN ( 1 )) // true console . log (! isNaN ( '1' )) // true console . log (! isNaN ( 'a' )) // false Number 함수를 이용하여 확인해 볼게요. console . log ( Number ( 0 )) // 0 console . log ( Number ( '0' )) // 0 console . log ( Number ( '' )) // 0 console . log ( Number ( 1 )) // 1 console . log ( Number ( '1' )) // 1 console . log ( Number ( 'a' )) // NaN console . log ( Number ( 0 ) >= 0 ) // true co...

git push 취소

이미지
git push를 실수로 했을 경우 취소 하고 싶을 때가 많습니다. push를 보기 전에 commit 취소부터 보겠습니다. commit 취소 예제 실수로 commit을 한 상태입니다. 취소 명령어는 다음과 같습니다. $ git reset HEAD^ $ git reset HEAD~1 1번은 최종커밋 취소, 2번은 N개만큼 취소 입니다. push 취소 예제 푸시까지 된 상황을 보겠습니다. 1. 로컬에 커밋을 취소해야 합니다. 리셋 명령어는 앞의 내용 참고 부탁드립니다. 2. 현재 로컬의 상태를 remote 저장소에 강제 푸시 해야합니다. $ git push origin -f $ git push --force 위의 명령어를 응용해서 사용하시면 됩니다.  origin은 remote 저장소 입니다. remote 확인하는 방법은 아래 부분을 참고해주세요. -f 옵션은 --force의 약자 입니다. remote 확인 git에 다양한 remote 저장소를 연결하여 사용할 수 있습니다. 기본은 origin 으로 사용을 합니다. $ git remote 자세히 보고 싶으면 -v 옵션을 사용하면됩니다. 정리 $ git reset HEAD^ # commit 취소 $ git push origin -f # 현재 상태 강제 푸시

nginx Response Header Server 정보 제거

이미지
nginx에 설정을 추가하지 않으면 현재 사용하고 있는 서버 정보가 노출됩니다. 이는 보안에 취약점이 될 수 있습니다. 설정하기 nginx.conf server { listen 80 ; server_name localhost ; proxy_pass_header Server; location / { proxy_pass http: //127.0.0.1:3000; } } 다음 설정을 추가하면 간단히 제거됩니다. nginx 설치, 실행은 다음 페이지를 참고해주세요. https://withccm.blogspot.com/2020/12/macos-nginx.html  

자바 URL 인코딩 디코딩

이미지
URL을 변수로 할당하여 개발할 때가 많이 있습니다. 예를 들어 소셜 로그인 후에 redirect_uri를 query string으로 전달 되는 것을 보실 수 있습니다. 이때 query string에  URL이 전달 되는경우에 인코딩을 해야 기대하는 결과를 받아 볼 수 있습니다. http://localhost?redirect_uri=https://www.youtube.com/watch?v=9PPaSkVIu98&list=all 위와 같이 전달하게 되면  redirect_uri  = https://www.youtube.com/watch?v=9PPaSkVIu98 list = all 원하지 않는 결과를 만나게 됩니다. 이외에 공백이라든지 특수문자를 사용하는 경우에도 인코딩해야합니다. 자바에서 인코딩, 디코딩 하는 방법을 살펴보겠습니다. @Test public void test () throws UnsupportedEncodingException { String url = "https://www.youtube.com/watch?v=9PPaSkVIu98" ; log .debug( "url === {}" , url) ; String encodedUrl = URLEncoder. encode (url , "UTF-8" ) ; log .debug( "encodedUrl === {}" , encodedUrl) ; String decodedUrl = URLDecoder. decode (encodedUrl , "UTF-8" ) ; log .debug( "decodedUrl === {}" , decodedUrl) ; } 실행 결과  url === https://www.youtube.com/watch?v=9PPaSkVIu98&list=all encodedUrl === https%3A%2F%2Fwww.youtube.com%2Fwatch...

자바 LocalDate json 변환에 관하여

이미지
 안녕하세요. 자바가 java.time 패키지를 제공하면서, 기존 Date 객체에 비하여 개발이 편해졌습니다. LocalDate를 json으로 변환하여 사용할때 만나는 문제를 다뤄보겠습니다. jackson 라이브러리를 사용하여 json으로 변환하고 다시 읽어 보겠습니다. jackson 라이브러리 json 변환 예제1 @Test public void objectMapper () throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper() ; LocalDate ld = LocalDate. now () ; String json = objectMapper.writeValueAsString(ld) ; System. out .println( "json == " + json) ; LocalDate ldFromJson = objectMapper.readValue(json , LocalDate. class ) ; System. out .println( "ld1 == " + ld) ; System. out .println( "ld2 == " + ldFromJson) ; } 실행 결과1 json으로 변환할때 LocalDate의 모든 속성이 그대로 변환된 것을 볼 수 있습니다. 이경우 serializer, deserializer를 구현하여 형식을 정할 수 있습니다. jackson 라이브러리 json 변환 예제2 import java.time.LocalDate ; import java.time.format.DateTimeFormatter ; import com.fasterxml.jackson.core.JsonProcessingException ; import com.fasterxml.jackson.databind.ObjectMapper ; import com.fasterxml.jackson.databind.mo...

자바스크립트 Array 를 map 으로 변환, 일부만 변경, 합치기

javascript array to map Array(배열, 리스트, List)를 map으로 변환하여 특정키의 값이 존재하는지 여부를 찾고 싶을 때가 있습니다. (저는 자바를 주로 사용하기 때문에 자바 stream의 collect  사용하고 싶었습니다.) Array to map, list to map const books = [ { id : 'a' , name : '1' , author : 'q' } , { id : 'b' , name : '2' , author : 'w' } , { id : 'c' , name : '3' , author : 'e' } ] ; // array to map , list to map const bookMap = books. reduce ((acc , currentValue) => { acc[currentValue. id ] = currentValue ; return acc ; } , {}) ; console . log (bookMap) ; const newBooks = [ { id : 'b' , name : 'n2' , author : 'w' } , { id : 'c' , name : 'n3' , author : 'e' } , { id : 'd' , name : 'n4' , author : 'r' } , { id : 'f' , name : 'n5' , author : 't' } ] // 이전에 등록된 데이터 확인하기 const oldBooks = newBooks. filter (each => !bookMap[each. id ]) console . log (oldBooks) acc의 이전 결과 내...

Spring boot Webflux에서 block 찾기

이미지
Webflux로 개발하는 경우 block가 있으면 성능이 현저하게 낮아 집니다. 따라서 개발 후에 개발한 코드에 Block을 발생 시키는 코드가 있는지 확인하는 것은 중요합니다. 이것을 도와 주는 라이브러리가 Blockhound 입니다. 1. 의존성 추가 testImplementation( 'org.springframework.boot:spring-boot-starter-test' ) testImplementation 'io.projectreactor:reactor-test' testImplementation 'io.projectreactor.tools:blockhound:1.0.6.RELEASE' testImplementation 'io.projectreactor.tools:blockhound-junit-platform:1.0.6.RELEASE' Blockhound를 사용하면 Block을 발생시키는 곳에서 에러를 발생시킵니다. 따라서 운영 환경에서는 사용을 피해야 합니다. 테스트 환경에서 사용하는 것을 추천 드립니다. 2. 샘플 라우터 작성 @Configuration public class BlockingRouter { @Bean public RouterFunction<ServerResponse> blockRouter () { return RouterFunctions. route (RequestPredicates. GET ( "/nonBlock" ).and(RequestPredicates. accept (MediaType. APPLICATION_JSON )) , request -> { return ServerResponse. ok ().body(Mono. just ( "nonblock response" ) , String. class ) ; }).andRoute(RequestPredicates. GET ...

Spring boot webflux + mysql

스프링 부트의 webflux의 rest api 예제 입니다. 샘플 코드 https://github.com/withccm/spring-webflux-study/tree/feature/webflux-mysql-sample 북 테이블 CREATE TABLE `book` ( `id` int ( 11 ) NOT NULL AUTO_INCREMENT , `bookname` varchar ( 200 ) DEFAULT NULL , PRIMARY KEY (`id`) ) ; 1. 의존성 추가 implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' runtimeOnly 'mysql:mysql-connector-java' implementation 'dev.miku:r2dbc-mysql' 2. spring data r2dbc bean 등록 @Configuration @EnableTransactionManagement @EnableR2dbcRepositories public class DataSourceR2DBCConfig extends AbstractR2dbcConfiguration { @Bean @Primary public ConnectionFactory connectionFactory () { ConnectionFactoryOptions options = ConnectionFactoryOptions. builder () .option(ConnectionFactoryOptions. DRIVER , "pool" ) .option(ConnectionFactoryOptions. PROTOCOL , "mysql" ) .option(ConnectionFactoryOptions. HOST , "localhost" ...