본문 바로가기

IT&Dev/BACK-END

[JAVA]HashMap을 사용하여 메뉴정보 가져오기

 

프로젝트를 진행하면서 기능 별 접근권한과 사용여부에 따라 메뉴 구성이 달라지고 화면에 표출하기 위해서는 지금 구조를 바꿀 필요가 있었다. 메뉴 데이터를 가공할 때 전제 조건으로,

 

1. 전체 메뉴에서 사용자가 가진 접근 권한이 없을 때는 표출하지 않는다.

2. 접근 권한이 없는 메뉴를 제거했을 때 하위메뉴가 없는 상위메뉴도 표출하지 않는다.

3. 상위메뉴는 하위메뉴의 갯수정보를 가지고 있다.

4. 각각의 메뉴는 자신의 정렬 순서 정보를 가지고 있다.

5. 3, 4번의 정보가 DB에 저장되어 있는데, 접근 권한이 없는 메뉴를 제거할 때마다 숫자가 달라져야 한다.

 

먼저 Menu 정보를 확인해보면, 

// 메뉴번호
	private Integer menuNo;
	// 메뉴명
	private String menuNm;
	// 메뉴레벨
	private Integer menuLevel;
	// 메뉴순서
	private Integer menuOrdr;
	// 상위메뉴번호
	private Integer menuUpperNo;
	// 하위메뉴 개수
	private Integer menuLwprtCnt;
	// 메뉴정렬코드
	private String menuSortCode;
	// 메뉴 표시여부
	private String menuShowAt;
	// 권한프로그램ID
	private String authProgrmId;
	// 프로그램 URL
	private String progrmUrl;
	// 프로그램 권한
	private String authCate;
	// 메뉴 URL
	private String menuUrl;
	// 메뉴 타겟
	private String menuTarget;
	// 최초등록일
	private String frstRegisterPnttm;
	// 최초등록자
	private String frstRegisterId;
	// 최초등록IP
	private String frstRegisterIp;
	// 최종수정일
	private String lastUpdusrPnttm;
	// 최종수정자
	private String lastUpdusrId;
	// 최종수정IP
	private String lastUpdusrIp;
	// 삭제여부
	private String deleteAt;
	// 사용자 번호
	private int usersNo;
	// URL 직접입력
	private String customUrl;
	// 하위 메뉴 리스트
	private List<Menu> subMenuList = new ArrayList<>();

여기서 각각의 메뉴는 자식 메뉴정보(하위메뉴)를 List로 가지게 된다. 

 

 

List<AuthProgrm> authProgrmlist = authProgrmService.selectAuthProgrmSubMenuList(authProgrmVO);		
// 권한 map(key:progrmId, value: Y)
Map<String, String> authMap = new HashMap<>();
for(AuthProgrm forVo : authProgrmlist) {
	authMap.put(forVo.getAuthProgrmId(), "Y");
}

먼저 사용자 세션 정보를 통해 내가 가진 프로그램 권한을 조회하여 hashMap으로 저장하였다.

(권한이 있다면, Y로 저장)

 

/** 메뉴 리스트 추가 **/
MenuVO menuVO = new MenuVO();
menuVO.setSearchDeleteAt("N");
menuVO.setSearchMenuShowAt("Y");

List<Menu> menuLeftList = menuService.selectLeftMenuList(menuVO);

다음으로 모든 메뉴의 정보를 조회하였다.

 

Menu topMenu = new Menu();
topMenu.setMenuNo(1);
topMenu.setMenuNm("Top Menu Info");
topMenu.setMenuLevel(0);
topMenu.setMenuOrdr(0);
topMenu.setMenuLwprtCnt(0);
topMenu.setMenuSortCode("001");
topMenu.setMenuShowAt("N");
topMenu.setDeleteAt("N");

Map<String, Menu> menuMap = new LinkedHashMap<>();
menuMap.put(topMenu.getMenuNo()+"", topMenu);

이제 최종적으로 활용할 메뉴정보를 HashMap으로 생성하였다.

