반응형

JavaAgent란?

Java 프로그램이 시작할 때 JVM에 의해 클래스로딩이 수행되는 시점에 자바 바이트 코드를 변조를 할 수 있도록 해주는 프로그램이다

이를 통해 별도의 메인 프로그램의 코드를 변경하지 않고도 프로그램에 대한 모니터링 등을 수행 할 수 있다

프로그램의 원본 코드를 수정하지 않아도 모니터링을 할 수 있기 때문에 APM툴에서 많이 사용되고 있다

JavaAgent 실행 방법

JavaAgent는 JVM 옵션을 통해 실행할 JavaAgent를 지정하여 실행할 수 있다

-javaagnet:jarpath[=options]

**ex)**
-javaagent: /home/monitoring/monitoring.jar

JavaAgent 동작 원리

  1. Java 애플리케이션 실행을 위해 JVM이 실행 되면서 JavaAgent의 Premain 함수 수행
  2. ClassFileTransformer 구현체 로딩
  3. Class Loader에 의해 Java 애플리케이션 Class File 로딩 시 Class 파일 ClassFileTransformer에 의해 바이트 코드 변경
  4. 변경된 바이트 코드 로딩
반응형

'공부 > Java' 카테고리의 다른 글

Java SSL 인증서 검증 흐름 및 확인  (0) 2025.06.17
Out Of Memory 문제 분석  (0) 2025.05.31
[Java] HashMap get 메서드에 관하여  (0) 2021.09.13
Java Virtual Machine(JVM)  (0) 2021.05.08
Primitive, Reference Type  (0) 2021.05.07
반응형

Java는 소스 코드를 컴파일 하고 컴파일의 결과로 만들어진 바이트코드를 인터프리터에 의해 해석하여 실행되는 언어이다.

JVM 구조

https://www.nowwatersblog.com/cs/JVM

 

JVM의 실행 순서

  1. JVM이 OS로부터 필요로 하는 메모리를 할당 받는다. JVM은 할당받은 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
  2. Class Loader를 통해 자바 바이트 코드가 JVM Runtime Data Areas로 로딩 된다.
  3. 로딩된 바이트 코드가 Execution Engine에 의해 해석 된다.
  4. 해석된 바이트 코드는 JVM Runtime Data Areas에 배치되어 실행 된다.
  5. 실행 과정에서 Garbage Collection이 메모리 관리 작업을 수행한다.

 

Runtime Data Area

Heap

  • 객체 인스턴스와 배열이 저장되는 영역
  • Java에서 생성된 모든 객체는 이 힙 영역에 할당
  • 힙은 모든 스레드가 공유하며, 가비지 컬렉터에 의해 관리

Stack

  • 각 스레드마다 독립적으로 존재하는 메모리 영역
  • 메서드 호출 시 생성되는 프레임(스택 프레임) 저장
  • 각 프레임에는 메서드의 로컬 변수, 매개변수, 반환 주소 등 포함
  • 메서드가 호출될 때 프레임이 스택에 추가되고, 메서드 실행이 완료되면 프레임 제거

Method

  • 클래스에 대한 정보를 저장하는 영역
  • 클래스의 구조(클래스 이름, 메서드, 필드, 상수 풀 등)와 정적 변수(static 변수) 정보 포함
  • 모든 스레드가 공유

PC Register

  • 각 스레드마다 존재하는 작은 메모리 공간
  • 현재 실행 중인 JVM 명령 주소 저장
  • 스레드가 실행 될 때, 해당 스레드의 PC 레지스터 업데이트

Native Method

  • Java가 아닌 언어로 작성된 네이티브 메서드 호출 시 사용하는 스택
  • 네이티브 메서드의 로컬 변수와 매개변수 저장
반응형

'공부 > Java' 카테고리의 다른 글

Java SSL 인증서 검증 흐름 및 확인  (0) 2025.06.17
Out Of Memory 문제 분석  (0) 2025.05.31
[Java] HashMap get 메서드에 관하여  (0) 2021.09.13
JavaAgnet  (0) 2021.05.09
Primitive, Reference Type  (0) 2021.05.07
반응형

Primitive Type

Primitive 타입은 원시 타입이라고도 아래와 같은 타입이 존재한다.

  • byte (1 byte, 정수형)
  • short (2 byte, 정수형)
  • int (4 byte, 정수형)
  • long (8 byte, 정수형)
  • float (4 byte, 부동소수점형)
  • double (8 byte, 부동소수점형)
  • char (2 byte, 문자형)
  • boolean (1 byte)

Primitive 타입은 일반적으로 Stack에 데이터가 저장 된다.

데이터를 메모리에 직접 저장하기 때문에 성능 우수

필요한 크기에 맞는 Primitive 타입을 선택하여 사용할 수 있으므로 메모리 사용에 효율적이다.

Reference Type

Reference Type은 참조 타입으로 객체를 참조하는 데이터 타입니다.

Reference Type에는 아래와 같은 타입이 존재한다.

  • 클래스 (class)
  • 배열 (array)
  • 인터페이스 (interface)
  • 열거형 (enum)

Reference Type의 경우는 데이터를 Stack이 아닌 Heap에 저장하고 그 데이터의 참조값을 Stack에 저장하여 데이터에 접근할 때는 Stack을 거쳐 Heap까지 가야하기 때문에 Premitive 타입 보다 느리다.

한가지 주의해야할 것이 Reference Type을 포인터라고 생각하는 경우가 있는데,

포인터는 주소를 직접 다루는 변수이고 Java의 Reference는 간접적으로 참조하는 변수이다.

Reference 변수로 데이터에 접근하지만 우리가 직접 메모리 주소를 조작하거나 할 수 없다.

Java의 메모리 관리는 가비지 컬렉터에 의해 자동으로 처리된다.

String의 경우는 조금 특별하다.

String a = “abc”;

형식으로 String 객체를 생성할 수 있는데, 이것을 String 리터럴이라고 하고, 데이터가 리터럴 풀에 저장되어 재사용되게 된다.

리터럴 풀은 heap의 일부이다.

String b = new String(”abc”);

이 경우는 새로운 String 객체를 리터럴 풀에 생성하는 것이 아닌 heap에 생성하게 된다.

반응형

'공부 > Java' 카테고리의 다른 글

Java SSL 인증서 검증 흐름 및 확인  (0) 2025.06.17
Out Of Memory 문제 분석  (0) 2025.05.31
[Java] HashMap get 메서드에 관하여  (0) 2021.09.13
JavaAgnet  (0) 2021.05.09
Java Virtual Machine(JVM)  (0) 2021.05.08
반응형

Filter는 말 그대로 요청이나 결과를 Filtering 하는 역할을 수행한다.

 

https://gowoonsori.com/blog/spring/architecture/

 

Servlet과 Spring의 구조를 정말 잘 표현한 이미지이다.

 

Filter는 Servlet Stack으로 Dispatcher Servlet 앞단에 위치하고 있으며, Filter Chain으로 동작한다.

Filter는 Filter interface를 구현하면 되고 doFilter 메소드를 호출하면 chain 형식으로 다음 필터를 호출하는 식으로 동작 한다.

 

Interceptor랑 햇갈리는 경우가 많은데,

Interceptor의 위치는 Dispatcher Servelt에 요청이 들어온 다음에 위치하고 있다.

 

Filter와 Interceptor는 지향하는 점이 다르다고 할 수 있다.

물론 둘 다 요청과 응답을 제어할 수 있다는 점에 대해서는 같지만,

대체적으로 Filter의 경우 요청과 응답에 대한 처리가 필요한 경우(인증 등) 사용하는 경우가 많고,

