Avatar
πŸ˜‰

Organizations

  • Kubernetes(μΏ λ²„λ„€ν‹°μŠ€)와 Docker(도컀)의 κ΄€κ³„λŠ” **“경쟁 관계"κ°€ μ•„λ‹ˆλΌ “μƒν˜Έ 보완적인 관계”**μž…λ‹ˆλ‹€. 이 λ‘˜μ˜ 차이λ₯Ό λͺ…ν™•νžˆ μ΄ν•΄ν•˜κΈ° μœ„ν•΄ κ°€μž₯ μ‰¬μš΄ λΉ„μœ λ₯Ό λ“€μ–΄ μ„€λͺ…ν•΄ λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.


    1. 핡심 λΉ„μœ : ν™”λ¬Όμ„ κ³Ό ν•­λ§Œ μ‹œμŠ€ν…œ

    이 두 기술의 관계λ₯Ό λ¬Όλ₯˜ μ‹œμŠ€ν…œμ— λΉ„μœ ν•˜λ©΄ μ•„μ£Ό λͺ…ν™•ν•΄μ§‘λ‹ˆλ‹€.

    • Docker (μ»¨ν…Œμ΄λ„ˆ): **‘κ·œκ²©ν™”λœ ν™”λ¬Ό μ»¨ν…Œμ΄λ„ˆ λ°•μŠ€’**μž…λ‹ˆλ‹€.

    • 물건(μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œ, 라이브러리 λ“±)을 λ°•μŠ€μ— λ‹΄μ•„ 포μž₯ν•˜λŠ” κΈ°μˆ μž…λ‹ˆλ‹€.

    • 이 λ°•μŠ€λ§Œ 있으면 μ–΄λ–€ λ°°(μ„œλ²„)λ‚˜ 트럭(λ…ΈνŠΈλΆ)에 싀어도 λ‚΄μš©λ¬Όμ΄ μ•ˆμ „ν•˜κ²Œ μ „λ‹¬λ©λ‹ˆλ‹€.

    • Kubernetes (μ‘°νƒ€μˆ˜/ν•­λ§Œ κ΄€λ¦¬μž): **‘수천 개의 μ»¨ν…Œμ΄λ„ˆλ₯Ό κ΄€λ¦¬ν•˜λŠ” μ‹œμŠ€ν…œ’**μž…λ‹ˆλ‹€.

    • μ»¨ν…Œμ΄λ„ˆκ°€ 배에 잘 μ‹€λ ΈλŠ”μ§€, λ°°κ°€ 흔듀렀 μ»¨ν…Œμ΄λ„ˆκ°€ λ–¨μ–΄μ§€λ©΄(μ—λŸ¬ λ°œμƒ) λ‹€μ‹œ μ‹€μ–΄μ£ΌλŠ”μ§€, 화물이 λ§Žμ•„μ§€λ©΄ λ°°λ₯Ό 더 λΆ€λ₯Όμ§€(μŠ€μΌ€μΌλ§)λ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.

    Created Tue, 06 Jan 2026 10:30:03 +0900
  • λ‹΅

    import java.util.ArrayList;
    
    // 30. κ°„λ‹¨ν•œ μœ λ‹ˆμ˜¨ νŒŒμΈλ“œ μ•Œκ³ λ¦¬μ¦˜ κ΅¬ν˜„ν•˜κΈ°
    public class Solution30 {
    
        private static int[] parent;
    
        private static int findRootNode(int x) {
            if (parent[x] == x) {
                return x;
            }
            parent[x] = findRootNode(parent[x]);
            return parent[x];
        }
    
        private static void union(int x, int y) {
            int root1 = findRootNode(x);
            int root2 = findRootNode(y);
            parent[root2] = root1;
        }
    
        public static Boolean[] solution(int k, int[][] operations) {
    
            parent = new int[k];
    
            for (int i = 0; i < k; i++) {
                parent[i] = i;
            }
    
            ArrayList<Boolean> answer = new ArrayList<>();
    
            for (int[] op : operations) {
                if (op[0] == 0) {
                    union(op[1], op[2]);
                }
                else {
                    answer.add(findRootNode(op[1]) == findRootNode(op[2]));
                }
            }
    
            return answer.toArray(new Boolean[0]);
        }
    }
    

    μ½”λ“œμ—μ„œ return answer.toArray(new Boolean[0]); ꡬ문은 ArrayList<Boolean> νƒ€μž…μΈ answerλ₯Ό Boolean[] λ°°μ—΄λ‘œ λ³€ν™˜ν•˜μ—¬ λ°˜ν™˜ν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.

    Created Mon, 29 Dec 2025 09:37:03 +0900
  • ν”„λ‘œκ·Έλž¨μœΌλ‘œ ν™•μΈν•˜κΈ°.

    방법 1: 직접 λ§Œλ“  슀크립트 (μ˜μ‘΄μ„± μ—†μŒ)

    chmod +x scan-secrets.sh
    ./scan-secrets.sh
    

    방법 2: gitleaks μ‚¬μš© (더 정확함, ꢌμž₯)

    # gitleaks μ„€μΉ˜
    brew install gitleaks  # λ˜λŠ” apt install gitleaks
    
    # 각 λ ˆν¬μ—μ„œ μ‹€ν–‰
    git clone git@github.com:dev-minimalism/kr-canslim-notifier.git
    cd kr-canslim-notifier
    gitleaks detect --source . --verbose
    
    # 전체 νžˆμŠ€ν† λ¦¬ 포함
    gitleaks detect --source . --verbose --log-opts="--all"
    

    방법 3: truffleHog (μ—”νŠΈλ‘œν”Ό 기반 탐지)

    pip install truffleHog
    truffleHog git git@github.com:dev-minimalism/kr-canslim-notifier.git --since_commit HEAD~100
    

    ν˜Ήμ€ νžˆμŠ€ν† λ¦¬ λ‹€ 날렀버리고 μ΄ˆκΈ°ν™” ν•˜κΈ°

    git checkout --orphan latest_branch
    git add .
    git commit -m "initial commit after reset"
    git branch -D main
    git branch -m main
    git push -f origin main
    

    νŠΉμ • 파일만 νžˆμŠ€ν† λ¦¬μ—μ„œ μ™„μ „νžˆ μ—†μ• κΈ° (.env의 예)

    git filter-branch --force --index-filter "git rm --cached --ignore-unmatch .env" --prune-empty --tag-name-filter cat -- --all
    
    Created Wed, 17 Dec 2025 11:16:03 +0900
  • 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