Skip to content

fix: 권한 그룹 배정 목록 처리를 단일 트랜잭션으로 묶음 - #93

Merged
jei007 merged 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/authorgroup-batch-tx
Sep 18, 2026
Merged

jei007 merged 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/authorgroup-batch-tx

Conversation

@wantaekchoi

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

EgovAuthorGroupAPIController의 authorGroupInsert·authorGroupDelete는 화면에서 세미콜론으로 이어 보낸 사용자 목록을 항목마다 순회하며, 각 항목에서 서비스의 insert·update·delete를 직접 호출합니다.

for (int i = 0; i < strUserIds.length; i++) {
    authorGroupVO.setScrtyDtrmnTrgetId(strUserIds[i]);
    authorGroupVO.setMberTyCode(strMberTyCodes[i]);
    authorGroupVO.setAuthorCode(strAuthorCodes[i]);

    if ("N".equals(strRegYns[i])) {
        service.insert(authorGroupVO);
    } else {
        service.update(authorGroupVO);
    }
}
String[] strUserIds = userIds.split(";");
for (String strUserId : strUserIds) {
    authorGroupVO.setScrtyDtrmnTrgetId(strUserId);
    service.delete(authorGroupVO, userInfo);
}

insert·update·delete는 각각 @Transactional입니다.

@Transactional
@Override
public AuthorGroupVO insert(AuthorGroupVO authorGroupVO) {
@Transactional
@Override
public void delete(AuthorGroupVO authorGroupVO, Map<String, String> userInfo) {

컨트롤러가 서비스 빈(프록시)의 메서드를 항목마다 호출하므로, @Transactional은 호출마다 새 트랜잭션을 엽니다. 항목이 여러 개인 요청 중간에 예외가 나면 앞쪽 항목은 이미 커밋된 채 남고 뒤쪽 항목은 처리되지 않아, 화면이 보낸 한 번의 저장·삭제 요청이 부분적으로만 반영됩니다. 이 프로젝트는 AspectJ 로드타임 위빙을 쓰지 않아(-javaagent 설정·@EnableTransactionManagement(mode=ASPECTJ) 없음) @Transactional은 기본값인 프록시 기반으로 동작합니다.

서비스에 배치 메서드를 추가해, 컨트롤러의 두 루프를 서비스 메서드 안으로 옮겼습니다. 프록시 기반 AOP는 같은 인스턴스 안의 자기호출(this.insert(...) 등)을 가로채지 않으므로, 안쪽 호출은 새 트랜잭션을 열지 않고 바깥 메서드가 연 트랜잭션 하나를 그대로 씁니다.

@Transactional
@Override
public void insertOrUpdateList(String[] userIds, String[] mberTyCodes, String[] authorCodes, String[] regYns, AuthorGroupVO authorGroupVO) {
    for (int i = 0; i < userIds.length; i++) {
        authorGroupVO.setScrtyDtrmnTrgetId(userIds[i]);
        authorGroupVO.setMberTyCode(mberTyCodes[i]);
        authorGroupVO.setAuthorCode(authorCodes[i]);

        if ("N".equals(regYns[i])) {
            this.insert(authorGroupVO);
        } else {
            this.update(authorGroupVO);
        }
    }
}

@Transactional
@Override
public void deleteList(String[] userIds, AuthorGroupVO authorGroupVO, Map<String, String> userInfo) {
    for (String userId : userIds) {
        authorGroupVO.setScrtyDtrmnTrgetId(userId);
        this.delete(authorGroupVO, userInfo);
    }
}

컨트롤러는 이 메서드들만 호출합니다.

service.insertOrUpdateList(strUserIds, strMberTyCodes, strAuthorCodes, strRegYns, authorGroupVO);
service.deleteList(strUserIds, authorGroupVO, userInfo);

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

EgovAuthorGroupRepository를 Mockito로 스텁해 EgovAuthorGroupServiceImplBatchTest를 추가했습니다. insertOrUpdateList가 항목마다 올바른 사용자·권한코드로 저장하는지(신규는 insert, 기존은 update), deleteList가 목록의 사용자 전원을 삭제하는지 확인합니다.

수정 전(RED, deleteList가 첫 항목만 처리하도록 되돌려 재현):

$ mvn -o -Dtest=EgovAuthorGroupServiceImplBatchTest -DfailIfNoTests=false test
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.455 s <<< FAILURE! -- in egovframework.com.sec.rgm.service.impl.EgovAuthorGroupServiceImplBatchTest
[ERROR]   EgovAuthorGroupServiceImplBatchTest.deleteListDeletesEachUserWithAuthenticatedCaller:61 
[ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 0

수정 후(GREEN):

$ mvn -o -Dtest=EgovAuthorGroupServiceImplBatchTest -DfailIfNoTests=false test
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.437 s -- in egovframework.com.sec.rgm.service.impl.EgovAuthorGroupServiceImplBatchTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

같은 모듈의 기존 테스트 2건(EgovAuthorGroupServiceImplTest·EgovAuthorGroupInfoServiceImplTest)은 @SpringBootTest로 로컬 MySQL 접속이 필요한데, 이 환경에는 그 DB가 떠 있지 않아 origin/main 기준으로도 이미 실패합니다. 이 변경과 무관합니다.

테스트 브라우저 Test Browser

  • Chrome
  • Firefox
  • Edge
  • Safari
  • Opera
  • Internet Explorer
  • 기타 Others

JUnit 테스트로 대체합니다.

테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video

위 JUnit 테스트 실행 결과로 대체합니다.

@jei007 jei007 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

표준프레임워크에 대한 지속적인 참여에
대단히 감사드립니다.

@jei007
jei007 merged commit add3eff into eGovFramework:main Sep 18, 2026
11 checks passed
@wantaekchoi
wantaekchoi deleted the fix/authorgroup-batch-tx branch September 18, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants