SpringBoot App에 외부 libs 추가

JAVA/Spring|2023. 11. 19. 22:57

SpringBoot는 기본적으로 jar내에 BOOT-INF에 classes, libs를 클래스패스로 물고 올라간다.

build.gradle혹은 pom.xml에 설정하여 빌드 타이밍에 같이 묶긴하면 BOOT-INF에 포함되어 사용하는데 문제 없지만

별도 jar로 제공 받아 활용을 해야한다면.

추가적으로 외부의 Libs를 ClassPath를 설정하기 위해서는 PropertiesLauncher 를 사용하고

-Dloader.path 를 설정하여 외부 jar도 활용 가능하다.

(특정 Bean을 external.jar로 만들어 추가한다거나..)

 

ex)

java -cp bootApp.jar -Dloader.path=external-plain.jar org.springframework.boot.loader.PropertiesLauncher

java -cp bootApp.jar -Dloader.path=plugins/ org.springframework.boot.loader.PropertiesLauncher

https://www.masterspringboot.com/configuration/web-server/how-to-use-an-external-jar-in-a-spring-boot-application/

'JAVA > Spring' 카테고리의 다른 글

[Spring] SessionStatus는 어떻게 동작할까?  (5) 2020.09.08
[JPA] LockType  (0) 2020.07.23
[Spring] LifeCycle, SmartLifeCycle  (0) 2020.06.23
[MSA] sidecar 패턴  (0) 2020.01.13
[SpringConfig] Properties 암호화  (0) 2019.12.24

댓글()

split과 동시에 assign

Kotlin|2021. 11. 29. 21:02

 

val text = "a,b"
val (one,two) = text.split(",")
/*
val one = text.split(",")[0]
val two = text.split(",")[1]
*/

 

코드 작성중 신기하고 편리해보이는 문법

까먹지 않기 위해 기록

 

text.split(",")의 size가 2보다 크더라도 [0], [1] 만 assign되지만

size가 2보다 작으면 IndexOutOfBoundsException 발생함

 

댓글()

NestJS Controller

NestJS|2021. 11. 17. 08:05

Spring과 거의 비슷

 

import { Controller, Get, Render, Param, Query } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get("html")
  @Render('index')
  getHbs(){
    return { message: 'messageBinding' };
  }

  @Get(':id')
  findOne(@Param('id') id: string, @Query('getParam') getParam): string {
    
    console.log('getParam : ${getParam}')
    console.log("getParam : ${getParam}")
    console.log(`getParam : ${getParam}`)
    return `This action returns a #${id} cat`;
  }
}

 

Spring Next.js  
@{HttpMethod}Mapping @{HttpMethod}() @GetMapping -> @Get()
@PathVariable @Param()  
@RequestParam @Query()  
@RequestBody @Body() DTO로 바인딩도 가능
@ResponseEntity @Res() res 아래와 같은 방식으로 response 응답 정의 가능
res.status(HttpStatus.OK).json()

 

 

 

'NestJS' 카테고리의 다른 글

NestJS 시작  (0) 2021.10.21

댓글()

NestJS 시작

NestJS|2021. 10. 21. 22:18

지금까지 자바를 주로 사용해오고, 코틀린을 끄적 끄적 사용해왔지만

추후 Serveless에 활용되기에는 너무 먼것같고(Graalvm은 아직 멀고 멀어보인다..ㅠㅠ)

 

효율적인 Node.js 에 괜찮은 프레임워크가 나왔다길래 공부해보려고 합니다.

(추후 Serverless나 Toy 프로젝트에 조금씩 활용해볼수 있을듯..)

 

Nest CLI 설치

npm i -g @nestjs/cli

 

설치 후 'nest' 를 입력하면 command 들에 대해 설명이 잘 기술되어있습니다.

nest  
Usage: nest <command> [options]

Options:
  -v, --version                                   Output the current version.
  -h, --help                                      Output usage information.

