From 53e693bea6612091cd6241de6810e695120d5502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Sun, 18 Oct 2026 22:06:11 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20DB=EB=A7=8C=20=EB=8B=A4=EB=A3=A8?= =?UTF-8?q?=EB=8A=94=20=EC=84=9C=EB=B9=84=EC=8A=A4=EC=9D=98=20=ED=8A=B8?= =?UTF-8?q?=EB=9E=9C=EC=9E=AD=EC=85=98=20=EC=84=A0=EC=96=B8=EC=9D=84=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B8=B0=EB=B3=B8=EA=B0=92=20+?= =?UTF-8?q?=20=EC=93=B0=EA=B8=B0=20=EB=8D=AE=EC=96=B4=EC=93=B0=EA=B8=B0?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=9E=EC=B6=98=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 외부 호출이 없고 모든 public 메서드가 이미 @Transactional을 선언하던 서비스 7개를 클래스 @Transactional(readOnly = true) + 쓰기 메서드 @Transactional로 바꾼다. 메서드별 실효 속성(읽기 전용/쓰기)은 그대로다. Slack·메일·HTTP 호출이 있거나 트랜잭션 밖에서 도는 메서드가 있는 서비스(AuthService, PasswordResetService, AdminMemberService, SlackProfileSyncService, MemberSlackIdWriter, Dues 알림 등)와 쓰기 전용 트랜잭션 경계 빈(*Writer, *Issuer 등)은 그대로 둔다. --- .../bcsdinternalapiv2/ledger/service/ExemptionService.java | 3 +-- .../ledger/service/LedgerEntryService.java | 2 +- .../bcsdinternalapiv2/ledger/service/RosterService.java | 3 +-- .../bcsdinternalapiv2/ledger/service/SemesterService.java | 2 +- .../member/service/MemberDirectoryService.java | 4 +--- .../bcsdinternalapiv2/member/service/MemberService.java | 4 +--- .../reservation/service/ReservationService.java | 6 +----- 7 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/ExemptionService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/ExemptionService.java index ee58dac..e97d6aa 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/ExemptionService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/ExemptionService.java @@ -20,19 +20,18 @@ */ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class ExemptionService { private final DuesExemptionRepository exemptionRepository; private final DuesExemptionReasonRepository reasonRepository; private final MemberRepository memberRepository; - @Transactional(readOnly = true) public ExemptionListResponse getExemptions() { return new ExemptionListResponse( exemptionRepository.findAllByOrderByIdAsc().stream().map(ExemptionResponse::from).toList()); } - @Transactional(readOnly = true) public ExemptionReasonListResponse getReasons() { return new ExemptionReasonListResponse(reasonRepository.findAllNames()); } diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/LedgerEntryService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/LedgerEntryService.java index 49c65fd..c22e08a 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/LedgerEntryService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/LedgerEntryService.java @@ -14,6 +14,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class LedgerEntryService { private final LedgerEntryRepository entryRepository; @@ -22,7 +23,6 @@ public class LedgerEntryService { private final EvidenceLinkWriter evidenceLinkWriter; /** 쿼리 파라미터(필터)는 받지 않는다. FE가 전체를 받아 클라이언트에서 거른다. */ - @Transactional(readOnly = true) public LedgerEntryListResponse getEntries() { return new LedgerEntryListResponse(assembler.toResponses(entryRepository.findAllLatestFirst())); } diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/RosterService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/RosterService.java index a9ffd1d..49066f4 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/RosterService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/RosterService.java @@ -27,6 +27,7 @@ */ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class RosterService { private final DuesSemesterReader semesterReader; @@ -35,7 +36,6 @@ public class RosterService { private final MemberRepository memberRepository; private final DuesLinkRepository linkRepository; - @Transactional(readOnly = true) public SemesterRosterResponse getRoster(String semesterId) { DuesSemester semester = semesterReader.get(semesterId); List members = rosterRepository @@ -46,7 +46,6 @@ public SemesterRosterResponse getRoster(String semesterId) { return new SemesterRosterResponse(members); } - @Transactional(readOnly = true) public RosterCandidateListResponse getCandidates(String semesterId) { DuesSemester semester = semesterReader.get(semesterId); List members = rosterRepository.findCandidates(semester.getId()).stream() diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/SemesterService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/SemesterService.java index a3f54a5..f757c9e 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/SemesterService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/ledger/service/SemesterService.java @@ -21,6 +21,7 @@ */ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class SemesterService { private final Clock clock; @@ -29,7 +30,6 @@ public class SemesterService { private final DuesSemesterWriter semesterWriter; private final DuesQueryService duesQueryService; - @Transactional(readOnly = true) public SemesterCreatableResponse getCreatable() { Creatable creatable = creatable(); return SemesterCreatableResponse.of(creatable.current(), creatable.next(), creatable.creatable()); diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberDirectoryService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberDirectoryService.java index 2a7bc06..f508bdc 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberDirectoryService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberDirectoryService.java @@ -36,6 +36,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class MemberDirectoryService { private final MemberRepository memberRepository; @@ -43,13 +44,11 @@ public class MemberDirectoryService { private final PositionRepository positionRepository; private final PhotoStorageService photoStorageService; - @Transactional(readOnly = true) public MemberDirectoryResponse getDirectory(MemberDirectoryQuery query, Pageable pageable) { return MemberDirectoryResponse.of(findPage(query, pageable), buildCounts()); } /** 관리자 인명부. 일반 인명부 항목에 관리자 전용 필드(직장, 계정 유무)를 더한다. */ - @Transactional(readOnly = true) public AdminMemberDirectoryResponse getAdminDirectory(MemberDirectoryQuery query, Pageable pageable) { return AdminMemberDirectoryResponse.of(findPage(query, pageable), buildCounts()); } @@ -123,7 +122,6 @@ public void changeWithdrawal(Long memberId, boolean withdrawn) { } } - @Transactional(readOnly = true) public PhotoPresignedUrlResponse issuePhotoPresignedUrl(Long memberId, PhotoPresignedUrlRequest request) { if (!memberRepository.existsById(memberId)) { throw new MemberException(MemberExceptionType.MEMBER_NOT_FOUND); diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberService.java index 3dfb974..9ffcca3 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/member/service/MemberService.java @@ -28,6 +28,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class MemberService { private final MemberRepository memberRepository; @@ -36,12 +37,10 @@ public class MemberService { private final AuthService authService; private final PhotoStorageService photoStorageService; - @Transactional(readOnly = true) public MemberResponse getMe(Long memberId) { return MemberResponse.from(getMemberOrThrow(memberId)); } - @Transactional(readOnly = true) public MemberResponse getInitialSetupInfo(Long memberId, long tokenPasswordVersion) { Member member = getMemberOrThrow(memberId); if (!member.isPendingSetup()) { @@ -126,7 +125,6 @@ public void changePassword(Long memberId, PasswordChangeRequest request) { .forEach(refreshToken -> refreshToken.revoke(now)); } - @Transactional(readOnly = true) public PhotoPresignedUrlResponse issuePhotoPresignedUrl(Long memberId, PhotoPresignedUrlRequest request) { return photoStorageService.issuePresignedUrl(memberId, request); } diff --git a/src/main/java/com/bcsdlab/bcsdinternalapiv2/reservation/service/ReservationService.java b/src/main/java/com/bcsdlab/bcsdinternalapiv2/reservation/service/ReservationService.java index c98aea1..282d207 100644 --- a/src/main/java/com/bcsdlab/bcsdinternalapiv2/reservation/service/ReservationService.java +++ b/src/main/java/com/bcsdlab/bcsdinternalapiv2/reservation/service/ReservationService.java @@ -37,6 +37,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class ReservationService { private static final int MAX_DAILY_MINUTES = 180; @@ -68,7 +69,6 @@ public ReservationCreateResponse create(Long memberId, ReservationCreateRequest return createRepeat(memberId, request, now); } - @Transactional(readOnly = true) public DailyReservationResponse getDaily(LocalDate date, Long viewerMemberId) { List reservations = reservationRepository.findByReservationDateAndCancelledAtIsNullOrderByStartMinuteAsc(date); @@ -76,14 +76,12 @@ public DailyReservationResponse getDaily(LocalDate date, Long viewerMemberId) { return DailyReservationResponse.of(date, reservations, namesById, viewerMemberId); } - @Transactional(readOnly = true) public MonthlyOccupancyResponse getMonthlyOccupancy(YearMonth month) { LocalDate from = month.atDay(1); LocalDate to = month.atEndOfMonth(); return MonthlyOccupancyResponse.of(month, toDays(reservationRepository.sumReservedMinutesByDateBetween(from, to))); } - @Transactional(readOnly = true) public MonthlyOccupancyResponse getMyMonthlyOccupancy(Long memberId, YearMonth month) { LocalDate from = month.atDay(1); LocalDate to = month.atEndOfMonth(); @@ -91,7 +89,6 @@ public MonthlyOccupancyResponse getMyMonthlyOccupancy(Long memberId, YearMonth m return MonthlyOccupancyResponse.of(month, toDays(rows)); } - @Transactional(readOnly = true) public MyReservationResponse getMyReservations(Long memberId, String status) { LocalDate today = LocalDate.now(clock); List reservations = "past".equalsIgnoreCase(status) @@ -104,7 +101,6 @@ public MyReservationResponse getMyReservations(Long memberId, String status) { return MyReservationResponse.of(pickGroupRepresentatives(reservations)); } - @Transactional(readOnly = true) public ReservationDetailResponse getDetail(Long memberId, Long reservationId) { Reservation reservation = getOwnedReservation(memberId, reservationId); ReservationDetailResponse.Group group = null;