1. 다형성을 사용하면 좋은 점은?

  • 다형성 : 한 타입의 참조 변수를 통해 여러 타입의 객체를 참조할 수 있도록 하는 것. 즉, 상위 클래스 타입의 참조 변수를 통해서 하위 클래스의 객체를 참조할 수 있도록 허용하여 상위 클래스가 동일한 메시지로 하위 클래스들이 서로 다른 동작을 할 수 있도록 한다.
  • 클래스가 상속 관계에 있을 때 나타나는 다채로운 성질
  • 장점
    • 코드를 유지보수하기 쉽다. 
    • 여러 클래스를 하나의 타입으로 묶어서 사용할 수 있기 때문에 코드를 압축할 수 있다.
  • https://inpa.tistory.com/entry/OOP-JAVA%EC%9D%98-%EB%8B%A4%ED%98%95%EC%84%B1Polymorphism-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4 참고

2. 언제 interface 사용하고, 언제 abstract class 사용 하는가? (문법적인 차이도)

  • 인터페이스
    • 모든 메서드가 추상 메서드로 구성되어 있고 구현 클래스에서 이를 구현해야 한다.
    • 다중 상속을 지원한다.
    • 주로 다중 상속을 필요로 하는 상황에서 사용한다. 여러 인터페이스를 구현함으로써 한 클래스가 다양한 역할을 수행할 수 있게 하는 상황
    • 다중 상속이 필요하거나 구현 객체 간의 계약을 정의할 필요가 있는 경우
  • 추상 클래스
    • 추상 메서드와 일반 메서드를 모두 포함하고 일부 기능을 구현한다. 
    • 다중 상속을 지원하지 않는다.
    • 공통적인 기능을 가진 클래스들 사이에서 코드의 재사용성을 높이기 위해 사용한다. 
    • 상속을 통해 코드의 재사용성을 높이고 공통적인 기능을 효율적으로 관리할 수 있게 한다.

3. checked exception vs unchecked exception

  • checked exception
    • 컴파일 단계에서 확인
    • 반드시 예외처리를 해야 함
    • 예외발생 시 트랜잭션 처리에서 롤백하지 않음(복구 가능한 메커니즘을 가져서)
    • RuntimeException의 하위 클래스가 아니면서 Exception 클래스의 하위 클래스들
  • unchecked exception
    • 실행단계에서 확인
    • 명시적인 예외 처리를 강제하지 않음
    • 외발생 시 트랜잭션 처리에서 롤백함
    • RuntimeException의 하위 클래스들

4. StringBuffer는 내부적으로 동기화 처리가 어떻게 되어 있나요?

  • StringBuilder와 StringBuffer의 append 메소드에는 차이가 있다.
  • StringBuilder
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str) {
    super.append(str);
    return this;
}
  • StringBuffer
@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}
  • Synchronized 메서드를 호출하였을 때, 자신이 포함된 객체에 lock 걸게 된다. 

5. enum 어떤 메모리에 저장이 될까요? (method 영역, Heap 영역 분리하여)

  • enum 클래스의 정보가 메서드 영역에 저장된다.
  • enum 객체 인스턴스가 힙 영역에 저장된다.
  • enum 클래스는 상수 하나당 인스턴스 하나를 생성해서 public static final로 공개한다. 열거 타입의 인스턴스는 클라이언트가 직접 생성할 수 없고, 인스턴스는 런타임에 한 번만 생성된다. 이런 특징으로 싱글톤 패턴을 구현할 때 사용되기도 한다.

6. inner class vs nested class (+ GC의 대상이 되는건 누구?)

  • inner class
    • static 키워드를 사용하지 않고 다른 클래스 내부에 정의된 클래스
    • 내부 클래스는 외부 클래스 멤버에 접근할 수 있다.
    • 내부 클래스 객체를 생성하려면 외부 클래스의 객체부터 생성해야 한다.
    • 내부 클래스에서 외부 클래스 멤버에 접근할 때는 외부클래스.this 로 사용한다. 내부 클래스 멤버에 접근하려면 this만 사용한다.
  • nested class
    • static 키워드를 사용하고 다른 클래스 내부에 정의된 클래스
    • 기술적으로는 내부 클래스가 아니다.
    • 내부 클래스에서 외부 클래스의 멤버에 접근할 수 없다.
    • 내부 클래스를 인스턴스화하기 위해 외부 클래스를 인스턴스화할 필요는 없다.
  •   inner class는 외부 클래스에 종속되어 있기 때문에 외부 클래스의 인스턴스가 더 이상 쓰이지 않고 GC의 대상이 되었을 때 inner class도 GC의 대상이 된다. 즉, 외부 클래스의 인스턴스가 메모리에 계속 남아있다면 inner class도 그렇다. nested class는 외부 클래스와 독립적으로 이루어져 있고 static이 붙은 클래스이기 때문에 GC의 대상이 될 수 없다.

7. 어노테이션을  왜 쓸까요? (+ 리플렉션 적용 과정)

  • 용도
    • 소스 코드에 메타데이터 추가
    • 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보 제공
    • 소프트웨어 개발툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
    • 실행 시 특정 기능을 실행하도록 정보 제공
  • 리플렉션 : 힙 영역에 로드된 Class 타입의 객체를 통해, 원하는 클래스의 인스턴스를 생성할 수 있도록 지원하고, 인스턴스의 필드와 메소드를 접근 제어자와 상관 없이 사용할 수 있도록 지원하는 API이다. 컴파일타임이 아닌 런타임에 동적으로 특정 클래스의 정보를 추출할 수 있는 프로그래밍 기법이다.
  • 어노테이션은 소스 코드에 메타데이터를 추가하는 방법이며, 리플렉션은 실행 시간에 클래스의 정보를 검사하고 조작하는 데 사용됩니다. 어노테이션을 사용하여 클래스에 메타데이터를 추가하고, 리플렉션을 사용하여 그 정보를 동적으로 검사하고 처리한다.
  • 리플렉션 적용 과정
    • 클래스 객체 얻기 
    • 얻고자 하는 클래스의 정보를 얻기 위해 클래스 객체의 메서드를 사용한다. 이러한 메서드는 클래스의 필드, 메서드, 생성자, 어노테이션 등에 접근할 수 있는 다양한 방법을 제공합니다.
    • 얻은 클래스, 필드, 메서드 등에 어노테이션을 조사하여 필요한 작업을 수행할 수 있다.
Class<?> clazz = MyClass.class;
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();

 

 

8. GC에서 사용하는 알고리즘은 무엇이 있고, Java는 어떤 알고리즘을 사용하나요?

9. 부동 소수점의 오류란?

  • 부동 소수점 숫자를 정확하게 표현하지 못하는 문제, 부동 소수점 숫자를 이진수로 표현할 때 발생한다.
  • 예를 들어, 10진수 0.1을 이진 소수점으로 정확하게 표현할 수 없다. 따라서 이진 소수점으로 근사하여 표현하게 되는데, 이 과정에서 정확한 값과 약간의 차이가 발생할 수 있다. 이러한 근사로 인해 부동 소수점 오류가 발생할 수 있다.
  • 계산 결과의 정확성에 영향을 미칠 수 있다. 특히 금융 애플리케이션과 같이 정밀한 계산이 필요한 경우에는 이러한 오류를 최소화해야 한다.
  • 이를 위해 BigDecimal과 같은 정확한 십진수 연산을 지원하는 데이터 타입을 사용한다.

※ 다음 주 예습 주제

1. 제네릭 

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%A0%9C%EB%84%A4%EB%A6%ADGenerics-%EA%B0%9C%EB%85%90-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%B3%B5%ED%95%98%EA%B8%B0

2. ArrayList

https://inpa.tistory.com/entry/JAVA-%E2%98%95-ArrayList-%EA%B5%AC%EC%A1%B0-%EC%82%AC%EC%9A%A9%EB%B2%95

3. Stack 클래스

https://inpa.tistory.com/entry/JCF-%F0%9F%A7%B1-Stack-%EA%B5%AC%EC%A1%B0-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%AC

4. Set, HashSet, Queue, LinkedList

5. Map, HashMap

 

※ 프로젝트