Commands:
  new|n [options] [name]                          Generate Nest application.
  build [options] [app]                           Build Nest application.
  start [options] [app]                           Run Nest application.
  info|i                                          Display Nest project details.
  update|u [options]                              Update Nest dependencies.
  add [options] <library>                         Adds support for an external library to your project.
  generate|g [options] <schematic> [name] [path]  Generate a Nest element.
    Available schematics:
      ┌───────────────┬─────────────┬──────────────────────────────────────────────┐
      │ name          │ alias       │ description                                  │
      │ application   │ application │ Generate a new application workspace         │
      │ class         │ cl          │ Generate a new class                         │
      │ configuration │ config      │ Generate a CLI configuration file            │
      │ controller    │ co          │ Generate a controller declaration            │
      │ decorator     │ d           │ Generate a custom decorator                  │
      │ filter        │ f           │ Generate a filter declaration                │
      │ gateway       │ ga          │ Generate a gateway declaration               │
      │ guard         │ gu          │ Generate a guard declaration                 │
      │ interceptor   │ in          │ Generate an interceptor declaration          │
      │ interface     │ interface   │ Generate an interface                        │
      │ middleware    │ mi          │ Generate a middleware declaration            │
      │ module        │ mo          │ Generate a module declaration                │
      │ pipe          │ pi          │ Generate a pipe declaration                  │
      │ provider      │ pr          │ Generate a provider declaration              │
      │ resolver      │ r           │ Generate a GraphQL resolver declaration      │
      │ service       │ s           │ Generate a service declaration               │
      │ library       │ lib         │ Generate a new library within a monorepo     │
      │ sub-app       │ app         │ Generate a new application within a monorepo │
      │ resource      │ res         │ Generate a new CRUD resource                 │
      └───────────────┴─────────────┴──────────────────────────────────────────────┘

 

 

 

프로젝트 생성(proj_name에 생성하고싶은 이름 입력, 해당 이름으로 디렉토리 생성됨)

nest n proj_name

생성된 디렉토리를 진입하면 /src 디렉토리가 보이고

생성된 디렉토리에서 "nest start"를 입력하면 바로 서버가 기동된다.

(localhost:3000 호출시, 기본적으로 Hello World는 볼수 있도록 샘플 코드가 같이 생성된다)

/src 디렉토리를 확인하면 파일들이 5개 정도 존재하는데

 

app.controller.spec.ts : Test 코드
//
app.controller.ts : Controller 코드, Spring 처럼 어노테이션들을 볼 수 있다.
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}
//
app.module.ts : 모듈 선언(의존성 선언 같은), AppController는 AppService를 의존성을 가지고 있도록 생성됨
@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
//


app.service.ts : 서비스 코드(@Injectable은 없어도 Injection에는 문제는 없던데 추후에 학습해봐야겠다)
main.ts : SpringBootApplication 처럼, 메인이며, Nest를 실행하며, 포트에 대한 선언도 이 코드에 있다.

기본적으로 restController 처럼 값을 응답할텐데, View를 표현할 필요가 있다면 hbs 와 같은 모듈을 추가하여 동적 View도 제공 가능 합니다.

'NestJS' 카테고리의 다른 글

NestJS Controller  (0) 2021.11.17

댓글()

구분자와 문자열 추가 StringJoiner

JAVA|2021. 8. 26. 21:47

Effective Java에서 바로  StringBuffer, StringBuilder는 관련해서 나오는 이야기는 두가지 정도로 기억한다.

 

첫번째는 "text" + "text" 연산보다 StringBuffer, StringBuilder 가 좋은 이유는 +연산마다 새로운 객체를 생성되기 때문에 많은 문자열 더하기를 할때는 계속 불필요한 객체생성되는 + 연산보다는 StringBuffer, StringBuilder 를 사용하라

 

두번째는 StringBuffer는 append()시에 락(synchronized)을 잡기 때문에 여러 스레드에서 같은 StringBuffer 객체를 공유해서 써야하는경우(이런 경우를 지금까지는 보지 못했다..)아니고서는 락을 잡는것은 낭비이기 때문에 락(synchronized)을 잡지 않는 StringBuilder를 사용하라

 

 

StringBuffer.append()
StringBuilder.append()

 

보통 로깅을 한다거나, 문자열 붙이기를 할때

문자열 사이에 라인변경(\n)을 추가하거나, 콤마(,) 를 자주 추가하곤했는데

간단한 코드지만 중간에 구분자를 넣는작업은 귀찮긴 했습니다.

 

그래서 guava의 Joiner를 많이 사용했었는데

JDK8에 StringJoiner로 대체할수 있습니다.

 

StringBuilder로 추가 문자열마다 라인변경을 한다고 했을때

(첫번째 추가할때는 구분자를 넣지 않고, 첫번째가 아니라면 구분자 추가)

ArrayList<String> strings = Lists.newArrayList("name1", "name2", "name3");
        final StringBuilder stb = new StringBuilder();
        strings.forEach(string -> {
            stb.append(string);
            if (stb.length() != 0) {
                stb.append("\n");
            }
        });

 

StringJoiner로 추가 문자열마다 라인 변경을 한다고 했을때 생성자에 구분자("\n")넣고 add로 문자열을 붙인다

