컴퓨터와 프로그래밍 기초
메모리 구조, 깊은 복사와 얕은 복사, Parameter와 Argument, Call By Value와 Call By Reference, 프레임워크와 라이브러리의 차이에 대해 배워봅니다.
메모리 구조
코드 영역 : 실행할 프로그램의 코드가 저장되는 영역
데이터 영역 : 프로그램의 전역 변수와 정적 변수가 저장되는 영역
힙 영역 : 참조 타입의 메모리 주소를 저장하는 영역
- Java에서는 가비지 컬렉터가 자동으로 해제해줌
- class, interface, enum, array 등
스택 영역 : 원시 타입이 저장되는 영역 (파이썬은 원시타입이 없음)
- 또한 참조 타입의 주소를 참조하는 변수가 저장됨
- 메서드의 호출이 종료되면 메모리가 소멸됨
- int, boolean 등
- string의 경우 참조 타입인 언어와 원시 타입인 언어가 나뉜다.
- 예로 자바는 참조 타입이고, 자바스크립트는 원시 타입이다.
깊은 복사와 얕은 복사 차이
b = a를 예시로 들었을 때, a의 타입에 따라 깊은 복사와 얕은 복사로 나뉘게 됩니다.
메모리 구조에서 스택 영역에 저장되는 원시 타입의 경우 깊은 복사가 되는데, 이 경우에는 스택 영역의 변수를 복사하므로 A와 B가 온전히 다른 값을 가지게 됩니다.
하지만 힙 영역에 저장되는 참조 타입의 경우 얕은 복사가 되는데, 이 경우에는 힙 영역의 메모리 주소를 복사하므로 A와 B가 같은 값을 공유하게 됩니다.
예를 들어 이에 대한 개념을 모른다면 아래 문법의 차이를 이해할 수 없습니다.
# python
a = ['a']
b = a # 리스트이므로 얕은 복사가 일어난다
a = a + b
print(a, b) # ['a', 'a'], ['a']
a += b
print(a, b) # ['a', 'a'], ['a', 'a']
a = a + b는 새로 리스트를 만들어 a에 대입하기 때문에 a와 같은 주소값을 가지고 있는 b의 값이 변경되지 않습니다. 하지만 a += b의 경우 a를 재사용하기 때문에 a와 같은 주소값을 가지고 있는 모든 값이 변경되어 b의 값도 변경됩니다.
Parameter와 Argument 차이
파라미터는 함수를 정의할 때 외부로부터 받겠다고 선언하는 임의의 값을 의미합니다. 하지만 아규먼트는 그와 달리 함수를 호출할 때 파라미터에 값을 넘겨주는 값을 아규먼트라 합니다.
// golang
func add(nums ...int) {
result := 0
for _, v := range nums {
result += v
}
return v
}
func main() {
print(add(1, 3, 5, 4)) // 13
}
위 예시의 add(1, 3, 5, 4)에서 1, 3, 5, 4는 아규먼트가 되며 파라미터는 int 타입의 nums입니다.
Call By Value와 Call By Reference 차이
보통 함수의 파라미터 타입에 따라 둘이 나뉘게 됩니다.
Call By Value는 인자로 받은 값을 복사하여 처리하므로 원래의 값에 영향을 미치지 않습니다. 깊은 복사가 일어나는 원시 타입의 경우 대부분의 언어에서 Call By Value로 처리됩니다.
Call By Reference는 인자로 받은 값의 주소를 참조하므로 원래의 값에 영향을 미치게 됩니다. 얕은 복사가 일어나는 참조 타입의 경우 대부분의 언어에서 Call By Reference로 처리됩니다.
// java, call by reference 예제
public static void main(String[] args) {
StringBuilder a = new StringBuilder("EELLO");
list(a);
System.out.println(a); // HELLO
}
static void list(StringBuilder a) {
a.setCharAt(0, 'H');
}
또한 포인터를 지원하는 언어에서는 원시 타입 또한 Call By Reference로 넘겨줄 수 있습니다.
// golang, Pointer 사용 예제
func list(a *int) {
*a = 1 // 실제 주소가 가리키는 값을 변경
}
func main() {
a := 0
list(&a) // a의 주소 값을 넘김
print(a) // 1
}
프레임워크와 라이브러리
프레임워크는 전체적인 흐름에 대한 제어권을 프레임워크가 관리하게 됩니다. 즉, 개발자가 프레임워크에 맞게 개발해야 하는 것입니다. 스프링 프레임워크를 사용하여 서버를 개발할 때 자바는 개발 도구일 뿐, 자바로 개발한다고 말하지 않습니다.
하지만 라이브러리는 전체적인 흐름에 대한 제어권을 개발자가 관리하고, 특정 흐름만을 가져다가 사용하는 것입니다.
Leave a comment