seban21의 등록된 링크

 seban21로 등록된 네이버 블로그 포스트 수는 78건입니다.

[Spring Boot] 스프링 부트 가상 스레드로 웹소켓 사용 [내부링크]

Spring Boot에 Java 21 LTS 가상 스레드에 WebSocket 사용 하기 스프링 부트 텍스트 기반 Stomp 웹소켓 예제는 많지만 바이너리 기반 웹소켓 예제는 많이 없어서 자료를 남긴다. 데이터 베이스 연동 또는 레디스 연동으로 인한 블로킹 구간의 처리량을 올리기 위해 가상 스레드를 사용한다. 간단한 외부 연동 블로킹 확인을 위해 타임 서버도 구성 하였다. Time 서버 application.yml server: shutdown: graceful port: 9090 tomcat: threads: max: 4 min-spare: 4 ServerTimeController.java package com.example.controller; import lombok.Builder; import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.b

[자바] java BigDecimal 지수 표현 [내부링크]

생성자 전달 값 그대로 표현 System.out.println(new BigDecimal(2174000.0D).toString()); System.out.println(new BigDecimal("2564000").toString()); System.out.println(new BigDecimal("2.564E6").toString()); 실행결과> 2174000 2564000 2.564E+6 지수 표현 제거, toPlainString 메소드 사용 System.out.println(new BigDecimal(1.150216E7).toPlainString()); System.out.println(new BigDecimal(1.150216E7D).toPlainString()); System.out.println(new BigDecimal("1.150216E7").toPlainString()); 실행결과> 11502160 11502160 11502160 지수 표현 있으면 지수로, 없으면

[Spring Boot] 스프링 부트 가상 스레드로 Redis 사용 [내부링크]

Spring Boot에 Java 21 LTS 가상 스레드에 레디스 사용 하기 스프링 부트 자동 설정의 LettuceConnectionFactory 사용해서 레디스 연결 // RedisAutoConfiguration ... @Bean @ConditionalOnMissingBean(RedisConnectionFactory.class) @ConditionalOnThreading(Threading.VIRTUAL) LettuceConnectionFactory redisConnectionFactoryVirtualThreads( ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers, ClientResources clientResources) { LettuceConnectionFactory factory = createConnectionFactory(builderCustomizers, clientResource

[Spring Boot] 스프링 부트 가상 스레드로 Async 및 Scheduled 어노테이션 사용 [내부링크]

