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

vi 붙여넣기 주석 및 자주 사용하는 명령어 set paste

  리눅스 환경에서 서버 관리를 하다 보면 vi(vim)를 사용해야될 때가 있습니다. 자주 만나게 되는 고민/문제 해결 방법을 확인해 보겠습니다. 들어가기 전에 vi는 다양한 모드(mode)를 가지고 있습니다.  1. 처음 실행하면 Normal 모드 2. :를 입력하면 명령어 모드 3. v를 입력한 경우 블록을 선택할 수 있는 비주얼 모드 4. io등등 글자를 입력할 수 있는 끼워넣기(Insert) 모드 그리고 대소문자별로 명령어가 다릅니다.  1. 붙여넣기 했을때 주석이후 계단 현상 :set paste 붙여넣기 설정을 추가한 후에 붙여 넣기 하면 해결됩니다. 외부에서 ctrl+C한 내용 붙여넣기 안될때 Normal모드에서 "+p 순서대로 입력하면 됩니다. 2. 라인 표시 :set number 3. 단어 검색 명령어 모드에서 /검색단어 엔터 n다음, N이전 4. 해당 라인으로 이동 :123 원하는 라인 입력 제일 마지막 라인으로 이동  G 첫 라인으로 이동 gg 5. 삭제, 복사, 실행취소 dd 한줄 삭제 yy 한줄 복사 v로 원하는 블록만큼 선택 후 y 하면 복사가 됨 p 붙여넣기 (대문자 P는 앞라인에 붙여넣기) u 실행 취소(undo) Ctrl+r redo

crontab 시간 설정 방법

이미지
 crontab나 jenkins에서 주기적으로 실행해야 할 때가 많이 있습니다. 예를 들어 매일 랭킹을 추출하는 경우가 있습니다.  시간 설정 방법을 예제를 통해 알아보겠습니다.  기본 명령어 crontab -l # 등록된 목록 출력 crontab -e # 수정 crontab -r # 삭제 등록 예제 5 * * * * /directory/exe_file.sh 시간 요소 시간 설정은 5가지 요소로 이루어져있습니다. * * * * * 분(0-59), 시간(0-24), 날(1-31), 월(1-12), 요일(0-6) 0은 일요일 위의 예제는 1분 마다 실행 시간 예제 0 * * * * 0분에 1시간마다 실행 -> 00시00분, 01시00분, 02시00분... */5 * * * * /로 나눠서 실행 주기를 설정할 수 있습니다. 5분마다 실행 -> 00시00분, 00시05분, 00시10분...   0 3 * * * 매일 3시에 실행  -> 5월10일 03시00분, 5월11일 03시00분, 5월12일 03시00분... * 9-18 * * * -를 사용하여 범위를 지정할 수 있습니다. 매일 9-18시 사이에 1분마다 실행 -> 09시00분, 09시01분, 09시00분, ... 18시58분, 18시59분, ... 다음날 09시00분,... 30 9-18/2 * * * 매일 9-18시 사이에 30분에 2시간마다 실행 -> 09시30분, 11시30분, 13시30분... 30 9,18 * * * ,를 사용하여 필요한 숫자를 지정할 수 있습니다. 매일 9시30분, 18시30분에 실행 0 1 1 * * 매달 1일 1시00분 마다 실행 -> 9월1일 01시0분, 10월1일1시01분, 11월1일1시01분... 10 3 * * 6 매주 토요일 3시10분에 실행 -> 2022년9월10일 03시10분, 2022년9월17일 03시10분, 2022년9월24일 03시10분... 참고로 젠킨스에서는 분설정 부분에...

