인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

xk130님의 프로필 이미지
xk130

작성한 질문수

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

회원 웹 기능 - 등록

회원 가입 시 member

작성

·

356

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]
여기에 질문 내용을 남겨주세요.

    public Long join(Member member){
        validateDuplicateMember(member);
        System.out.println(member.getId());
        memberRepository.save(member);
        System.out.println(member.getId());
        return member.getId();
    }

위 코드는 멤버 가입 시 MemberService의 join 메소드 입니다.
member의 아이디가 부여되는 시점은 memberRepository.save(member);가 호출되어 저장이 되는 시점입니다.

위 코드에서 return member.getId();의 member는 컨트롤러에서 넘어온 member왜 같은 인스턴스라고 생각됩니다.

1. memberRepository.save(member);가 아닌

  1. member = memberRepository.save(member);


2번의 코드의 경우 id가 생긴 member를 다시 member에 저장하게 되어 member.getId()를 호출하면 아이디가 나오는 것이 맞다고 생각되는데 1번처럼 코드를 작성해도 member에 id가 왜 저장되어 있는지 궁금합니다.

답변 2

0

안녕하세요. xk130님, 공식 서포터즈 코즈위버입니다.

우선 변수의 원시타입과 참조타입의 차이에 대한 이해가 필요합니다. 자바에서 어떤 메서드를 호출하며 파라미터를 넘길 수 있는데, 이때 '값 복사'가 발생합니다. 값 복사는 말그대로 변수가 가지고 있는 값을, 메서드의 파라미터 인자에 복사하는 행위입니다.

아래와 같은 코드가 있을 때

int a = 10;

sum(a); #1

...

public void sum(int p) { #2

}

#1 에서 sum()을 호출하며 int a를 전달합니다. 그러면 #2의 p에 10의 값을 복사하게 되고, sum() 메서드 안에서 p를 이용할 수 있습니다. int 형 a는 원시타입 변수라고 합니다. 그러면 참조타입은 어떨까요.

 

Member m = new Member("codes");
sum(m); #1
...
public void sum(Member member); #2

위의 코드에서 #1에서 sum()메서드를 호출하며 m을 전달합니다. 그러면 #2에서 member 변수에 m이 가지고 있던 값을 복사하는 과정은 똑같으나, m이 참조타입 변수입니다. 그래서 주소값의 복사가 발생합니다. 주소값이라는 건 new Member("codes");로 생성한 객체가 메모리 어딘가에 저장되며 이 메모리에 접근하기 위한 주소를 말합니다.

이처럼 new 연산자를 이용해 인스턴스를 생성하고, 이 주소를 참조하는 변수를 참조타입이라고 합니다. 참조타입은 값 자체에 대한 복사 및 연산이 이뤄지는것이 아니라 주소값을 가지고 전달하므로, 메소드 내부에서 인스턴스 내부의 값을 수정하면 메소드 외부에서도 이 변경사항이 그대로 반영됩니다.

그래서 memberRepository.save(member); 내부에서 member의 아이디값을 할당하기 때문에 별도로 아이디를 다시 설정하지 않아도 됩니다.

감사합니다.

xk130님의 프로필 이미지
xk130
질문자

@Override
public Member save(Member member) {
    member.setId(++sequence);
    store.put(member.getId(), member);
    return member;
}

이해되었습니다. save 메소드에서 member.setId(++sequence)를 통해서 id를 부여하므로 아이디 값이 할당되는 원리였네요 감사합니다!

0

안녕하세요, 인프런 AI 인턴입니다.

xk130님의 질문에 답변드립니다.

제공된 정보 내에는 직접적인 MemberServicejoin 메소드에 대한 설명이 포함되어 있지 않아, 일반적인 JPA 동작 원리를 기반으로 설명드리겠습니다.

JPA를 사용할 때, save를 호출하게 되면 JPA가 해당 엔티티를 관리하게 됩니다. 이때, 해당 엔티티의 ID가 자동으로 생성되는 경우(예를 들어, ID가 자동 증가하는 경우), save 메소드 실행 후 엔티티 인스턴스의 ID 필드에 값이 할당됩니다. 따라서, 질문하신 1번 경우에도 memberRepository.save(member);를 호출한 후에는 memberid 필드에 실제 저장된 ID 값이 반영됩니다.

이는 JPA가 엔티티 매니저를 통해 엔티티의 생명주기를 관리하면서, 엔티티의 상태 변화를 추적하기 때문입니다. save 호출 시에 JPA는 해당 엔티티를 영속 상태로 만들고 데이터베이스에 저장합니다. 저장 과정에서 ID가 생성되면, 이 ID를 엔티티 인스턴스에도 반영하기 때문에 save 이후에 member.getId()를 호출해도 ID를 정상적으로 얻을 수 있습니다.

결론적으로, memberRepository.save(member); 호출 후에는 member의 ID가 데이터베이스에 저장되면서 동시에 member 인스턴스에도 반영되기 때문에 따로 member를 다시 할당하지 않아도 member.getId()를 통해 ID 값을 얻을 수 있습니다.

강의 내용과 정확하게 일치하지 않을 수 있으니, 강의 자료나 추가적인 자료를 참고하시는 것도 좋은 방법입니다.

xk130님의 프로필 이미지
xk130

작성한 질문수

질문하기