반응형

gopls was not able to find modules in your workspace.When outside of GOPATH, gopls needs to know which modules you are working on ~

* Mac

* vscode

* Golang 1.20

 

상황

vscode에서 go run main.go를 실행하는데 발생한 에러입니다.

 

해결

1. vscode 설정 수정

*이 방법은 인터넷에서 가장 많이 찾은 방법이지만 현재 2023.07.26 기준으로 (제가 했을 때)안됩니다.*

먼저 settings에 들어가서 gopls을 검색 후 settings.json에 들어갑니다.

들어간 후 “gopls” : { “"build.expandWorkspaceToModule": true,”} 입력해주면 됩니다.

 

* 저는 Invalid settings: gopls setting "experimentalWorkspaceModule" is deprecated 발생하여 작동하지 않습니다. 뜨면서 해결되지 않았습니다.

 

2. Golang이 directory를 인식하지 못하는걸 인식할 수 있도록 수정

최상의 directory(root 폴더)에 go.work를 생성해준 후 go work use <폴더 위치>를 통해 go.work에 폴더 위치를 추가해줍니다.

 

 

저는 2번으로만으로 해결되었습니다.

반응형
반응형
반응형

 

EXISTS 사용 방법

EXISTS는 먼저 쿼리를 조회해서 하나의 레코드를 가지고 오고 나서 서브쿼리를 실행하여 서브쿼리에 대한 결과가 존재하는지를 확인해서 있다면 레코드를 출력해줍니다.

여기서 가장 중요한 것은 서브쿼리에 대한 결과가 NULL이여도 결과가 존재한 것이기 때문에 결과가 True가 되어 레코드를 출력하게 됩니다.

 

 

TEST

테스트 해볼 사이트: https://sqltest.net/

 

SQL Test

Free Online SQL Test Tool

sqltest.net

SQL Script

CREATE TABLE mysql_test_a ( 
id VARCHAR(30),
name VARCHAR(30) NOT NULL
); 


INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('1', 'abab');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('2', 'John');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('3', 'dd');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('4', 'bb');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('5', 'aa');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('2', 'omokoe');
INSERT INTO `mysql_test_a` (`id`, `name`) 
VALUES ('6', 'John');

SQL Query

SELECT * FROM mysql_test_a a
where exists (
    select 1 from mysql_test_a b
    where a.id = b.id
    and b.name = 'John'
);

 

결과

'2', 'John'
'2', 'omokoe'
'6', 'John'

 

왜 '2', 'omokoe' 가 결과 값에 포함되어 있을까?

앞서 말했드이 먼저 쿼리를 조회하고 나서 서브쿼리를 조회 하는데, 서브쿼리 b 전체 행을 조회합니다. b 테이블에 id 값이 2인데 name에 값이 John인 레코드가 있으면 return True가 되고 레코드에 출력되는 것입니다. 그래서 '6', 'John'도 출력되는 것입니다.

반응형

'DB > MySQL' 카테고리의 다른 글

MySQL 계정에 DB 권한 부여  (0) 2024.09.05
MySQL Query 최대 용량  (1) 2024.09.05
Join 속도 개선  (0) 2023.05.17
반응형

시세 플랫폼이란?

시세 플랫폼은 실시간 시세 데이터를 안전하고 빠르게 처리해야합니다. 거래소 데이터를 받아 가공한 후 내부 서비스들에게 제공하거나 과거 데이터를 누적 또는 여러 정보를 합성하여 제공하기도 합니다.

그리고 최우선 목표로 낮은 지연시간과 빠른 장애복구가 있습니다.

시세 플랫폼 구성

시세 플랫폼은 총 3가지 파트로 구성되어 있습니다.

수신부는 거래소가 제공하는 시세 데이터를 UDP 멀티캐스트 그룹에 접속해서 읽어오는 일을 합니다. 그리고 처리부에게 데이터를 전송할 때 수신 시각을 Header에 포함하여 처리부에서 총 처리 시간을 측정하는데 사용합니다.

처리부는 비즈니스 로직이 모여있는 곳입니다. 처리 결과를 Redis에 저장하거나 실시간 정보를 서비스들에게 바로 전달합니다. 비즈니스 로직 중에는 Blocking I/O가 있기 때문에 처리 시간에 가장 많은 영향을 주는 곳이기도 합니다.

