서론
환경변수를 관리하고 있는 서버가 모종의 이유로 더 이상 서버에 접근할 수 없고, 사용하고 있는 환경변수를 백업하지 않았다면 환경변수 값을 정확하게 알기 어렵습니다. 그래서 이번 포스팅에서는 이미 올라가 있는 서버에 대해, JVM Heap Dump를 활용하여 환경변수를 찾아오는 방법에 대해 공유해드리고자 합니다.
사용한 기술 및 소프트웨어
Java11, Spring Boot 2.6.11, Docker, Filezilla
JVM Heap Dump?
일단 JVM Heap Dump에 대해 간단하게 소개를 드리겠습니다. JVM Heap Dump는 JVM의 힙 메모리에 저장된 모든 객체들의 스냅샷을 저장한 파일입니다. 해당 파일들은 다음과 같은 정보를 가지고 있습니다.
- 힙에 저장된 객체 정보
- 객체 간의 참조 관계
- 클래스별 메모리 사용량
JVM Heap Dump의 용도
위와 같은 정보를 바탕으로 다음 메모리 문제 원인에 대해 파악하고 해결할 수 있습니다.
- 메모리 누수 감지: 메모리 누수로 인해 메모리 사용량이 증가하는 경우, 어떤 객체가 GC에 의해 제거되고 있지 않는지 확인할 수 있습니다(힙에 저장된 객체 정보, 객체 간 Strong reference).
- 성능 문제 진단: 객체 생성 비용이 비싸거나 객체 생성이 빈번해 메모리를 많이 사용하는 경우에도 사용할 수 있습니다.
환경 변수 찾기
본격적으로 환경변수를 찾기 위해서 어떤 시도를 했는지 공유드리겠습니다. 이번 글은 아래와 같은 전제를 가지고 작성됐습니다.
- 이미 도커 컨테이너로 서버는 동작하고 있는 상태
- 환경변수를 관리하는 서버는 외부적인 이유로 더 이상 접근할 수 없는 상태
이제 JVM Heap Dump를 사용해 어떻게 환경변수를 확인했는지 설명드리겠습니다.
1. Docker Container에서 JVM 덤프 뜨기
1.1 JVM Heap Dump 사용할 컨테이너 확인
- JVM Heap Dump를 사용하기 위해 PID를 확인해야 하는데, 그전에 대상이 될 Container ID를 획득합니다.
docker ps -a
1.2 Docker Container PID 확인
- 파악한 Container ID를 통해, JVM Heam dump를 사용할 도커 컨테이너에 접속해 인터렉티브 셸을 시작합니다.
- 이후 실행중인 프로세스를 확인하기 위해 procps 패키지를 설치한 뒤, 실행 중인 프로세스 PID를 확인합니다.
docker exec -it {:containerId} /bin/bash
yum install -y procps
ps -aux
1.3 Docker Container JVM Heap Dump 뜨기
- 이전에 확인한 PID를 기반으로 JVM Heap Dump를 수행합니다.
jmap -dump:format=b,file=/tmp/{filename} {pid}
exit
1.4 Docker Conatiner에서 파일 다운로드
- {id}에 해당하는 컨테이너의 /tmp/{filename} 파일을 현재 호스트의 디렉터리로 복사합니다.
- 그리고 파일에 대해 권한을 재설정해주었습니다.
docker cp {id}:/tmp/{filename} .
chmod 777 {filename}
- 복사한 파일은 FTP 툴인 Filezilla를 통해서 로컬로 다운로드 받았습니다.
- 복사했던 파일은 이후에 필요가 없기 때문에, 아래 명령어를 실행해 삭제해줍니다.
rm {filename}
docker exec -it {id} sh
rm /tmp/{filename}
2. JVM Heap Dump 결과물에서 환경변수 찾기
환경변수를 찾기 위해서 텍스트 툴을 사용할 수 있지만, Intellij 툴에서도 JVM Heap Dump 결과물인 hprof 확장자 파일 분석을 지원하고 있습니다. 그래서 이번에는 Intellij 툴을 활용해 주입받은 환경변수를 찾아보고자 합니다. 주입받은 환경변수 값들은 한 곳에 저장되어 있는 게 아니기 때문에, 원하는 변수를 찾기 위해서는 패키지 경로 및 클래스명 정보가 필요합니다.
2.1 환경변수 찾기 예시 코드
- 예를 들어 사용하고 있던 JWT Secret Key를 잃어버렸다고 가정해 보겠습니다. 아래는 환경변수가 주입된 클래스 예시입니다.
@Service
@RequiredArgsConstructor
public class JwtService {
@Value("${jwt.secretKey}")
private String secretKey;
@Value("${jwt.access.expiration}")
private Long accessTokenExpirationPeriod;
//... JWT 관련 로직
}
2.2 환경변수 확인하기
Intellij에서 다음 순서를 통해 환경변수를 확인할 수 있습니다.
- 다운로드한 hprof 파일을 intellij에서 실행시킨다.
- 찾으려는 클래스명을 검색하여 패키지 경로까지 확인하여 일치한 지 확인한다.
- 대상 클래스를 더블 클릭하고 찾으려는 환경변수에 대해 확인한다.
그러면 아래와 같이 입력했던 환경변수 값을 확인할 수 있습니다.
느낀 점
단순히 JVM Heap Dump를 사용하는 경우는 어플리케이션 서버에 메모리 이슈가 있을 때만 있을 거라고 생각했는데, 환경변수도 확인 가능하다는 것을 추가로 습득할 수 있었습니다. 이번 환경변수를 찾는 과정에서 JVM Heap Dump에 조금 더 찾아봐야겠다는 생각이 들었습니다. 읽어주셔서 감사합니다.
'Spring' 카테고리의 다른 글
Gradle 설정 알아보기 (1편) (0) | 2025.02.16 |
---|---|
Flyway 도입 전 탐색해보기 (2) | 2024.12.07 |
JPA 양방향 매핑 탈출기 (0) | 2024.10.27 |
@PathVariable 엔드포인트 매핑 원리 (1) | 2024.10.12 |
Redis, 그리고 Spring 에서 Redis 활용 (6) | 2024.09.07 |