자바 리스트 정렬 방법 java list sorting

  리스트 정렬 방법에 대해 간단히 알아 보겠습니다.  예제에서 사용할 Book 클래스 import lombok. AllArgsConstructor ; import lombok. Builder ; import lombok. Getter ; import lombok. ToString ; import java.time.LocalDateTime ; @AllArgsConstructor @Getter @Builder @ToString public class Book { private Integer id ; private String title ; private LocalDateTime createdDate ; } Book 객체 생성하는 함수입니다. private Book makeBook ( int id , int day) { return Book. builder () .id(id) .createdDate(LocalDateTime. of ( 2022 , 5 , day , 10 , 0 )) .build() ; } id와 day를 파라미터로 받아 Book 객체를 생성합니다. 리스트 정렬을 하기 위해 stream을 생성하고, sorted 함수를 사용했습니다. 조건1개를 오름차순으로 정렬하는 예제 @Test public void 조건 1 개 _ 오름차순 _ 정렬 () { // given List<Book> books = new ArrayList<>() ; books.add(makeBook( 1 , 7 )) ; books.add(makeBook( 2 , 5 )) ; books.add(makeBook( 3 , 9 )) ; books.add(makeBook( 4 , 10 )) ; books.add(makeBook( 5 , 4 )) ; // when List<Book> result ...

자바 JUnit Mock 테스트

 복잡한 로직의 코드를 작성할때, 리팩토링을 해야할때 잘 짜여진(경우의 수를 반영한) 테스트 코드가 있으면 코드의 결과에 대한 확신이 생깁니다.  이때 Mocking을 활용하면 테스트 코드를 더 원활하게 작성할 수 있습니다. Mocking이란 단위 테스트를 작성할때 데이터베이스와 같이 외부에 의존하지 않고, 실행될 함수를 테스트에 직접 정의하여 대체하는 기법입니다. 1. 의존성 주입 dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' testCompile group : 'junit' , name : 'junit' , version : '4.12' testImplementation 'org.mockito:mockito-core:3.6.0' testImplementation 'org.easytesting:fest-assert:1.4' } mockito를 사용했습니다. fest-assert는 테스트 검증을 쉽게 할 수 있도록 도와줍니다. (필수 아님). lombok나 string-boot는 편의를 위해 사용했습니다. 2. Book관련 클래스 정의 import lombok. AllArgsConstructor ; import lombok. Builder ; import lombok. Getter ; import lombok. ToString ; @AllArgsConstructor @Getter @Builder @ToString public class Book { private Integer id ; private String title ; } 데이터 클래스 입니다. import lombok.extern.slf4j. Slf4j ; import org.springf...

LocalDateTime atStartOfDay 날짜 시작 시간으로

개발하다보면 해당 날짜에 00시00분00초가 필요한 경우가 많습니다. 예를들어 오늘 작성된 댓글을 조회하고 싶은경우 날짜의 시작부터 다음날까지 조회를 하게 됩니다. 날짜만 사용하는 경우가 되지요. 이때 필요한 함수가 atStartOfDay입니다. 함수명에서 잘 나타나있는데요. 이 함수는 LocalDate에 있기때문에 한번 변환과정이 필요합니다. 예제 LocalDateTime ldt = LocalDateTime. now () ; System. out .println(ldt) ; LocalDateTime onlyDate = ldt.toLocalDate().atStartOfDay() ; System. out .println(onlyDate) ; 실행결과 2022 - 09 - 06 T22: 25 : 56.904512100 2022 - 09 - 06 T00: 00 시작날짜 종료날짜 예제 LocalDateTime ldt = LocalDateTime. now () ; System. out .println(ldt) ; LocalDateTime startDate = ldt.toLocalDate().atStartOfDay() ; LocalDateTime endDate = startDate.plusDays( 1 ).toLocalDate().atStartOfDay() ; System. out .println( "startDate === " + startDate) ; System. out .println( "endDate === " + endDate) ; plusDays를 활용하여 내일날짜를 가져옵니다. 실행결과 2022 - 09 - 06 T23: 35 : 04.765255100 startDate === 2022 - 09 - 06 T00: 00 endDate === 2022 - 09 - 07 T00: 00

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의 이전 결과 내...