Interceptor는 Business 로직에 좀 더 지향적인 처리가 필요한 경우(트랜잭션 등) 사용하는 경우가 많다.

반응형

'공부 > Spring' 카테고리의 다른 글

[Spring] DI란?  (0) 2021.09.20
[Spring] IoC란 무엇인가?  (0) 2021.09.16
@Transactional 동작하지 않는 경우  (0) 2021.09.10
[Spring] AOP란?  (0) 2021.09.08
Servlet Working Flow  (0) 2021.05.04
반응형

스프링의 전체적인 실행 흐름을 알기 위해서는 Servlet에 대해서 먼저 이해하는게 좋다.

그렇다면 서블릿이란 무엇인가?

이를 알기 위해 과거로 돌아가 보면 과거의 웹 페이지들은 주로 정적인 HTML 페이지로 구성되어있고, 이러한 것은 동적인 컨텐츠를 보여주는데 한계가 있었다.

ex) 로그인하면 OOO님 안녕하세요! 같은 것을 보여주는 것

이러한 동적인 컨텐츠를 만들어 내기위해 자바 진영에 만들어진 웹 기술이 바로 Servlet이다.

Servlet은 HttpServlet 클래스는 클래스를 구현하여 만들 수 있다.

class TestServlet extends HttpServlet {
		// 이런 느낌
}

그리고 사용자의 요청에 맞는 Servlet을 찾아 실행하고 관리하는 역할을 하는 것이 Servlet Container 이고 우리가 알고있는 Tomcat 이고 WAS(Web Application Server)라고 부른다.

그리고 이러한 동적인 웹 컨텐츠를 생성하는 것이 아닌 정적인 컨텐츠 HTML, CSS 등을 제공하는 것이 바로Apache HTTP Server WEB 서버다.

보통 우리가 아파치 톰캣이라고 부르는 것은 이 둘을 말하는 것이다.

 

서블릿 컨테이너 서블릿 실행 흐름( https://lalwr.blogspot.com/2018/03/blog-post_20.html )

 

Servlet의 아래의 과정으로 실행이 된다.

  1. init() : 인스턴스가 생성될 후 최초 한번 수행 하는 메소드
  2. service() → doGet() / doPost() 등 : 요청을 받으면 service 메소드가 실행되고 요청 메소드에 따라 doGet, doPost 중 선택되어 실행 하여 비즈니스 로직 수행 후 결과 반환
  3. destroy() : 서즐릿 종료시 호출되는 메소드

이처럼 서블릿을 이용하면 정해져있는 메소드를 구현 하기만 하면 비즈니스 로직을 수행할 수 있다.

좋은 것 처럼 보인다.

그런데 과연 홈페이지의 기능이 하나가 아니라면? ⇒ 필요한 기능을 구현한 파일이 많아진다.

그리고 구현된 것을 다른 곳에 사용하고 싶다면 과연 어떻게 될까? ⇒ HttpServlet을 extends하고 있어서 다른 곳에서 사용하기는 어려워 보인다.

우리의 java 파일은 점점 많아지게 되고 이를 유지보수 하기 어려워진다.

이러한 문제를 해결하기 위한 시도에 의해 생겨난 것이 Spring 이다.

반응형

'공부 > Spring' 카테고리의 다른 글

[Spring] DI란?  (0) 2021.09.20
[Spring] IoC란 무엇인가?  (0) 2021.09.16
@Transactional 동작하지 않는 경우  (0) 2021.09.10
[Spring] AOP란?  (0) 2021.09.08
[Spring] Filter & Interceptor  (0) 2021.05.05
반응형

개방 폐쇄 원칙은 소프트웨어의 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다는 원칙이다.

정리하면 기존 코드에 대한 변경 없이 새로운 기능을 추가할 수 있어야 한다.

개방 폐쇄 원칙을 지키게 되면 아래와 같은 장점이 있다.

  1. 유지보수 용이
  2. 재사용성
  3. 확장성

OCP를 위반한 케이스

class DiscountService {
    public int calculateDiscount(int price, String type) {
        switch (type) {
            case "FIXED":
                return price - 1000;
            case "RATE":
                return (int)(price * 0.9);
            default:
                return price;
        }
    }

    public static void main(String[] args) {
        DiscountService discountService = new DiscountService();
        System.out.println(discountService.calculateDiscount(10000, "FIXED")); // 9000
        System.out.println(discountService.calculateDiscount(10000, "RATE"));  // 9000
    }
}

새로운 정책을 추가할 때 마다 calculateDiscount 메소드를 수정해야 한다

해당 메소드는 여러 할인 정책이 있으므로 변경에 닫혀있어야하는 정책을 위반하게 된다

OCP 준수한 케이스

public interface DiscountPolicy {
    boolean supports(String type);
    int discount(int price);
}
public class FixedDiscountPolicy implements DiscountPolicy {
    @Override
    public boolean supports(String type) {
        return "FIXED".equalsIgnoreCase(type);
    }

    @Override
    public int discount(int price) {
        return price - 1000;
    }
}
import java.util.List;

public class DiscountService {
    private final List<DiscountPolicy> policies;

    public DiscountService(List<DiscountPolicy> policies) {
        this.policies = policies;
    }

    public int calculateDiscount(int price, String type) {
        for (DiscountPolicy policy : policies) {
            if (policy.supports(type)) {
                return policy.discount(price);
            }
        }
        return price;
    }
}

----

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        DiscountService discountService = new DiscountService(Arrays.asList(
            new FixedDiscountPolicy(),
            new RateDiscountPolicy()
        ));

        System.out.println(discountService.calculateDiscount(10000, "FIXED")); // 9000
        System.out.println(discountService.calculateDiscount(10000, "RATE"));  // 9000
        System.out.println(discountService.calculateDiscount(10000, "NONE"));  // 10000
    }
}

