Avatar
πŸ˜‰

Organizations

  • JVM(Java Virtual Machine)μ—μ„œλŠ” λ‚΄λΆ€μ μœΌλ‘œ μ—¬λŸ¬ μ’…λ₯˜μ˜ μŠ€νƒ(stack) 을 μ‚¬μš©ν•©λ‹ˆλ‹€. 각각의 μŠ€νƒμ€ JVM의 μ‹€ν–‰ 및 λ©”λͺ¨λ¦¬ 관리 λ“±μ—μ„œ μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. μ£Όμš” μŠ€νƒ μ’…λ₯˜λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:


    🧠 1. Java Virtual Machine Stack (λ˜λŠ” Thread Stack)

    • μ„€λͺ…: 각 μŠ€λ ˆλ“œ(thread) λ§ˆλ‹€ ν•˜λ‚˜μ”© μ‘΄μž¬ν•˜λŠ” μŠ€νƒμž…λ‹ˆλ‹€.
    • μ—­ν• : λ©”μ„œλ“œ 호좜 μ‹œ μƒμ„±λ˜λŠ” μŠ€νƒ ν”„λ ˆμž„(stack frame) 을 μ €μž₯ν•©λ‹ˆλ‹€. 각 ν”„λ ˆμž„μ—λŠ”:
      • μ§€μ—­ λ³€μˆ˜(Local Variables)
      • ν”Όμ—°μ‚°μž μŠ€νƒ(Operand Stack)
      • λ©”μ„œλ“œ λ°˜ν™˜ μ£Όμ†Œ 등이 포함됨
    • μ˜ˆμ™Έ: μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš° λ°œμƒ μ‹œ StackOverflowError λ°œμƒ

    πŸ” 2. Native Method Stack

    • μ„€λͺ…: λ„€μ΄ν‹°λΈŒ λ©”μ„œλ“œ(C둜 κ΅¬ν˜„λœ JNI λ©”μ„œλ“œ λ“±) 호좜 μ‹œ μ‚¬μš©λ˜λŠ” μŠ€νƒμž…λ‹ˆλ‹€.
    • μ—­ν• : C/C++ λ“± JVM μ™ΈλΆ€ μ–Έμ–΄λ‘œ κ΅¬ν˜„λœ λ©”μ„œλ“œμ—μ„œ ν•„μš”ν•œ 데이터λ₯Ό μ €μž₯
    • νŠΉμ΄μ‚¬ν•­: 일뢀 JVM κ΅¬ν˜„μ—μ„œλŠ” Java μŠ€νƒκ³Ό ν†΅ν•©λ˜κΈ°λ„ 함

    πŸ’Ύ 3. Operand Stack (ν”Όμ—°μ‚°μž μŠ€νƒ)

    • μ„€λͺ…: μœ„μ˜ JVM Stack의 각 μŠ€νƒ ν”„λ ˆμž„ 내에 μ‘΄μž¬ν•˜λŠ” μŠ€νƒμž…λ‹ˆλ‹€.
    • μ—­ν• : λ°”μ΄νŠΈμ½”λ“œ λͺ…λ Ήμ–΄κ°€ μ‹€ν–‰ 쀑인 쀑간 μ—°μ‚° κ²°κ³Όλ₯Ό μž„μ‹œλ‘œ μ €μž₯
    • μ˜ˆμ‹œ: iadd, imul 같은 λ°”μ΄νŠΈμ½”λ“œ λͺ…령은 이 μŠ€νƒμ—μ„œ ν”Όμ—°μ‚°μžλ₯Ό κΊΌλ‚΄ 계산

    🧱 4. Call Stack (호좜 μŠ€νƒ)

    • μ„€λͺ…: JVM Stack의 ꡬ쑰적인 츑면을 μ§€μΉ­ν•˜λŠ” μš©μ–΄λ‘œ, λ©”μ„œλ“œ 호좜의 흐름을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€.
    • μ—­ν• : ν˜„μž¬ μ‹€ν–‰ 쀑인 λ©”μ„œλ“œλΆ€ν„° μ‹œμž‘ν•΄ 호좜된 λ©”μ„œλ“œλ“€μ΄ 차곑차곑 μŒ“μ—¬ 있음
    • νŠΉμ§•: 디버깅 μ‹œ “Stack Trace"둜 확인 κ°€λŠ₯

    μΆ”κ°€λ‘œ JVMμ—λŠ” μŠ€νƒ 이외에도 λ‹€μŒκ³Ό 같은 λ©”λͺ¨λ¦¬ μ˜μ—­μ΄ μžˆμŠ΅λ‹ˆλ‹€:

    Created Tue, 01 Apr 2025 15:44:09 +0900
  • JVM(Java Virtual Machine)μ—μ„œ heap λ©”λͺ¨λ¦¬λŠ” μžλ°” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λŸ°νƒ€μž„ μ‹œ λ™μ μœΌλ‘œ μƒμ„±ν•˜λŠ” 객체듀이 μ €μž₯λ˜λŠ” μ˜μ—­μž…λ‹ˆλ‹€. 즉, new ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ μƒμ„±ν•˜λŠ” λŒ€λΆ€λΆ„μ˜ 객체듀이 이 μ˜μ—­μ— μ €μž₯λ©λ‹ˆλ‹€.


    πŸ“Œ Heap λ©”λͺ¨λ¦¬ ꡬ성

    Heap은 크게 λ‹€μŒ 두 μ˜μ—­μœΌλ‘œ λ‚˜λ‰©λ‹ˆλ‹€:

    • Young Generation (Young Gen): μƒˆλ‘œ μƒμ„±λœ 객체가 μ €μž₯λ˜λŠ” κ³³.
      • Eden: λŒ€λΆ€λΆ„μ˜ μƒˆ 객체가 여기에 생성됨.
      • Survivor: Edenμ—μ„œ 살아남은 객체듀이 이동.
    • Old Generation (Tenured Gen): Young Gen을 거쳐 였래 살아남은 객체듀이 μ΄λ™ν•˜λŠ” 곡간.

    Garbage Collector(GC)λŠ” 이 heap μ˜μ—­μ˜ 객체듀을 주기적으둜 κ²€μ‚¬ν•΄μ„œ 더 이상 μ°Έμ‘°λ˜μ§€ μ•ŠλŠ” κ°μ²΄λŠ” λ©”λͺ¨λ¦¬μ—μ„œ μ œκ±°ν•©λ‹ˆλ‹€.

    Created Tue, 01 Apr 2025 13:59:38 +0900
  • @Cacheable μ–΄λ…Έν…Œμ΄μ…˜μ€ Spring Frameworkμ—μ„œ λ©”μ„œλ“œμ˜ λ°˜ν™˜κ°’μ„ μΊμ‹œμ— μ €μž₯ν•˜μ—¬, 같은 μΈμžκ°€ λ“€μ–΄μ˜¬ 경우 μΊμ‹œλœ 값을 μž¬μ‚¬μš©ν•˜λ„λ‘ ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€. 즉, λ©”μ„œλ“œλ₯Ό 반볡적으둜 ν˜ΈμΆœν•˜λ”λΌλ„ μ‹€μ œλ‘œλŠ” 처음 ν•œ 번만 μ‹€ν–‰λ˜κ³ , 이후 ν˜ΈμΆœμ€ μΊμ‹œλœ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜κ²Œ λ©λ‹ˆλ‹€.


    πŸ“Œ μ£Όμš” μ—­ν•  μš”μ•½

    • 쀑볡 호좜 λ°©μ§€: λ™μΌν•œ μž…λ ₯값에 λŒ€ν•΄ λ©”μ„œλ“œλ₯Ό 반볡 ν˜ΈμΆœν•˜λ©΄, μΊμ‹œλœ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•΄ μ„±λŠ₯ ν–₯상.
    • κ²°κ³Ό μ €μž₯: λ©”μ„œλ“œ μ‹€ν–‰ κ²°κ³Όλ₯Ό μΊμ‹œμ— μ €μž₯.
    • 쑰건뢀 캐싱: νŠΉμ • 쑰건에 따라 캐싱 μ—¬λΆ€ μ œμ–΄ κ°€λŠ₯.

    βœ… κΈ°λ³Έ μ‚¬μš© μ˜ˆμ‹œ

    @Cacheable("users")
    public User findUserById(Long id) {
        // μ‹€μ œλ‘œλŠ” DBλ‚˜ μ™ΈλΆ€ API 호좜
        return userRepository.findById(id).orElse(null);
    }
    
    • μœ„ λ©”μ„œλ“œλŠ” usersλΌλŠ” μΊμ‹œ μ΄λ¦„μœΌλ‘œ κ²°κ³Όλ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.
    • idκ°€ λ™μΌν•œ 경우, 이후 ν˜ΈμΆœμ€ μΊμ‹œλœ User 객체λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

    πŸ”§ μ£Όμš” 속성

    속성 μ„€λͺ…
    value λ˜λŠ” cacheNames μ‚¬μš©ν•  μΊμ‹œ 이름 μ§€μ •
    key μΊμ‹œ ν‚€λ₯Ό μ§€μ • (SpEL ν‘œν˜„μ‹ μ‚¬μš© κ°€λŠ₯)
    condition 캐싱할 쑰건 μ§€μ • (SpEL)
    unless κ²°κ³Όλ₯Ό μ €μž₯ν•˜μ§€ μ•Šμ„ 쑰건 (SpEL)

    μ˜ˆμ‹œ:

    @Cacheable(value = "books", key = "#isbn", unless = "#result == null")
    public Book findBook(String isbn) {
        return bookRepository.findByIsbn(isbn);
    }
    

    🧠 ν•¨κ»˜ μ•Œμ•„λ‘λ©΄ 쒋은 μ–΄λ…Έν…Œμ΄μ…˜

    • @CachePut : μΊμ‹œλ₯Ό κ°•μ œλ‘œ μ—…λ°μ΄νŠΈν•  λ•Œ μ‚¬μš©
    • @CacheEvict : μΊμ‹œλ₯Ό μ‚­μ œν•  λ•Œ μ‚¬μš©
    • @Caching : μ—¬λŸ¬ μΊμ‹œ μ–΄λ…Έν…Œμ΄μ…˜μ„ ν•¨κ»˜ μ‚¬μš©ν•  λ•Œ

    ν•„μš”ν•˜λ‹€λ©΄ Redisλ‚˜ Caffeine 같은 μΊμ‹œ μŠ€ν† μ–΄μ™€ ν•¨κ»˜ 연동도 κ°€λŠ₯ν•©λ‹ˆλ‹€.

    Created Tue, 01 Apr 2025 11:34:10 +0900
  • βœ… μ„œλΈŒλͺ¨λ“ˆ μ™„μ „νžˆ μ΄ˆκΈ°ν™”ν•˜κ³  λ‹€μ‹œ μ…‹νŒ…

    1. μ„œλΈŒλͺ¨λ“ˆμ„ Gitμ—μ„œ λ¨Όμ € 제거

      git submodule deinit -f .
      
    2. μ„œλΈŒλͺ¨λ“ˆ 디렉토리λ₯Ό 제거

      rm -rf .git/modules/<μ„œλΈŒλͺ¨λ“ˆ_이름>
      rm -rf <μ„œλΈŒλͺ¨λ“ˆ_디렉토리>
      
    3. .gitmodules 파일 μ‚­μ œ

      rm .gitmodules
      
    4. μΈλ±μŠ€μ—μ„œ μ„œλΈŒλͺ¨λ“ˆ 흔적 제거

      git rm --cached <μ„œλΈŒλͺ¨λ“ˆ_디렉토리>
      
    5. 컀밋

      git commit -m "Remove submodule completely"
      
    6. μƒˆλ‘œμš΄ μ„œλΈŒλͺ¨λ“ˆ μΆ”κ°€ (ν•„μš”ν•œ 경우)

      git submodule add <repo-url> <path>
      git commit -m "Add submodule"
      

    🧠 μ •λ¦¬ν•˜μžλ©΄:

    • λ‹¨μˆœνžˆ .gitmodules 파일만 μ§€μš°λ©΄ μ•ˆ 되고,
    • Git λ‚΄λΆ€μ˜ μ„œλΈŒλͺ¨λ“ˆ 정보 (.git/modules, 인덱슀 λ“±)도 같이 μ •λ¦¬ν•΄μ€˜μ•Ό ν•΄μš”.
    Created Tue, 01 Apr 2025 11:25:45 +0900
  • k8sλž€?

    **Kubernetes (k8s)**λŠ” μ»¨ν…Œμ΄λ„ˆν™”λœ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μžλ™μœΌλ‘œ 배포, ν™•μž₯, κ΄€λ¦¬ν•΄μ£ΌλŠ” μ˜€ν”ˆμ†ŒμŠ€ μ»¨ν…Œμ΄λ„ˆ μ˜€μΌ€μŠ€νŠΈλ ˆμ΄μ…˜ ν”Œλž«νΌμž…λ‹ˆλ‹€. κ΅¬κΈ€μ—μ„œ κ°œλ°œν•œ κΈ°μˆ μ„ 기반으둜 CNCF(Cloud Native Computing Foundation)에 κΈ°λΆ€λ˜μ—ˆκ³ , ν˜„μž¬λŠ” ν΄λΌμš°λ“œ ν™˜κ²½μ—μ„œ κ°€μž₯ 널리 μ‚¬μš©λ˜λŠ” μ»¨ν…Œμ΄λ„ˆ 관리 μ‹œμŠ€ν…œμ΄μ—μš”.


    핡심 κ°œλ… 정리

    • μ»¨ν…Œμ΄λ„ˆ(Container): μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό κ·Έ μ‹€ν–‰ ν™˜κ²½μ„ νŒ¨ν‚€μ§•ν•œ λ‹¨μœ„ (주둜 Docker μ‚¬μš©)
    • Pod: Kubernetes의 κ°€μž₯ μž‘μ€ 배포 λ‹¨μœ„. ν•˜λ‚˜ μ΄μƒμ˜ μ»¨ν…Œμ΄λ„ˆλ₯Ό 포함할 수 μžˆμ–΄μš”.
    • Node: μ»¨ν…Œμ΄λ„ˆκ°€ μ‹€μ œλ‘œ μ‹€ν–‰λ˜λŠ” 물리/가상 λ¨Έμ‹ 
    • Cluster: μ—¬λŸ¬ λ…Έλ“œλ‘œ κ΅¬μ„±λœ Kubernetes의 전체 인프라
    • Deployment: μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ›ν•˜λŠ” μƒνƒœ(예: λͺ‡ 개의 볡제본 μœ μ§€ λ“±)λ₯Ό μ •μ˜ν•˜κ³  관리
    • Service: Pod에 μ ‘κ·Όν•  수 μžˆλŠ” μ•ˆμ •μ μΈ λ„€νŠΈμ›Œν¬ μ£Όμ†Œλ₯Ό 제곡 (LoadBalancer, ClusterIP, NodePort λ“±)
    • Ingress: μ™ΈλΆ€ νŠΈλž˜ν”½μ„ λ‚΄λΆ€ μ„œλΉ„μŠ€λ‘œ λΌμš°νŒ…ν•΄μ£ΌλŠ” HTTP(S) 레벨 λΌμš°ν„°
    • ConfigMap / Secret: μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„€μ • κ°’μ΄λ‚˜ λ―Όκ°ν•œ 정보λ₯Ό μ™ΈλΆ€μ—μ„œ μ£Όμž…

    Kubernetes의 μž₯점

    • μžλ™ν™”λœ 배포 및 λ‘€λ°±: μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ†μ‰½κ²Œ 배포/μ—…λ°μ΄νŠΈν•˜κ³ , 문제 λ°œμƒ μ‹œ μžλ™μœΌλ‘œ 이전 λ²„μ „μœΌλ‘œ λ‘€λ°± κ°€λŠ₯
    • μžλ™ μŠ€μΌ€μΌλ§: νŠΈλž˜ν”½μ— 따라 Pod 수λ₯Ό μžλ™ 쑰절 κ°€λŠ₯
    • μžκ°€ 치유(Self-healing): μž₯μ•  λ‚œ μ»¨ν…Œμ΄λ„ˆλŠ” μžλ™μœΌλ‘œ λ‹€μ‹œ 생성
    • μ„œλΉ„μŠ€ λ””μŠ€μ»€λ²„λ¦¬ 및 λ‘œλ“œ λ°ΈλŸ°μ‹±: Pod κ°„ 톡신을 μ‰½κ²Œ ν•  수 있게 λ„μ™€μ€Œ

    κ°„λ‹¨ν•œ λ™μž‘ 흐름

    1. μ‚¬μš©μžλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ»¨ν…Œμ΄λ„ˆ(Docker)둜 νŒ¨ν‚€μ§•
    2. 이λ₯Ό Kubernetes ν΄λŸ¬μŠ€ν„°μ— 배포
    3. Kubernetesκ°€ 이λ₯Ό μ μ ˆν•œ Node에 μŠ€μΌ€μ€„λ§ν•˜κ³  μ‹€ν–‰
    4. μ„œλΉ„μŠ€λ‚˜ Ingressλ₯Ό 톡해 μ™ΈλΆ€ μ ‘κ·Ό κ°€λŠ₯

    helm μ΄λž€?

    Helm은 Kubernetes의 νŒ¨ν‚€μ§€ κ΄€λ¦¬μžμž…λ‹ˆλ‹€. μ‰½κ²Œ λ§ν•΄μ„œ, Kubernetesμ—μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 더 쉽고, μž¬μ‚¬μš© κ°€λŠ₯ν•˜κ²Œ 배포할 수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” λ„κ΅¬μž…λ‹ˆλ‹€. 마치 apt(Ubuntu), brew(macOS), npm(Node.js) 같은 λŠλ‚Œ.

    Created Mon, 31 Mar 2025 12:48:01 +0900
  • PreFlightCorsConfig example

    @Configuration
    public class PreFlightCorsConfig {
    
        private final CorsProperties corsProperties;
    
        public PreFlightCorsConfig(CorsProperties corsProperties) {
            this.corsProperties = corsProperties;
        }
    
        private static final String ALLOWED_HEADERS = "x-requested-with,authorization, refresh-token,Access-Control-Allow-Origin,Content-Type, credential,X-AUTH-TOKEN,X-CSRF-TOKEN";
    
        private static final String ALLOWED_METHODS = "GET, PUT, POST, PATCH, DELETE, OPTIONS";
    
        private static final String ALLOWED_CREDENTIALS = "true";
    
        // μ€‘μš” ν•΄λ‹Ή 헀더가 μ—†λ‹€λ©΄ axiosλ₯Ό ν†΅ν•œ ν”„λ‘ νŠΈμ—μ„œ 확인이 λΆˆκ°€λŠ₯함
        private static final String EXPOSE_HEADERS = "*,Authorization,Refresh-token,authorization,refresh-token";
    
        private static final String MAX_AGE = "3600";
    
        @Bean
        public WebFilter corsFilter() {
            return (ServerWebExchange ctx, WebFilterChain chain) -> {
                ServerHttpRequest request = ctx.getRequest();
                String requestOrigin = request.getHeaders().getOrigin();
    
                if (CorsUtils.isPreFlightRequest(request)) {
                    ServerHttpResponse response = ctx.getResponse();
                    HttpHeaders headers = response.getHeaders();
    
                    if (requestOrigin != null && corsProperties.getAllowedOrigins().contains(requestOrigin)) {
                        headers.add("Access-Control-Allow-Origin", requestOrigin);
                    }
    
                    headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
                    headers.add("Access-Control-Max-Age", MAX_AGE);
                    headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
                    headers.add("Access-Control-Allow-Credentials", ALLOWED_CREDENTIALS);
                    headers.add("Access-Control-Expose-Headers", EXPOSE_HEADERS);
    
                    // ν”„λ‘ νŠΈμ—μ„œ ν•΄λ‹Ή 헀더λ₯Ό ν™•μΈν• μˆ˜μž‡κ²Œ ν—ˆκ°€ν•΄μ€Œ
                    headers.add("Access-Control-Expose-Headers", EXPOSE_HEADERS);
                    if (request.getMethod() == HttpMethod.OPTIONS) {
                        response.setStatusCode(HttpStatus.OK);
                        return Mono.empty();
                    }
                }
    
                return chain.filter(ctx);
            };
        }
    }
    

    CorsProperties

    @Component
    @Getter
    @Setter
    @ConfigurationProperties(prefix = "app.cors")
    public class CorsProperties {
    
        private List<String> allowedOrigins = new ArrayList<>();
    }
    

    μ„€μ •

    • dev, prod profile λ³„λ‘œ λ‹€λ₯΄κ²Œ μ„€μ •ν•˜λŠ” 게 일반적
    # application-dev.yml
    cors:
      allowed-origins:
        - "http://localhost:3000"
        - "http://127.0.0.1:3000"
    
    # application-prod.yml
    cors:
      allowed-origins:
        - "https://example.com"
        - "https://another-domain.com"
    

    spspring-cloud-starter-gateway μ‚¬μš©μ‹œ

    Spring Cloud Gatewayλ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€λ©΄ PreFlightCorsConfig 같은 λ³„λ„μ˜ Java Config 없이도 application.yml에 μ„€μ •λ§ŒμœΌλ‘œ CORS μ²˜λ¦¬κ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.**

    Created Mon, 31 Mar 2025 00:49:17 +0900