Avatar
๐Ÿ˜‰

Organizations

  • SDKMAN์˜ ํ•ต์‹ฌ์€ **“์„ค์น˜(Install) -> ์ „ํ™˜(Switch) -> ํ™•์ธ(Check)”**์˜ ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ๋Š” ๋ช…๋ น์–ด ์œ„์ฃผ๋กœ ๊น”๋”ํ•˜๊ฒŒ ์ •๋ฆฌํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.


    1. ์„ค์น˜ ๊ฐ€๋Šฅํ•œ ๋ฒ„์ „ ๋ชฉ๋ก ๋ณด๊ธฐ (list)

    ๋จผ์ € ์–ด๋–ค ๋ฒ„์ „์„ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    sdk list java
    
    • ํ™”๋ฉด ์กฐ์ž‘: ๋ชฉ๋ก์ด ๊ธธ๊ฒŒ ๋‚˜์˜ต๋‹ˆ๋‹ค. Space(๋‹ค์Œ ํŽ˜์ด์ง€), Enter(ํ•œ ์ค„ ์•„๋ž˜), q(๋‚˜๊ฐ€๊ธฐ) ํ‚ค๋ฅผ ๊ธฐ์–ตํ•˜์„ธ์š”.
    • ์‹๋ณ„์ž(Identifier): ๋งจ ์˜ค๋ฅธ์ชฝ ์—ด์— ์žˆ๋Š” ํ…์ŠคํŠธ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: 24-open, 17.0.10-tem ๋“ฑ) ์„ค์น˜ํ•  ๋•Œ ์ด ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    2. ๋ฒ„์ „ ์„ค์น˜ํ•˜๊ธฐ (install)

    ์›ํ•˜๋Š” ๋ฒ„์ „์˜ ์‹๋ณ„์ž(Identifier)๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

    Created Mon, 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๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

    Created Tue, 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 ์ดํ›„๋กœ๋Š” ํ˜„๋Œ€์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ ๊ทน์ ์œผ๋กœ ์ˆ˜์šฉํ•˜๊ณ  ์žˆ์–ด, ์ง„์ •ํ•œ ๋ฉ€ํ‹ฐ ํŒจ๋Ÿฌ๋‹ค์ž„ ์–ธ์–ด๋กœ ์ง„ํ™”ํ–ˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    Created Mon, 20 Oct 2025 13:50:50 +0900
  • DB์˜ ํ…Œ์ด๋ธ”์˜ row๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„์งˆ๋–„ (์˜ˆ ํ•˜๋ฃจ์— 10๋งŒ๊ฑด์”ฉ ๋ˆ„์ ), ๋Œ€์ฒ˜ ๋ฐฉ๋ฒ•

    • โ€œํ•˜๋ฃจ 10๋งŒ ๊ฑด์”ฉ ๊ณ„์† ๋ˆ„์ โ€์ด๋ฉด 1๋…„์— 3,650๋งŒ ๊ฑด์ž…๋‹ˆ๋‹ค. ์ดˆ๋ฐ˜์—” ๋ฒ„ํ‹ฐ์ง€๋งŒ, ๋ช‡ ๋‹ฌ๋งŒ ์ง€๋‚˜๋„ ์ฟผ๋ฆฌยท๋ฐฑ์—…ยทVACUUM/OPTIMIZE ๋น„์šฉ์ด ๊ธ‰์ฆํ•˜์ฃ . ์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ์ ์šฉํ•ด๋ณด์„ธ์š”.

    1) ๋จผ์ € ๊ฒฐ์ •ํ•  ๊ฒƒ (์šด์˜ ์ •์ฑ…)

    • ๋ณด์กด ๊ธฐ๊ฐ„: ์˜ˆ) โ€œ6๊ฐœ์›”์€ ์˜จ๋ผ์ธ(ํ•ซ), 2๋…„์€ ์•„์นด์ด๋ธŒ(์ฝœ๋“œ), ๊ทธ ์™ธ ์‚ญ์ œโ€
    • ์ฃผ์š” ์กฐํšŒ ํŒจํ„ด: ์ตœ๊ทผ N์ผ๋งŒ ์กฐํšŒ? ํŠน์ • ์‚ฌ์šฉ์ž/ํ‚ค ๊ธฐ์ค€ ์กฐํšŒ? ์ง‘๊ณ„ ์œ„์ฃผ?
    • SLA/์„ฑ๋Šฅ: p95 ์‘๋‹ต์‹œ๊ฐ„, ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์“ฐ๊ธฐ ์ง€์—ฐ

    2) ์ฆ‰์‹œ ํšจ๊ณผ (์Šคํ‚ค๋งˆ/์ธ๋ฑ์Šค/์“ฐ๊ธฐ)

    • ์ธ๋ฑ์Šค ์Šฌ๋ฆผํ™”: ์‹ค์ œ ์กฐ๊ฑด/์ •๋ ฌ์— ์“ฐ๋Š” ์ปฌ๋Ÿผ๋งŒ ์ธ๋ฑ์Šค. ๋ถˆํ•„์š”ํ•œ ๋ณตํ•ฉ ์ธ๋ฑ์Šค ์ œ๊ฑฐ.

    Created Tue, 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 ํ‘œ์ค€์„ ์ค€์ˆ˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๋ณด์•ˆ ๋„๊ตฌ์™€ ์ธํ”„๋ผ๊ฐ€ ์ด๋ฅผ ์ „์ œ๋กœ ์„ค๊ณ„๋˜์–ด ์žˆ์–ด ๋” ๋‚˜์€ ๋ณด์•ˆ ๋ณด์žฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    Created Fri, 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());
        }
    }
    

    ๊ธฐ๋ณธ์€ โ€œ๋™๊ธฐ ์‹คํ–‰โ€์ด๋ผ ๋ฐœํ–‰ ์‹œ์ ์— ์ฆ‰์‹œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

    Created Mon, 01 Sep 2025 16:13:53 +0900