각 할인 정책은 DiscountPolicy 인터페이스를 구현하게 되기 때문에 DiscountService 는 구현체에 의존하는 것이 아닌 인터페이스에 의존하고 동적 바인딩을 통한 코드 실행 가능해진다

현재 Main 클래스 내에서 의존성을 직접 DiscountService에 주입하고 있지만 이 역할을 Spring IoC 컨테이너가 해주게 되어 기존 코드를 수정하지 않고 정책을 추가할 수 있게 된다

이를 통해 OCP를 준수하게 된다

반응형
반응형

단일 책임 원칙은 클래스, 객체 혹은 모듈이 하나의 책임을 가져야 한다는 원칙이다.

그렇다면 책임은 무엇일까?

책임이란 클래스 또는 객체가 하나의 작업이나 기능을 수행해야한다는 원칙이다.

그런데 책임이란 이런 작업이나 기능이보다는 역할이라는 말이 더 적합하다.

비디오 가게 코드를 예시로 보면

import java.util.ArrayList;
import java.util.List;

public class VideoStore {
    private List<Video> videos;

    public VideoStore() {
        videos = new ArrayList<>();
    }

    public void addVideo(Video video) {
        videos.add(video);
    }

    public void rentVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.rent();
                return;
            }
        }
    }

    public void returnVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.returnVideo();
                return;
            }
        }
    }
}

VideoStore 클래스는 비디오 가게에 비디오 리스트를 가지고 있고 추가, 대여, 반납 하는 기능이 있다.

VideoStore 클래스는 단일 책임 원칙이 잘 지켜지고 있다. 비디오 가게라는 역할에 맞는 기능들만을 가지고 있기 때문이다.

단일 책임 원칙을 지키게되면 좀 더 객체지향적으로 프로그래밍 할 수 있고, 다음과 같은 장점을 가질 수 있다.

  1. 높은 응집도
  2. 유지보수성
  3. 변경 용이성
