findById만 알고 있다가, getReferenceById도 알게 되어 차이에 대해 찾아보았다.
Optional<T> findById(ID id)T getReferenceById(ID id);(CrudRepository interface에서도 확인할 수 있다.)

이번에는 findById 코드를 살펴보자.
문서에서 확인한 것처럼, null이 아닐 경우 해당 값을 포함하는 Optional 객체를 반환하고, null일 경우 Optional.empty()를 반환한다.
@Override
public Optional<T> findById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
Class<T> domainType = getDomainClass();
if (metadata == null) {
return Optional.ofNullable(entityManager.find(domainType, id));
}
LockModeType type = metadata.getLockModeType();
Map<String, Object> hints = getHints();
return Optional.ofNullable(type == null ? entityManager.find(domainType, id, hints) : entityManager.find(domainType, id, type, hints));
}
Within a transaction, all the entities inside the persistence context have a direct representation in the database. This is a managed state. Thus, all the changes to the entity will be reflected in the database. Outside the transaction, the entity moved to a detached state, and changes won’t be reflected until the entity is moved back to the managed state.

(JpaRepository interface에서도 확인할 수 있다.)
EntityNotFoundException을 발생시킬 수 있다.
이번에는 getReferencedById 코드를 살펴보자.
문서에서 확인한 것과 마찬가지로 주어지는 식별자(id)값이 null이면 안된다.
문서와는 다르게 EntityNotFoundException이 없다. 반환하는 부분을 보면, entityManager.getReference 메서드에 의해 간접적으로 발생하는 것을 알 수 있다.
@Override
public T getReferenceById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
return entityManager.getReference(getDomainClass(), id);
}
Lazy-loaded entities behave slightly differently. Spring won’t load them until we explicitly use them in the persistence context:
Spring will allocate an empty proxy placeholder to fetch the entity from the database lazily. However, if we don’t do this, the entity will remain an empty proxy outside the transaction, and any call to it will result in a LazyInitializationException. However, if we do call or interact with the entity in the way it will require the internal information, the actual request to the database will be made:


아래 코드를 보자.
코드에서 user는 getReferencedById, study는 findById를 사용하였다.
User user = userRepository.getReferenceById(userId);
Study study = studyRepository.findById(studyId).orElseThrow(() -> new EntityNotFoundException("존재하지 않는 스터디입니다."));
String missionUrl = validateMissionUrl(study.getMission().getMissionType(), missionUrlRequestDTO.getMissionUrl());
StudyEnrollment studyEnrollment = studyEnrollmentRepository.findByUserAndStudy(user, study).orElseThrow(() -> new EntityNotFoundException("해당 스터디 참여 내역이 없습니다."));
studyEnrollment.updateMissionUrl(missionUrl);
참고
CrudRepository
JpaRepository
When to Use the getReferenceById() and findById() Methods in Spring Data JPA