Spring Boot에 Java 21 LTS 가상 스레드 및 Async 및 Scheduled 어노테이션 사용 하기 build.gradle plugins { id 'java' id 'org.springframework.boot' version '3.2.5' id 'io.spring.dependency-management' version '1.1.4' } group = 'com.example.vt' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '21' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() maven { url 'https://repo.spring.io/release/' } } dependencies { implementation 'org.springframework.boot:spring-boot

[Spring Boot] 스프링 부트 가상 스레드 [내부링크]

Spring Boot에 Java 21 LTS 가상 스레드 사용 하기 Java 21 LTS Gradle 8.7 Spring Boot 3.2 Spring Framework 6.1.x mysql-connector-java 8.0.33 MySQL 패키지에 사용된 synchronized 키워드가 가상 스레드 pinning을 유발 하므로 ReentrantLock으로 마이그레이션한 버전 사용 간략한 Time 서버와 Api 서버 구성 Time 서버 application.yml server: shutdown: graceful port: 9090 tomcat: threads: max: 8 min-spare: 8 spring: threads: virtual: enabled: false java code import com.example.vt.model.ServerTime; import org.springframework.web.bind.annotation.GetMapping; import org.spr

[자바] java 21 Virtual Thread Tcp Socket Server [내부링크]

Java Virtual Thread Tcp Socket Server java 11 소켓 클래스 java.net.SocketInputStream java 21 소켓 클래스 sun.nio.ch.NioSocketImpl JEP 353 (Reimplement the legacy Socket API) https://openjdk.org/jeps/353 에서 Socket API들을 재구현함으로써 코드의 변경없이 가상 스레드를 사용할 수 있도록 하였다. golang의 tcp 소켓 서버의 net poll 방식 구현과 유사한 방식으로 구현하였다. java 1.4 버전 이전의 tcp io socket server와 다른 부분은 연결 클라이언트 처리를 가상 스레드로 한다. 연결 클라이언트 관리, 단편화된 패킷 수신 처리, 버퍼 풀 등 추가 구현이 필요하다. ServerApplication.java import org.apache.logging.log4j.LogManager; import org.apac

[자바] java 21 switch null check [내부링크]

기존 switch 문의 경우 null 체크를 if문을 사용 하였다. private static void testSwitch(String str) { if (str == null) { System.out.println("Null!"); return; } switch (str) { case "A", "B" -> System.out.println("Hello"); default -> System.out.println("Ok"); } } java 21 부터는 switch 문에서 null 체크가 가능하다. private static void TestSwitch(String str) { switch (str) { case null -> System.out.println("Null!"); case "A", "B" -> System.out.println("Hello"); default -> System.out.println("Ok"); } } 참고링크: https://openjdk.org/jeps

[자바] java 21 Sequenced Collections [내부링크]

자바 21 이전의 컬렉션의 요소 처음과 마지막 접근은 아래와 같은 형태 였다. import java.util.*; public class SequencedCollections { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); // ... // First element list.get(0); // Last element list.get(list.size() - 1); Deque<Integer> deque = new ArrayDeque<>(); // ... // First element deque.getFirst(); // Last element deque.getLast(); SortedSet<Integer> sortedSet = new TreeSet<>(); // ... // First element sortedSet.first(); // Last element sortedSet.last

java 21 download [내부링크]

java 21 download site jdk 21 download site openjdk 21 download site https://jdk.java.net/21/ https://adoptium.net/temurin/nightly/?version=21 https://learn.microsoft.com/ko-kr/java/openjdk/download https://developers.redhat.com/products/openjdk/download

spring boot ApplicationContextInitializer [내부링크]

spring boot 실행시 가장 먼저 실행 해야할 기능이 있을경우 ApplicationContextInitializer 사용 spring test junit에서도 사용 가능하다. application.properties, application.yml 설정 파일 접근은 getEnvironment 메소드 사용 BootCtxInitializer.java package com.example.app.initializers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; public final class BootCtx

MySQL DB 스키마 Diff 생성 [내부링크]

MySQL diff Oracle에서 제공하는 MySQL Utilities를 받으시면 http://dev.mysql.com/downloads/utilities/ scripts 폴더에 mysqldiff가 있습니다. python으로 작성된 스크립트이고 사용법은 아래와 같습니다. mysqldiff --server1=user:pass@host1 --server2=user:pass@host2 db1:db2 --difftype=sql 결과는 아래와 같이 sql문을 출력해주는데, 이 sql을 db1에서 실행하면 db2와 동일한 스키마가 됩니다. # server1 on host1: ... connected. # server2 on host2: ... connected. # Comparing db1.table3 to db2.table3 [FAIL] # Transformation statements: ALTER TABLE db1.table3 DROP COLUMN notes; Compare failed.

자바(java) reverse()메소드 이용한 문자열 역순출력 [내부링크]

public class ReverseTest { public static void main(String[] args) { StringBuffer sb = new StringBuffer("korea"); sb.reverse(); System.out.println(sb.toString()); } }

자바(java) int 1 을 String 01로 포멧 변경하기(숫자 2자리로 표현하기) [내부링크]

int num = 1; System.out.println(String.format("%1$02d", num)); // 3자리 숫자이면 라면 : "%1$03d" 출처 : http://blog.naver.com/xxeno/150088000820

java(자바) String.format [내부링크]

import java.util.Date; public class TestMain { public static void main(String[] args) { // % [인자 번호] [플래그] [너비] [.정밀도] 유형 // %d 십진정수, %f 부동소수점, %x 16진수, %c 문자 // %tc 날짜와 시간 전부 표시 // %tr 시간만 표시할때 // %A %B %C 요일,월,일 표시 String fo = String.format("%,d", 1000000000); // 금액 System.out.println(fo); String fo0 = String.format("value %.2f", 77777.777); // 소숫점 2자리만 System.out.println(fo0); String fo1 = String.format("value %,.2f", 2231323.23132); // 금액 및 소숫점 2자리만 System.out.println(fo1); String fo2 = Stri

java(자바) Character를 이용한 문자열에서 숫자만 추출 [내부링크]

String str = "홍길동1222가33나"; char[] charArr = str.toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = 0, len = charArr.length; i < len; i++) { if (Character.isDigit(charArr[i])) { sb.append(charArr[i]); } } System.out.println(sb.toString()); >결과 122233

java(자바) json string pretty 예쁘게 출력 [내부링크]

public final static String INDENT = " "; public static String jsonPretty(String jsonString) { final int length = jsonString.length(); StringBuilder sb = new StringBuilder(length + 200); int indentDepth = 0; for (int i = 0, len = length; i < len; i++) { String targetString = jsonString.substring(i, i + 1); if (targetString.equals("{") || targetString.equals("[")) { sb.append(targetString).append("\n"); indentDepth++; for (int j = 0; j < indentDepth; j++) { sb.append(INDENT); } } else if (targetSt

java(자바) 아이피 체크 정규식 [내부링크]

ip check regex import java.util.regex.Pattern; public final class InetAddressUtils { private final static Pattern IPV4_PATTERN = Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$"); private final static Pattern IPV6_STD_PATTERN = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"); private final static Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4

java(자바) QueryString [내부링크]

1.쿼리스트링에서 값 가져오기 import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class QueryParams { private static class KVP { final String key; final String value; KVP(String key, String value) { this.key = key; this.value = value; } } private List<KVP> query = new ArrayList<>(); public QueryParams(String queryString) { parse(queryString); } public QueryParams() { } publi

자바 boolean 반대로 간략 소스 [내부링크]

private void power() { power = !power; } power()의 power = !power; 문은 power의 값이 true면 false로, false면 true로 변경하는 일을 한다. power의 값에 관계없이 항상 반대의 값으로 변경해주면 되므로 굳이 if문을 사용할 필요가 없다. 참고로 if문을 사용하여 코드를 작성하면 다음과 같다. if (power) { power = false; } else { power = true; }

java(자바) java.sql.Timestamp를 Date로 문자열로 변환 [내부링크]

데이터베이스 사용시 날짜시간 데이터형을 Timestamp로 사용하는 경우가 생긴다. 아래는 Timestamp자료형을 Date클래스를 사용한 문자열로 표현하는 방법이다. import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Locale; import java.sql.Timestamp; ... SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.KOREA); String str = sdf.format(new Date(timestamp.getTime())); System.out.println(str); ... 출력결과> 2012-02-01 11:15:45

java(자바) byte array hex dump [내부링크]

byte array hex dump HexDumpUtils.java public final class HexDumpUtils { private HexDumpUtils() { } public static String printHexString(byte[] target) { StringBuilder b = new StringBuilder(target.length * 2); for (int i = 0, len = target.length; i < len; ++i) { b.append(Integer.toHexString(0x0100 + (target[i] & 0x00FF)).substring(1).toUpperCase()).append(' '); } return b.toString(); } /** * <pre> * byte[]를 출력을 위해 포맷팅 된 Hex String의 문자열로 변환하여 리턴 * </pre> * * @param target - 대상 byte [] * @param line

java(자바) byte array offset 활용 [내부링크]

offset를 계산해서 하나의 byte[]만 생성해서 사용하기 ByteArrayOffsetLengthTest.java import java.nio.ByteBuffer; import java.nio.charset.Charset; public class ByteArrayOffsetLengthTest { private final static int ACK_SIZE = 32; private final static int CLIENT_SIZE = 22; private final static int TIME_SIZE = 8; // private final static int ACK_OFFSET = 0; private final static int CLIENT_OFFSET = ACK_SIZE; private final static int TIME_OFFSET = ACK_SIZE + CLIENT_SIZE; // private final static int TOTAL_SIZE = ACK_SIZE +

java(자바) Currency 나라별 통화 코드 [내부링크]

System.out.println(Currency.getInstance(Locale.KOREA).getSymbol()); System.out.println(Currency.getInstance(Locale.KOREA). getCurrencyCode()); import java.util.Currency; import java.util.Locale; public class CurrencyTest { private final static String[][] C = { { "아프리칸스어(남아프리카 공화국)", "af-ZA" }, { "알바니아어(알바니아)", "sq-AL" }, { "아랍어(알제리)", "ar-DZ" }, { "아랍어(바레인)", "ar-BH" }, { "아랍어(이집트)", "ar-EG" }, { "아랍어(이라크)", "ar-IQ" }, { "아랍어(요르단)", "ar-JO" }, { "아랍어(쿠웨이트)", "ar-KW" }, { "아랍어(레바논)", "ar-LB" }, {

java(자바) Math 클래스 [내부링크]

Math 클래스는 흔히계산을 하는데 도움이 되는 많은 수의 기본적 수학 함수들을 제공한다. Math 클래스는 Java 표준 클래스 라이브러리의 java.lang 패키지에 정의되어 있다. Math 클래스의 모든 메소드들은 정적 메소드(static method)로 클래스의 객체를 생성하지 않고 그 메소드가 정의된 클래스 이름을 통해서 호출될 수 있다. Math 클래스의 메소드 static int abs(int num) num의 절대 값을 반환한다. static double acos(double num) num의 arc cosine을 반환한다. static double asin(double num) num의 arc sine을 반환한다. static double atan(double num) num의 arc tangent를 반환한다. static double cos(double num) num의 cosine을 반환한다. static double sin(double num) num의 sine

[자바] java 8byte guid 생성 [내부링크]

16자리 long 자료 타입의 정수값으로 중복 안되는 id값 생성 16자리 long 자료 타입 정수값은 7byte, 마지막 1byte는 serverRunId로 사용 ... // 서버 시작시 Redis Server 로 부터 유일값 반환 int serverRunId = 255; // 0 ~ 255 TimeBasedGuid.current().setServerRunGuid(serverRunId); log.info("{}", TimeBasedGuid.current().getNextGuid()); ... 출력값> 3rhTPgQFBv8= java 21 가상 스레드에서도 사용 가능하기 위해 ReentrantLock 생성시 true값 사용 ReentrantLock reentrantLock = new ReentrantLock(true); import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Base64; import

csharp .net GUID 8 byte 생성 [내부링크]

C# 에서 기본적으로 지원하는 GUID 클래스의 경우 16 byte 크기의 GUID를 생성한다. 정수값 16자리 및 서버를 구분하는 유일한 아이디 발급이 가능할경우 8 byte로 GUID 생성이 가능하다. class TimebasedGuid { private static readonly Lazy<TimebasedGuid> Lazy = new (() => new TimebasedGuid()); private readonly object Lock = new object(); public long Ticks16; public byte ServerRunGuid { set; get; } private int counter; public static TimebasedGuid Instance { get { return Lazy.Value; } } private TimebasedGuid() { this.Ticks16 = CreateTimeTick16(); } public void Init(byte

csharp .net 비동기 공유 자원 시용 [내부링크]

async await 키워드 사용으로 비동기 동작 하는 구간의 공유 자원에 안전하게 접근 하기 위해 Semaphore 사용 Semaphore 생성 할때 name 파라미터에 유저를 구분 짓는 accountID를 사용 [ApiController] [Route("[controller]/[action]")] public class MyApiController : ControllerBase { ... [HttpPost] public async ValueTask<AccountRes> Api(AccountReq req) { string? sessionAccountId = HttpContext.Session.GetString("SESSION_ACCOUNT_ID"); if (string.IsNullOrEmpty(sessionAccountId)) return new AccountRes() { ResultCode = NOT_FOUND_ACCOUNT }; using var conn = MySQLDappe

java(자바) StringBuilder String.format 성능 비교 [내부링크]

QWE|ASD|ZXC|123|... 형태의 문자열 만들때 StringBuilder가 4배 이상 빠름 String.format("%s|%s|%s", str1, str2, str3); ... StringBuilder sb = new StringBuilder(128); sb.append(str1).append("|"); ... 가독성은 String.format가 더 좋음 테스트 코드 import com.google.common.base.Stopwatch; ... Stopwatch stopwatch = Stopwatch.createStarted(); ... stopwatch.stop(); log.debug("Elapsed time in Milliseconds {}", stopwatch.elapsed(TimeUnit.MILLISECONDS));

java(자바) Comparator Comparable 인터페이스 [내부링크]

Comparable<T> 인터페이스 <- [java.lang.Comparable] 인터페이스 이 인터페이스를 구현하는 각 클래스의 객체에 정렬 기준을 의미. 이는 클래스의 자연적 정렬 기준이라고 불려지며, compareTo() 메서드는 자연적 비교 메서드라고 불림. 이 인터페이스를 구현하는 객체는 Arrays.sort()나 Collections.sort() 등에 의해 정렬을 이룰 수 있다. compareTo(T o) 인터페이스로 구현한 현재 객체와 인자로 전달된 객체가 정렬을 위한 비교를 함. 이 때 현재 객체가 크다면 양수(1), 작다면 음수(-1), 서로가 같다면 0을 리턴하는 규칙으로 재정의해야 한다. Comparator<T> 인터페이스 <- [java.util.Comparator] 인터페이스 Comparator를 정렬 메서드인 Arrays.sort()나 Collections.sort() 등에 건네주면, 정렬 순서를 정확하게 제어 가능. 또한 Comparator를 사용하면 Tr

java(자바) AtomicInteger 사용한 순환 인덱스 [내부링크]

import java.util.concurrent.atomic.AtomicInteger; public final class ThreadSafeCycleIndex { private final static ThreadSafeCycleIndex INSTANCE = new ThreadSafeCycleIndex(); private final AtomicInteger atomicInteger; private int ix = 0; private final static int SIZE = 3; private ThreadSafeCycleIndex() { this.atomicInteger = new AtomicInteger(0); } public final static ThreadSafeCycleIndex getInstance() { return INSTANCE; } public int getCycleIndexNumber() { return atomicInteger.getAndSet((++ix) %

java(자바) 배열 역순 for문 [내부링크]

byte[] bytes = {1, 2, 3}; for (int i = bytes.length ; i-- > 0; ) { System.out.println( bytes[ i ] ); } output> 3 2 1

java(자바) 세션 ID 길이 짧게 하기 위해 64진수로 변환하기 [내부링크]

출처 : http://javacan.tistory.com/entry/use-64radix-for-generating-short-sessionid 요즘 밤에 틈이 나면 수련을 위한 개인 프로젝트를 진행중인데, 구현하는 과정 중에 클라이언트를 식별하기 위해 세션ID를 생성하는 기능이 필요해졌다. 이 기능을 직접 구현하기가 너무 너무 귀찮아서 자바에서 기본으로 제공하는 UUID 클래스를 사용하기로 마음 먹었다. UUID의 사용법은 간단한데, 조금 마음에 안 들었던 건 UUID를 문자열로 변환할 때 그 길이가 다소 길다는 것이었다. 아래 코드처럼 UUID를 문자열로 변환하면 32자 ('-' 포함하면 36자)이다. UUID uuid = UUID.randomUUID(); System.out.println(uuid.toString()); // --> "bf6f75a4-a1e9-4c0b-9b17-e9b6b5c0e5ed" 세션ID로 쓰기에 너무 길어서 이걸 조금이라도 줄여보고 싶은 마음에 16진수가

java(자바) 평균 초당 수신 byte수 출력 [내부링크]

서버작업을 하다보면 해당 소켓의 수신한 byte를 필요할경우가있다. 와이어샤크, netstat등등 툴로 확인가능하지만 java소스단에서 확인하는 방법을 설명함 셈플은 netty를 사용하였다. import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.util.Timeout; import io.netty.util.Timer; import io.netty.util.TimerTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; ... public class ByteServerHa

java(자바) nio2 file copy move readAllLines [내부링크]

자바 1.7에 commons-io FileUtils.copyFile 교체할만한 기능이 생겻다. import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.List; // 파일 복사 및 이동 Path source = Paths.get( "D:/download/TEST0.MKV" ); Path target = Paths.get( "D:/download/TEST1.MKV" ); try { Files.copy( source , target , StandardCopyOption.COPY_ATTRIBUTES ); //Files.move( source , target , StandardCopyOpt

java(자바) AtomicBoolean 멀티스레드에서 동시에 실행 안되게 하기 [내부링크]

... 구간은 동시 실행이 되어서는 안되는 부분 private AtomicBoolean safe= new AtomicBoolean(false); public void start() { if (safe.compareAndSet(false, true) == false) { return; } ... } public void end() { if (safe.compareAndSet(true, false) == false) { return; } ... }

java(자바) NumberFormat 화폐단위 표시 [내부링크]

System.out.println(NumberFormat.getCurrencyInstance(Locale.KOREA).format(3300D)); System.out.println(NumberFormat.getCurrencyInstance(Locale.JAPAN).format(3300D)); System.out.println(NumberFormat.getCurrencyInstance(Locale.US).format(0.99D)); System.out.println(NumberFormat.getCurrencyInstance(Locale.TAIWAN).format(0.99D)); ₩3,300 ¥3,300 $0.99 NT$0.99

java(자바) JVM 구동 옵션 확인 [내부링크]

디폴트로 설정된 값도 포함해서 출력 자바 구동시 아래 명령줄 추가 -XX:+PrintFlagsFinal

java(자바) BufferedReader fast read [내부링크]

1 2 3 4 5 6 7 8 9 10 11 ... BufferedReader stdOut = new BufferedReader(new InputStreamReader(process.getInputStream())); ... java.io.StringWriter sw = new java.io.StringWriter(1024 * 8); char[] buffer = new char[1024 * 4]; int n = 0; while (-1 != (n = stdOut.read(buffer))) { sw.write(buffer, 0, n); } String s = sw.toString(); ...

java(자바) String.hashCode()는 유일한 값을 반환할까? [내부링크]

네이버 카페 코드인에 심심해서 적어 놨던 글을 다시 옮겨옴. ( 워낙 포스팅이 없어서 ;; 요런걸로 때움. ㅋㅋㅋ ) ------- 안녕하세요. 찬 입니다. 우리가 일반적으로 Map이나 HashTable을 쓸때 다음과 같이 사용하지요. Map map = new HashMap(100); map.put("찬", new Person( Person.MEN, 29 ) ); map.put("철수", new Person( Person.MEN, 15) ); map.put("영희", new Person( Person.WOMAN , 13 ) ); 이때 map에 key로 "찬", "철수", "영희" 와 같이 String을 주고, value로는 Person 객체를 만들어서 넣어 줍니다. 이때, map에서는 key 값이 중복되면 기존에 있던 value에다가 새로운 value를 덮어 써 버리게 되는 것처럼 보입니다. map.put("찬", new Person( Person.MEN, 29 ) ); map.pu

java(자바) gzip 압축 및 해제 [내부링크]

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class GzipTest { public byte[] write(byte[] bytes) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); GZIPOutputStream

java(자바) 글자수를 세는 7가지 방법 [내부링크]

안녕하세요. 라인플러스 개발실에서 일하고 있는 박상진입니다. 이 블로그에서는 글자 수를 세는 방법에 대해서 얘기해보고자 합니다.라인 서비스에서는 프로필이름, 그룹이름, 상태메시지 등 여러 곳에서 글자 수를 세게 되는데요. 글이 화면에 부족하거나 넘치지 않게 하고, 스토리지 용량을 정확하게 할당하기 위해서는 글자 수를 정확히 세는 것은 중요한 일입니다. 특히 라인은 전세계에서 사용하는 서비스인만큼 다른 언어들의 글자 수도 정확히 셀 수 있어야 합니다. 어느 날 BTS(Bug Tracking System)의 프로필 이름에 emoji를 입력하면 1자가 2자로 표시되는, 글자 수가 정확히 카운트되지 않는다는 이슈가 올라왔습니다. emoji란 일본에서 처음 쓰이기 시작한 것으로 지금은 Unicode 표준에 포함되어 세계적으로 널리 쓰이고 있는 그림문자 세트인데요. 처음에는 단순히 Surrogate를 제대로 카운트하지 못하는 문제라고 짐작하고 분석을 시작했습니다. Surrogate란 쉽게 이야

java(자바) CountDownLatch [내부링크]

만약 백그라운드에서 실행되고 있는 싱글 쓰레드가 종료되기를 기다리는 코드를 작성해야 한다면 당장 Thread 클래스의 join() 메소드 부터 떠올리게 될 것이다. 아래와 같이 말이다. 하지만, 멀티 쓰레드에서 모든 동작이 끝나기를 기다려야 하는 상황이라면 join 을 사용하기 조금 난감하다. 이럴 땐 CountDownLatch 를 사용하면 참 편리하다. (안드로이드 API 설명 페이지로 링크합니다. 이 곳이 오라클 페이지보다 보기 좋아서;; http://developer.android.com/reference/java/util/concurrent/CountDownLatch.html ) CountDownLatch 는 생성할 때 1 이상의 카운트를 인자값으로 받는다. 그리고 특정 메소드 내부에서 await() 메소드로 대기 상태를 만들어주고 CountDownLatch 를 생성할 때 설정한 count 가 0이 되기만들 기다렸다가 0이 되는 순간 대기 상태를 해제한다. 원리는 아래 그림과

java(자바) Pipe 사용 [내부링크]

Pipe.java public class Pipe { public final static String INDENT = " "; public static void main(String[] args) throws java.io.IOException { java.io.BufferedReader input = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); String x = null; StringBuilder sb = new StringBuilder(); while ((x = input.readLine()) != null) { sb.append(x); } System.out.println(jsonPretty(sb.toString())); } public static String jsonPretty(String jsonString) { final int length = jsonString.length(); Stri

java(자바) CSV파일 TSV파일로 변환 [내부링크]

data.csv "2017-11-17 11:11:11","데이터1","타입1" "2017-11-17 11:11:11","데이터2","타입1" "2017-11-17 11:11:11","데이터3","타입2" "2017-11-17 11:11:11","데이터4","타입2" "2017-11-17 11:11:11","데이터5","타입1" java code import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; ... StringBuilder sb = new StringBuilder(); Scanner s = new Scan

java(자바) member class 변수 생성자를 사용하지 않고 생성 및 초기화 [내부링크]

package com.example; ... import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; ... private final Map<Integer, String> nonStaticMap = new HashMap<Integer, String>() { private static final long serialVersionUID = 1L; { put(0, "success"); put(1, "failure"); } }; private static final Map<Integer, String> STATIC_MAP = new HashMap<Integer, String>() { private static final long serialVersionUID = 1L; { put(0, "success"); put(1, "failure"); } }; private final

java(자바) CharSequence 를 String 으로 변환하는 방법 [내부링크]

import org.junit.Test; public class CharSequenceTest { @Test public void test1() throws Exception { String s = "a string"; CharSequence cs = new StringBuffer("a string"); String s2 = cs.toString(); System.out.println("s.equals(s2): " + s.equals(s2)); System.out.println("s == s2: " + (s == s2)); cs = new StringBuilder("a string"); s2 = cs.toString(); System.out.println(s2); } } 출력결과> s.equals(s2): true s == s2: false a string

java(자바) 파일구분자(File.separator)를 대체하는 Path, Paths 사용하기 [내부링크]

windows D:\\tmp\\calendar.zip unix(linux) /tmp/calendar.zip import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; ... // windows Path path = Paths.get("d:", "tmp", "calendar.zip"); // unix(linux) // Path path = Paths.get("/", "tmp", "calendar.zip"); File file = path.toFile(); log.debug("{}", file.isFile()); log.debug("{}", file.isDirectory()); ... 출처: https://java.ihoney.pe.kr/342?category=398192

java(자바) 디렉토리 사용량 확인 [내부링크]

# cat centos-release CentOS Linux release 7.4.1708 (Core) # useradd test1 # echo 123456 | passwd --stdin test1 java.nio.file.Path folder = java.nio.file.Paths.get("/home/test1"); long size = java.nio.file.Files.walk(folder).filter(p -> p.toFile().isFile()).mapToLong(p -> p.toFile().length()).sum(); System.out.println(size); 참고링크: https://www.baeldung.com/java-folder-size

[자바] java Integer.valueOf(127) == Integer.valueOf(127) 는 참일까요? [내부링크]

안녕하세요. Java에는 최적화를 위해 객체들을 Cache를 하는 로직이 있습니다. Cache 로직은 애플리케이션의 성능 향상을 하도록 도와주지만, 의도치 않은 결과를 발생시키기도 합니다. 심지어 크리티컬한 장애 상황의 원인이 되기도 합니다. Naresh Joshi의 [Java Integer Cache — Why Integer.valueOf(127) == Integer.valueOf(127) Is True] 블로그 글을 옮겨보며, Java Integer Cache에 대해서 살펴보는 시간을 가져봅시다. 인터뷰에서, 내 친구가 다음과 같은 질문을 받았습니다. Integer a = 127; Integer b = 127; 위와 같은 2개의 Integer 객체가 있습니다. a == b (true? false?) a == b 의 답은 뭘까요? 본문에서는 이 질문에 대한 답과, 답에 대한 설명을 말하고자 합니다. 답을 간단히 말하자면, int 리터럴을 Integer reference로 직접 대입

[자바] java 타임존이 포함된 ISO 8601 문자열을 LocalDateTime으로 변환하기 [내부링크]

타임존? 과거에는 개발자들이 타임존을 크게 신경 쓰지 않았다. 하지만 시스템 또는 플랫폼 간의 의사소통 방식으로서의 API가 대중화되고 서비스 지역이 전세계로 확장되면서 API 요청 및 응답에 있어 타임존 정보를 적절하게 인식하고 가공하는 작업이 중요해졌다. 이번 글에서는 Java 8에서 타임존이 포함된 날짜/시간 정보를 다루는 방법을 소개하고자 한다.타임존 포함 ISO 8601 문자열의 표현 날짜/시간 및 타임존을 다루는 국제적인 규약은 상당히 다양하다. RFC 822, 1036, 1123, 2822, 3339, ISO 8601 등이 있다. 여기서는 ISO 8601과 RFC 3339와 관련된 표기법을 소개한다.// 로컬 시간을 의미하는 ISO 8601 문자열 2017-11-06T15:00:00.000 // UTC(GMT) 시간을 의미하는 ISO 8601 문자열 2017-11-06T06:00:00.000Z // 로컬 시간을 의미하면서 UTC(GMT) 대비 +09:00 임을 의미하는

[자바] java Scanner와 BufferedReader 차이 [내부링크]

자바에서 사용자의 입력을 받을 때, 또는 파일을 읽을 때, Scanner와 BufferedReader 클래스를 자주 사용합니다. 그럼 이 둘의 차이점을 알아 보도록 하겠습니다. 1. Scanner - java.util 패키지에 존재한다. - 데이터를 파싱해서 원하는 type으로 들어온다. 파싱하는데 시간이 걸리므로 느리다. - 버퍼의 사이즈가 1024byte(1KB)로, BufferedReader에 비해 작다. - thread unsafe하다. - I/O Exception을 던지지 않는다. 2. BufferedReader - java.io 패키지에 존재한다. - character InputStream 으로부터 읽어온다. 데이털르 파싱하지 않아 Scanner보다 빠르게 받아온다. - Scanner에 BufferedReader 를 넘겨서 데이터를 파싱 할 수 있다. - 버퍼의 사이즈가 8192byte(8KB)로, Scanner에 비해 크다. - thread safe하다. - I/O Ex

[자바] java StampedLock [내부링크]

private StampedLock mutex = new StampedLock(); ... long stamp = mutex.readLock(); ... mutex.unlockRead(stamp); 참고링크: http://www.yunsobi.com/blog/599 http://isuru-perera.blogspot.com/2016/05/benchmarking-java-locks-with-counters.html https://github.com/chrishantha/microbenchmarks/blob/v0.0.1-initial-counter-impl/counters/src/main/java/com/github/chrishantha/microbenchmark/counter/impl/StampedCounter.java https://github.com/chrishantha/microbenchmarks/blob/v0.0.1-initial-counter-impl/counters/src/

[자바] java LocalDateTime 경과 시간 가져오기 [내부링크]

import java.time.LocalDateTime; import java.time.Month; import java.time.temporal.ChronoUnit; LocalDateTime startDateTime = LocalDateTime.of(2021, Month.OCTOBER, 1, 0, 0, 0, 0); LocalDateTime nowDateTime = LocalDateTime.of(2031, Month.OCTOBER, 1, 0, 0, 0, 0); long time = ChronoUnit.MINUTES.between(startDateTime, nowDateTime); log.debug("{}", time); // 5258880 7자리 숫자 LocalDateTime startDateTime = LocalDateTime.of(2021, Month.JANUARY, 1, 0, 0, 0, 0); LocalDateTime nowDateTime = LocalDateTime.of(20

[자바] java java11 gc log [내부링크]

java 11버전에서 gc log를 남기는 옵션값이 변경 되었다. -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps ==> decoration options -XX:+PrintGCDetails ==> -Xlog:gc* -Xlog:::time,level,tags -XX:+PrintGCApplicationStoppedTime ==> -Xlog:safepoint -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles -XX:GCLogFileSize ==> output options -Xlog::::filecount=5,filesize=1024 아래와 같은 형태로 만들어야 한다. -Xlog:gc*,safepoint:gc.log:time,uptime,level,tags:filecount=10,filesize=100M $ /tools/java/jdk11.0.10/bin/java -Xlog:gc*,safepoint:gc.log:ti

[자바] java 서비스 가용성 확보에 필요한 Rate Limiting Algorithm에 대해 [내부링크]

서비스를 운영하다보면 의도적이든 의도적이지 않던간에 서비스의 가용성(API레벨, 네트워크 레벨, 컨테이너 레벨, CPU 레벨이든)을 유지하기 위해서 클라이언트의 과도한 사용에 대해 스스로를 보호해야 합니다. 간과하기 쉽지만, 서비스의 가용성을 유지하기 위한 노력은 클라이언트 측(앱/웹))에도 같이 설계를 해주는 것이 바람직합니다. 서비스를 보호해주는 수단으로 Rate Limit 알고리즘 적용하는데, 이를 효과적으로 적용하기 위해서는 알고리즘에 대한 이해도를 높일 필요가 있고 또, 서비스의 트래픽 특성도 파악해 둘 필요가 있습니다. 여기에서는 Rate Limit 알고리즘 정리하는 것을 목표로 하고 간단한 알고리즘을 구현함으로써 이해도를 높이도록 하겠습니다. 왜 Rate Limit 알고리즘이 필요한가? 과도한 트래픽으로부터 서비스를 보호. Resource 사용에 대한 공정성과 합리성 유도. 트래픽 비용이 서비스 예산을 넘는 것을 방지. Rate에 대해 과금을 부과하는 Business M

[자바] java instanceof와 Class.isAssignableFrom의 차이점 [내부링크]

instanceof는 특정 Object가 어떤 클래스/인터페이스를 상속/구현했는지를 체크 Class.isAssignableFrom()은 특정 Class가 어떤 클래스/인터페이스를 상속/구현했는지 체크 // instanceof MacPro obj = new MacPro(); if (obj instanceof Computer) { ... } // Class.isAssignableFrom() if (Computer.class.isAssignableFrom(MacPro.class)) { ... }

csharp .net 이벤트 발생시 데이터 넘기기 (EventArgs, EventHandler 델리게이트) [내부링크]

이벤트 발생시 넘겨줄 데이터 class EventPublisherArgs : EventArgs { public string myEventData; public EventPublisherArgs(string myEventData) { this.myEventData = myEventData; } } 이벤트 게시자 class EventPublisher { public event EventHandler? MyEvent; // 이벤트 정의 public void Publish() { if (MyEvent == null) { return; } EventPublisherArgs args = new EventPublisherArgs("데이터 " + Guid.NewGuid().ToString()); MyEvent(this, args); // 이벤트 발생 } } 이벤트 구독자 class Subscriber { // MyEvent 이벤트가 발생하면 호출되는 메서드 // EventPublisherArgs

csharp .net 장기 실행 태스크 설정 [내부링크]

Task 생성시 옵션으로 TaskCreationOptions.LongRunning을 설정해 줄 경우 ThreadPool에서 할당하지 않고 별도의 Thread를 생성하여 할당하기 때문에 Thread Pool의 부족현상을 해결 할 수 있다. var longRunTask = new Task(() => { // }, TaskCreationOptions.LongRunning); longRunTask.Start(); 참고링크: https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.taskcreationoptions?view=net-7.0

csharp .net for 문 내부 람다식 사용시 변수 참조 주의 사항 [내부링크]

람다는 변수 참조시 최종값을 참조 한다. foreach (var str in ...) { list.Add(() => { ... str 변수 사용 x }); } foreach (var str in ...) { string _str = str; // 새로운 변수 대입 list.Add(() => { ... _str 변수 사용 }); }

csharp .net SuperSocket Lite [내부링크]

TCP 소켓 통신 서버 구현때 사용할 가벼운 라이브러리 BinaryPacketReceiveFilter.cs using System; using SuperSocket.Common; namespace EchoServer; public sealed class NetworkBinaryRequestInfo : SuperSocket.SocketBase.Protocol.BinaryRequestInfo { public Int16 TotalSize { get; private set; } public Int16 PacketID { get; private set; } public SByte Value1 { get; private set; } public const int HEADER_SIZE = 5; public NetworkBinaryRequestInfo(Int16 totalSize, Int16 packetID, SByte value1, byte[] body) : base(null, body) { t

csharp .net 비주얼 스튜디오 파일 인코딩 설정 [내부링크]

.editorconfig root = true [*] charset = utf-8 참고링크: https://learn.microsoft.com/ko-kr/visualstudio/ide/create-portable-custom-editor-options?view=vs-2022 https://learn.microsoft.com/ko-kr/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-170 https://learn.microsoft.com/ko-kr/visualstudio/ide/how-to-save-and-open-files-with-encoding?view=vs-2022 https://learn.microsoft.com/ko-kr/visualstudio/ide/code-styles-and-code-cleanup?view=vs-2022 https://learn.microsoft.

csharp .net 생산자/소비자 패턴 컬렉션 [내부링크]

기능 Channel<T> BlockingCollection<T> BufferBlock<T> AsyncProducerConsumerQueue<T> AsyncCollection<T> 큐 역할 O O O O O 스택/백 역할 X O X X O 동기 API O O O O O 비동기 API O X O O O 가득 차면 항목 버림 O X X X X 마이크로소프트 검증 O O O X X 참고링크: https://learn.microsoft.com/ko-kr/dotnet/core/extensions/channels https://learn.microsoft.com/ko-kr/dotnet/standard/collections/thread-safe/blockingcollection-overview https://learn.microsoft.com/ko-kr/dotnet/api/system.threading.tasks.dataflow.bufferblock-1?view=net-6.0 https://lea

java(자바) 구동시 타임존 지정 [내부링크]

Asia/Seoul -Duser.timezone=GMT+09:00 UTC -Duser.timezone=UTC

[자바] java const enum [내부링크]

style 1 public enum ProcessResult { OK(0, "ok"), NOT_FOUND_USER(1, "not found user"), ; ProcessResult(int code, String message) { this.CODE = code; this.MESSAGE = message; } public int CODE; public String MESSAGE; } import com.example.dto.ProcessResult; import org.junit.jupiter.api.Test; class ProcessResultTests { @Test void test1() { ProcessResult processResult = ProcessResult.OK; if (processResult.CODE == ProcessResult.OK.CODE) { System.out.println("1: " + processResult.MESSAGE); } if (process

[자바] java 실행 속도 높이기 [내부링크]

-XX:TieredStopAtLevel=1 -noverify $ java ... -XX:TieredStopAtLevel=1 -noverify ... -jar application.jar 개발 환경과 빠르게 실행후 종료되는 어플리케이션에 사용 일반적인 live 서버 에서는 사용해서는 안된다.

java(자바) StringBuilder initialValue ThreadLocal [내부링크]

private final static ThreadLocal< StringBuilder > SB_BUFFER = new ThreadLocal< StringBuilder >( ) { @Override protected StringBuilder initialValue( ) { return new StringBuilder( 1024 ); } }; ... // 메소드 블록 시작 { StringBuilder buf = SB_BUFFER.get( ); buf.setLength( 0 ); .. buf.append( .... ); .. String str = buf.toString( ); // 메소드 블록 종료 } 매번 객체를 생성하여 사용하는것보다 처리속도가 빠르다. 멀티쓰레드에 안전한 방식

[자바] java concurrent 패키지 queue 비교 [내부링크]

java.util.concurrent.ArrayBlockingQueue java.util.concurrent.LinkedBlockingQueue java.util.concurrent.ConcurrentLinkedQueue 간략 하게 비교 new ArrayBlockingQueue<byte[]>(10000, true); new LinkedBlockingQueue<byte[]>(10000); new ConcurrentLinkedQueue<byte[]>(); ArrayBlockingQueue 큐의 크기 지정 가능 스레드간 엑세스 공정성 정책 설정 가능 LinkedBlockingQueue 큐의 크기 지정 가능 ConcurrentLinkedQueue 큐의 크기 지정 불가 생산자-소비자 producer-consumer 모델 에서 비교 LinkedBlockingQueue 생산자가 많고 하나의 소비자일 경우에 사용 추천 ConcurrentLinkedQueue 생산자가 하나이고 소비자가 많을 경우에

[GO언어] golang 이벤트 루프 네트워킹 gnet 라이브러리 [내부링크]

이벤트 루프 기반의 네트워킹 gnet 라이브러리 main.go package main import ( "github.com/panjf2000/gnet" ) // EventServer 구조체 type echoServer struct { *gnet.EventServer } // 서버 데이터를 보낼 때 수행하는 함수를 구현 // 해당 함수는 서버가 클라이언트로부터 입력 데이터를 수신하면 호출 func (es *echoServer) React(c gnet.Conn) (out []byte, action gnet.Action) { top, tail := c.ReadPair() out = top if tail != nil { out = append(top, tail...) } // ring 버퍼를 초기화 c.ResetBuffer() return } func main() { echo := new(echoServer) // echoServer 구조체를 객체로 할당 err := gnet.Serve(e

[GO언어] golang http 패키지 [내부링크]

package main import ( "flag" "fmt" "net/http" ) func init() { } func main() { dir := flag.String("Dir", "", "a string") flag.Parse() if *dir == "" { fmt.Println("-Dir=dir path") return } fmt.Println("ok") http.ListenAndServe(":8080", http.FileServer(http.Dir(*dir))) } 웹 어플리케이션을 개발하려고 Go 언어를 살펴보기 시작했다. 앞서 정리한 몇 가지 기본 패키지는 net/http 패키지를 사용하기 위한 준비 과정이라 생각하자. 이번에는 네트웍 프로그래밍을 위한 net/http 패키지 사용법을 정리해 보겠다. Get 요청하기 브라우져는 사용자가 입력한 url를 통해 해당 웹페이지를 요청한다. 이처럼 웹상의 리소스를 요청하려면 패키지의 Get 함수를 사용한다. func Get(u

[GO언어] golang tcp [내부링크]

golang의 경우 tcp에 net poll 방식을 사용함 리눅스의 경우 아래 순서로 IO 성능 차이가 있음 epoll > poll > select

[GO언어] golang AES GCM 암복호 [내부링크]

9.6 Encrypting and decrypting data The previous section describes how to securely store passwords, but sometimes it might be neccessary to modify some sensitive encrypted data that has already been stored into our database. When data decryption is required, we should use a symmetric encryption algorithm instead of the one-way hashing techniques we've previously covered. Advanced encryption and decryption The Go language supports symmetric encryption algorithms in its crypto package. Do not use a

[GO언어] golang UTC 타임존 변경 [내부링크]

t := time.Now().UTC() // UTC기준 현재 시간을 가져온다. t = t.In(time.FixedZone("KST", 9*60*60)) // 9시간을 더하고, KST라고 부른다. fmt.Println(t.Format("2006-01-12 15:04:05")) // yyyy-MM-dd HH:mm:ss 형태로 formatting한다. (선택) 참고링크: https://hakurei.tistory.com/category/%EA%B0%9C%EB%B0%9C/Go

[GO언어] golang 고루틴 스택 덤프 [내부링크]

LINUX, UNIX 계열에서는 'kill' 명령어를 사용하여 확인 가능하다. kill -3 [PID] 자바 프로그램을 실행한 터미널에서 stdout으로 출력될 것이고, stdout이 리다이렉트 된 경우엔 해당 파일을 확인하면 된다. Windows에서는 자바를 실행한 cmd나 powershell 창에서 'Ctrl' + 'Break' 키를 입력하면 스택 덤프를 확인할 수 있다. 다만, 해당 자바 프로그램이 백그라운드로 동작할 경우에는 동작하지 않으니 사용에는 약간의 제약 사항이 따를 수밖에 없다. https://bestugi.tistory.com/38

[GO언어] golang yaml 설정 파일 읽기 [내부링크]

golang의 경우 json을 기본 지원해서 json 설정 파일을 사용해도 되지만 yaml 설정 파일도 사용해야 할경우 우선 라이브러리 추가 $ go mod init gopkg.in/yaml/repo $ go get gopkg.in/yaml.v3 config.yml ## 한글 주석 a: Easy! b: c: 2 d: [3, 4] e: - "A" - "B" f: ["A", "B"] g: "A" h: ["A"] i: "2021-07-21T11:11:11.000Z" j: true k: 1.123 ## migration.6_to_7.enabled: false ## scheduler: - action: "start" time: "2021-07-21T11:11:11" - action: "stop" time: "2021-07-21T21:11:11" main.go // Package main package main // import "example.com/yaml/main" import ( "en

[GO언어] golang tcp socket server [내부링크]

golang tcp socket server golang 서버 구성시 10k ~ 15k 동시 접속자 처리도 가능하다. 수신 패킷 단편화 처리, 접속 클라이언트 관리, 파일 로그 등등 추가 기능을 포함하면 실무에서도 사용 가능하다. 개발툴은 vscode를 사용했다. 프로젝트 디렉토리 구조 tcp_socket_server.code-workspace server - main.go - client.go - channelGroup.go - go.mod client - main.go - client.go - go.mod tcp_socket_server.code-workspace { "folders": [ { "path": "./server" }, { "path": "./client" } ], "settings": { "workbench.list.openMode": "doubleClick", "editor.minimap.enabled": false, "[go]": { "editor.formatO

[GO언어] golang websocket binary client [내부링크]

golang 1.19 vscode websocket_binary_client.code-workspace { "folders": [ { "path": "./main" } ], "settings": { "workbench.list.openMode": "doubleClick", "editor.minimap.enabled": false, "[go]": { "editor.formatOnSave": false }, "go.useLanguageServer": true, "go.buildOnSave": "off", "go.lintOnSave": "off", "go.vetOnSave": "off", "go.buildFlags": [], "go.vetFlags": [], "go.useCodeSnippetsOnFunctionSuggest": false, "go.formatTool": "goreturns", "go.lintTool": "gometalinter", "go.lintFlags": ["--dis

[GO언어] golang json gojay 라이브러리 [내부링크]

서버와 클라이언트간 연동시 구조체를 json으로 변환해서 할 경우 gojay 라이브러리의 Marshal 함수를 사용하면 json 생성을 golang에서 제공하는 라이브러리보다 좋은 성능을 낼 수 있다. gojay를 사용할 경우 구조체 별로 MarshalJSONObject 함수 정의가 필요하다. // Package main package main // import "example.com/gojay/main" import ( "bytes" "encoding/json" "fmt" "testing" "github.com/francoispqt/gojay" ) func Test1(t *testing.T) { a := Address{Text: "a", Post: 1, Enabled: true} c := &Car{Name: "a", Size: 1} p1 := Phone{Name: "a", Number: 1} p2 := Phone{Name: "2", Number: 1} var p PhoneSlice

[자바] java 21 가상 스레드 Virtual Thread [내부링크]

Virtual Thread 곧 출시될 표준 Java의 장기 지원 릴리스인 JDK(Java Development Kit) 21은 9월로 예정되어 있다. 추가 되는 기능으로는 크게 가상 스레드 시퀀스 컬렉션 문자열 템플릿 외부 함수 및 메모리 API 기타 기능 가장 기대하고 있는 가상 스레드에 대해 간략하게 정리 하였다. 기존 다른 언어에는 있는 기능인데 늦게 라도 추가되어 다행이다. 내가 알고 있는 언어로는 erlang, golang 에서 경량 스레드 개념의 기능이 있다. 가상 스레드 JDK(Java Development Kit) 21은 처리량이 많은 동시 애플리케이션을 작성 및 유지 관리 및 관찰하는 문제를 크게 줄일 수 있는 경량 스레드인 최종 가상 스레드를 제공한다. 이 기능의 이면에는 서버 애플리케이션이 최적의 하드웨어 활용으로 효과적으로 확장할 수 있도록 하고, 기존 lang.Thread API 코드에 대한 최소한의 변경으로 가상 스레드 채택을 촉진하고, 현재 JDK 도구를