여기서 가장 최상위 메뉴 정보를 임으로 만들어 menuMap에 저장하였다.

 

for(Menu forVo : menuLeftList) {
	forVo.setMenuLwprtCnt(0);
	forVo.setMenuOrdr(0);
	if(StringUtil.notEmpty(forVo.getAuthProgrmId())) {
		if("Y".equals(authMap.get(forVo.getAuthProgrmId()))) {	// 프로그램 권한이 존재할 때
			Menu upperMenu = menuMap.get(forVo.getMenuUpperNo()+""); // menuMap에 있는 부모메뉴 정보 조회
			upperMenu.setMenuLwprtCnt(upperMenu.getMenuLwprtCnt()+1); // 부모메뉴 정보에서 하위메뉴 갯수 1 증가					
			forVo.setMenuOrdr(upperMenu.getMenuLwprtCnt()+1); // 자신의 메뉴 정보에서 정렬 순서 지정
			menuMap.put(forVo.getMenuNo()+"", forVo); // menuMap에 자신의 메뉴 정보 저장					
								
			List<Menu> tempList = upperMenu.getSubMenuList();
			tempList.add(forVo);
			upperMenu.setSubMenuList(tempList);
			menuMap.put(forVo.getMenuUpperNo()+"", upperMenu);
		}					
	} else {
		Menu upperMenu = menuMap.get(forVo.getMenuUpperNo()+"");
		upperMenu.setMenuLwprtCnt(upperMenu.getMenuLwprtCnt()+1);					
		forVo.setMenuOrdr(upperMenu.getMenuLwprtCnt()+1);
		menuMap.put(forVo.getMenuNo()+"", forVo);					
							
		List<Menu> tempList = upperMenu.getSubMenuList();				
		tempList.add(forVo);
		upperMenu.setSubMenuList(tempList);
		menuMap.put(forVo.getMenuUpperNo()+"", upperMenu);
	}
}

이제 메뉴의 정보를 menuMap에 저장하는데, menuMap에서 부모 메뉴에 대한 정보를 조회하여 "자식 메뉴정보List"에 자신을 추가한다. 

 

이렇게 하면 전체 메뉴정보를 조회한 데이터에서 권한이 없는 메뉴를 지운 뒤 menuMap에 담게 된다. 

여기까지가 위에서 정한 전제조건 1,3,4,5번을 해결하였고 마지막으로 2번을 해결하기 위해 hashMap을 다시 스캔하여 하위메뉴가 없는 상위메뉴를 map에서 제거하였다.

 

그런데,

for(String key : menuMap.keySet()) {
  if(menuMap.get(key).getMenuLwprtCnt() < 1 && StringUtil.isEmpty(menuMap.get(key).getAuthProgrmId())) { // 하위 메뉴가 없을 때
  	menuMap.remove(key);
  }
}

위와 같이 for문 안에서 map.remove(key)를 했을 때 다음과 같은 에러가 발생하였다. 

 

반복문에서 remove를 호출하면 반복문 생성 당시의 index 값과 remove 수행 뒤 크기가 맞지 않아 발생하는 에러라고 한다. 이럴 때 해결 방안은,

 

Vector<String> clsList = new Vector<String>();
for(String key : menuMap.keySet()) {
	if(menuMap.get(key).getMenuLwprtCnt() < 1 && StringUtil.isEmpty(menuMap.get(key).getAuthProgrmId())) {
		clsList.add(key); // 삭제할 key정보를 담는다.
	}
}

//삭제할 key정보를 담은 Vector를 활용하여 remove 호출
for(int i = 0; i < clsList.size(); i++) {
	menuMap.remove(clsList.get(i));
}

이렇게 반복문에서는 삭제 조건에 맞는 key를 Vector에 별도로 저장하고, 반복문 밖에서 삭제를 하면 된다. 

 

 

위에서 정한 전제조건을 충족하는 메뉴정보를 hashMap을 활용하여 저장하는 방법을 알아보았다.

 

 

2020/09/15 - [IT&Dev/BACK-END] - [JAVA]HashMap을 사용하여 메뉴정보 가져오기2