๐Ÿ“ŒSpring ์ˆ™๋ จ ๊ณผ์ œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

euphonyยท2025๋…„ 2์›” 13์ผ
0

๋‚ด์ผ๋ฐฐ์›€์บ ํ”„

๋ชฉ๋ก ๋ณด๊ธฐ
48/66

์ผ์ •์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ • ๊ด€๋ฆฌ ์•ฑ API๋ฅผ ๊ฐœ๋ฐœํ–ˆ๋‹ค. ๊ณผ์ œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…๊ณผ ๊ณ ๋ฏผํ–ˆ๋˜ ์ , ๋ฐฐ์šด ์  ๋“ฑ์„ ๊ธฐ๋กํ•˜๊ณ ์ž ํ•œ๋‹ค.

INSERT ๋์ง€๋งŒ ํ…Œ์ด๋ธ”์ด ์•ˆ๋ณด์ด๋Š” ๋ฌธ์ œ

๋Œ“๊ธ€ ์ž‘์„ฑ ์‹œ, ์•„๋ž˜์™€ ๊ฐ™์ด INSERT๋ฌธ์€ ์ œ๋Œ€๋กœ ์‹คํ–‰๋œ ๊ฒƒ ๊ฐ™์€๋ฐ DB์—์„œ๋Š” comment ํ…Œ์ด๋ธ”์ด ๋ณด์ด์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

@Transactional์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด ์›์ธ์ด๋‹ค. ํŠธ๋žœ์žญ์…˜์ด ์ž๋™์œผ๋กœ ์ปค๋ฐ‹๋˜์ง€ ์•Š์•„์„œ ๋ฐ์ดํ„ฐ๊ฐ€ DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜๋˜ ๊ฒƒ์ด๋‹ค. Service ๊ณ„์ธต์—์„œ DB ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ @Transactional ์„ ์‚ฌ์šฉํ•ด ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•ด์•ผํ•œ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด @Transactional ์„ ๋ถ™์ธ๋‹ค.

@Transactional
public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
    Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
    Member member = memberRepository.findByEmailOrElseThrow(email);

    Comment comment = new Comment(dto.getContents(), member, schedule);
    Comment savedComment = commentRepository.save(comment);

    return new CommentResponseDto(
        savedComment.getId(),
        savedComment.getContents(),
        member.getUsername(),
        savedComment.getCreatedAt(),
        savedComment.getModifiedAt()
    );
}

์ด๋ ‡๊ฒŒ ํ•ด๋„ ๋˜์ง€๋งŒ, ์–ด์ œ <์—ฐ๊ด€ ๊ด€๊ณ„ ๋งคํ•‘ ์„ธ์…˜>์—์„œ ํŠœํ„ฐ๋‹˜๊ป˜์„œ ํด๋ž˜์Šค ๋ ˆ๋ฒจ์— ์šฐ์„ @Transactional(readOnly = true)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ด ๊ธฐ์–ต๋‚˜ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๋‚œ๋ฒˆ ํ”ผ๋“œ๋ฐฑ์„ ๋‹ค์‹œ ๋ณด๋‹ˆ ๋‹ค๋ฅธ ํŠœํ„ฐ๋‹˜๊ป˜์„œ๋„ "ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„๋ฅผ ํ™•์‹คํžˆ ํ•˜๊ธฐ ์œ„ํ•ด DB ์—…๋ฐ์ดํŠธ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ์ž‘์—…์„ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค."๋ผ๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ๋‚จ๊ฒจ์ฃผ์…จ๋‹ค.

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CommentService {

    private final CommentRepository commentRepository;
    private final ScheduleRepository scheduleRepository;
    private final MemberRepository memberRepository;

    @Transactional
    public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
        Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
        Member member = memberRepository.findByEmailOrElseThrow(email);

        Comment comment = new Comment(dto.getContents(), member, schedule);
        Comment savedComment = commentRepository.save(comment);

        return new CommentResponseDto(
            savedComment.getId(),
            savedComment.getContents(),
            member.getUsername(),
            savedComment.getCreatedAt(),
            savedComment.getModifiedAt()
        );
    }
}

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ์ž˜ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•˜๋˜ ๋ถ€๋ถ„์˜ ๊ฐœ๋…์„ ํ™•์‹คํžˆ ์ตํžˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

  • ํด๋ž˜์Šค ๋ ˆ๋ฒจ์˜ @Transactional(readOnly = true) ์ ์šฉ
    • ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋Š” ์ฝ๊ธฐ ์ „์šฉ ํŠธ๋žœ์žญ์…˜ ์‚ฌ์šฉ
    • ๋ณ€๊ฒฝ ๊ฐ์ง€(Dirty Checking) ๋น„ํ™œ์„ฑํ™” โ†’ ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ๊ฐ์ง€ ๋กœ์ง ์ƒ๋žต โ†’ ์„ฑ๋Šฅ ์ตœ์ ํ™”
    • ์กฐํšŒ ์‹œ @Transactional์ด ์—†์–ด๋„ ๋™์ž‘ํ•˜์ง€๋งŒ, @Transactional(readOnly = true)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์ตœ์ ํ™” ๋˜๋ฉฐ Lazy Loading(์ง€์—ฐ ๋กœ๋”ฉ) ์‚ฌ์šฉ ์‹œ ํŠธ๋žœ์žญ์…˜ ์œ ์ง€๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Œ
  • ์“ฐ๊ธฐ ์ž‘์—…์—๋Š” @Transactional์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผ ํ•จ.
    • ๋ฉ”์„œ๋“œ ๋ ˆ๋ฒจ์—์„œ @Transactional์„ ๋ช…์‹œํ•˜๋ฉด, ํด๋ž˜์Šค ๋ ˆ๋ฒจ์˜ readOnly = true๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•œ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋™์ž‘