import java.util.ArrayList;
import java.util.List;

public class VideoStore {
    private List<Video> videos;
    private List<User> users;

    public VideoStore() {
        videos = new ArrayList<>();
    }

    public void addVideo(Video video) {
        videos.add(video);
    }

    public void rentVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.rent();
                return;
            }
        }
    }

    public void returnVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.returnVideo();
                return;
            }
        }
    }
    
    public void addUser(User user) {
        users.add(user);
    }
}

위의 코드는 단일 책임 원칙이 깨진 코드이다.

VideoStore가 비디오만 관리하는 것이 아니라 사용자 정보도 관리하기 때문에 VideoStore는 두 가지 역할을 가지고 있다.

물론 이런 경우에도 기능을 정상적으로 작동할 것이고 문제가 없을 가능성이 크다.

다만 이렇게 단일 책임 원칙이 깨지게 되면, 클래스의 역할 즉 클래스가 해야할 일은 모호해지고, 변경에 대한 복잡도가 증가하게 되어 유지보수성이 떨어진다.

 

 

SRP를 지킨 코드

VideoManager

public class VideoManager {
    private List<Video> videos = new ArrayList<>();

    public void addVideo(Video video) {
        videos.add(video);
    }

    public void rentVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.rent();
                return;
            }
        }
    }

    public void returnVideo(String title) {
        for (Video video : videos) {
            if (video.getTitle().equalsIgnoreCase(title)) {
                video.returnVideo();
                return;
            }
        }
    }
}

UserManager

public class UserManager {
    private List<User> users = new ArrayList<>();

    public void addUser(User user) {
        users.add(user);
    }
}

VideoStore

public class VideoStore {
    private VideoManager videoManager = new VideoManager();
    private UserManager userManager = new UserManager();

    public void registerVideo(Video video) {
        videoManager.addVideo(video);
    }

    public void registerUser(User user) {
        userManager.addUser(user);
    }
    
    // business
}

비디오를 관리하고 사용자를 관리하는 것은 각각 VideoManager와 UserManager가 책임을 가지고 있다

그리고 이 Manager들을 활용하여 VideoStore Business 로직을 구현 한다

반응형
반응형

 

JPA(Java Persistence Api)

 

우선 JPA를 배우기 전에 JPA가 무엇인지 부터 알아야할 것같습니다.

일반적으로 Spring으로 개발 시에 Mybatis와 같은 ORM 프레임워크를 활용합니다.

 

ORM을 사용하게 되면 쿼리를 통해 DB로 부터 데이터를 가져온 후 이를 VO 또는 DTO 객체로 받아서 데이터를 가공 또는 처리하는 순서로 진행이 될 것입니다.

이는 아주 간단한 데이터를 조회할 때도 동일하게 동작합니다.

 

Service(Java, xml) - Mybatis - JDBC - DB

간단하게 작성하면 위 구조로 동작을 한다고 볼 수 있다.

 

여기서 작성한 쿼리를 통해 가져온 결과를 DTO 객체에 매핑을 해주게 된다

 

위와 같이 동작을 하게 되면 단순 조회나 값 변경 등에 있어서 많은 과정을 거쳐야된다.

 

JPA는 이러한 문제점을 해결해주고 객체를 이용해서 데이터 베이스의 값을 변경하고 제어할 수 있게 해주는 API 명세서이다.

그리고 이러한 JPA를 구현한 것이 많이들 사용하고 있는 Hibernate 프레임워크 이다.

 

JPA는 명세서

Hibernate는 명세서를 구현한 프레임워크

 

반응형

'공부 > JPA' 카테고리의 다른 글

JPA N+1 문제 원인  (0) 2025.07.06
JPA 조회 함수에서 @Transactional이 필요한 경우(LazyInitializationException)  (1) 2025.07.06
JPA 순환 참조  (1) 2025.06.24

+ Recent posts