조회부는 REST API를 서비스들에게 제공합니다.

처리부 장애

이 중 처리부는 코드 변경이 빈번하게 발생하여 장애 발생 확률이 높습니다. 만약 처리부에서 장애가 발생하고 장애가 복구 되어도 API를 사용하는 서비스들은 여전히 장애를 겪게 됩니다. 왜냐하면 장애 시간동안 데이터가 유실되었거나 오염되었을 수도 있기 때문입니다.

<문제 해결>

이러한 문제를 해결하기 위해 처리부와 Redis를 두 개의 그룹으로 만들어서 처리할 수 있습니다.

평상시에는 처리부A에만 할당하다가 장애가 발생할 시 처리부B로 전환하는 방법입니다. 이 방법의 장점으로는 처리부 A와 처리부 B를 서로 번갈아 배포하면서 둘 간의 차이를 비교할 수 있고, 배포의 문제가 있다면 트래픽 전환만으로 빠르게 롤백할 수 있어 배포 부담감을 많이 줄일 수 있습니다.

시스템 장애를 대비해 각 처리부를 2개로 늘리고 ZooKeeper Group을 통해 Leader를 선출하도록 했습니다. 이 경우 중복 데이터 발생하는 것을 막기 위해 오직 각 그룹에 Leader만 데이터를 처리하도록 하였습니다.

수신부 성능 저하

이런 처리도 결국 수신부가 각 처리부의 갯수만큼 데이터를 보내야 하기 때문에 수신부의 성능 저하를 야기하게 됩니다.

이 문제를 해결하기 위해 수신부와 처리부 사이에 메세지 브로커를 사용하여 해결할 수 있었습니다. 메세지 브로커를 사용하므로서 수신부와 처리부를 Decoupling 할 수 있고 수신부는 데이터를 한 번만 전송해도 되게 됩니다.

하지만 시세 플랫폼에서 가장 중요한 것이 ‘낮은 지연시간‘인데 메세지 브로커로 인해 지연시간이 늘어나게 됩니다. 그렇기에 메세지 브로커로 어떤걸 사용할지가 중요합니다.

메세지 브로커의 후보는 아래와 같습니다.

  1. UDP(User Datagram Protocol) 멀티캐스트
    • UDP 멀티캐스터는 속도는 빠르지만 라우터 설정과 Kubernetes 배포 설정이 필요하다는 단점이 있습니다.
  2. Kafka
    • 높은 처리량과 뛰어난 안정성을 제공하지만 Redis Pub/Sub 보다 속도가 느리다는 단점이 있습니다.
  3. Redis Pub/Sub
    • Kafka보다 5배 빠른 속도를 보여줬습니다. 즉, 낮은 지연시간과 사용하기 쉽고 편리한 커맨드 지원을 해줍니다.

처리부 성능 저하

수신부에 속도가 개선되어도 처리부에서 속도가 느리다면 지연시간이 늘어날 수 있습니다.

처리부에서는 TCP Socket으로부터 데이터를 읽는 일과 비즈니스를 처리하는 일을 합니다. 이 때 처리부가 데이터를 읽는 속도가 지연시간에 큰 영향을 줍니다. 그렇기 때문에 데이터를 읽는 Thread와 비즈니스 처리 Thread를 따로 두어 처리해야 합니다.

이를 위해 Spring Data Redis에서 제공하는 ReactiveRedisTemplate을 사용했습니다. Spring Data Redis에서 기본 제공하는 Lattuce를 사용하여 네트워크 라이브러리인 Natty를 사용하고 Natty의 Channel은 Socket을 추상화한 레이어로서 커넥션이 맺어진 이후 EventLoop에 등록됩니다. EventLoop는 무한 루프를 돌면서 수신 버퍼의 데이터를 읽는 역활을 합니다.

EventLoop

EventLoop은 운영체제에 따라 Nio, Epoll, KQueue등 여러 방식을 지원합니다.

NioEventLoop는 실행되면(run) 버퍼에 데이터가 있는지 확인하고(select), 데이터를 읽고(read) 변환하여(decode) 결과를 통보(notify) 합니다. 그렇기에 NioEventLoop가 비즈니스 로직을 처리하지 않는 것이 중요합니다.