์„ธ์…˜ ํ‚ค ๊ฐ€์ ธ์˜ฌ ๋•Œ ClassCastException

๋Œ“๊ธ€ ์ƒ์„ฑ ์‹œ, ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ member์˜ ์„ธ์…˜ํ‚ค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ณผ์ •์—์„œ ClassCastException ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

HttpSession session = request.getSession(false);
Long memberId = (Long) session.getAttribute("sessionKey"); // ์˜ค๋ฅ˜ ๋ฐœ์ƒ 
CommentResponseDto commentResponseDto = commnetService.save(id, memberId, dto);

์„ธ์…˜ํ‚ค๋กœ Email์„ ์ €์žฅํ–ˆ๋Š”๋ฐ, String์„ Long์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.

HttpSession session = request.getSession(false);
String email = (String) session.getAttribute("sessionKey");
CommentResponseDto commentResponseDto = commnetService.save(id, email, dto);

Service์—์„œ๋„ id๋กœ ์ฐพ๋˜ member๋ฅผ email๋กœ ์ฐพ์•„ ๋ฐ˜ํ™˜ํ–ˆ๋‹ค.

// Member member = memberRepository.findByIdOrElseThrow(id); // ๊ธฐ์กด ์ฝ”๋“œ
Member member = memberRepository.findByEmailOrElseThrow(email);

Validation ์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉ ์‹คํŒจ

