3 minute read

문제 해결 방법 - [문제 4] 풀이

  1. [문제 4] 지점명 입력시 해당지점의 거래금액 합계 출력

우선 문제에 조건가운데 분당점이 판교로 이관되었다는 것에 집중 했습니다. 신용보증기금 차세대 프로젝트를 진행하면서 이수관 업무를 맏았던 저로서는 정상적으로 이관이 완료가 되었다면 해당 하위 데이터가 모두 판교점으로 이관 되어야 한다고 생각했습니다. 즉 분당점의 데이터는 판교점으로 조회할때 같이 조회가 되어야 됩니다. 하지만 어디까지나 4번 문제 한정의 상황에서 그 모든 것을 반영하기 위해서 DB의 내용을 바꿀수는 없었습니다. 상황을 반영하기위해 일부 하드코딩이 필요했습니다.

JAVA 서비스 로직 부분입니다.

@Service
@Transactional
public class KakaoServiceImpl implements KakaoService {
	
	/** ...중략... **/
	

	@Override
	public HashMap<String, Object> selectSumAmtByBrToBrName(HashMap<String, Object> param, HttpServletResponse response) 
	throws Exception{
		
		//입력 파라미터 체크
		String br_name = (String)param.get("brName");
		//영업점이 4개 이상일 수 있으므로 DB에서 조회
		List<String> brNameList = mapper.selectBrName();
		
		//[테스트를 전제 하에 하드 코딩. 시작] : 이관된 분당점 삭제
		if(brNameList.contains("분당점")) {
			brNameList.remove("분당점");
		}
		/* 원래는 업무적으로 이관이 이루어 지면 분당점은 지워지고
		 * 이관과 관련되어 모든 데이터가 바뀌어 있어야 정상입니다.
		 * 현재는 테스트 상에 과제를 이행 하는 차원으로 가정하고
		 * 위와 같이 하드코딩을 사용하였습니다.
		 * [테스트를 전제 하에 하드 코딩. 끝]
		 */
		
		//mapper 입력 파라미터 수정
		HashMap<String, Object> paramForTest = new HashMap<String, Object>();
		List<String> listIn = new ArrayList<String>(); //mybatis in에 사용될 리스트 구성
		
		// 분단 조회시 또는 없는 영업점의 경우..
		if(!brNameList.contains(br_name)) {
			HashMap<String, Object> errorMap = new HashMap<String, Object>();
			errorMap.put("메세지", "br code not found error");
			errorMap.put("code", "404");
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);//http status 변경
			return errorMap;
		}
		
		//[테스트를 전제 하에 하드 코딩. 시작] : 분당점으로 이관된 데이터를 판교점에서 같이 조회 할 수 있도록 처리
		else {
			if("판교점".equals(br_name)) {
				listIn.add(br_name);
				listIn.add("분당점");
			}
			else {
				listIn.add(br_name);
			}
		}
		paramForTest.put("list_in", listIn);
		//원래는 정상적으로 이관이 이루어 졌다면, 해당 로직 또한 원래 필요 없어야 되는 로직입니다.
		//[테스트를 전제 하에 하드 코딩. 끝] 
		
		return mapper.selectSumAmtByBrToBrName(paramForTest);
	}
	/** ...후략... **/
}

소스에 주석으로 설명을 달아 놨지만 해당 로직은 문제 4번의 상황을 특정하여 추가로직 부분이 들어간 상황입니다. 그리고 판교점의 특수 상황을 조회 하기 위해 쿼리에 IN 연산을 사용했습니다. 위에 보시면 분당점과 같은 없는 영업점을 조회하는 경우 errorMap을 리턴하도록 처리 했습니다. 원래 구상은 kakaoException처리를 하려고 했으나 그렇게 에러를 처리하는 경우 400 에러가 발생해서 문제의 정답과 틀려지게 되었습니다. exception안에 response를 받게 처리 할까도 생각했지만, 상태코드를 어거지로 몇번씩 바꾸는게 모양이 좋지 않아 그냥 서비스 안에서 한번만 바꾸도록 처리 했습니다.

위에 주석처럼 조회시 IN연산을 사용했기 때문에 Mybatis dynamic 쿼리를 사용했습니다. xml 파일소스로 같이 올립니다.

	<select id="selectSumAmtByBrToBrName" resultType="hashmap" parameterType="hashmap">
		<![CDATA[
			select
				b.br_name as brName,
			    b.br_code as brCode,
			    sum(c.tr_amount) as sumAmt
			from
				tbl_account a,
			    tbl_branch b,
			    tbl_transaction c
			where 1 = 1
			and	a.acct_no = c.acct_no
			and a.br_code = b.br_code
			and c.can_yn = 'N'
		    and b.br_name in 
		]]>
		<foreach collection="list_in" item="br_name" index="index" separator="," open="(" close=")">
        		#{br_name}
    		</foreach>
	</select>