- 유저 시나리오 작성하기

- API 문서 작성하기

- 최소한의 기능이 무엇인지 고민해보기

'공부 > f-lab' 카테고리의 다른 글

f-lab 7주차  (0) 2024.04.30
f-lab 6주차  (0) 2024.04.24
f-lab 4주차  (0) 2024.04.09
f-lab 3주차  (0) 2024.04.02
f-lab 2주차  (0) 2024.03.26

1. 객체 지향 언어가 상태를 가져서 좋은 점은?(절차 지향과 비교)

  • 객체 지향은 클래스라는 개념으로 데이터와 함수를 묶어서 사용한다.  그 클래스의 데이터들을 객체의 상태라고 할 수 있다. 이것을 캡슐화라고 할 수 있고 캡슐화를 하면 정보를 은닉해두기 때문데 외부에서 그 객체의 메서드를 호출하지 않는 이상 객체의 상태를 변경할 수 없다. 
  • 절차지향에서는 클래스라는 개념을 사용하지 않고 데이터와 함수를 묶지 않고 분리해서 사용하기 때문에 데이터가 예기치 않게 변경될 수 있다.
  • 절차 지향에서는 주로 전역 변수를 사용하고 어느 곳에서나 쉽게 접근할 수 있고 객체 지향에서는 상태를 행동을 통해서만 변경할 수 있다.

2. SSD에서는 전기 신호로 어떻게 데이터를 읽어 오는가?

  • SSD는 플래시 메모리를 사용해서 전기 신호로 데이터를 읽고 저장한다.
  • 플래시 메모리는 비휘발성 메모리의 한 유형으로, 데이터를 저장하는 데 사용되는 전자 소자이다. 플래시 메모리는 전기 신호를 이용하여 데이터를 읽고 쓰며, 전원이 꺼져도 저장된 데이터를 유지할 수 있다.

3. HDD와 SSD의 데이터 액세스 포인트 개수 차이는?

  • HDD는 보통 한 번에 하나의 데이터 액세스 포인트에 액세스 할 수 있다.
  • SSD는 병렬로 한 번에 여러 개의 데이터에 액세스 할 수 있으며 물리적은 접근이 아니기 때문에 가능하다.

4. JVM 링크에서 심볼릭 레퍼런스란?

  • 클래스로더의 링크 과정에서 마지막 단계인 해결단계와 관련된 용어이다.
  • 메서드 영역 내의 런타임 상수 풀에 있는 심볼릭 레퍼런스를 직접 참조로 대체한다. 
  • 심볼릭 레퍼런스란 우리가 코드를 작성하면서 사용한 클래스, 필드, 메서드의 이름을 지칭한다. 해결 단계에서 클래스, 필드, 메서드 , 상수 풀의 심볼릭 레퍼런스를 실제 메모리 주소로 변환한다.
  • 심볼릭 레퍼런스 : 특정 객체를 참조할 때 객체의 이름으로 참조하는 것, 상수 풀에 저장됨
  • 직접 참조 : 객체를 메모리의 실제 주소 값으로 참조하는 것

5. 상속을 타입 공유로 사용하였을 때의 장점

  • 업캐스팅을 이용해서 자식 객체를 부모 클래스의 타입으로 변환할 수 있다.(=업캐스팅, 반대는 불가능)
  • 다양한 자식 객체들을 부모의 타입으로 묶어서 관리할 수 있다.

  • 각각의 자식 객체들은 같은 부모 타입이지만 각각의 객체를 참조하기 때문에 같은 이름의 메서드를 실행해도 각각의 자식 클래스에서 재정의된 메서드로 실행된다.
  • 다형성을 구현하고 코드의 유연성을 높인다.

6. 상속의 단점은?

  • 결합도가 높아짐 :  부모 클래스의 변경이 자식 클래스에 영향을 미칠 수 있기 때문에 유지보수를 어렵게 만든다.
  • 불필요한 기능 상속 : '동물'이라는 부모 클래스에 '날다'라는 메서드가 있다면 '호랑이'라는 자식 클래스에는 불필요한 메서드가 상속된다.
  • 부모 클래스의 결함이 그대로 넘어옴
  • 부모 클래스와 자식 클래스의 동시 수정 문제  : OCP 법칙 위반(확장에는 열려 있고 수정에는 닫혀있다)
  • 메서드 오버라이딩의 오동작
  • 불필요한 인터페이스 상속 문제
  • 클래스 폭발 : 상속을 남용하게 되면 새롭게 만든 클래스에 하나의 기존 기능을 연결하기 위해 상속을 하게 되고, 이러한 과정이 반복되면 필요 이상으로 수많은 클래스를 추가해야 한다.
  • 단일 상속의 한계 : 상속이 필요한 클래스가 이미 다른 클래스를 상속하고 있다면 또 클래스를 나누어서 상속을 해야 하는데 이렇게 하면 결국 클래스 폭발 문제로 이어진다.
  • https://brightstarit.tistory.com/43 참고

7. instanceof는 왜 성능이 안좋은가?

  • instanceof를 사용하면 알맞은 타입을 찾을 때까지 컴파일 시에 모든 타입을 돌며 검사해야한다.
  • 대신에 is타입명() 과 같은 메서드의 다형성을 적용해야 성능이 더 좋다.

8. 언제 interface 사용하고, 언제 abstract class 사용 하는가?

  • 인터페이스 : 상속 관계를 타고 올라갔을 때 다른 부모 클래스를 상속하는데 같은 기능이 필요할 경우
  • 추상 클래스 : 상속 관계를 타고 올라갔을 때 같은 부모 클래스를 상속하는데 같은 기능도 필요할 경우
  • 상속을 받아 기능을 확장하고자 할 때는 추상클래스를 사용하고 동일한 기능을 구현하는 클래스 간의 메서드나 변수의 이름을 통일하고자 할 때는 인터페이스를 사용한다.

9. final 키워드에 대해 설명

  • final 키워드는 한 번 초기화되면 변경할 수 없음을 나타낸다.
  • final 변수 
    • 한 번 할당되면 값을 변경할 수 없다. 즉, 변수가 초기화된 후 다른 값으로 재할당할 수 없다.
    • 선언 시 초기화를 해야 한다. 초기화를 하지 않고 선언만 하면 컴파일 오류가 발생한다.
    • 보통 상수를 표현할 때 사용된다.
  • final 메서드
    • 하위 클래스에서 오버라이딩할 수 없다. 즉, final 메서드는 하위 클래스에서 변경할 수 없다.
    • 보안, 성능 최적화, 메서드의 의도된 동작 보호 등을 위해 사용됩니다.
  • final 클래스 
    • 상속할 수 없는 클래스이다. 즉, final 클래스는 하위 클래스를 가질 수 없다.
    • 보안, 불변 클래스(immutable class) 설계, 효율성 등을 위해 사용된다.
  • final 키워드를 사용하면 코드의 안정성을 높일 수 있다. final 변수는 값이 변경되지 않음을 보장하고, final 메서드와 final 클래스는 의도된 대로 동작하도록 보호할 수 있다. 따라서 코드의 의도를 명확히 전달하고 오류를 방지하기 위해 final 키워드를 적절히 활용하는 것이 좋다.