StringJoiner는 생성자가 두종류, (구분자) , (구분자, Prefix, Suffix)

ArrayList<String> strings = Lists.newArrayList("name1", "name2", "name3");
        final StringJoiner joiner = new StringJoiner("\n");
        strings.forEach(string -> {
            joiner.add(string);
        });

StringJoiner.add(), 여기서 elts는 String[]

동작이 조금 다른건 전달받은 String을 StringBuilder는 byte[] 로 관리, StringJoiner는 String[]로 관리

 

StringJoiner의 경우 추가한 문자열에대해서만 String[]에 추가하고, del의 경우는 추가로 저장하고 있는것은 아니기 때문에

메모리를 적게 먹을것이고, 

 

StringBuilder의 경우 del이나 Prefix, Suffix 구분이 딱히 없어서 일반 추가한 문자열 취급을 하기 때문에

bytes에 추가될것임

 

문자를 붙일때마다, 구분자가 필요하거나 Prefix, Suffix가 필요한경우

StringJoiner를 사용하는것이 여러모로 유리하다고 생각합니다.

'JAVA' 카테고리의 다른 글

ActiveMQ JDK Version  (0) 2020.09.09
DCL(Double Checked Locking)  (0) 2020.09.08
Java Stream  (0) 2020.07.14
Java Time  (0) 2020.07.06
SortedQueue...  (0) 2020.07.02

댓글()

코틀린 upgrade 1.3.7 to 1.5.0

Kotlin|2021. 5. 28. 20:10

코틀린 버전이 아주 빠르게 올라가고 있습니다

마침 Jetbrains 홈페이지에서 1.5.0 출시에 대해 소식을 들을수 있었고

최근 재설계 되는 프로젝트에 맞춰 코틀린 버전업을 하면 좋을것 같아서

각 버전별 차이점을 조금씩 살펴보며 기록을 남깁니다.

(Native와 JS에 대한 내용은 살펴보지 않았습니다)

 

Version : 1.3.7, release : 20.03.03

 

표준 라이브러리에 대한 새로운 함수 및 클래스

* StringBuilder 멤버들 없던것들 추가(JVM에서는 별 영향 없을듯..)

* KClass에 대해 더이상 "kotlin-reflect"를 필요로 하지 않고, JVM에 의존적이지 않음(JVM에서는 별 영향 없을듯..)

* @Experimental @UseExperimental은 1.4 부터는 사용되지 않음, @OptIn, @RequiresOptIn으로 대체

* 시간 측정 API, Clock ClockMark 이름이 TimeSource TimeMark 로 변경

* ArrayDeque 추가

* Collection builders

  * collections의 builder 함수, builderList, buildset, buildMap 추가, 결과는 read-only collection

* reduceOrNull(), randomOrNull() 추가(기존 reduce(), random()은 emptyCollection이면 exception)

* scan() 추가, fold 처럼 acculated

 

InteliJ Kotlin 플러그인 개선

* gradle.kts 지원

* 자동완성개선

* 신규 색상 스키마

* 디버깅 개선

 

 

출처

https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/

 

Version : 1.4.0, release : 20.08.17

IDE 성능 및 안정성 향상을 포함한 Kotlin의 전반적인 개발환경을 개선하는데 초점

* 코루틴 디버거 도입

* 새로운 컴파일러, 목표는 속도 개선, 모든 플랫폼을 통합하며 확장기능의 API 제공(1.5에서는 디폴트로..)

 

신규 기능

* 코틀린 인터페이스에 SAM(Single Abstract Method) 컨벤션

* 라이브러리 개발자를 위한 명시적 API(메소드 가시성 수정 등)

* 일반 파라미터, 네임드 파라미터 혼용 가능

* 후행 콤마(trailing comma)

* callable method ref(::callableMethod)

* loop 내에 when에서 라벨없이 break와 continue 사용가능

 

 

 

출처

https://blog.jetbrains.com/kotlin/2020/08/kotlin-1-4-released-with-a-focus-on-quality-and-performance/

 

 

Version : 1.4.10, release : 20.09.07

블로그 글이 안보이네요..^^;;

 

 

Version : 1.4.20, release : 20.11.23

 

JVM 신규 기능 지원(invokedynamic을 통한 String concatenation)(1.5에 기본값으로 변경 예정)

* JDK9 부터 String 을 합치는 부분은 dynamic method invocation(invokedynamic)을 통해 수행한다.