이제 앞서 말씀 프로그래밍 로직 외에 다른 이유로 시간을 굉장히 잡아 먹었던 문제에 대해 말씀드리도록 하겠습니다. 저 해당 쿼리가 문제였습니다. 테스트를 위해 먼저 MySQL Workbench에서 작성할 때는 정말 잘 조회가 되던 쿼리었는데 이상하게 mybatis 를 통해서 조회하게 되면 조회 값이 null로 나오는 것이었습니다. 다이나믹 쿼리에 이상이 있나 싶었고 구글링을 통해 문제를 찾기위해 개천절, 거의 하루 절반을 보냈습니다. 너무 답답해서 스텍오버플로어에 부족한 영어실력을 보태며 질문을 올려보기도 했지만 답이 바로 오지는 않았습니다. resultType과 parameterType이 같으면 그럴 수 있다고 해서 paramterType을 String으로 바꿔 보기도 했지만 답이 아니었습니다. IN 입력 조건을 지우고 or로 변경해도 마찬가지였고 그냥 = 로 처리해도 마찬가지였습니다. 그러다 입력조건을 지우고 조회를 해봤더니 조회가 되는 것을 확인 했습니다. 이 문제는 입력을 받는 유일힌 문제였고, 그 유일한 입력값이라는 것도 한글 이었습니다. 10시가 넘긴 시간이었습니다. 순간 문득 인코딩 이라는 글자가 머리를 스쳐지나갔습니다.

평가자께서 어떻게 그런 초보적인 실수에 시간을 그렇게 허비하느냐고 실망하실 것 같습니다. 하지만 테이블 생성시 UTF-8로 설정했고 처음부터 프레임워크를 짤때 JAVA, html, xml, js등등 모든 워크스페이스의 인코딩 환경을 UTF-8로 맞춰 놓고 시작했고 위에 3문제에서 조회 할때는 정상적으로 한글이 조회되는 것을 확인 했기 때문에 인코딩이 틀어져 한글이 깨지리라고는 생각하지 못했습니다. 무엇보다 원격으로 AWS와 접속한 MySQL Workbench에서 조회 할때는 정상 조회가 되는것을 두눈으로 확인했기에 설마 그 문제일 거라고는 차마 생각하지 못했습니다. 단, AWS EC2 리눅스 콘솔에 접속하지 전까지 말입니다.(putty,xshall) 인코딩의 문제라는 것으로 범위를 좁혀나가고 그 어디에도 UTF-8 타입이 아닌 곳을 찾을 수 없었지만 단 한곳, AWS EC2 리눅스에서의 MySql dbms는 확인하지 못했다는 것을 11시가 넘어가는 시간에 깨닫게 되었습니다. 서버에 접속해서 mysql에 들어가 해당 쿼리를 조회해보니 애초부터 한글이 입력되지 않았고 그로인해 데이터 조회 결과가 null로 나오는 것이었습니다. 아니나 다를까 AWS MySql dbms의 입력 인코딩 설정은 ‘ISO Latin-1(SIO-8859-1)’ 이었습니다.

원격으로 AWS에 연결해서 MySQL Workbench를 이용하면 한글이 입력/조회가 되었고 csv 파일에 임포트가 되었었기에 거기에 문제가 있었을 거라고 생각하지 못했던 것이었습니다. AWS에서 다운 받은 MySqlSever을 설치를 할 경우 windows에서 처럼 친절하게 한글 인코딩 설정을 묻지도 않습니다. AWS는 기본적으로 US-us 설정이기 때문에 설치할 때도 가장 기본값의 Latin-1 인코딩 설정을 따릅니다. 이걸 깨닫고 my.cnf를 찾아가 인코딩 설정을 수정했습니다. 그제서야 한글이 입력되었고 정상적으로 조회가 되었습니다. mybatis는 데이터소스에 직접 접근하기 때문인지 Workbench와는 다르게 중간에 인코딩 변환을 하지 않았고 서버에 db는 알지도 못하는 쿼리의 한글값을 인식하지 못했던 것이었습니다. 그렇게 허탈한 마음을 다스리며 문제를 모두 해결했을때 시간을 돌아보니 벌써 자정을 넘기게 되었습니다. 처음 Database 서버를 구축할때 세심하게 인코딩 설정을 신경쓰지 못한 문제였고 정말 많은 것을 배우게되는 순간이었습니다.

Categories:

Updated:

Comments