10. exception vs error

  • exception(프로그램 안) 
    • 프로그램의 실행 도중 발생할 수 있는 예외적인 상황을 나타낸다. 이러한 예외적인 상황은 일반적으로 프로그램의 사용자 또는 외부 환경의 영향을 받아 발생한다.
    • 주로 프로그램 코드 내에서 예상할 수 있는 오류나 예외적인 상황을 처리하기 위해 사용된다. 예를 들어, 파일을 찾을 수 없는 경우나 배열 범위를 벗어나는 경우 등이 있다.
    • checked exception은 반드시 처리되어야 하는 예외이며, 컴파일 시에 확인된다. unchecked(runtime) exception은 명시적으로 처리하지 않아도 되는 예외로, 실행 시에 확인된다.
    • 스레드에만 영향을 준다.
    • checked  exception
    • unchecked(runtime) exception : 예외를 미리 감지하디 못했을 때 발생. 컴파일시에 체크를 하지 않는다.
  • error(프로그램 밖)
    • 일반적으로 프로그램이 복구할 수 없는 심각한 상황을 나타낸다. 이러한 상황은 주로 시스템 레벨에서 발생하며, 프로그램 자체의 문제보다는 주로 시스템 리소스 부족, 가상 머신의 오동작, 하드웨어 장애 등과 관련이 있다.
    • 프로그램이 직접 처리할 수 없으며, 대부분의 경우 프로그램이 종료되거나 예외처리 기능을 사용하여 처리할 수 없다. Error는 주로 시스템 관리자나 개발자에게 알려주는 역할을 한다.
    • 예를 들어, OutOfMemoryError는 메모리 부족으로 인해 발생하는 오류이며, StackOverflowError는 스택 오버플로우로 인해 발생하는 오류이다.
    • 프로세스에 영향을 준다.
  • exception은 프로그램의 예외적인 상황을 처리하는 데 사용되며, 프로그램이 복구할 수 있는 상황을 나타내는 반면, error는 프로그램이 처리할 수 없는 심각한 상황을 나타내며, 주로 시스템 레벨의 문제와 관련이 있다.

11. String vs StringBuilder vs StringBuffer

  • String 
    • 불변(immutable)한 클래스이다. 즉, 한 번 생성된 문자열은 변경할 수 없다.
    • 문자열이 변경되면 새로운 문자열 객체가 생성되며, 기존 문자열은 가비지 컬렉션의 대상이 된다.
  • StringBuilder 
    • 가변적인(mutable)인 문자열을 다루는 데 사용된다. 즉, 문자열을 변경할 수 있다.
    • 내부적으로 가변적인 크기의 문자열을 저장하기 위한 버퍼를 사용하며, 이 버퍼는 동기화(synchronization)를 지원하지 않기 때문에 단일 스레드 환경에서 안전하게 사용할 수 있다.
  • StringBuffer
    • 가변적인 문자열을 다루는 데 사용된다. 그러나 StringBuilder와 달리 StringBuffer는 스레드 안전(thread-safe)한 클래스이다.
    • 멀티 스레드 환경에서 안전하게 사용할 수 있습니다. 여러 스레드가 동시에 StringBuffer 객체를 수정해도 상호간섭없이 안전하게 작동한다.
  • 멀티 스레드 환경에서는 StringBuffer를 사용해야 하지만 대부분의 경우 단일 스레드 환경에서 문자열 조작이 이루어지기 때문에 StringBuilder를 주로 사용한다.  StringBuffer는 동기화를 적용하기 때문에 오버헤드가 발생할 수 있다.

12. C1 컴파일러와 C2 컴파일러의 차이

  • C1 컴파일러 : 빠른 컴파일 시간과 작은 코드 풋프린트를 갖는 환경에서 사용된다. 1~3레벨, 낮은 수준의 최적화
  • C2 컴파일러 : 더 높은 수준의 최적화를 수행하여 더 높은 성능을 제공하는 대규모 서버 및 데스크톱 애플리케이션과 같은 환경에서 사용된다. 4레벨

