• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

이 코드가 여전히 이해가 안갑니다..

22.05.24 23:05 작성 조회수 431

7

안녕하세요. 

해당 싱글톤을 만드는 코드가 여전히 이해가 가지 않습니다. 앞전에 static 부분을 공부 하라는 조언에 따라서 관련된 지식을 습득하려고 노력했지만 궁금증을 해결하지 못했습니다.

 

제가 해당 코드를 보고 드는 궁금증은 두 가지입니다. 

1. 최초에 애플리케이션이 실행되고, MemberRepository 클래스를 읽습니다. 이 때, MemberRepository 클래스에 있는 static 변수들을 static 영역에 올리겠죠. 그렇다면 차례대로 store, sequence가 static 영역에 올라갑니다. 여기까지는 늘 이해가 갑니다.

하지만 private static final MemberRepository instance = new MemberRepository() 이 코드가 이해가 가지 않습니다. 이 코드가 실행되는 시점에 MemberRepository 클래스는 세번 째 줄을 실행하고 있는 중인데, 어떻게 MemberRepository 객체를 생성해 instance 변수에 넣어 static 영역에 올릴 수 있는지 이해가 가지 않습니다. 다시 말해, MemberRepository 클래스가 적어도 한 번 실행된 후, new MemberRepository()를 통해 온전한 객체 생성이 가능하다는 생각이 듭니다. 즉, 세 줄 밖에 실행되지 않은 시점에 new MemberRepository()를 호출하면 아래 생성자, 메소드들은 없는 불완전한 객체가 존재하는 것 아닌지, 그런 종류의 의문이 풀리지 않습니다.

 

2. 두 번째는 첫 번째 궁금증은 해결 됐다고 치고, 그림을 한번 그려봤습니다.

instance는 참조 값으로 new MemberRepository() 객체를 참조하고, 그 값을 static에 올립니다. 이 과정에서 new MemberRepository에 해당되는 200이라는 주소를 가진 객체의 내부를 그려봤습니다. 그림에는 변수 명만 표시했지만 제가 알기로는 

private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
private static final MemberRepository instance = new MemberRepository();
public static MemberRepository getInstance() {
return instance;
}
private MemberRepository() {
}
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}

이와 같이 멤버 변수, 생성자, 메소드 등이 그대로 들어가는 것으로 알고있습니다. (기타 메소드는 생략) 여기서 두 번째 의문이 생깁니다. instance 변수는 200이란 주소를 참조한 상태로 static 영역으로 올라가는데, 실제 200이라는 주소 안에 객체에는  

private static final MemberRepository instance = new MemberRepository();

이와 같은 코드가 존재하고 있습니다. 그렇다면 앞선 과정이 해당 코드가 실행될 때 반복 돼야 한다고 생각합니다. 같은 맥락에서 그 과정은 계속 이어져, 무한 반복돼야 할 것 같다는 생각이 들었습니다. 여기서 그냥 static이기에 한 번 올라간게 끝이다라고 하기에는 뒤가 너무 구리고, 찝찝합니다.

 

1, 2 번 질문 모두 최대한 제가 궁금해 하는 부분이 무엇인지 표현하려고 많이 노력했습니다. 하지만 아주 명확하게 질문 하기는 불가능해서 위와 같이 질문을 남기게 됐습니다. 제가 궁금해 하는 부분에 대해 명확한 해답을 얻고 싶습니다. 지금 강의에서 싱글톤 구현 코드를 접하는 것이 두 번째인가 세 번째인데, 계속 위와 같은 의문에 대한 답을 찾지 못하고 있습니다. 아마 잘못 아는 부분이 있거나 기초 지식이 없는 상태에서 이것저것 배우다 보니 혼동 하는게 있어서 그렇다고 느껴지는데, 그게 어떤 부분인지 잘 모르겠습니다. 도움 부탁드리겠습니다. 

감사합니다.

답변 3

·

답변을 작성해보세요.

1

안녕하세요. 유진이님

JVM은 로딩 시점에 해당 클래스의 메타 정보를 모두 읽어들입니다. 따라서 해당 클래스 안에서 인스턴스를 생성하는데 아무런 문제가 없습니다.

감사합니다.

유진이님의 프로필

유진이

질문자

2022.06.02

안녕하세요. 영한님 

오랜만에 뵙네요. 좋은 강의 잘 보고 있습니다. 감사합니다.

답변 해주신 내용 참고해서 한 번 찾아보겠습니다. 

0

jung님의 프로필

jung

2023.06.20

jvm 클래스 로더 찾아보세용

0

hayeong lim님의 프로필

hayeong lim

2022.05.29

안녕하세용 혹시 도움이 될까싶어서 저의 생각을 달아봅니다!

1번문제에서 3번째줄을 실행하고 있는데 밑에있는 다른 필드들을 사용할 수 있는 이유는 JAVA 파일을 실행하면 일단 JVM이 모든 클래스들을 읽어오기때문이 아닌가 싶습니다~ !!

2번 문제는 제가 질문을 제대로 이해한건지 모르겠지만 static의 컨셉에 관련된 문제인 거 같습니다. instance 변수가 첫번째로 호출됐을때 MemberRepository객체가 생성됩니다. 그리고 두번째로 호출됐을때는 static이기때문에 또 다른 MemberRepository객체가 생성되는 게 아닌 이미 생성된 객체를 불러오게됩니다. 

그리고 final이 붙은 이유는 instance 변수의 값을 아무나 바꿀 수 없게 만들기 위해서이죠! 그래서 모든 클래스에서 instance를 부르면 같은 memberRepository객체를 부르게 되기 때문에 코드가 무한 반복되지 않을 거 같습니다~!!  

좋은하루되세용

 

유진이님의 프로필

유진이

질문자

2022.06.02

안녕하세요. 친절한 답변 잘 읽어봤습니다. 늘 궁금했는데 답변 주셔서 고맙습니다.

답변 주신 내용 중에 이해가 잘 가지 않는 부분이 있어서 추가적인 질문좀 남기겠습니다. 저는 자바의 장점 중 하나가 실행 클래스를 필요할 때 읽어오는 것이라고 알고 있었는데,  "JAVA 파일을 실행하면 일단 JVM이 모든 클래스들을 읽어오기때문이 아닌가 싶습니다~ !!" 이 부분이 헷갈립니다.

 

말씀하신 부분이 두 가지 중 어떤 것인지 알고 싶습니다. 

1. 어플리케이션 서버를 가동시킬때, JVM이 작성된 모든 JAVA 클래스를 읽어온다.

2.  예를들어, 지금 실행되는 곳에서 하나의 클래스가 필요하다면, 해당 클래스 하나를 실행하기 전 JVM이  클래스의 모든 부분을 먼저 읽어온다.

이 두가지 중에 말씀하신 부분이 있을까요?

 

글 내용 2번에 대해 답변 해주신 내용은 머리로는 알겠는데, 실질적으로는 아직 와닿지가 않네요. 아무래도 이 부분은 건너뛰고 다른 지식들을 좀 더 채워봐야겠습니다. ㅠㅠ 

다시한번 친절한 답변 감사드려요..! 제가 질문한 의도에 맞는 답변이라 도움이 많이 됐습니다. 고맙습니다.