현재 지금 다니는 회사에서는 서비스마다 Python과 Java를 구분해서 사용하고 있는데 이 두언어의 차이가 무엇인지 그리고 왜 이 두언어를 구분해서 사용하는지 한번 알아보자
우선 파이썬은 우리가 다 알다시피 간결하고 직관적이다. 이러한 특징 때문에 배우기가 쉽고 적은 코드로도 원하는 기능을 구현할 수 있다.
이에 반해 자바는 엄격하고 구조적이다. 명시적인 타입선언이 무조건적이고 객체 지향 설계로 코드가 길어지지만 명확하게 표현이 가능하다.
파이썬은 코드를 한줄씩 읽어서 실행하는 인터프리터 방식의 언어이다. 이 방식의 장점은 아래와 같다.
이에 반해 인터프리터가 가지고 있는 단점도 있는데
위에서는 파이썬의 실행흐름이었고 자바는 어떨까?
자바는 컴파일 방식 + JVM을 통해 실행이된다.
가장 대표적인 차이인 타입이다, 우선 파이썬은 동적 타임으로 어떤 변수든 데이터에 담을 수 있어 유연하다.
x = 10 # 정수
x = "Hello" # 문자열로 변경 가능
이에 반해 자바는 변수 타임을 미리 선언하는 정적 타입으로 컴파일 단계에서 오류를 발견할 수 있다.
int x = 10; // 정수
x = "Hello"; // 컴파일 오류 발생
파이썬은 GIL로 인해 단일 스레드로 밖에 실행이 되지 않는다.
여기서 GIL은 Global Interpreter Lock으로 여러 개의 스레드가 파이썬 바이트코드를 한번에 하나만 사용할 수 있게 락을 거는 것을 의미한다.
python에 GIL이 존재 이유에 대해 잠시 살펴보자면
- python은 객체 메모리 관리를 위해 참조 카운팅을 사용한다, 그러나 여러 스레드가 참조 카운트를 동시에 수정하면 경쟁 상태가 발생할 수 있기 때문에 이를 방지하기 위해 GIL(Global Interperter Lock)을 사용해 단일 스레드로만 수행되게 하는 것이다.
obj = [] # 참조 카운트 1
ref = obj # 참조 카운트 2
del obj # 참조 카운트 1
del ref # 참조 카운트 0 -> 메모리 해제
위 처럼 참조 카운트 방식으로 설정된 ref가 기존 변수인 obj 데이터를 삭제하니 ref 데이터도 삭제된 것을 볼 수 있다. 해당 문제가 멀티 스레드 방식을 지원할 경우 발생할 수 있기 때문에 GIL이 필요한 것이다.
따라서 파이썬은 해결하기 위해 멀티스레드 대신 멀티 프로세싱 모듈로 분리해 병렬성을 높이는 방식을 사용한다.
그렇다면 Java에서도 참조 카운팅 방식인데 왜 자바는 멀티 스레드가 될까?? 라는 질문이 나올 수 있다.
이는 Java의 메모리 관리가 파이썬과 다르기 때문이다. 자바에서는 참조 카운팅만 사용하는 것이 아니라 트리버설 방식을 사용하는데 이는 참조 카운트를 유지하지 않고 도달 가능성 분석을 통해 사용 하지 않는 객체를 식별하는 것이다.
이를 바탕으로 자바는 참조 카운트를 사용은 하지만 실시간 참조 카운팅을 사용하지 ㅇ낳고 도달 가능성 분석을 기반으로 참조 유형을 조합해 사용한다.
또한 동시성 문제를 방지하기 위해 Java의 가지비 컬렉터는 내부적으로 필요한 경우에 락이나 메모리 모델을 사용해 안전하게 작업하기 때문에 Java는 GIL로 부터 벗어날 수 있다.
| 특징 | python | java | |
|---|---|---|---|
| 카비지 컬렉션 방식 | 참조 카운팅 + 주기적인 GC | 실시간 참조 카운팅X, 도달 가능성 분석 | |
| 참조 카운팅 사용 여뷰 | O | X | |
| 동시성 관리(GIL) | GIL로 한번의 쓰레드만 실행 | GIL없음, 멀티 쓰레드 병렬 실행 지원 | |
| 가비지 컬렉션 성능 | 단일 스레드 위주로 동작 | 병렬 GC 및 고성능 GC 옵션 | |
| 스레드 안전성 | GIL로 참조 카운팅 동기화 문제 해결 | 메모리 모델로 객체 참조 변경을 안전하게 관리 |
👉🏻 파이썬의 가비지 컬렉션
파이썬 가비지 컬력션은 참조 카운팅과 사이클 검출 이 두가지 방식으로 메모리를 관리한다.
1. 참조 카운팅
a = [1, 2, 3] # 리스트 객체 생성, 참조 카운트 = 1
b = a # 참조 카운트 증가 = 2
del a # 참조 카운트 감소 = 1
del b # 참조 카운트 = 0 -> 메모리에서 삭제
장점
단점
👉🏻 자바의 가비지 컬렉션
자바의 가비지 컬렉션의 주요 특징은 아래와 같다
작동 방식
1. 세대별 메모리 관리
Stop-the-world
장점
단점
| 특징 | python | java |
|---|---|---|
| 메모리 관리 방식 | 참조 카운팅 + 순환 참조 검출 | 세대별 GC + 다양한 알고리즘 |
| 즉시 객체 해제 여부 | 참조 카운팅으로 즉시 해제 | GC가 실행될 때까지 객체가 메모리에서 유지 |
| GC 방식 | 주로 단일 스레드 | 병렬 및 병합 가능한 다양한 알고리즘 지원 |
| 성능 | 소규모 애플리케이션에 적합. 순환 참조 검출 시 성능 저하 | 대규모 애플리케이션에서 뛰어난 성능과 확장성 제공 |
| 병럴처리 | GC가 단일 스레드로 동작 | 병렬 GC를 통해 멀티코어를 활용한 효율적인 메모리 관리 기능 |
| 튜닝 가능성 | 제한적 | JVM 옵션을 통해 GC 동작을 세부적으로 튜닝 가능 |
파이썬은 인터프리터의 특징 및 병렬 처리의 문제로 대규모 프로젝트일 경우 성능 이슈가 발생할 수 있기 때문에 소규모 프로젝트 및 머신 러닝, 데이터 분석에 강하다.
반면에 자바는 엄격한 문법 덕분인지 안정적이고 튼튼하고 병렬처리와 뛰어난 GC 성능으로 인해 대규모 프로젝트에 강한 것을 볼 수 있었다.
이렇게 까지 자세히 포스팅을 할 계획은 없었지만 파면 팔수록 두언어 모두 각기 다른 특징을 지니고 있어 각자 다른 매력을 발견하면서 글이 길어지고 말았다..... 그럼 오늘 포스팅은 여기까지