13. 스프링 부트 + JSP 프로젝트에서 .jar로 빌드하는 방법은 없는가?

  • 스프링 부트 + JSP 프로젝트를 jar로 빌드하면 WEB-INF를 생성하지 못하기 때문에 jsp 파일을 가져올 수 없다.
  • 추가적으로 필요한 resource들을 담아주는 역할도 하는 META-INF를 사용하면 해결가능하다. resource에 jsp를 넣어주는 방법이다. 다음과 같이 WEB-INF를 복사해주고 원래 WEB-INF를 지워준다. 그리고 sub application을 dependency로 활용할 수 있도록 변경을 해줘야 한다.(https://oingdaddy.tistory.com/426 참고)

 

 

 

## 프로젝트

다음 3가지 주제 중 원하는 것 하나 정해서 "카카오 오븐으로 프로토 타이핑", "유저 시나리오 (글 + 그림으로 표현하면 좋음" 작성하기 (유저 시나리오까지 시간 어려우면 프로토 타이핑까지라도)
  • 필라테스, 헬스장 수업 예약
  • 서브웨이, 버거킹 등 음식점 미리 주문하기
  • 여행을 주제로 한 SNS인데, 같은 여행지에 있는 사람 찾기

'공부 > f-lab' 카테고리의 다른 글

f-lab 6주차  (0) 2024.04.24
f-lab 5주차  (0) 2024.04.16
f-lab 3주차  (0) 2024.04.02
f-lab 2주차  (0) 2024.03.26
f-lab 1주차  (0) 2024.03.19

1. 객체 지향 언어가 상태를 가져서 좋은 점은? (절차 지향과 비교)

  • 상태를 알면 행동의 결과를 쉽게 예측할 수 있다. 
  • 상태를 노출시키지 않고 행동으로 캡슐화하기 때문에 객체의 자율성을 높인다.
  • 상태를 이용하면 과거의 모든 이력을 설명하지 않고도 행동의 결과를 쉽게 예측하고 설명할 수 있음
  • 절차 지향에서는 데이터와 함수가 분리되어 있기 때문에 각각의 함수가 어떤 상태에 영향을 미치는지 추론하기 어렵다.

 

2. JVM에서 Warming Up이란?

  • 프로그램 실행 초기에는 캐시(코드 캐시)에 저장되는 기계어들이 없기 때문에 지연이 발생할 수 있다. 이것을 해결하기 위해 warm up이 필요하다.
  • warm up은 의도적으로 미리 자주 사용되는 로직을 실행시켜 기계어가 캐시에 저장되고 최적화될 수 있도록 하는 것이다. 
  • warm up의 방법에는 여러가지가 있는데, 스프링에서는 주로 ApplicationRunner를 이용해 스프링 애플리케이션이 기동될 때 특정 코드(자주 실행되는)를 실행할 수 있도록 한다. 
  • https://hudi.blog/jvm-warm-up/ 참고
  • https://www.youtube.com/watch?v=CQi3SS2YspY 참고

 

3. 스프링 부트에서 war를 사용할 때 그 이유는?

  • JSP를 사용하여 화면을 구성할 때 - 현재 회사에서 스프링부트에 war 파일을 쓰는 이유
  • 외장 WAS를 사용할 때

 

4. 데드락 해결 방법(예방, 회피 등)

  • 데드락 발생 조건 
    • 상호 배제 : 프로세스끼리 자원을 공유하지 않을 경우. 동시에 프로세스 하나만 해당 자원을 사용할 수 있다.
    • 점유 대기 : 자원을 최소한 하나 보유하고, 다른 프로세스에 할당된 자원을 점유하기 위해 대기하는 프로세스가 존재한다.
    • 비선점 : 이미 할당된 자원을 강제로 뺏을 수 없다. 자원을 반환할 때까지 기다려야 한다.
    • 순환 대기 : 프로세스들이 순환하는 형태로 서로의 자원을 기다린다.
  • 예방 : 데드락 발생 조건 4가지 중 1개가 충족되지 않도록 시스템 디자인
    • 상호 배제 :  프로세스끼리 자원을 공유하도록 설정. 하지만 이 방법은 거의 불가능하다. 프린터, CPU는 모두 동시에 사용할 수 없다.
    • 점유 대기 : 프로세스 실행에 필요한 모든 자원을 한꺼번에 요구하고 허용할 때까지 작업을 보류한다.
    • 비선점 : 추가적으로 자원을 기다려야 하면 다른 프로세스가 자원을 가져갈 수 있도록 한다. 
    • 순환 대기 : 모든 자원에 순서 체계를 부여해서 오름차순으로 자원을 요청. 자원을 한 쪽 방향으로만 요구하도록 한다.
  • 회피 : 실행 환경에서 현재 사용 가능한 자원, 이미 사용중인 자원 등의 정보를 활용해 데드락이 발생할 것 같은 상황을 미리 예측해서 자원을 할당하지 않거나 이미 할당된 자원을 해제함으로써 데드락을 회피한다. Banker Algorithm(은행원 알고리즘)을 사용하는데 자원 요청을 허락했을 때 데드락 발생 가능성이 있으면 자원을 할당해도 안전할 때까지 계속 요청을 거절하는 알고리즘이다.
  • 탐지와 복구 : 데드락을 허용하고 데드락이 발생하면 복구하는 과정. 복구 작업은 데드락을 일으킴 프로세스 중 하나 혹은 여러 개를 중단시키거나, 일시적으로 자원을 선점하는 것을 허용한다.

 

5. 하드디스크 vs SSD (동작 원리 중심으로)

  • 하드디스크 : 기계적인 부품을 사용하여 데이터를 저장한다. 데이터를 읽고 쓰는 데 시간이 더 오래 걸린다.
  • SSD : 반도체 메모리와 전기적인 신호를 이용해 데이터를 저장한다. 시간이 더 짧게 걸린다.

 

6. JVM에서 클래스를 로드하는 타이밍은? / 클래스로더 기초 학습

  • 클래스 로딩 시점 : 클래스의 인스턴스 생성, 클래스의 정적 변수 사용(final 키워드 X), 클래스의 정적 메서드 호출
  • 클래스로더는 런타임 중에 JVM의 메서드 영역에 동적으로 클래스를 로드하는 역할을 한다.
  • 클래스 로드의 단계
    • 로드 : 자바 바이트 코드를 메서드 영역에 저장한다. 로드된 클래스와 부모 클래스의 정보, 클래스와 Interface, Enum의 관련 여부, 변수나 메서드의 정보를 저장한다.
    • 링크 
      • 검증 : 읽어 들인 클래스가 자바 언어 명세 및 JVM 명세에 명시된 대로 잘 구성되어 있는지 검사한다.
      • 준비 : 클래스가 필요로 하는 메모리를 할당하고, 클래스에서 정의된 필드, 메소드, 인터페이스를 나타내는 데이터 구조를 준비한다.
      • 분석 : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
    • 초기화 : 클래스 변수들을 적절한 값으로 초기화 한다. 즉, static 필드들이 설정된 값으로 초기화한다.
  • 클래스 로더의 종류
    • 부트스트랩 클래스 로더 : JVM 시작 시 가장 최초로 실행되는 클래스 로더이다. 부트스트랩 클래스 로더는 자바 클래스를 로드하는 것이 아닌, 자바 클래스를 로드할 수 있는 자바 자체의 클래스 로더와 최소한의 자바 클래스(java.lang.Object, Class, ClassLoader)만을 로드한다.
    • 확장 클래스 로더 : 확장 클래스 로더는 부트스트랩 클래스 로더를 부모로 갖는 클래스 로더로서, 확장 자바 클래스들을 로드한다. java.ext.dirs 환경 변수에 설정된 디렉토리의 클래스 파일을 로드하고, 이 값이 설정되어 있지 않은 경우 ${JAVA_HOME}/jre/lib/ext 에 있는 클래스 파일을 로드한다.
    • 시스템 클래스 로더 : 자바 프로그램 실행 시 지정한 Classpath에 있는 클래스 파일 혹은 jar에 속한 클래스들을 로드한다. 쉽게 말하자면, 우리가 만든 .class 확장자 파일을 로드한다.
  • 클래스 로더의 동작 방식
    • 클래스가 호출되면 메서드 영역에 해당 클래스가 로드되어 있는지 확인한다. 있다면 해당 클래스를 사용한다.
    • 정보가 없으면 시스템 클래스 로더에게 클래스 로드를 요청한다.
    • 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임한다.
    • 확장 클래스 로더는 부트스트랩 로더에 요청을 위임한다.
    • 부트스트랩 클래스 로더는 classpath에 해당 클래스가 있는지 확인하고 없다면 확장 클래스 로더에 요청을 넘긴다. 
    • 확장 클래스 로더는 classpath에 해당 클래스가 있는지 확인하고 없다면 시스템 클래스 로더에 요청을 넘긴다. 
    • 시스템 클래스 로더는 classpath에 해당 클래스가 있는지 확인하고 없다면 ClassNotFoundException을 발생시킨다.

 

7. Pass by value vs Pass by Reference

  • 자바는 모든 데이터를 Pass By Value로 전달한다.
  • 객체가 전달되는 경우 복사 후 전달되는 값은 실제 메모리를 가리키는 참조값인 포인터라는 것이다.

 

8. 상속은 주로 언제 쓸까요?

  • 코드 재사용
  • 일반적인 클래스가 이미 구현이 되어 있는 상태에서 그보다 좀 더 구체적인 클래스를 구현하기 위해 사용

 

9. 상속의 단점은?

  • 상속을 제대로 활용하기 위해서는 부모 클래스의 내부 구현에 대해 상세하게 알아야 하기 때문에 자식 클래스와 부모 클래스 사이의 결합도가 높아질 수밖에 없다.
  • 상속 관계는 컴파일 시점에 결정되고 고정되기 때문에 코드를 실행하는 도중에 변경할 수 없다.
  • 따라서 여러 기능을 조합해야 하는 설계에 상속을 이용하게 된다면 모든 조합별로 클래스를 하나하나 추가해야 하는데 이 때 클래스 폭발 문제가 일어난다.
  • 부모 클래스에 메서드를 추가했을 때, 자식 클래스에는 적합하지 않는 메서드가 상속될 수 있다.
  • 부모 클래스에 결함이 있으면 자식 클래스에도 그대로 상속된다.
  • 부모 클래스를 변경하면 자식 클래스도 함께 변경해야 한다.

 

10. 상속과 조합(합성)의 차이

  • 상속은 하나의 클래스를 확장해서 사용하는 것 , 조합은 필드로 클래스의 인스턴스를 참조하게 만드는 설계
  • 상속은 객체 간의 관계가 수직 관계이고 조합은 수평 관계가 된다.
  • 조합은 구현에 대한 의존성을 결합에 대한 의존성으로 변경하여 결합도를 낮춘다.
  • 코드 작성 시점에 결정한 상속 관계는 변경이 불가능하지만 합성 관계는 실행 시점에 동적으로 변경할 수 있다.

 

11. instanceOf 키워드를 사용할 때 문제점은?

    하나의 타입이 여러 인스턴스를 가질 수 있을 때 instanceOf를 사용한다. (상속 관계일 때)

    object instanceOf type : object가 type 을 상속받는 클래스라면 true를 리턴하고 아니라면 false 리턴 

 

  • 추상화 계층을 깨뜨린다(캡슐화가 깨진다) : 추상 클래스를 이용하여 상속을 하면 하나의 추상화 계층이 형성된다. 추상화 계층이 형성되면, 해당 추상화 계층을 사용하는 외부에서는 아래의 하위 문제를 알 필요가 없어진다. instanceof는 추상화 및 캡슐화를 지키지 못한다는 의미를 담고 있다. 상위 계층인 클래스가 하위 계층인 클래스를 직접적으로 알 필요도 없고 알아서는 안된다.
  • OCP(Open Closed Principle, 객체가 확장에는 열려있고 변화에는 닫혀 있어야 한다) 위반 : 새로운 객체가 추가될 때마다 instanceof로 체크하는 로직이 추가되어야 하는데 이렇게 되면 기존의 코드를 계속 변경해야하기 때문에 OCP를 위반하게 된다.
  • SRP(Single Responsibility Principle, 객체는 한 가지의 책임만 가져야 한다) 위반 : instanceof를 사용하지 않으면 상위 계층 클래스를 사용하여 하위 계층 클래스의 로직은 알 필요가 없지만 instanceof를 사용하면 히위 클래스가 책임을 가지게 된다.

 

  • 해결 방법 : 다형성을 사용해서 해결한다.
    • 상위 클래스에 추상 메서드 선언
    • 하위 클래스에 추상 메서드 오버라이딩하여 구현
    • 외부에서 상위 클래스의 추상 메서드를 사용하여 메세지 전달

 

12. 얕은 복사 vs 깊은 복사

  • 얕은 복사 주소값을 복사하는 것이고, 깊은 복사 실제 값을 새로운 메모리 공간에 복사하여 저장하는 것이다.
  • 얕은 복사의 경우는 주소값을 복사하기 때문에 참조하고 있는 값이 같다. 복사한 객체가 변경되면 기존의 객체도 변경된다.
CopyObject original = new CopyObject("JuHyun", 20);
CopyObject copy = original; //얕은 복사
  • 깊은 복사
    • cloneable 인터페이스 구현 
public class CopyObject implements Cloneable //인터페이스 구현


CopyObject original = new CopyObject("JuHyun", 20);
CopyObject copy = original.clone(); //깊은 복사
  • 복사 생성자, 복사 팩토리
/* 복사 생성자 */
public CopyObject(CopyObject original) {
    this.name = original.name;
    this.age = original.age;
}

/* 복사 팩터리 */
public static CopyObject copy(CopyObject original) {
    CopyObject copy = new CopyObject();
    copy.name = original.name;
    copy.age = original.age;
    return copy;
}


CopyObject original = new CopyObject("JuHyun", 20);
CopyObject copyConstructor = new CopyObject(original); //복사 생성자를 통한 깊은 복사
CopyObject copyFactory = CopyObject.copy(original); //복사 팩토리를 통한 깊은 복사

 

 

13. 인터페이스란?

  • 추상화된 형태의 계약으로, 해당 인터페이스를 구현하는 클래스가 가져야 할 메서드의 시그니처를 정의한다. 이러한 메서드는 구현되지 않고 단지 선언만 되어 있으며, 실제로는 해당 인터페이스를 구현하는 클래스에서 메서드를 구현해야 한다. 이를 통해 다형성을 구현하고 객체 간의 느슨한 결합을 가능하게 한다. 인터페이스는 코드 재사용을 높이고, 코드 유지보수를 용이하게 한다.
  • 다형성이라는 객체 지향의 특징을 구현하는 핵심
  • 객체의 내부 구현이 어떻든 깊이 알 필요없이 필요한 메서드만 호출하고 원하는 결과 값을 제대로 받게 해주는 간편한 상호작용 기능
  • 인터페이스의 역할
    • 프레임워크의 내부구성 학습 없이 지원해주는 메서드를 이용하여 간편하게 프로그램을 개발할 수 있게 해준다.
    • 일종의 '스펙'을 지정하게 하여 소프트웨어 확장을 유리하게 한다.
  • 추상화를 통해 관련 있는 메서드들의 집합을 정의한다.
  • 메서드의 명세만을 가지고 있고(시그니처만 선언하고) 메서드에 대한 구현부분은 없다.
  • 다중 상속이 가능하다. 한 클래스에서 여러 인터페이스를 구현할 수 있다.
  • 자바 API에서도 Comparable, Runnable, Serializable 등의 인터페이스를 구현하고 있다.
  • 위의 세가지 인터페이스는 마커 인터페이스. 아무 메서드도 선언하지 않은 인터페이스. 객체의 타입과 관련된 정보만을 제공한다. 
  • 인터페이스에서는 구현체 간의 일관된 동작을 보장하고 상태의 변경을 허용하지 않아야 해서 필드를 상수로만 선언할 수 있다.
  • 자바8 이후부터는 디폴트 메서드와 스태틱 메서드를 통해 구현 메서드를 정의할 수 있다.
  • 인터페이스 사용의 장점
    • 인터페이스 다형성 : 클래스가 여러 개의 인터페이스를 구현하게 되면 변수로 타입으로도 다양하게 쓸 수 있다는 말이다. 인터페이스 타입으로 변수를 선언하면 사용하는 입장에서는 뒤에 오는 모든 인터페이스만 구현한 객체이면 되기 때문에 시스템이 더 유연해진다. 적당한 인터페이스가 있다면 반환값, 변수, 필드, 매개변수를 인터페이스로 사용하면 좋다.
    • 형제 관계를 맺어줌 : 아무 관계도 없는 클래스들에게 공통적인 인터페이스를 구현함으로 관계를 맺어줄 수 있다.
    • 타입 접근 제한 
    • 메서드 접근 제한
  • https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC 참고

 

14. 인터페이스 vs 추상클래스   

    자바에서 인터페이스와 추상클래스는 객체 지향 프로그래밍의 다형성을 구현하는 요소이다. 공통적으로 인스턴스를 생 
    성할 수 없으며, 하나 이상의 추상 메서드를 포함한다.

 

    인터페이스는 모든 메서드가 기본적으로 추상 메서드이고 추상 클래스는 추상 메서드와 일반 메서드 모두를 포함한다.
    인터페이스는 구현할 기능의 '계약'을 정의하고, 추상 클래스는 '계승'을 통해 기능을 확장하거나 일부 구현을 제공한다.

 

  • 인터페이스 : 클래스와 별도로 구현 객체가 같은 기능을 한다는 것을 보장하기 위해 사용한다. / 추상클래스 : 클래스 간의 연관 관계를 구축하는 데 초점을 맞춘다.
  • 인터페이스의 장점
    • 다중 상속의 문제를 해결하고 클래스 간의 느슨한 결합을 가능하게 한다. 
    • 구현 클래스가 인터페이스의 메서드를 반드시 구현해야 하므로 일관된 API를 제공할 수 있다.
    • 한 클래스가 여러 인터페이스를 구현할 수 있으므로 다양한 기능을 조합하여 사용할 수 있다.
    • 메서드의 시그니처만을 정의하기 때문에 구현 클래스는 인터페이스가 요구하는 메서드를 자유롭게 구현할 수 있다. 
    • 시스템의 확장성과 유지보수성을 향상시키는 데 기여한다.
  • 추상클래스의 장점
    • 공통적인 일부 기능을 구현하고 나머지는 상속받는 클래스에서 구현하도록 강제하는 데 사용된다.
    • 코드의 재사용성을 높이고 일관된 구현을 보장한다.
    • 상속받는 클래스에 대한 공통의 템플릿을 제공하므로, 설계 단계에서는 클래스 계층구조를 명확히 할 수 있다.
    • 인스턴스 변수를 가질 수 있으므로 상속받는 클래스들이 이 변수들을 공유하거나 활용할 수 있어서 데이터 관리에 유용하다.
    • 상속을 통한 기능의 확장에 초점을 맞추므로 특정 기능을 계승하고자 할 때 유리하다. 이는 클래스 간의 결합을 형성하지만 효율적인 코드 재사용을 가능하게 한다.

 

15. 언제 인터페이스를 사용하고 언제 추상클래스를 사용하는지?

  • 인터페이스 : 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 기능을 구현 / 추상클래스 : 자신의 기능들을 하위 클래스로 확장
  • 추상클래스는 미리 논리적인 클래스 상속 구조를 만들어놓고 사용이 결정되는 느낌, 인터페이스는 그때 그때 필요에 따라 구현해서 자유롭게 붙였다 뗐다 하는 느낌
  • 추상클래스를 사용하는 경우
    • 상속 받을 클래스들이 공통으로 가지는 필드와 메서드들이 많아 중복 맴버를 통합할 경우
    • 멤버에 public 이외의 접근자들의 선언이 필요할 경우
    • non-static, non-final 필드 선언이 필요한 경우(각 인스턴스에서 상태 변경을 위한 메서드가 필요한 경우)
    • 요구사항과 함께 구현 세부 정보의 일부 기능만 지정했을 경우
    • 하위 클래스가 오버라이드하여 재정의하는 기능들을 공유하기 위한 상속 개념을 사용할 경우
    • 추상 클래스는 이를 상속할 각 객체들의 공통점을 찾아 추상화시켜 놓은 것으로, 상속 관계를 타고 올라갔을 때 같은 부모 클래스를 상속하며 부모 클래스가 가진 기능들을 구현해야 할 경우
  • 인터페이스를 사용하는 경우
    • 어플리케이션의 기능을 정의해야 하지만 그 구현 방식이나 대상에 대해 추상화 할 때
    • 서로 관련성이 없는 클래스들을 묶어주고 싶을 때 (형제 관계)
    • 다중 상속(구현)을 통한 추상화 설계를 해야할 때
    • 특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우
    • 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용

 

16. 프로젝트 주제 후보

  • 필라테스/헬스장 수업 예약 시스템
  • 음식점 주문 시스템(서브웨이, 버거킹 등)
  • 여행 SNS (여행 동행자 찾기, 여행지 공유 등의 기능)

'공부 > f-lab' 카테고리의 다른 글

f-lab 6주차  (0) 2024.04.24
f-lab 5주차  (0) 2024.04.16
f-lab 4주차  (0) 2024.04.09
f-lab 2주차  (0) 2024.03.26
f-lab 1주차  (0) 2024.03.19

1. 객체 지향 언어가 상태를 가져서 좋은 점은?

  • 상태 = 객체의 속성 = 해당 객체가 가지고 있는 데이터 → 객체의 특성을 정의하고 객체가 수행할 수 있는 작업을 결정
  • 상태가 중요한 이유
    • 데이터 보관 : 해당 객체가 가진 데이터를 보관한다.
    • 행동 지정 : 객체가 수행할 수 있는 작업을 결정하는데 중요한 역할을 한다.
    • 상호 작용 : 객체들 간에 서로의 상태를 변경하고 이를 통해 상호작용을 할 수 있다.
    • 시스템 상태 관리 : 시스템의 상태를 객체들의 상태의 집합으로 나타낼 수 있다.
    • 객체에 새로운 상태를 추가하거나 상태를 변경함으로써 기능을 확장할 수 있다.

2. JIT 컴파일러

  • 프로그램이 실행되는 동안 필요한 부분을 실시간으로 컴파일해서 기계어로 변환하는 동적 컴파일 방식
  • 장점
    • 실행 도중에 컴파일을 하기 때문에 실행 환경에 최적화된 기계어를 생성할 수 있다.
    • 실행 환경에 최적화된 기계어를 만들기 때문에 여러 플랫폼에서 실행될 수 있다.
    • 필요한 코드만을 실행시키기 때문에 메모리를 효율적으로 관리할 수 있다.

3. .class vs .jar vs .war

  • .class : 자바 소스 코드를 컴파일하여 생성한 바이트 코드 파일. JVM에서 실행된다. 
  • .jar
    • 자바 애플리케이션 또는 라이브러리 배포에 사용되는 파일.
    • 자바 클래스 파일, 리소스 파일, 메타데이터 파일들을 하나로 묶은 압축 파일.
    • 클래스 파일과 관련된 리소스들을 패키징하고 배포하는 데 사용된다.
  • .war 
    •  웹 애플리케이션을 패키징하고 배포하기 위한 파일.
    • 서블릿, JSP, HTML, 이미지, CSS 및 기타 웹 애플리케이션 구성 요소들을 포함할 수 있다.

4. 동시성 이슈

  • 멀티 스레딩 프로그램에서 발생할 수 있는 여러가지 문제
    • 경쟁 조건( Race Condition ) : 여러 스레드가 공유된 자원에 동시에 접근하려고 할 때 발생되는 문제
    • 데드락( Deadlock ) : 두 개 이상의 스레드가 서로가 소유한 자원을 대기하고 있어 상황을 벗어나지 못하는 상태
    • 스레드 안정성( Thread Safety ) : 여러 스레드가 동시에 접근해도 안전하게 사용될 수 있는 프로그램의 속성 
  • synchronized 키워드 사용
    • synchronized 키워드를 메서드나 블록에 선언해서 임계 영역으로 설정한다. 
    • 임계 영역인 코드는 스레드가 하나만 진입할 수 있고 진입 시점에 락(lock)을 획득하고 실행이 끝나면 락을 해제한다.
    • 락이 획득된 임계 영역에 접근하려는 스레드는 대기열에 있게 되고 락이 해제된 뒤 락을 획득하고 접근할 수 있다.
  • synchronized vs ReentrantLock
    • 둘 다 임계 영역에 재진입할 수 있지만 ReentrantLock에서는 명시적으로 생성되어야 한다.
    • synchronized는 공정한 락만 제공하지만 ReentrantLock은 비공정한 락도 제공한다.
    • ReentrantLock은 락의 범위를 더 유연하게 세밀하게 설정할 수 있다.

5. 클래스 변수는 GC의 대상이 되는가? 어떤 메모리에 저장되는가? GC의 대상이 되는 변수는?

  • 클래스 변수는 메서드 영역에 저장된다. 
  • GC의 대상은 주로 힙 영역이지만 메서드 영역이나 스택 영역도 대상이 될 수 있다.
  • 클래스/인스턴스/지역/매개 변수 모두 GC의 대상이 될 수 있다.
  • 어떤 영역에 있든 객체가 참조되어 있지 않다면 GC의 대상이 된다.
  • static final 변수는 GC의 대상이 되지 않는다. 

6. 메모리가 디스크보다 데이터에 대한 접근 속도가 빠른 이유는?

  • 메모리와 CPU는 동일한 버스를 사용하기 때문에 데이터의 전송 속도가 더 빠르고 디스크는 디스크 컨트롤러를 통해 이루어지기 때문에 더 느리다.
  • 메모리는 캐시 메모리와 함께 동작하기 때문에 더 빠르고 디스크도 캐시가 있긴 하지만 사용률이 크지 않기 때문에 더 느리다.
  • 메모리는 전기적 신호에 의해 데이터에 빨리 접근하지만 디스크는 회전하는 디스크나 플래시 기반 메모리를 사용하여 데이터에 접근하기 때문에 더 느리다. 

7. String 상수 풀 저장 위치(java7 vs java8)

  • Permanent Generation 메모리 영역 → Metaspace 영역
  • permgen 은 자바 힙 영역에 있었고 Metaspace 는 네이티브 메모리 영역에 있다. 
  • permgen은 메모리가 제한된 크기를 가지고 있고 Metaspace 동적으로 크기를 조절할 수 있다.

 

8. ArrayList 동작 방식

  • 끝에 요소를 추가하는 경우 :  arraylist의 상태를 확인하고 현재 배열의 크기의 1.5배의 새로운 배열을 생성한다. 새로 생성한 배열에 원래 배열의 값을 인덱스도 그대로 복사한다. 새로운 요소를 배열의 마지막 인덱스에 저장한다. 원래 배열은 사용되지 않는 메모리로 해제된다.
  • 중간에 요소를 추가하는 경우 : arraylist의 상태를 확인하고 현재 배열의 크기의 1.5배의 새로운 배열을 생성한다. 새로 생성한 배열에 원래 배열의 값을 인덱스도 그대로 복사한다. 새로운 요소를 추가할 인덱스부터 기존의 값들을 뒤로 하나씩 미룬다. 해당 인덱스에 값을 저장한다.  원래 배열은 사용되지 않는 메모리로 해제된다.
  • 삭제할 경우 : 삭제할 요소의 인덱스 이후의 값들을 앞으로 하나씩 이동하고 해당 요소를 제거한 뒤 배열의 크기를 1 감소시킨다.

9. Static Block이란? 언제 사용하는지? 단점은?

  • Static Block
    • 클래스가 로드될 때 실행되는 블록. 클래스가 처음으로 로드될 때 한 번만 실행된다.
    • 클래스 내에 선언되어야 하고 메서드 내에서는 선언될 수 없다.
    • 여러 개 선언될 수 있으며 선언된 순서대로 호출된다.
    • static 블록 안에서는 static한 것만 호출할 수 있다.
  • 정적 변수나 정적 메서드를 초기화하는 것처럼 클래스를 초기화할 때 꼭 수행되어야 하는 작업이 있을 경우 사용될 수 있다.
  • 단점 : 블록 안에서 수행되는 것이 많을수록 초기에 클래스 로드하는데 시간이 지연될 수 있고, 블록이 많이 선언되어 있거나 블록 안의 변수나 객체가 많을 경우 메모리를 많이 쓰게 된다.

10. Pass by value와 Pass by reference의 차이는?

  • 매개 변수가 함수에 전달될 때 값이 전달되는 방식
  • Pass by value(값에 의한 전달) 
    • 함수에 전달되는 매개변수의 값이 복사되어 전달된다.
    • 함수 내에서 값이 변경되어도 호출자에 영향을 주지 않는다.
    • 원래 변수의 값이 변경되지 않는다.
    • 기본형 변수에 대해 적용된다.
  • Pass by reference(참조에 의한 전달) : 
    • 함수에 전달되는 매개변수의 참조가 전달된다.
    • 함수 내에서 매개변수를 통해 원래 변수를 변경할 수 있고 호출자에게 영향을 준다.
    • 객체나 배열 등 참조 타입에 적용된다.

11. Java는 포인터 없는 언어라고 했는데 왜 NullPointerException이 발생하는 걸까요?

  • 포인터의 개념은 메모리상에서 주소를 참조하는 변수를 뜻한다.
  • 자바에서는 직접적으로 포인터라는 개념을 사용하지는 않지만 참조형 변수가 포인터와 유사한 역할을 한다.
  • 참조형 변수가 null을 가리키는 상태에서 객체의 멤버나 메서드를 참조하려고 할 때 NullPointerException이 발생한다. 

12. 그 밖의 포인터 관련 개념들

13. JVM의 구조와 작동 원리에 대해 더 깊이 공부하기

 

 

※ 용어사전 & 참고사항

  • 자바 애플리케이션과 웹 애플리케이션 : 자바 애플리케이션은 로컬 환경에서 실행(자바 기반의 데스크톱 애플리케이션이나 콘솔 응용 프로그램)되며, 사용자와 직접 상호작용하거나, 특정 작업을 수행하는 프로그램을 의미하며, 웹 애플리케이션은 웹 브라우저를 통해 실행되며, 네트워크를 통해 사용자에게 제공되는 서비스를 의미한다.
  • 임계 영역 : 여러 스레드가 동시에 접근하면 안되는 코드 영역
  • 메타데이터 : 데이터에 대한 데이터. 데이터를 설명하거나 분류하기 위한 정보 
  • 메타스페이스(Metaspace) : 자바의 클래스로더가 로드한 클래스들의 메타데이터가 저장되는 공간

 

'공부 > f-lab' 카테고리의 다른 글

f-lab 6주차  (0) 2024.04.24
f-lab 5주차  (0) 2024.04.16
f-lab 4주차  (0) 2024.04.09
f-lab 3주차  (0) 2024.04.02
f-lab 1주차  (0) 2024.03.19
  • 1. Java 언어를 사용하는 이유 / 장점 / 단점
    • 이유와 장점
    • - 자바는 한번의 개발로 여러 플랫폼에서 실행할 수 있다는 플랫폼 독립성을 가지고(WORA = Write One, Run
    •    Anywhere), JVM위에서 실행되기 때문에 운영 체제에 상관없이 동일한 코드가 동작한다.
    • - 자바는 객체 지향 프로그래밍의 장점을 제공함으로써 코드의 재사용성, 유지보수성, 확장성을 향상시킨다.
    • - JIT(Just-In-TIme) 컴파일러를 통해 런타임 성능이 향상되었다. 
    • - 다중 스레드 지원, 자동 메모리 관리 등의 기능이 대규모 시스템 개발에 적합한 환경을 제공한다.
    • - 표준 라이브러리와 오픈 소스 라이브러리가 풍부하다.
    • - 가상 머신을 통해 실행되기 때문에 악성 코드의 실행을 제한하도 다양한 보안 기능을 적용할 수 있다.
    •  
    • 단점
    • - 가비지 컬렉션 메커니즘과 가상 머신의 오버헤드 때문에 자바 프로그램은 메모리 사용량이 크다.
    • - 무거운 IDE(통합 개발 환경)을 사용해야 하기 때문에 초기 설정이나 메모리 사용양 측면에서 불편할 수 있다. 
  • 2. 객체지향 언어의 장점 / 단점
    • 장점
    • - 모듈화 : 모드를 객체로 나누어 모듈화할 수 있다. → 코드의 재사용성 증가, 유지보수 용이
    • - 상속 : 부모 클래스의 속성과 메서드를 자식 클래스가 상속받는 기능 → 코드 중복 방지, 코드 일관성 유지
    • - 다형성 : 하나의 인터페이스나 추상 클래스를 통해 여러 객체를 다룰 수 있는 기능 → 코드 유연성, 확장성
    • - 캡슐화 : 객체의 상태와 행위를 하나로 묶어 외부로부터 은닉하는 기능 → 코드의 안정성과 보안
    • - 재사용성 : 코드를 재사용하기 쉽도록 설계함 
    •  
    • 단점
    • - 적절한 객체와 클래스의 설계가 복잡할 수 있다.
    • - 각 객체의 상태를 저장하기 위한 메모리가 필요하기 때문에 프로그램의 메모리 사용량을 늘릴 수 있다.
    • - 상속을 오용하면 클래스 간의 결합도가 높아지고 유연성이 감소할 수 있다.
  • 3. 절자 지향 프로그래밍과 객체 지향 프로그래밍의 차이
    • 절차 지향 프로그래밍
    • - 프로그램을 순차적인 절차로 나누어 설계한다.
    • - 데이터와 관련된 함수들이 따로 존재하며 이러한 함수들이 데이터를 처리하며 데이터에 대한 직접적인 접근이 
    •   가능하다.
    • - 함수의 구조가 간단하여 작은 규모의 프로그램에서는 유지보수가 용이할 수 있지만, 큰 규모릐 프로그램에서는
    •   유지보수가 어려울 수 있다.
    •  
    • 객체 지향 프로그래밍
    • - 프로그램들을 객체들의 집합으로 구성하고 객체 간의 상호 작용을 통해 프로그램이 동작한다.
    • - 데이터와 해당 데이터를 조작하는 메서드가 하나의 단위인 객체로 묶여 있다.
    •  
    • ★ 절차 지향 프로그래밍은 프로그램을 명령어의 집합으로 구성하고, 데이터와 함수를 분리하여 작성하는데 초점
    •     을 맞춘다. 객체 지향 프로그래밍은 프로그램을 상호 작용하는 객체들의 집합으로 구성하며 데이터와 해당 데
    •     이터를 조작하는 함수를 객체로 묶어 설계한다.
  • 4. JVM 기초 (클래스 로더, 런타임 데이터 영역, 실행 엔진 등) -> 특히 런타임 데이터 영역 자세히
    • JVM이란?
    • 자바 프로그램이 실행되는 가상 머신. 자바 바이트 코드를 해석하고 실행하여 호스트 플랫폼(운영 체제 및 하드웨어)에 독립적으로 자바 프로그램을 실행할 수 있도록 한다.
    •  
    • - 바이트 코드 해석기 : 자바 컴파일러에 의해 변환된 바이트 코드를 해석하고 실행 
    • - 가비지 컬렉터 : 자동 메모리 관리를 위해 더 이상 사용되지 않는 객체를 자동으로 탐지하고 해제하여 메모리 누
    •   수를 방지한다.
    • - 메모리 관리 : 힙 영역과 스택 영역으로 구분된 메모리 공간을 관리한다. 힙은 객체와 배열이 저장되는 영역이고,
    •   스택은 메서드 호출과 관련된 지역 변수 및 실행 정보를 저장한다.
    • - 클래스 로더 : 동적으로 필요한 클래스 파일을 로드하고 연결한다. 
    • - 런타임 데이터 영역 : JVM이 자바 프로그램을 실행하는 동안 데이터를 저장하고 관리하는 메모리 영역
      • 1) 메서드 영역 : 클래스 및 메서드의 바이트 코드, 정적 변수, 메서드 정보 등을 저장한다. JVM이 시작될 때
      •     생성되며, 모든 스레드가 공유하는 공간이다.
      • 2) 힙 영역 : JVM이 시작될 때 미리 할당되며, 가비지 컬렉터에 의해 관리된다. 
      • 3) 스택 영역 : 각 스레드마다 개별적으로 할당된다. 스택 프레임은 각 메서드 호출 시마다 스택 영역에 생성
      •     되며, 메서드 실행이 완료되면 해당 프레임이 제거된다.
      • 4) PC 레지스터 : 현재 실행중인 스레드의 명령어 주소를 저장한다.
      • 5) 네이티브 메서드 스택 : 자바 코드가 네이티브 코드를 호출할 때 사용된다.
      •  
      • ※ JVM내에서 메서드 영역과 힙 영역은 하나, 스택 영역/PC 레지스터/네이티브 메서드 스택은 스레드의 개수만큼 생성된다. 
      •  
    • - 실행 엔진 : 바이트 코드를 기계어로 변환하고 실행하는 과정을 담당한다. 
    •  
  • 5. java의 .class 파일은 언제 기계어가 되는가?
    • - JVM의 인터프리터나 JIT 컴파일러에 의해 변환될 때 
  • 6. .class 파일 vs war 파일
    • - class 파일은 자바 프로그램의 클래스와 인터페이스를 나타내고 war 파일은 웹 애플리케이션의 자원과 파일들을 포함하여 배포할 수 있는 형식이다. class 파일은 자바 컴파일러에 의해 만들어지고 war 파일은 빌드로 만들어진다.
  • 7. 컴파일과 빌드의 차이
    • - 컴파일 : 소스 코드를 바이트 코드나 기계어로 변환하는 과정
    • - 빌드 : 소프트웨어 프로젝트를 실행 가능한 형태로 만드는 과정
  • 8. 멀티 스레딩 환경에서 static 변수를 여러 곳에서 고치려고 할 때 단점
    • - 경쟁 상태 : 두 개 이상의 스레드가 동시에 공유된 자원에 접근하려고 할 때 예상치 못한 결과가 발생한다. 
    • - 일관성 유지의 어려움 : 변수의 일관성을 유지하기 어렵다. 
    • - 데이터 손실 가능성 
    • - 성능 저하 : 동기화 메커니즘을 사용하여 여러 스레드 간의 경쟁 상태를 방지하려고 하면 성능 저하가 발생할 수
    •   있다.
  • 9. 싱글 스레딩 환경에서 static 변수를 여러 곳에서 고치려고 할 때 단점
    • - 단일 스레드 환경에서는 여러 스레드가 존재하지 않기 때문에 경쟁 상태가 일어나지 않는다. 변수를 여러 곳에
    •   서 고치더라도 다른 스레드가 변수에 접근하는 일은 없다.
  • 10. equals() vs hashCode() (특히 해시 코드가 무엇인지 학습)
    • - 두 메서드는 모두 객체의 동등성을 확인하는 메서드이다. (참고 : == 은 두 객체의 동일성 확인)
    • - equals() : 객체의 내부 상태를 비교하여 두 객체가 동등한지를 비교한다.
    • - hashCode() :  객체의 해시코드값을 반환한다. 해시코드란 데이터에 고정된 길이의 정수값을 주는 것이고 데이터를 빠르게 검색하고 비교하는 데 사용한다.
    • - 두 메서드를 함께 오버라이딩 해야 하는 이유는 equals()로 두 객체가 같다고 판단되면 두 객체는 같은 해시코드
    •   를 반환하는데 해시 기반의 자료 구조는 해시코드를 이용해 객체를 검색하기 때문에   equals()와 hashCode()가
    •   일관되지 않으면 같은 두 객체가 다른 객체로 인식될 수 있기 때문이다.
  • 11. 객체와 클래스, 인스턴스의 차이
    • - 클래스 : 객체를 생성하기 위한 , 객체의 특성(속성)과 메서드를 정의하는데 사용된다.
    • - 객체 : 클래스의 인스턴스, 클래스를 기반으로 실제로 메모리에 할당된 데이터를 가지고 있다.
    • - 인스턴스 : 클래스를 사용하여 생성된 특정한 객체
  • 12. 객체 지향 프로그래밍이란? (역할, 책임, 상태, 행동, 협력 키워드 이해하기)
    • - 역할 : 객체가 수행할 수 있는 특정한 기능이나 역할
    • - 책임 : 객체가 역할을 수행하기 위해 가져야 하는 의무나 기능
    • - 상태 : 객체가 가지고 있는 데이터의 상태
    • - 행동 : 객체가 수행할 수 있는 작업이나 동작
    • - 협력 : 객체 간의 상호 작용
  • 13. GC란 무엇이고, 어느 메모리 영역이 대상인가?
    • - 가비지 컬렉터란 프로그램에서 더 이상 사용되지 않는 객체를 자동으로 탐지하여 데이터를 해제하는 역할을 한다. 메모리 영역이 그 대상이고 객체가 더 이상 참조되지 않을 때 해제하여 메모리를 확보한다.  
  • 14. GC의 대상이 되는 변수는? (class, instance, argument, local 변수 중에)
    • - 클래스 변수 : 클래스 변수는 프로그램이 종료될 때까지 메모리에 유지되기 때문에 대상이 되지 않는다.(해당 클
    •   래스의 모든 인스턴스들이 공유하는 변수이기 때문에)
    • - 인스턴스 변수 : 클래스 내에 선언된 변수로, 객체가 생성될 때마다 각각의 인스턴스에 대해 별도의 메모리 공간
    •   이 할당된다. 객체가 더 이상 참조되지 않을 때 가비지 컬렉터의 대상이 된다.
    • - 매개 변수 : 메서드의 수행 도중에만 사용되는 값으로 메서드의 실행이 완료되면 메모리에서 해제된다.
    • - 지역 변수 : 메서드 내에 선언된 변수로, 메서드가 호출될 때 스택 프레임 내에 할당 되었다가 메서드가 실행을
    •   완료하고 스택 프레임이 제거되기 때문에 메모리에서 해제된다.
  • 15. 디스크와 메모리의 차이
    • - 디스크 : 느리고 저렴하지만 대용량 데이터를 영구적으로 보관할 수 있다. 데이터의 영구적인 저장과 검색에 사
    •   용된다.
    • - 메모리 : 빠르고 비싸며 휘발성이 있다. 프로그램 및 애플리케이션의 실행에 사용된다.
  • 16. String literal vs new String("")
    • - String literal : String Constant Pool에 같은 문자열이 있는지 확인하고 있으면 그 객체를 재사용한다. 
    • - new String("") : 문자열을 재사용하지 않고 새로운 문자열 객체를 생성한다.
  • 17. String Constant Pool이란?
    • - 문자열 상수 풀은 문자열 리터럴이 저장되는 공간. 문자열 리터럴을 생성하면 이곳에 저장된다. 
    • - 중복 문자열 제거 : 동일한 문자열 리터럴을 하나의 인스턴스로만 저장하고 재사용한다.
    • - 힙 영역과 다른 메모리에 저장된다.
    • - 가비지 컬렉터의 영향을 받지 않음 : 프로그램이 실행되는 동안 계속해서 유지된다.
    • - 해당 클래스가 로딩될 때 생성됙 프로그램이 실행되는 동안 유지된다.
  • 18. 동시성 이슈
    • - 여러 스레드가 동시에 공유된 자원에 접근할 때 생길 수 있는 문제

 