๋‹ค์Œ๊ณผ ๊ฐ™์ด Validation ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ์šฉํ•˜๊ณ  ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.

    @NotBlank(message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.")
    @Size(min = 8, max = 12, message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 8์ž ์ด์ƒ, 12์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
    @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*?&]+$", message = "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ์ ์–ด๋„ 1๊ฐœ ์ด์ƒ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
    @Setter
    @Column(nullable = false)
    private String password;

๋ฌธ์ž ๊ธธ์ด ์กฐ๊ฑด์€ ์ถฉ์กฑํ•˜๊ณ , ํŒจํ„ด ์กฐ๊ฑด์€ ์ถฉ์กฑํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ ํ–ˆ์„ ๋•Œ 1๊ฐœ์˜ ์˜ค๋ฅ˜๋ฅผ ์˜ˆ์ƒํ–ˆ์ง€๋งŒ 2๊ฐœ์˜ ์˜ค๋ฅ˜ ๋ชจ๋‘ ๋‚˜์™”๋‹ค. ์ˆœ์„œ๋„ ๋ฐ”๊ฟ”๋ณด๊ณ  ๋ช‡ ๋ฒˆ์ด๋‚˜ ์กฐ๊ฑด์„ ๋‹ค์‹œ ํ™•์ธํ–ˆ๋Š”๋ฐ ๊ณ„์† ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค.

ํŠœํ„ฐ๋‹˜๊ป˜ ์—ฌ์ญค๋ณด๋‹ˆ ์ƒ์„ฑ์ž์—์„œ ๋ฉ”์„ธ์ง€๋ฅผ ์ฐ์–ด๋ณด๋ผ๊ณ  ํ•˜์…”์„œ ์ฐ์–ด๋ณด๋‹ˆ ๋‚ด๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์ด ์•„๋‹Œ ์•”ํ˜ธํ™” ๋œ ๊ฐ’์ด ๋‚˜์™”๋‹ค. ์•Œ๊ณ ๋ณด๋‹ˆ ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์€ DTO ํด๋ž˜์Šค์— ์ ์šฉํ•ด์•ผํ•˜๋Š”๋ฐ Member ์—”ํ„ฐํ‹ฐ ํด๋ž˜์Šค์— ์ ์šฉํ•ด์„œ ์ƒ๊ธด ๋ฌธ์ œ์˜€๋‹ค.

๋ฌด์ž‘์ • ์ ์šฉํ•˜๋ ค๋‹ค ๋ณด๋‹ˆ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด ๊ฒƒ ๊ฐ™๋‹ค. DTO์— ์ ์šฉํ•˜๋‹ˆ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜์˜€๋‹ค.

@Setter ๋Œ€์‹  ๋ช…ํ™•ํ•œ ๋„๋ฉ”์ธ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•˜๊ธฐ

๊ฐ•์˜๋ฅผ ์ฐธ๊ณ ํ•ด ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ์™œ Setter๋ฅผ ์‚ฌ์šฉํ•˜์ง€์•Š๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตณ์ด updatePassword() ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ์ˆ˜์ •ํ•˜๋Š”์ง€ ๊ถ๊ธˆํ–ˆ๋‹ค.

public void updatePassword(String password) {
    this.password = password;
}

Member ์—”ํ‹ฐํ‹ฐ์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด @Setter๋ฅผ password ํ•„๋“œ ์œ„์— ์ถ”๊ฐ€ํ•˜๋ฉด ์•ˆ๋˜๋Š” ๊ฒƒ์ผ๊นŒ?

@Setter
@Column(nullable = false)
private String password;

์ฐพ์•„๋ณด๋‹ˆ Setter์˜ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜๋Š” ์ด์œ ๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ์—ˆ๋‹ค.

  • ๊ฐ’์„ ๋ณ€๊ฒฝํ•œ ์˜๋„๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ํž˜๋“ค๋‹ค.
    • ๋‹จ์ˆœํžˆ ์ด๋ฆ„์ด setter์ธ ๋ฉ”์„œ๋“œ๋“ค์ด ๋‚˜์—ด๋˜์–ด์žˆ๋‹ค๋ฉด ์–ด๋–ค ์˜๋„๋กœ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
  • ๊ฐ์ฒด์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
    • setter๋ฅผ ์ ์šฉํ•˜๋ฉด ์–ด๋””์„œ๋“  ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํ†ต์ œํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๋‹ค.

setPassword()๋งŒ์œผ๋กœ๋Š” ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฒ˜์Œ ์ €์žฅํ•˜๋Š” ์šฉ๋„์ธ์ง€, ๋ณ€๊ฒฝํ•˜๋Š” ์šฉ๋„์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค. ๋˜ํ•œ, ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ ์‹œ ๊ธฐ์กด ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ ๊ฐ™์€ ์ถ”๊ฐ€ ๋กœ์ง์ด ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ, updatePassword()์ฒ˜๋Ÿผ ์—ญํ• ์ด ๋ช…ํ™•ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋” ๋ฐ”๋žŒ์งํ•˜๋‹ค.

ํ”ผ๋“œ๋ฐฑ

โœ”๏ธ ์ž˜ํ•œ์ 

  • request์™€ response์—์„œ ์‚ฌ์šฉํ•˜๋Š” dto๋“ค์ด ์ž˜ ๋‚˜๋ˆ ์ ธ ์žˆ๋‹ค.
  • HTTP ์ƒํƒœ์ฝ”๋“œ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ–ˆ๋‹ค.
  • @Transactional(readOnly = true)๊ณผ @Transactional์ด ์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.
  • ์ฝ”๋“œ๊ฐ€ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ž˜ ์ž‘์„ฑ๋˜์–ด์žˆ๊ณ , ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋‚˜ ์„ธ์…˜์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ถ€๋ถ„์„ ์ž˜ ๊ตฌํ˜„ํ–ˆ๋‹ค.

โœ”๏ธ ์ƒ๊ฐํ•ด๋ณผ ์ 

  • ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ HttpStatus.OK๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ResponseEntity์— ๋‹ด์•„์„œ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋กœ๊ทธ์ธ ํ›„ ์ •๋ณด๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ๋” ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ”๏ธ ๊ถ๊ธˆํ•œ ์  & ์–ด๋ ค์› ๋˜ ์ 

  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์–ผ๋งˆ๋‚˜ ์„ธ์„ธํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ?
    • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋Š” ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ๊ณผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ๋งค์šฐ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋ก ์ข‹๋‹ค.
    • ์ ์ ˆํ•œ HTTP ์ƒํƒœ ์ฝ”๋“œ๋„ ๊ฐ™์ด ๋„ฃ์–ด์ฃผ์ž.
  • repository์—์„œ default ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹๊ณผ service์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹ ์ค‘ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹์€ ๋ฌด์—‡์ด๊ณ , default ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ repository์—์„œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•˜๋‹ค.
    • findByScheduleIdOrElseThrow()์™€ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ repository์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹๊ณผ service์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ฐฉ์‹์€ ๋‘˜ ๋‹ค ์œ ํšจํ•˜๋ฉฐ, ์„ ํƒ์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค.
    • ์„œ๋น„์Šค ๋ ˆ์ด์–ด๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ํ๋ฆ„๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์ด๋‹ค. ๋”ฐ๋ผ์„œ ์„œ๋น„์Šค ๋ ˆ์ด์–ด์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ์ผ๋ฐ˜์ ์ด๋‹ค.
    • Spring Data JPA์˜ findById()์™€ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ํ™œ์šฉํ•  ๋•Œ, Optional์„ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ๊ธฐ๋ณธ์ ์ธ throw ์ฒ˜๋ฆฌ๋งŒ ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์—๋Š” respository์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ํŠน์ • ์˜ˆ์™ธ๋ฅผ ์ž์ฃผ ๋˜์ง€๋Š” ๊ฒฝ์šฐ์—๋„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด