Skip to content

[Feat/#187] 아카이빙 관련 링크를 행사 연결로 전환 - #191

Open
sangrae2325 wants to merge 4 commits into
feat/#185-admin-archive-queriesfrom
feat/#187-archive-related-target
Open

sangrae2325 wants to merge 4 commits into
feat/#185-admin-archive-queriesfrom
feat/#187-archive-related-target

Conversation

@sangrae2325

@sangrae2325 sangrae2325 commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

#️⃣연관된 이슈

🎯 해결하려는 문제가 무엇인가요?

아카이빙에 붙는 관련 링크를 행사 참조로 바꿉니다. 관리자 화면이 드롭다운에서 행사를 고르면, 학생 앱 상세에서 눌러 그 행사로 이동할 수 있게 합니다.

"relatedEvent": { "eventId": 12, "title": "2026 해오름제" }

❓ 왜 해결해야 하나요?

지금은 archive_related_links가 제목+URL 자유 링크를 여러 개 담습니다. 이 모양으로는 세 가지가 안 됩니다.

  1. 앱이 어디로 가야 할지 모릅니다. 식별자를 복원할 수 없고, 저장소에 행사 URL을 만드는 코드도 없습니다(StorageUrlBuilder는 파일 전용)
  2. 제목이 낡습니다. 복사해 저장하므로 행사명을 고쳐도 아카이빙 화면은 옛 제목 그대로입니다
  3. 관리자 화면이 드롭다운에서 고르는 구조인데, 받을 자리가 URL뿐입니다

⭐ 어떻게 해결했나요?

커밋 3개로 나눴고 각각 단독으로 컴파일됩니다.

1. 행사 단건 조회 경로 — EventService.getByIdOrNull을 더합니다. 저장소에는 이미 같은 모양(EventRepository.findById)이 있고 서비스만 안 내보내고 있었습니다.

기존 getPublishedEvent를 못 쓰는 이유가 둘입니다. 미게시 행사를 못 가져와 **운영진 화면에서도 null**이 되고, EventDetail은 질문 목록·신청자 수까지 묶은 무거운 읽기 모델이라 제목 하나 쓰자고 끌어올 게 아닙니다.

이름은 find~가 아니라 getByIdOrNull입니다. 저장소 관행이 find~는 Optional인데 여기는 Optional을 벗기기로 해서, 이름이 null 반환을 직접 드러내게 뒀습니다.

2. 스키마·도메인 전환(V28) — related_event_id 하나를 더하고 archive_related_links를 DROP합니다. ArchiveRelatedLink 도메인·엔티티·리포지토리를 지웁니다.

연결 대상이 행사뿐이라 컬럼 하나로 끝납니다. 종류를 함께 저장하는 다형 참조(type + id)도, 그 짝을 묶는 VO도 필요 없습니다. related_event_id가 NULL이면 연결 없음, 값이 있으면 연결 — 상태가 둘뿐이라 "둘 다 있거나 둘 다 없어야 한다" 같은 불변식 자체가 생기지 않습니다.

3. 연결 행사 응답 — 관리자·학생 앱 상세에 relatedEvent를 담습니다. 제목은 조회할 때마다 원본에서 가져오므로 행사명을 고쳐도 항상 최신입니다. 아카이빙과 행사는 같은 모듈의 서로 다른 도메인이라 서비스끼리 부르지 않고 api의 UseCase가 조합합니다(architecture.md 6-1절).

🧩 이 PR의 한계 & 트레이드오프

  • UseCase와 조합 record가 두 모듈에 복제됩니다. 실제 코드 차이는 한 줄(!event.isPublished())이고 나머지는 javadoc입니다. app-api와 admin-api는 서로를 모르고, 공유하려면 common-api가 event 도메인을 알아야 합니다 — #141에서 Layout·LockerPeriodParams 복제를 같은 이유로 승인하신 선례를 따랐습니다. 학생 앱은 미게시 행사를 숨기고 운영진은 보여주므로 앞으로 더 갈릴 자리이기도 합니다
  • 이미지 조회만 UseCase 밖에 남았습니다. 제목은 UseCase가, 이미지는 컨트롤러가 FileService를 직접 부릅니다. fileService 직접 호출은 #40부터 있던 모양이고 저장소 전체가 같아서(AdminLockerSectionController 등) 범위 밖으로 뒀는데, UseCase가 생기면서 비대칭이 새로 보이는 자리입니다
  • ArchiveServiceImpl.getArchive에 레거시 @Transactional(readOnly = true)가 남아 있습니다. 이 PR이 본문을 고치는 바로 그 메서드라 diff 바로 위에 찍힙니다. [Docs/#157] 조회 메서드 readOnly 트랜잭션 컨벤션 제거 #158 이후 새 코드에는 붙이지 않았고(EventService.getByIdOrNull), 기존 것은 #136에서 "이번 PR 범위가 아니라 그대로 두셔도 된다"고 하신 기준에 따라 남겨뒀습니다
  • "연결 없음"과 "행사가 삭제됨"을 구분하지 않습니다. 둘 다 relatedEvent: null입니다. 끊어진 참조는 운영진이 그 아카이빙을 다시 저장할 때 정리되고, 지워진 행사로 가는 링크는 쓸모가 없어 구분할 값이 없다고 봤습니다
  • 테스트 코드는 없습니다. AGENTS.md 원칙에 따랐습니다

⛓️ 기존 기능에 미치는 영향

  • 학생 앱 상세 응답이 바뀝니다. relatedLinks: [{title, url}] → relatedEvent: {eventId, title}. 앱이 아직 아카이빙 API를 붙이지 않고 목업으로만 그리고 있어 조율 비용이 없습니다
  • EventService에 메서드가 하나 늘어납니다. 기존 메서드 동작은 그대로입니다. NoticeService는 건드리지 않습니다
  • archive_related_links가 사라집니다. 이 PR 전에는 관리자 API로 넣을 수단이 없어 손으로 넣은 행만 있을 수 있습니다
  • EventService.getByIdOrNull은 미게시 행사도 돌려줍니다. 감추는 일은 부르는 쪽이 Event.isPublished()로 합니다. 관리자 행사 등록·조회·수정 API 추가 #135·#137이 AdminEventService를 만들면 이 메서드가 그쪽으로 옮겨갈 수 있습니다

🔀 Edge Case & 실패 시나리오

상황 동작
연결하지 않은 아카이빙 relatedEvent가 null
연결한 행사가 삭제됨 relatedEvent가 null (아카이빙은 정상 조회)
연결한 행사가 미게시 학생 앱은 null, 관리자는 제목을 보여준다
행사명이 수정됨 다음 조회에 바뀐 제목이 나간다 (저장해 두지 않는다)
연결이 없는 아카이빙 상세 행사 쿼리를 아예 타지 않는다

📋 검토한 대안과 선택 이유

  • URL을 저장하기: 드롭다운에서 고르는 구조라 저장할 건 URL이 아니라 참조입니다. URL을 저장하면 앱 내 라우팅을 못 하고, 제목을 복사해 두면 원본 수정 시 낡습니다
  • 공지도 연결할 수 있게 다형 참조(type + id)로 두기: 처음엔 그렇게 만들었다가 접었습니다. 팀에서 연결 대상은 행사면 충분하다고 정리돼서, 컬럼 하나로 줄이고 enum·VO·NoticeService 변경을 전부 걷어냈습니다. 나중에 공지도 필요해지면 related_target_type을 더하고 기존 행을 백필하면 됩니다
  • archive_related_links에 event_id를 더해 재활용하기: title·url이 NOT NULL인데 행사에는 URL이 없고, display_order는 한 건만 쓰면 의미가 없어집니다. 조회할 때 테이블을 한 번 더 읽어야 하는 것도 있고요
  • 제목을 함께 저장해 쿼리를 아끼기: 원본을 고치면 낡습니다. 상세는 한 건씩만 열어 목록 N+1이 아니라 쿼리 한 번이 늘 뿐입니다
  • 두 모듈의 UseCase를 common-api로 합치기: #141에서 같은 종류의 중복을 복제로 두기로 하신 판단을 따랐습니다

💬 리뷰 포인트

  • [c] archive_related_links DROP 전에 행 수를 확인해야 합니다. 저장소 첫 DROP TABLE이고 되돌릴 수 없습니다. 연결은 행사 한 건이면 충분하다고 정해서 옮기는 백필을 두지 않았는데, dev에 행이 있으면 적용 전에 손으로 옮겨야 합니다
  • [c] V28 번호와 머지 순서 — [Feat/#185] 아카이빙 목록·상세 조회 관리자 API 추가 #188(V27) 다음입니다. outOfOrder가 꺼져 있어서 선행 PR이 밀리면 이 번호도 같이 밀립니다
  • [a] 두 모듈의 UseCase·record 복제를 그대로 둘지 봐주세요. 한 줄(미게시 행사 처리)이 이미 갈려 있어 앞으로 더 달라질 자리라고 봤습니다

로컬에서 Docker로 MySQL 8을 띄워 마이그레이션 21개를 순서대로 적용하고 ddl-auto: validate까지 통과하는 것을 확인했습니다 — 엔티티 삭제와 DROP TABLE이 어긋나면 기동이 막히는 변경이라 직접 돌려봤습니다.

@sangrae2325 sangrae2325 self-assigned this Oct 29, 2026
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sangrae2325
sangrae2325 force-pushed the feat/#187-archive-related-target branch from 66e385b to 7df969b Compare October 29, 2026 08:24
@sangrae2325 sangrae2325 changed the title [Feat/#187] 아카이빙 관련 링크를 공지·행사 연결로 전환 [Feat/#187] 아카이빙 관련 링크를 행사 연결로 전환 Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

아카이빙 관련 링크를 행사 연결로 전환

2 participants