ERD 1:1 관계에서 FK를 PK로 설정할 때 – @MapsId의 활용

wjd15sheep·2025년 6월 19일
0

Spring Boot

목록 보기
14/19
post-thumbnail

Spring Data JPA를 사용하다 보면, 1:1 관계에서 외래 키(FK)를 기본 키(PK)로 사용하는 설계가 필요할 때가 있습니다.
예를 들어 프로젝트 K-FreeMarket에서 Question 엔티티가 존재하고, 그에 대한 Answer가 정확히 하나만 존재해야 하는 것입니다.

이번 글에서는 Answer의 기본 키를 Question의 외래 키로 사용하는 방식과,
이때 사용하는 핵심 어노테이션인 @MapsId의 개념 및 작동 방식, 그리고 MySQL ERD 상에서 나타나는 한계를 함께 정리합니다.


🔗 관계 설명

  • QuestionAnswer는 1:1 관계입니다.
  • Answer는 반드시 Question에 종속됩니다. 즉, Question이 존재해야 Answer를 저장할 수 있습니다.
  • Answer기본 키(PK)는 Question의 외래 키(FK)를 그대로 따릅니다.

이 구조를 구현하기 위한 핵심 키워드는 바로 @MapsId입니다.

💡 @MapsId란?

@MapsIdJPA에서 외래 키(FK)를 기본 키(PK)로 공유할 때 사용합니다.
쉽게 말해, 연관된 엔티티의 PK를 이 엔티티의 PK로 "덮어쓰도록 매핑"하는 역할을 합니다.

📌 엔티티 예시

//Question.java

   @OneToOne(mappedBy = "question", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private Answer answer;
    
    
// Answer.java

      @Id
    @Column(name = "question_id")
    private Long id;

    @OneToOne(fetch = FetchType.LAZY)
    @MapsId  // 핵심! 이걸 통해 question_id를 PK로도 사용
    @JoinColumn(name = "question_id")
    private Question question;
}

  • Answer의 id 필드는 실제 DB에서는 question_id 컬럼과 매핑됩니다.
  • @MapsId는 question.getId() 값을 자동으로 id 필드에 설정합니다.

🔄 작동 방식

  • @Id 필드는 question_id와 매핑되어 PK로 동작합니다.
  • @JoinColumn(name = "question_id")QuestionFK를 설정합니다.
  • @MapsId는 FK 필드인 question을 통해 자동으로 PK 값도 설정되도록 해줍니다.

즉, Answer의 id는 명시적으로 설정하지 않아도, question 필드를 통해 자동으로 세팅됩니다.

Question q = questionRepository.save(new Question(...));
Answer a = new Answer();
a.setQuestion(q);  // a.setId(q.getId())는 필요 없음
answerRepository.save(a);

📉 MySQL ERD 상의 오해

MySQL Workbench 등 ERD 도구에서는 AnswerQuestion의 관계가 1:N처럼 보이는 경우가 많습니다.
이는 ERD 도구가 단순히 외래 키 제약 조건만 보고 기본적으로 1:N 관계로 시각화하기 때문입니다.


그러나 실제 DB 스키마에는 다음과 같이 명시됩니다

CREATE TABLE `answer` (
  `question_id` bigint NOT NULL,
  `content` varchar(255) DEFAULT NULL,
  ...
  PRIMARY KEY (`question_id`),
  CONSTRAINT FOREIGN KEY (`question_id`) REFERENCES `question` (`question_id`)
)
  • question_idPK이자 FK입니다.
  • 따라서 동일한 question_id로는 Answer에 하나의 행만 삽입 가능하므로, 1:1 관계가 성립됩니다.

✅ 1:1 관계 검증 예시

-- 예: 같은 question_id에 두 개의 answer를 삽입해보자
INSERT INTO answer (question_id, content) VALUES (1, '첫 번째 답변');
INSERT INTO answer (question_id, content) VALUES (1, '두 번째 답변'); -

두 번째 쿼리는 PK 중복 오류로 인해 삽입되지 않으며, 이를 통해 1:1 관계가 유지되는 것을 확인할 수 있습니다.


✍️ 마무리

  • @MapsIdFKPK로 활용할 수 있게 해주는 JPA의 유용한 기능입니다.
  • DB ERD 도구가 보여주는 관계 시각은 참고용일 뿐이며, 실제 제약 조건이 중요합니다.
  • 1:1 관계에서 관계 주체가 명확하고, 종속성이 있을 경우 @MapsId 설계는 매우 유효합니다.

[참고]

profile
성장 위해 노력하는 웹 개발자 주니어

0개의 댓글