비즈니스 처리에는 Blocking I/O가 포함되어 있기 때문에 처리 성능을 높이기 위해 다음과 같이 멀티 스레딩을 사용해야 합니다. 하지만 이 경우 비즈니스 처리의 순서가 역전될 수 있다는 문제가 있습니다.

 

<문제 해결>

이 문제를 방지하기 위해 멀티 스레딩 대신 EventLoopGroup을 사용하여 해결할 수 있습니다.

EventLoop는 Queue를 이용하여 순서를 보장하고 하나의 Thread만 사용하기 때문에 동기화가 필요 없다는 장점이 있습니다. EventLoop를 사용해도 어떤 EventLoop에서 처리해야 할지 알아야 순서를 보장할 수 있기 때문에 미리 종목 코드를 알아야하고 이를 위해서 JSON을 객체로 변환해야 했습니다.

문제는 이 변환 작업이 트랙픽 양이 증가함에 따라서 NioEventLoop의 CPU 자원을 많이 사용하여 지연의 원인이 된다는 것입니다.

 

<문제 해결>

이 문제를 해결하기 위해 Redis Pub/Sub에서 제공하는 Channel을 사용했습니다.

수신부가 데이터를 보낼 때 처리부의 EventLoop 개수만큼 Channel을 나누어 보내고, 처리부는 이 Channel 명을 보고 해당하는 EventLoop를 찾는 것입니다. 이를 통해 수신부에서 발송한 데이터의 순서를 처리부에서 그래도 유지할 수 있고, NioEventLoop에서 더 이상 객체 변환을 하지 않아도 되기 때문에 성능이 향상된것을 확인 할 수 있습니다.

EventLoop 구현

  • Spring에서 제공하는 ThreadPoolTaskExecutor의 corePoolSize와 maxPoolSize를 1로 설정함으로써 쉽게 만들 수 있습니다.
  • Queue가 꽉 찰 경우를 위한 정책은 DiscardOldestPolicy를 사용했습니다. Circular Queue와 유사합니다.
  • Queue의 크기를 의미하는 queueCapacity는 얼마가 적당한지 정답이 없습니다. 만약 크기가 작으면 많은 피크 시간에 데이터가 유실될 수 있고, 너무 크면 오래된 데이터가 Queue에 적재되어 실시간성을 떨어트립니다.
  • EventLoopGroup은 ThreadPoolTaskExecutor를 여러 개 생성하여 리스트 형태로 만들었습니다. List<ThreadPoolExecutor>.
    • 리스트의 개수는 EventLoop의 개수를 의미합니다.
    • 리스트의 개수를 줄일려고 했는데, 이는 EventLoop의 개수가 늘어날수록 Context Switching으로 인해 NioEventLoop의 성능에도 악영향을 주기 때문입니다. 하지만 무조건 줄이게 되면 EventLoop에 Backpressure가 발생해서 지연시간이 훨씬 늘어나게 됩니다.

EvnetLoop 개수를 줄이는 방법

  • EventLoop가 더 효율적으로 동작하게 만듭니다.
    • Non-Blocking I/O 사용
      • 비즈니스 처리를 하는 EventLoop는 한 번에 한 작업만 처리합니다. 작업에 마지막에는 Redis에 데이터를 저장하는 일이 반복되었는데 굳이 데이터가 저장되기까지 기달릴 필요가 없었습니다. 그래서 ReactiveRedisTemplate의 비동기 함수를 이용하여 EventLoop가 더이상 Block 되지 않고 다음 작업을 처리할 수 있도록 하였습니다.
    • 데이터 조회 시 Local Cache 사용
      • 비즈니스 로직 중, Redis에서 과거 데이터를 조회하는 경우가 많습니다.조회는 앞의 예처럼 비동기로 처리할 수가 없습니다. 만약 비동기로 처리하게 되면 순서가 역전될 수 있기 때문입니다. 그래서 매번 Redis에서 데이터를 읽기보다는 LocalCache에서 먼저 데이터를 읽도록 함으로써 Blocking I/O 횟수를 줄였습니다.
    • 무거운 작업을 위한 별도 EventLoopGroup 분리
      • 배치 작업이나 MySQL 저장과 같은 상대적으로 무거운 작업은 기존의 EventLoop가 아닌 별도의 그룹에서 처리하도록 하였습니다. 이 방법은 기존의 EventLoop가 Blocking 당하는 것을 방지함으로써 효율적인 처리를 가능하게 합니다.

