-
SDKMAN์ ํต์ฌ์ **“์ค์น(Install) -> ์ ํ(Switch) -> ํ์ธ(Check)”**์ ํ๋ฆ์ ๋๋ค. ๊ฐ์ฅ ์์ฃผ ์ฐ๋ ๋ช ๋ น์ด ์์ฃผ๋ก ๊น๋ํ๊ฒ ์ ๋ฆฌํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
1. ์ค์น ๊ฐ๋ฅํ ๋ฒ์ ๋ชฉ๋ก ๋ณด๊ธฐ (
list)๋จผ์ ์ด๋ค ๋ฒ์ ์ ์ค์นํ ์ ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
sdk list java- ํ๋ฉด ์กฐ์: ๋ชฉ๋ก์ด ๊ธธ๊ฒ ๋์ต๋๋ค.
Space(๋ค์ ํ์ด์ง),Enter(ํ ์ค ์๋),q(๋๊ฐ๊ธฐ) ํค๋ฅผ ๊ธฐ์ตํ์ธ์. - ์๋ณ์(Identifier): ๋งจ ์ค๋ฅธ์ชฝ ์ด์ ์๋ ํ
์คํธ๊ฐ ์ค์ํฉ๋๋ค. (์:
24-open,17.0.10-tem๋ฑ) ์ค์นํ ๋ ์ด ์ด๋ฆ์ ์ฌ์ฉํฉ๋๋ค.
2. ๋ฒ์ ์ค์นํ๊ธฐ (
install)์ํ๋ ๋ฒ์ ์ ์๋ณ์(Identifier)๋ฅผ ์ ๋ ฅํ์ฌ ์ค์นํฉ๋๋ค.
CreatedMon, 08 Dec 2025 08:49:54 +0900 - ํ๋ฉด ์กฐ์: ๋ชฉ๋ก์ด ๊ธธ๊ฒ ๋์ต๋๋ค.
-
IT ๊ฐ๋ฐ์์ Aggregate ํจํด๊ณผ Bulkhead ํจํด์ ๋ชจ๋ **๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ(MSA)**๋ ๋ถ์ฐ ์์คํ ์์ ์์ฃผ ์ฌ์ฉ๋๋ **์ค๊ณ ํจํด(Design Pattern)**์ ๋๋ค. ๊ฐ๊ฐ์ ๋ชฉ์ ์ ๋ค๋ฅด์ง๋ง, ์์คํ ์์ ์ฑ๊ณผ ์๋ต ํจ์จ์ ๋์ด๊ธฐ ์ํ ๊ณตํต ๋ชฉํ๋ฅผ ๊ฐ์ง๋๋ค. ์๋์์ ์์ธํ ์ค๋ช ๋๋ฆด๊ฒ์.
๐งฉ 1. Aggregate ํจํด
๐ก ๊ฐ๋
Aggregate ํจํด์ **๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ(DDD: Domain-Driven Design)**์์ ๋ฑ์ฅํ๋ ๊ฐ๋ ์ผ๋ก, ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ๊ณผ ๋ณ๊ฒฝ ๋จ์๋ฅผ ์ ์ํ๊ธฐ ์ํ ๊ตฌ์กฐ์ ๋๋ค. ์ฆ, ๊ด๋ จ๋ ์ํฐํฐ(Entity)์ ๊ฐ ๊ฐ์ฒด(Value Object)๋ฅผ ํ๋์ **์งํฉ(Aggregate)**์ผ๋ก ๋ฌถ๊ณ , ๊ทธ ์งํฉ์ ์ผ๊ด์ฑ์ ์ฑ ์์ง๋ ๋ฃจํธ ์ํฐํฐ๋ฅผ Aggregate Root๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
CreatedTue, 11 Nov 2025 10:16:50 +0900 -
Java๋ ๋ฉํฐ ํจ๋ฌ๋ค์ ์ธ์ด์ธ๊ฐ?
Java๋ ๋ฉํฐ ํจ๋ฌ๋ค์ ์ธ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค. ํนํ Java 8 ์ดํ๋ก๋ ๋์ฑ ๋ช ํํด์ก์ต๋๋ค. ์ด๊ธฐ์๋ “์์ํ” ๊ฐ์ฒด์งํฅ ์ธ์ด๋ฅผ ๋ชฉํ๋ก ํ์ง๋ง, ์๊ฐ์ด ์ง๋๋ฉด์ ๋ค์ํ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ์์ฉํ๊ฒ ๋์์ต๋๋ค.
Java๊ฐ ์ง์ํ๋ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์
1. ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ (OOP) - ํต์ฌ ํจ๋ฌ๋ค์
// ํด๋์ค, ์์, ์บก์ํ, ๋คํ์ฑ public class Animal { private String name; public void makeSound() { System.out.println("Some sound"); } } public class Dog extends Animal { @Override public void makeSound() { System.out.println("Woof!"); } }2. ๋ช ๋ นํ ํ๋ก๊ทธ๋๋ฐ (Imperative)
// ์ํ ๋ณ๊ฒฝ๊ณผ ์ ์ด ํ๋ฆ์ ๋ช ์์ ์ผ๋ก ์์ฑ public static int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; // ์ํ ๋ณ๊ฒฝ } return result; }3. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ (Functional) - Java 8+
import java.util.*; import java.util.function.*; import java.util.stream.*; public class FunctionalExample { public static void main(String[] args) { // 1. ๋๋ค ํํ์๊ณผ ๊ณ ์ฐจ ํจ์ Function<Integer, Integer> square = x -> x * x; Function<Integer, Integer> addOne = x -> x + 1; // ํจ์ ํฉ์ฑ Function<Integer, Integer> squareThenAdd = square.andThen(addOne); System.out.println(squareThenAdd.apply(3)); // 10 // 2. ๋ถ๋ณ์ฑ๊ณผ ์์ ํจ์ List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> doubled = numbers.stream() .map(n -> n * 2) // ์๋ณธ์ ๋ณ๊ฒฝํ์ง ์์ .collect(Collectors.toList()); // 3. ํจ์๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ calculate(10, 5, (a, b) -> a + b); // 15 calculate(10, 5, (a, b) -> a * b); // 50 } static void calculate(int x, int y, BinaryOperator<Integer> operation) { System.out.println(operation.apply(x, y)); } }4. ์ ๋ค๋ฆญ ํ๋ก๊ทธ๋๋ฐ (Generic)
// ํ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํ ์ผ๋ฐํ public class Box<T> { private T content; public void set(T content) { this.content = content; } public T get() { return content; } } // ์ ๋ค๋ฆญ ๋ฉ์๋ public static <T extends Comparable<T>> T findMax(List<T> list) { return list.stream() .max(Comparable::compareTo) .orElse(null); }5. ๋์์ฑ/๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ (Concurrent/Parallel)
import java.util.concurrent.*; public class ConcurrentExample { public static void main(String[] args) throws Exception { // CompletableFuture๋ฅผ ์ฌ์ฉํ ๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ CompletableFuture<String> future1 = CompletableFuture .supplyAsync(() -> fetchDataFromAPI1()); CompletableFuture<String> future2 = CompletableFuture .supplyAsync(() -> fetchDataFromAPI2()); // ๋ ์์ ์ ๊ฒฐํฉ CompletableFuture<String> combined = future1 .thenCombine(future2, (result1, result2) -> result1 + " " + result2); System.out.println(combined.get()); } }6. ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ (Reactive) - ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ
// RxJava ๋๋ Project Reactor ์ฌ์ฉ ์์ Flux.just(1, 2, 3, 4, 5) .filter(n -> n % 2 == 0) .map(n -> n * 2) .subscribe(System.out::println);๋ค์ํ ํจ๋ฌ๋ค์์ ํผํฉํ ์ค์ ์์
import java.util.*; import java.util.concurrent.*; import java.util.stream.*; // OOP: ํด๋์ค์ ์ธํฐํ์ด์ค ์ ์ interface DataProcessor<T> { CompletableFuture<List<T>> process(List<T> data); } public class HybridExample implements DataProcessor<Integer> { private final ExecutorService executor = Executors.newFixedThreadPool(4); @Override public CompletableFuture<List<Integer>> process(List<Integer> data) { // ํจ์ํ + ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ return CompletableFuture.supplyAsync(() -> data.parallelStream() // ๋ณ๋ ฌ ์ฒ๋ฆฌ .filter(n -> n > 0) // ํจ์ํ: ํํฐ๋ง .map(this::complexCalculation) // ๋ฉ์๋ ์ฐธ์กฐ .sorted() // ์ ๋ ฌ .collect(Collectors.toList()), executor ); } // ๋ช ๋ นํ ์คํ์ผ์ ๋ณต์กํ ๊ณ์ฐ private Integer complexCalculation(Integer n) { int result = n; for (int i = 0; i < 3; i++) { result = result * 2 + 1; } return result; } public static void main(String[] args) throws Exception { HybridExample processor = new HybridExample(); List<Integer> data = Arrays.asList(1, -2, 3, 4, -5, 6); // ๋น๋๊ธฐ ์ฒ๋ฆฌ ์์ CompletableFuture<List<Integer>> future = processor.process(data); // ์ฝ๋ฐฑ ์ฒด์ธ (ํจ์ํ) future.thenApply(result -> { System.out.println("์ฒ๋ฆฌ ๊ฒฐ๊ณผ: " + result); return result; }) .thenAccept(result -> { // ๊ฒฐ๊ณผ ํ์ฉ int sum = result.stream().mapToInt(Integer::intValue).sum(); System.out.println("ํฉ๊ณ: " + sum); }) .get(); // ์๋ฃ ๋๊ธฐ processor.executor.shutdown(); } }Java์ ๋ฉํฐ ํจ๋ฌ๋ค์ ํน์ง
์ฅ์
- ์ ์ง์ ๋์ : ๊ธฐ์กด OOP ์ฝ๋๋ฒ ์ด์ค์ ํจ์ํ ์์๋ฅผ ์ ์ง์ ์ผ๋ก ๋์ ๊ฐ๋ฅ
- ์ ์ฐ์ฑ: ๋ฌธ์ ์ ๊ฐ์ฅ ์ ํฉํ ํจ๋ฌ๋ค์ ์ ํ ๊ฐ๋ฅ
- ์ํ๊ณ: ๋ค์ํ ์คํ์ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํธํ
ํ๊ณ
- ์์ ํ์ง ์์ ํจ์ํ: ๋ถ๋ณ์ฑ์ด ์ธ์ด ์ฐจ์์์ ๊ฐ์ ๋์ง ์์
- ํผ์ฌ๋ ์คํ์ผ: ์ฌ๋ฌ ํจ๋ฌ๋ค์์ด ์์ฌ ์ผ๊ด์ฑ ์ ์ง๊ฐ ์ด๋ ค์ธ ์ ์์
- ํ์ต ๊ณก์ : ๋ชจ๋ ํจ๋ฌ๋ค์์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ํ์ต์ด ํ์
๊ฒฐ๋ก
Java๋ “์ค์ฉ์ ์ธ” ๋ฉํฐ ํจ๋ฌ๋ค์ ์ธ์ด์ ๋๋ค. ์์ํ ํจ์ํ ์ธ์ด(Haskell)๋ ์์ํ ๊ฐ์ฒด์งํฅ ์ธ์ด(Smalltalk)์ ๋ฌ๋ฆฌ, Java๋ ์ค์ฉ์ฑ์ ์ค์ํ๋ฉฐ ์ฌ๋ฌ ํจ๋ฌ๋ค์์ ์ฅ์ ์ ์ ํ์ ์ผ๋ก ํ์ฉํ ์ ์๊ฒ ์ค๊ณ๋์์ต๋๋ค. ํนํ Java 8 ์ดํ๋ก๋ ํ๋์ ์ธ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ์ ๊ทน์ ์ผ๋ก ์์ฉํ๊ณ ์์ด, ์ง์ ํ ๋ฉํฐ ํจ๋ฌ๋ค์ ์ธ์ด๋ก ์งํํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
CreatedMon, 20 Oct 2025 13:50:50 +0900 -
DB์ ํ ์ด๋ธ์ row๊ฐ ๋๋ฌด ๋ง์์ง๋ (์ ํ๋ฃจ์ 10๋ง๊ฑด์ฉ ๋์ ), ๋์ฒ ๋ฐฉ๋ฒ
- โํ๋ฃจ 10๋ง ๊ฑด์ฉ ๊ณ์ ๋์ โ์ด๋ฉด 1๋ ์ 3,650๋ง ๊ฑด์ ๋๋ค. ์ด๋ฐ์ ๋ฒํฐ์ง๋ง, ๋ช ๋ฌ๋ง ์ง๋๋ ์ฟผ๋ฆฌยท๋ฐฑ์ ยทVACUUM/OPTIMIZE ๋น์ฉ์ด ๊ธ์ฆํ์ฃ . ์๋ ์์๋๋ก ์ ์ฉํด๋ณด์ธ์.
1) ๋จผ์ ๊ฒฐ์ ํ ๊ฒ (์ด์ ์ ์ฑ )
- ๋ณด์กด ๊ธฐ๊ฐ: ์) โ6๊ฐ์์ ์จ๋ผ์ธ(ํซ), 2๋ ์ ์์นด์ด๋ธ(์ฝ๋), ๊ทธ ์ธ ์ญ์ โ
- ์ฃผ์ ์กฐํ ํจํด: ์ต๊ทผ N์ผ๋ง ์กฐํ? ํน์ ์ฌ์ฉ์/ํค ๊ธฐ์ค ์กฐํ? ์ง๊ณ ์์ฃผ?
- SLA/์ฑ๋ฅ: p95 ์๋ต์๊ฐ, ํ์ฉ ๊ฐ๋ฅํ ์ฐ๊ธฐ ์ง์ฐ
2) ์ฆ์ ํจ๊ณผ (์คํค๋ง/์ธ๋ฑ์ค/์ฐ๊ธฐ)
-
์ธ๋ฑ์ค ์ฌ๋ฆผํ: ์ค์ ์กฐ๊ฑด/์ ๋ ฌ์ ์ฐ๋ ์ปฌ๋ผ๋ง ์ธ๋ฑ์ค. ๋ถํ์ํ ๋ณตํฉ ์ธ๋ฑ์ค ์ ๊ฑฐ.
CreatedTue, 14 Oct 2025 11:25:18 +0900 -
HTTP API ํธ์ถ ์ access token์ ํค๋์ ๋ฐ๋์ ๋ณด๋ด๋ ๊ฒ ์ฌ์ด์๋ ๋ช ๊ฐ์ง ์ค์ํ ๋ณด์์ ์ฐจ์ด์ ์ด ์์ต๋๋ค:
์ฃผ์ ๋ณด์ ์ฐจ์ด์
1. ๋ก๊น ๋ฐ ๋ชจ๋ํฐ๋ง
- ํค๋: ๋๋ถ๋ถ์ ์น ์๋ฒ์ ํ๋ก์๋ ๊ธฐ๋ณธ์ ์ผ๋ก Authorization ํค๋๋ฅผ ๋ก๊ทธ์์ ๋ง์คํนํ๊ฑฐ๋ ์ ์ธํฉ๋๋ค
- ๋ฐ๋: ์์ฒญ ๋ฐ๋๋ ๋๋ฒ๊น ๋ชฉ์ ์ผ๋ก ๋ก๊ทธ์ ๊ธฐ๋ก๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ํ ํฐ์ด ํ๋ฌธ์ผ๋ก ๋ ธ์ถ๋ ์ํ์ด ์์ต๋๋ค
2. ์บ์ฑ ๋์
- ํค๋: HTTP ์บ์๋ Authorization ํค๋๊ฐ ์๋ ์์ฒญ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์บ์ํ์ง ์์ต๋๋ค
- ๋ฐ๋: ๋ฐ๋์ ํ ํฐ์ด ์์ด๋ ์บ์ ์ ์ฑ ์ ๋ฐ๋ผ ์๋ต์ด ์บ์๋ ์ ์์ด, ์๋์น ์์ ํ ํฐ ๋ ธ์ถ ์ํ์ด ์์ต๋๋ค
3. ํ๋ก์ ๋ฐ ๋ฏธ๋ค์จ์ด ์ฒ๋ฆฌ
- ํค๋: ํ์ค ์ธ์ฆ ํค๋๋ก ์ธ์๋์ด ๋ณด์ ๋ฏธ๋ค์จ์ด์์ ์ ์ ํ ์ฒ๋ฆฌ๋ฉ๋๋ค
- ๋ฐ๋: ์ผ๋ฐ ๋ฐ์ดํฐ๋ก ์ทจ๊ธ๋์ด ๋ณด์ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋ ์ ์์ต๋๋ค
4. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ
- ํค๋: ๋คํธ์ํฌ ํญ์์ ๋ณผ ์๋ ์์ง๋ง, Authorization ํค๋์์ ๋ช ํํ ์ธ์ํ ์ ์์ต๋๋ค
- ๋ฐ๋: ์ผ๋ฐ ๋ฐ์ดํฐ์ฒ๋ผ ๋ณด์ฌ ๊ฐ๋ฐ์๊ฐ ๋ฏผ๊ฐํ ์ ๋ณด์์ ๋์น ์ ์์ต๋๋ค
๊ถ์ฅ์ฌํญ
// โ ๊ถ์ฅ: Authorization ํค๋ ์ฌ์ฉ fetch('/api/data', { headers: { 'Authorization': 'Bearer ' + accessToken, 'Content-Type': 'application/json' } }); // โ ๋น๊ถ์ฅ: ๋ฐ๋์ ํ ํฐ ํฌํจ fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accessToken: accessToken, otherData: data }) });๊ฒฐ๋ก : Authorization ํค๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณด์์ ๋ ์์ ํ๋ฉฐ, HTTP ํ์ค์ ์ค์ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋๋ถ๋ถ์ ๋ณด์ ๋๊ตฌ์ ์ธํ๋ผ๊ฐ ์ด๋ฅผ ์ ์ ๋ก ์ค๊ณ๋์ด ์์ด ๋ ๋์ ๋ณด์ ๋ณด์ฅ์ ์ ๊ณตํฉ๋๋ค.
CreatedFri, 12 Sep 2025 08:25:18 +0900 -
1) ์ด๋ฒคํธ ์ ์ (POJO/record ๊ถ์ฅ)
// src/main/java/com/example/user/event/UserSignedUpEvent.java package com.example.user.event; import java.time.Instant; public record UserSignedUpEvent(Long userId, String email, Instant occurredAt) {}Spring 6+/Boot 3์์๋
ApplicationEvent๋ฅผ ์์ํ ํ์๊ฐ ์์ต๋๋ค. ํ๋ฒํ POJO/record๊ฐ ์ข์์.
2) ์ด๋ฒคํธ ๋ฐํ (raise)
// src/main/java/com/example/user/service/SignUpService.java package com.example.user.service; import com.example.user.event.UserSignedUpEvent; import com.example.user.model.User; import com.example.user.repo.UserRepository; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.Instant; @Service public class SignUpService { private final UserRepository userRepository; private final ApplicationEventPublisher publisher; public SignUpService(UserRepository userRepository, ApplicationEventPublisher publisher) { this.userRepository = userRepository; this.publisher = publisher; } @Transactional public Long signUp(String email, String name) { User user = userRepository.save(new User(email, name)); // JPA ์ํฐํฐ ์ ์ฅ ๊ฐ์ // ์ด๋ฒคํธ ๋ฐํ (ํธ๋์ญ์ ์์์) publisher.publishEvent(new UserSignedUpEvent(user.getId(), user.getEmail(), Instant.now())); return user.getId(); } }
3) ๋๊ธฐ ๋ฆฌ์ค๋ (๊ธฐ๋ณธ)
// src/main/java/com/example/user/listener/AuditLogListener.java package com.example.user.listener; import com.example.user.event.UserSignedUpEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component public class AuditLogListener { private static final Logger log = LoggerFactory.getLogger(AuditLogListener.class); @Order(0) // ์ฌ๋ฌ ๋ฆฌ์ค๋๊ฐ ์์ ๋ ์์ ์ ์ด ๊ฐ๋ฅ (๋ฎ์์๋ก ๋จผ์ ) @EventListener public void onUserSignedUp(UserSignedUpEvent event) { log.info("AUDIT: userId={}, email={}, at={}", event.userId(), event.email(), event.occurredAt()); } }๊ธฐ๋ณธ์ โ๋๊ธฐ ์คํโ์ด๋ผ ๋ฐํ ์์ ์ ์ฆ์ ํธ์ถ๋ฉ๋๋ค.
CreatedMon, 01 Sep 2025 16:13:53 +0900