* 이전보다 더 빠르고 메모리를 적게 소모하며 바이트코드 변경없이 최적화 할수 있는 여지를 제공한다.

  * ex) 이전에는 StringBuilder로 하나한 연결 했던 바이트 코드를 생성했기 때문에 최적화할 여지가 더 없지만, ivokedynamic을 통해 bootstrap method를 호출하는 형태의 바이트코드로 생성되고 bootstrap method는 호출되는 시점에 생성되기 때문에 최적할 여지가 생김(Bootstap에 호출은 보통 StringConcatFactory.makeConcatWithConstrants를 호출한다고 함

* invokedynamic : https://docs.oracle.com/javase/7/docs/technotes/guides/vm/multiple-language-support.html#invokedynamic

  * https://openjdk.java.net/jeps/280

  * https://www.baeldung.com/java-string-concatenation-invoke-dynamic

 

성능 개선 및 KMM프로젝트에 대한 에러 핸들링

* 주로 Kotline/Native

* String.replace 성능 개선

JDK Path

 

출처

https://blog.jetbrains.com/kotlin/2020/11/kotlin-1-4-20-released/

 

Version : 1.4.30, release : 21.02.04

1.4.x에 마지막 릴리즈

1.5.0에 계획된 많은 실험적인 기능들 추가

 

언어 기능 및 컴파일러

* new JVM backend BETA

  * JVM backend : 코틀린 코드를 JVM에 동작하기 위한 바이트 코드로 생성하는데 활용되는 백엔드

* Value class, JVM records, sealed interface

  * Inline classes(Value class) : 인라인 클래스는 별도의 언어 기능이였지만, 현재는 하나의 매개변수가 있는 Value 클래스에 대해 JVM 최적화가 되었음, Value 클래스보다는 일반적인 개념이며 추후 다양한 최적화를 지원함.

  * JVM record : JDK14에 공개된 record에 대한지원, kotline의 data class와 유사

    * https://openjdk.java.net/jeps/395

  * sealed interface : 해당 인터페이스를 구현하거나 상속받은 클래스 혹은 인터페이스는 동일한 컴파일 단위 및 동일한 패키지에 있어야함, 그전에는 같은 파일에 존재했어야 했으나, 1.5에서는 다른파일에도 존재가능

    * JDK15에 도입되었으며 Kotlin 에서 JVM17이상 사용하는 경우에는 JVM에 있는 sealed class를 사용되도록 할것임

빌드 툴

  * 코틀린 gradle 플러그인에 캐시지원 설정

    * 주로 안드로이드 처럼 빌드가 오래걸리는 케이스에 대한...

 

 

출처

https://blog.jetbrains.com/kotlin/2021/02/kotlin-1-4-30-released/

 

Version : 1.5.0, release : 21.05.05

1.4.30에 도입되었던 신규 기능의 stable 버전

* JVMRecord 지원

  * data 클래스에 @JvmRecord 어노테이션 사용시 JVM에 record를 활용하도록 됨

* sealed class

  * 이전에는 모든 상속받은 클래스는 같은패키지 같은 파일내에 있어야 했지만, 현재는 다른 파일에서도 가능

* value class,  1개의 필드를 가진 value holder 클래스 이며 메모리 할당 오버헤드 없이 사용할수 있도록 함, 단, @JvmInline을 반드시 써줘야함

 

Kotlin/JVM

* 신규 JVM IR(Intermediate Representation) compiler 도입

* 람다를 invokedynamic로 컴파일(실험 기능)

* 디폴트 JVM은 1.8, 1.6은 사용중단* 

 

 

 

출처

https://blog.jetbrains.com/kotlin/2021/05/kotlin-1-5-0-released/

댓글()

[DB] 기초부터다시, ACID, CAP

DB|2020. 9. 14. 15:53

ACID

트랜잭션은 이러한 성질을 만족해야 안전하게 수행됬다고 볼수 있다는 특징들의 약자

 

A : Atomicity, 원자성, 트랜잭션 내에 작업은 모든 상태가 반영되거나, 모든 상태가 되지 않아야 한다.

C : Consistency, 일관성, PK 규정이라거나, 타입 상태의 규정, 및 규정들은 언제나 일관성있도록 깨지지 않아야한다.

I : Isolation, 독립성, 트랜잭션 수행내용은 다른 트랜잭션이 끼어들지 못하도록 해야한다

               (성능상에 이유로 유연성 있는 제약조건이라고 함, 커밋되지 않은 항목에 대한 읽기 라거나 여러 조건들이..)

               (DB는 보통 낙관적으로 커밋될것이라 처리하기 때문에 일단 반영하고 트랜잭션 밖에서 select 요청이 들어오면 redo로그..? 를 통해 해당 트랜잭션 버전에 맞게 변경 후 보여준다고 한것 같은데.. 이러한 성능 저하를 겪지 않으려는 목적인듯함.. 내용이 틀리다면 피드백 부탁드립니다.)

D : Durability, 지속성, 트랜잭션이 성공하면 해당 내용은 언제나 반영되어있어야 한다, 커밋 후 장애가 발생하더라도 로그를 통해서라도 복구가 가능해야 한다.

 

CAP

어떤한 분산 시스템도 CAP(Consistency, Availability, Partition tolerrance) 3가지를 동시에 만족시킬수 없다는 이론

 

C(Consistency, 일관성) : 모든 서버들은 같은 시간에 같은 내용의 데이터를 보여주는것을 보장해야 한다.

A(Availability, 가용성) : 언제나 모든 사용자들이 읽기 및 쓰기가 가능해야 하며, 다른 서버의 장애시에 영향을 받아서는 안된다.

P(Partition tolerrance, 분할내성) : 시스템 일부가 장애에 빠져도 시스템을 서비스 할 수 있어야 한다.

 

출처 :  rndblog.github.io/nosql/architecture/2015/09/13/notes-on-nosql-basics.html

전통적인 RDB는 C와 A를 만족하여 트랜잭션을 통해 데이터 일관성과 단일 서버를 통한 가용성을 제공하낟.

 

또한 NoSQL의 경우 C와 P를 만족하기 위하여, 분산 환경을 제공하고, 분산환경에서 일관성을 제공하기 위해 분산 서버간의 sync 작업이 진행되며, 일관성을 맞추는 sync작업이 진행되는동안 클라이언트가 read/write가 불가능 할수 있기 때문에 A가 포기된다..

 

AP를 선택한 CouchDB, Cassandra의 경우 C를 만족하지 않기 때문에 여러 클라이언트가 일관성 없는 데이터를 바라볼수 있지만, 언제나 읽고 쓸수 있도록 A 를 제공하고 분산 환경인 P를 제공하기 때문에

데이터 일관성이 꼭 중요하지 않는 경우에 선택된다. 

 

 

'DB' 카테고리의 다른 글

GraphQL 끄적끄적  (0) 2020.08.20
기초부터다시, 조인  (0) 2020.08.18
[MongoDB] 해킹된 후 보안 설정 관련  (0) 2019.12.23
[MyBatis] MyBatis 문법 파서  (0) 2019.05.29
DB 스키마를 관리하자  (0) 2018.12.20

댓글()

ActiveMQ JDK Version

JAVA|2020. 9. 9. 12:51

ActiveMQ는 "Classic" 버전과 "Artemis" 버전이 있습니다.

각 버전의 차이점은 여러가지가 있겠지만

그중 Classic은 JMS1.1을 지원 Artemis는 JMS1.1과 2.0를 지원 합니다.

 

체감한 1.1과 2.0의 차이는

1.1에서는 ConnectionFactory를 통해 Connection을 생성하고 Session을 생성해야하는것을

2.0에서는 Connection과 Session을 모두 포함한 JMSContext를 제공하여

2.0에서는 ConnectionFactory로 JMSContext를 생성하여 관리 할 수 있습니다.

 

현재 활용하는 WAS는 JMS2.0을 지원하기 때문에 그에 맞는 테스트를 위해

"Classic" 과 "Artemis" 중 "Artemis"를 선택했고

 

개발 최소 환경이 JDK7이 될수 있기 때문에 그에 맞는 버전을 찾아야 했습니다.

 

현재 "Classic" 최신버전은 5.16이며 JDK8로 빌드가 되어있고

JDK7으로 빌드된 버전을 디컴파일러로 찾아보니 5.11~5.14는 JDK7으로 빌드되어있습니다.

 

그리고 "Artemis"는 현재 최신버전은 2.15이며 2.x에는 모두 JDK8로 빌드가 되어있고

쭉 찾아보니 1.4.0버전은 JDK7으로 빌드되어있어서 1.4.0 기준으로 테스트 예정입니다.

 

JDK 버전 제약이 있으면 최신 오픈소스들을 활용하는데에 쉽지 않네요..;;;

 

 

'JAVA' 카테고리의 다른 글

구분자와 문자열 추가 StringJoiner  (0) 2021.08.26
DCL(Double Checked Locking)  (0) 2020.09.08
Java Stream  (0) 2020.07.14
Java Time  (0) 2020.07.06
SortedQueue...  (0) 2020.07.02

댓글()