※ 용어사전 

  • 인터프리터 : 프로그래밍 언어의 소스 코드를 한 줄씩 읽고 해석하여 실행하는 프로그램(  컴파일러)
  • 자바 컴파일러 : 개발자에 의해 작성된 자바 코드를 JVM이 이해할 수 있는 바이트 코드로 변환하는 컴파일
  • JIT(Just-In-TIme) 컴파일러 : 인터프리터와 컴파일러의 중간 형태로, 프로그램을 실행하는 도중에 필요한 부분을 실시간으로 기계 코드로 컴파일하는 컴파일러
  • 가상 머신의 오버헤드 : 가상 머신 환경에서 추가적으로 발생하는 성능 손실
  • 객체 지향 프로그래밍 : 현실 세계의 개체를 모델링하고 그들 간의 상호 작용을 표현하는 프로그래밍 패러다임
  • 네이티브 코드 : 해당 플랫폼의 CPU가 이해하고 실행할 수 있는 기계어로 작성된 코드
  • 동일성 : 객체가 메모리 상에서 같은 인스턴스를 가리키는지를 비교하는 메서드
  • 동등성 : 객체가 가지고 있는 내용이 같은지를 비교

'공부 > f-lab' 카테고리의 다른 글

f-lab 6주차  (0) 2024.04.24
f-lab 5주차  (0) 2024.04.16
f-lab 4주차  (0) 2024.04.09
f-lab 3주차  (0) 2024.04.02
f-lab 2주차  (0) 2024.03.26

+ Recent posts