ETC

처리량(Throughput)이 더 이상 올라가지 않는다면?

  • Socket 수신 버퍼 확인
    • Netstat -na | grep <포트번호> 혹은 ss -t dst : <포트번호> 을 사용하여 Socket의 수신 버퍼와 송신 버퍼를 눈으로 직업 확인합니다.
    • Recv-Q와 Send-Q는 해당 Sockek이 얼마나 처리 대기 상태로 남아있는지 의미합니다.
    • 만약 Recv-Q가 지속적으로 0보다 크다면 아래와 같은 방법을 시도해 볼 수 있습니다.
      • NioEventLoop 확인
        • 데이터 변환, 객체 생성 혹은 로깅 등 제거
      • CPU 사용량 확인
        • CPU Profiling을 통해 프로세스 내에 불필요한 Thread를 찾아내어 제거하거나 개수를 줄이면 Context Switching이 줄어들게 됩니다.
      • NioEventLoop를 여러 개 사용
        • 병렬로 처리함으로써 Socket 버퍼 읽기 속도를 올려줄 수 있습니다.
        • NioEventLoop의 개수는 ReactiveRedisTemplate을 여러 개 생성함으로써 늘릴 수 있습니다.

Reference

반응형
반응형

스프링 표준 코딩 작성 방법

  1. 적절한 패키징 스타일
    • 적절한 패키징은 코드와 애플리케이션의 흐름을 쉽게 이해하는 데 도움이 됩니다.
    • 의미 있는 패키징으로 애플리케이션을 구조화할 수 있습니다.
    • 컨트롤러를 별도의 패키지에, 서비스를 별도의 패키지에, 유틸 클래스를 별도의 패키지에 포함시킬 수 있습니다... 등. 이 스타일은 소규모 마이크로서비스에서 매우 편리합니다.
    • 거대한 코드 베이스에서 작업하는 경우, 기능 기반 접근 방식을 사용할 수 있습니다. 요구사항에 따라 결정할 수 있습니다.
  2. 디자인 패턴 사용
    • 어디에 사용할지는 파악해야합니다.
  3. 스프링 부트 스타터 사용
    • 단일 종속성을 하나하나 추가하지 않고 매우 쉽게 스타터 종속성을 사용할 수 있습니다. 이러한 스타터 종속성은 이미 필요한 종속성과 함께 번들로 제공됩니다. 예를 들어, spring-boot-starter-web 종속성을 추가하면 기본적으로 jackson, spring-core, spring-mvc 및 spring-boot-starter-tomcat 종속성이 번들로 제공됩니다. 따라서 우리는 별도로 종속성을 추가할 필요가 없습니다. 또한 버전 불일치를 피하는 데 도움이 됩니다.
  4. 적절한 라이브러리 버전 사용
    • 언제나 최신 안정적인 GA(General Availability) 버전을 사용하는 것이 권장됩니다. 때때로 이는 Java 버전, 서버 버전, 애플리케이션의 유형 등에 따라 달라질 수 있습니다. 동일한 패키지의 다른 버전을 사용하지 않고 여러 종속성이 있는 경우 항상 <properties>를 사용하여 버전을 지정하십시오.
  5. Lombok 사용
    • Lombok은 자바 라이브러리로, 해당 어노테이션을 사용하여 코드를 줄이고 깔끔한 코드를 작성할 수 있도록 도와줍니다. 예를 들어, 엔티티, 요청/응답 객체, DTO 등과 같은 몇 가지 클래스에서는 getter와 setter를 위해 많은 줄을 작성해야 하는데 Lombok을 사용시 한 줄로 처리될 수 있습니다. 필요에 따라 @Data, @Getter 또는 @Setter를 사용할 수 있습니다. 또한 롬복 로거 어노테이션을 사용할 수도 있습니다. @Slf4j를 권장합니다.
  6. Lombok을 이용한 생성자 주입
    • 의존성 주입(Dependency Injection)에서 생성자 주입을 강력히 권장하는데, Lombok의 @RequiredArgsConstructor 어노테이션을 사용하여 생성자 주입을 할 수 있습니다.
    • import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class SampleController { private final SampleService sampleService; @GetMapping("/hello") public String sayHello() { return sampleService.getGreeting(); } }
  7. slf4j logging를 사용
    • System.out.print()를 사용하지 마세요.
    • Spring Boot의 기본 로깅 프레임워크인 logback과 함께 사용하기 위해 Slf4j를 권장합니다. 항상 slf4j {}를 사용하고, 로거 메시지에 문자열 보간법(String interpolation)을 사용하지 않도록 해야 합니다. 왜냐하면 문자열 보간법은 더 많은 메모리를 사용하기 때문입니다. Lombok의 @Slf4j 어노테이션을 사용하면 로거를 매우 쉽게 생성할 수 있습니다.
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.stereotype.Service;
      
      @Service
      @Slf4j
      public class SampleService {
          public void performTask() {
              log.debug("Debug message");
              log.info("Info message");
              log.warn("Warning message");
              log.error("Error message");
          }
      }
      
    • ** String interpolation: ${변수명}처럼 변수명을 사용하여 문자를 출력하는 것을 말합니다.
    • 마이크로서비스 환경에서는 ELK 스택을 사용할 수 있습니다.
  8. 컨트롤러는 라우팅으로만 사용
    • 컨트롤러는 상태를 가지지 않으며 싱글톤입니다.
    • 비즈니스 로직은 컨트롤러에 위치해서는 안 됩니다.
  9. 서비스에서 비즈니스 로직 구현
    • 서비스는 싱글톤입니다.
    • 비즈니스 로직은 여기에 포함되며, 유효성 검사, 캐싱 등이 이루어집니다.
    • 서비스는 영속성 계층과 통신하고 결과를 받아옵니다.
  10. NullPointerException 피하기
    • java.util 패키지의 Optional, Apache Commons StringUtils을 사용하여 NullPointerException을 피할 수 있습니다.
    • toString() 대신 valueOf()를 사용하세요.
    • IDE 기반의 @NotNull 및 @Nullable 어노테이션을 사용하세요.
  11. 컬렉션 프레임워크에 대한 모범 사례
    • 데이터 세트에 적합한 컬렉션을 사용하세요.
    • Java 8의 기능을 활용하여 forEach를 사용하고, 레거시 for 루프는 피하세요.
    • 구현 대신 인터페이스 유형을 사용하세요.
    • 가독성을 위해 size() 대신 isEmpty()를 사용하세요.
    • null 값을 반환하지 마세요. 대신 빈 컬렉션을 반환할 수 있습니다.
    • 해시 기반 컬렉션에 저장될 데이터로 객체를 사용하는 경우, equals()와 hashCode() 메서드를 오버라이드해야 합니다.
  12. pagination 사용
    • pagination을 사용하면 애플리케이션의 성능이 향상됩니다.
    • Spring Data JPA를 사용하는 경우, PagingAndSortingRepository를 사용하면 페이지네이션을 매우 쉽게 사용할 수 있고 노력도 적게 듭니다.
  13. 캐싱 사용
    • Spring Boot는 기본적으로 ConcurrentHashMap을 사용하여 캐싱을 제공하며, @EnableCaching 어노테이션을 통해 이를 구현할 수 있습니다.
    • 기본 캐싱에 만족하지 못하는 경우 Redis, Hazelcast 또는 기타 분산 캐싱 구현체를 사용할 수 있습니다. Redis와 Hazelcast는 메모리 내 캐싱 방법입니다. 또한 데이터베이스 캐시 구현체를 사용할 수도 있습니다.
  14. 전역 예외 처리를 위해 사용자 정의 예외 처리기를 전역 예외 처리와 같이 사용
    • 일반적인 예외 외에도 특정한 오류 상황을 식별해야 할 수 있습니다. @ControllerAdvice를 사용하여 예외 어드바이저를 만들고 의미 있는 세부 정보를 갖는 별도의 예외를 생성할 수 있습니다.
    • import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex) { // 예외 처리 로직 작성 // 클라이언트에게 적절한 응답을 반환하거나 로깅 등을 수행할 수 있습니다. // 예시로 500 Internal Server Error를 반환합니다. return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error"); } }
  15. 사용자 정의 응답 객체 사용
    • 사용자 정의 응답 객체를 사용하면 HTTP 상태 코드, API 코드, 메시지 등과 같은 특정 데이터를 가진 객체를 반환할 수 있습니다.
    • 빌더 디자인 패턴을 사용하여 사용자 정의 속성이 있는 응답 객체를 생성할 수 있습니다.
  16. 불필요한 코드, 변수, 메서드 및 클래스 제거
    • 사용되지 않는 변수 선언은 일부 메모리를 차지합니다. 사용되지 않는 메서드, 클래스 등을 제거하세요.
    • 중첩된 반복문을 피하려고 노력하세요. 대신 맵을 사용할 수 있습니다.
  17. 주석 사용
    • 주석은 남용하지 않는 한 좋은 관행입니다. 모든 것에 주석을 달지 마세요. 대신 클래스, 함수, 메서드, 변수 등에 의미 있는 단어를 사용하여 설명적인 코드를 작성할 수 있습니다.
    • 주석을 사용하여 경고 및 처음 보는 사람에게 이해하기 어려운 내용을 설명할 수 있습니다.
  18. 클래스, 메서드, 함수, 변수 및 기타 속성에 의미 있는 단어 사용
    • 적절하고 의미 있는 이름 규칙을 사용하고 적절한 케이스를 사용하세요.
    • 일반적으로 클래스, 변수 및 상수를 선언할 때는 명사 또는 짧은 구문을 사용합니다. 예: String firstName, const isValid
    • 함수와 메서드에는 동사와 형용사와 함께 짧은 구문을 사용할 수 있습니다. 예: readFile(), sendData()
    • 변수 이름을 약어로 사용하거나 의도를 드러내는 이름을 사용하는 것을 피하세요. 예: int i; String getExUsr;
  19. 선언에 적절한 케이스 사용
    • 다양한 케이스(UPPERCASE, lowercase, camelCase, PascalCase, snake_case, SCREAMING_SNAKE_CASE, kebab-case 등)가 있습니다. 각 변수에 어떤 케이스를 사용해야 할지를 파악해야 합니다.methods & variables — camelCaseDB-related fields — snake_case
    • constants — SCREAMING_SNAKE_CASE
    • classes — PascalCase
  20. 단순
    • 항상 간단하고 가독성이 좋은 코드를 작성하려 노력하세요. 동일한 간단한 논리를 다른 방식으로 구현할 수 있지만, 가독성이나 이해하기 어렵다면 어려울 수 있습니다. 때로는 복잡한 논리가 더 많은 메모리를 사용합니다. 코드를 작성할 때 KISS, DRY 및 SOLID 원칙을 사용하려 노력하세요. 이에 대해 나중에 기사로 설명하도록 하겠습니다.
  21. 공통적인 코드 포맷 스타일 사용
    • 코딩 스타일은 개발자마다 다양할 수 있습니다. 코딩 스타일 변경은 변경 사항으로 간주되며, 코드 병합을 어렵게 만들 수 있습니다. 이를 피하기 위해 팀은 공통된 코딩 포맷을 가질 수 있습니다.
  22. SonarLint 사용
    • SonarLint는 코드 품질과 유지 관리성을 개선하는 데 도움이 되는 강력한 코드 분석 도구입니다. 이 도구는 업계 모범 사례와 코딩 표준을 기반으로 실시간 피드백과 제안을 제공합니다. SonarLint를 개발 환경에 통합하면 버그, 취약점, 코드 품질 문제 등을 사전에 식별하고 해결할 수 있습니다.

 

 

Reference

반응형

'SpringBoot' 카테고리의 다른 글

[error]Spring-docs + WebSecurityConfig  (0) 2023.06.11
[error]Sequence "MEMBER_SEQ" not found; SQL statement:  (0) 2023.06.04
반응형
반응형

Fault Tolerant System(FTS)

Fault Tolerant System은 하드웨어나 소프트웨어의 결함이 발생하더라도 규정된 기능을 수행할 수 있는 시스템을 말합니다. 그렇기 때문에 컴퓨터 부품 또는 모듈이 제거 또는 재장착을 하는 동안 시스템은 기능을 수행하고 있습니다.

 

Fault Tolerant System 단계

  1. Fault Detection (장애 감지)
  2. Fault Diagnosis (장애 진단)
  3. Fault Recovery (장애 복구)
반응형
반응형

Java version 7 functions

 

Functions

1. try-with-resources

try (InputStream in = new FileInputStream(inFile); // try에 자원 객체를 전달하면 finally 블록으로 종료 처리를 하지 않아도 try 코드 블록이 끝나면 자동으로 자원을 종료해주는 기능.
     OutputStream out = new FileOutputStream(outFile)) {
    ...
} catch(IOException ex) {
    ...
}

 

2. multicatch

try (InputStream in = new FileInputStream(inFile); // try에 자원 객체를 전달하면 finally 블록으로 종료 처리를 하지 않아도 try 코드 블록이 끝나면 자동으로 자원을 종료해주는 기능.
     OutputStream out = new FileOutputStream(outFile)) {
    ...
} catch(IOException ex) {
    ...
}

 

3. switch-case에 문자열 지원

String str = "비밀";

switch(str) {
    case "진실": ...
         break;
    case "비밀": ...
         break;
    ...
    default: ...
         break;
}

 

4. Fork/Join

  • 어떤 계산 작업을 할 때 여러 개로 나누어 계산한 후 결과를 모으는 작업합니다.
  • 별도로 구현하지 않아도 라이브러리에서 Work Stealing 작업을 알아서 수행합니다.
// 기본
long total = 0;
for(int loop = from; loop <= to; loop++) {
	total += loop;
}

// Fork/Join
public class ForkJoinSample {
	static final ForkJoinPool mainPool = new ForkJoinPool();
    
	public static void main(String[] args) {
		long from = 0;
		long to = 10;
		GetSum sum = new GetSum(from, to);
		
		// 계산을 수행하는 객체를 넘겨주어 작업을 실행하고 결과를 받음
		Long result = mainPool.invoke(sum);
		System.out.println("total:" + result);
	}
}

public clas GetSum extends RecursiveTask<Long> {
	long from, to;
    
  public GetSum(long from, long to) {
    this.from = from;
    this.to = to;
	}

	public Long compute() {
		long gap = to - from;
		
		// 작업 단위가 작을 경우
		if(gap <= 3) {
			long result = 0;
		  for(int loop = from; loop <= to; loop++) {
			  result += loop;
			}
		  
			return result;
		}
		
		// 작업 단위가 클 경우
		// 두 개의 작업으로 나누어 동시에 실행시키고, 두 작업이 끝날 때 까지 결과를 기다림
		long middle = (from + to) / 2;
		GetSum prev = new GetSum(from, middle);
		prev.fork();
		GetSum post = new GetSum(middle + 1, to);
		// compute() 함수는 람다식을 통해서 기존의 값에 어떻게 연산을 할지 지정할 수 있습니다.
		return post.compute() + prev.join();
        
  }
}

 

5. ECC 암호화 기능 제공

반응형
반응형
반응형

JDK, JRE, JVM이란?

 

JDK(Java Development kit)

- 자바 소스 파일을 바이트 코드로 변환

- 컴파일러, 역 어셈블러(기계어를 어셈블리어로 변환하는 컴퓨터 프로그램), 디버거, 의존관계 분석을 제공

 

JRE

- javac(JDK)가 만든 클래스 파일을 해석 및 실행

- 자바 실행 명령, 클래스 로더와 바이트 코드의 실행에 필요한 라이브러리 제공

 

JVM

- Java가 동작하는 가상 환경

- os에 실행될 수 있도록 추상층을 제공

- os에 맞게 언어를 변경할 때 Interpreter 또는 JIT를 사용

 

반응형

'Java' 카테고리의 다른 글

Java 7 functions  (0) 2023.06.18
[ERROR]cannot find symbol  (0) 2023.05.29
[ERROR]Illegal modifier for the interface field Observer.name; only public, static & final are permitted  (0) 2023.05.29
AOP이란?  (0) 2023.05.11
반응형
반응형

 

Build

코드 파일을 컴퓨터에서 실행할 수 있도록 형태 변화하는 것을 Build라고 합니다.

자바 개발을 하면 .java 파일이 생성되고 build하게 되면 .java 코드 파일을 컴퓨터에서 실행할 수 있도록 변화(compile한다고 합니다.)과정을 거치면 .class 파일이 생성됩니다. 그리고 META-INF와 MANIFEST.MF 들을 하나로 압축하는 과정을 진행합니다.

 

Deploy

Build된 파일을 원하는 위치에 옮기는 것을 말합니다.

 

Complie

인간이 작성한 코드를 기계가 읽을 수  있도록 작업하는 것을 compile이라고 합니다.

반응형

+ Recent posts