jsp의 jstl과 html의 백틱이 충돌이 날 때에는 $ 앞에 \ 를 붙인다.

 

 

html

var data =
            `   
                <form method="put" id="frmData">
                <input type="hidden" id="currentPageNum" name="currentPageNum" value="${pageNum}">
                회원코드
                <input type="text" id="member_code" name="member_code" value="${memValues[0]}"><br>
                이름
                <input type="text" id="member_name" name="member_name" value="${memValues[1]}"><br>
                핸드폰
                <input type="text" id="mobile_no" name="mobile_no" value="${memValues[2]}"><br>
                주소
                <input type="text" id="address" name="address" value="${memValues[3]}"><br>
                나이
                <input type="text" id="age" name="age" value="${memValues[4]}"><br>
                성별
                <input type="text" id="sex" name="sex" value="${memValues[5]}"><br>
                비밀번호
                <input type="text" id="password" name="password"><br>
                <button type="button" onClick="doModify()"> 수정 </button>
                <button type="button" onClick="findAll(${pageNum})">목록</button>
                </form>
            `

 

 

 

jsp

 

var data =
            `   
                <form method="put" id="frmData">
                <input type="hidden" id="currentPageNum" name="currentPageNum" value="\${pageNum}">
                회원코드
                <input type="text" id="member_code" name="member_code" value="\${memValues[0]}"><br>
                이름
                <input type="text" id="member_name" name="member_name" value="\${memValues[1]}"><br>
                핸드폰
                <input type="text" id="mobile_no" name="mobile_no" value="\${memValues[2]}"><br>
                주소
                <input type="text" id="address" name="address" value="\${memValues[3]}"><br>
                나이
                <input type="text" id="age" name="age" value="\${memValues[4]}"><br>
                성별
                <input type="text" id="sex" name="sex" value="\${memValues[5]}"><br>
                비밀번호
                <input type="text" id="password" name="password"><br>
                <button type="button" onClick="doModify()"> 수정 </button>
                <button type="button" onClick="findAll(\${pageNum})">목록</button>
                </form>
            `

조건에 따라 정렬 방식을 선택할 수 있는 기능을 구현하려고 했는데

너무 생각 없이 로직을 짜버렸다....

이렇게 지저분하게 짤 것이 아니라 동적 SQL문을 활용하면 훨씬 깔끔하고 간결할텐데

하는 생각이 불현듯 들어서 정리를 했다.

 

 

조건은 총 6개다

 

전체포인트 - 오름차순 / 내림차순

가용포인트 - 오름차순 / 내림차순

사용포인트 - 오름차순 / 내림차순

 

 

 

그래서 나는 메소드를 6개를 만들어 버린 것이다.. ^^ 컨트롤러, 서비스, 레파지토리에.... 6개씩..

SQL문도 6개...

 

이것을 모두 1개로 정리했다.

 

 

 

 

 

매핑 URI 값에 가변 변수를 하나 추가했다. 그래서 두개를 받는다.

pointArrange 부분에 totalAsc / totalDesc / reqAsc / reqDesc / useAsc / useDesc 총 6개의 값이 들어오고

pageNum 에는 페이지 넘버가 들어온다.

 

 

 

그리고 매개변수로 들어온 pointArrange 값을 가지고 서비스와 레파지토리를 거쳐 매퍼 파일로 들어간다.

각 조건에 따라 다른 order by 절을 실행한다.

 

 

 

 

 

정상적으로 돌아가는 것을 확인하고

가입 승인 회원 조회, 가입 미승인 회원 조회, 탈퇴 상태 회원 조회 이 3개의 메소드도 하나로 묶어 버렸다.

 

 

 

 

 

페이징 처리 때문에 목록을 만들기 위해서는 원래 가변 변수 int pageNum 을 받아야 하고

memberState, pointArrange를 가변 변수로 받는다.

 

 

 

그런데 오류가 난다.....

java.lang.IllegalStateException: Ambiguous handler methods mapped for '/api/member/members/approvaly/1': 

더보기


java.lang.IllegalStateException: Ambiguous handler methods mapped for '/api/member/members/approvaly/1': {public com.nordic.dto.common.ResponseDto com.nordic.api.MemberApiController.PointArrange(java.lang.String,int) throws java.lang.Exception, public com.nordic.dto.common.ResponseDto com.nordic.api.MemberApiController.MemberState(java.lang.String,int) throws java.lang.Exception}
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:432) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:383) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:125) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:67) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:498) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1265) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1047) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:670) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.68.jar:9.0.68]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_333]

 

 

매핑이 모호하다는 메시지를 보고 생각을 해봤는데

포인트 정렬의 매핑값은 "/members/{pointArrange}/{pageNum}" 이고

활동 상태별 정렬의 매핑값은 "/members/{memberState}/{pageNum}" 이라서

제대로 매핑이 안 되는 듯 했다.

 

그래서 uri 형식을 약간 변경해주었다.

그랬더니 해결!

 

 

 

암호화 하지 않고 그대로 데이터를 넣었을 때

 

select member_code, member_name, password
from member
where member_code = '10001';

 

 

 

 

 

단방향 암호화 SHA256 - 복호화 x

여러가지 종류가 있다.

비밀번호 암호화에 사용된다.

 

UPDATE member SET 
PASSWORD = SHA2('1234', 256)
WHERE member_code = '10000';

 

 

 

 

 

 


 

 

 

 

 

양방향 암호화 Base64 

보안을 위해서 사용하는 암호화 방식 x

binary 파일을 텍스트로 나타날 때 사용.

2진 데이터를 아스키 코드화 하는 해시 암호화.

 

SELECT 
    member_code, member_name, 
    TO_BASE64('password'), FROM_BASE64(TO_BASE64('password'))
FROM member
WHERE member_code = '10000';

 

 

 

 

 

 

 

 

양방향 암호화 AES-ENCRYPT

개인정보를 암호화 해서 전송할 때 사용. 비밀번호는 양방향이 아닌 단방향 방식을 사용한다.

 

hex(AES_ENCRYPT('암호화 할 문자열', '암호화 키'))
--문자열에는 비밀번호를, 암호화 키에는 복호화 시 사용할 키 입력

UPDATE member SET
    PASSWORD = HEX(AES_ENCRYPT('1234', '1'))
WHERE member_code = '10000';

 

 

 

 

 

양방향 복호화 AES_DECRYPT

 

AES_DECRYPT(UNHEX(복호화 할 컬럼), '암호화 키')
--복호화 할 컬럼 명을 입력하고, 암호화 시 지정했던 키를 입력한다

SELECT 
    member_code, member_name, 
    AES_DECRYPT(UNHEX(password), '1')
FROM member 
WHERE member_code = '10000';

 

 

 

 

 

만약 암호화 시 입력한 키 대신 다른 값을 넣는다면? ('1' 대신 '2'를 넣어봄)

 

 

 

 

 

 

 

스프링 시큐리티에서 사용하는 암호화, 복호화, 데이터 비교 

https://blog.naver.com/gikimirane/222650988301

 

 

 

 

 

동적 SQL문을 활용해 검색 기능을 구현하려고 했는데

자꾸 무언가 문제가 일어났다.

 

        <span id="searchBox">
            <form id="frmSearch">
                <select id="search">
                    <option value="member_code">회원코드</option>
                    <option value="member_name">이름</option>
                    <option value="mobile_no">핸드폰</option>
                    <option value="address">주소</option>
                    <option value="age">나이</option>
                    <option value="sex">성별</option>
                </select>
            <input type="text" id="keyword">
            <button type="button" onClick="doSearch(1)">찾기</button>
        </form>
        </span>

 

 

셀렉트 박스에서 분류를 택하고 

text 폼에 키워드를 입력해서 백으로 넘기면 DB에서 데이터를 찾아 프론트로 넘겨 화면에 출력을 해야한다.

 

그래서 SearchDto를 따로 만들고, 컨트롤러부터 매퍼까지 작성을 마쳤다.

 

그런데 자꾸 문제가 일어났다.

 

 

 

 

 

 

1. 프론트에서 검색 분류와 키워드를 입력해 백으로 넘기면 null 값으로 도착함

 

이것은 두 가지 방법으로 해결했다.

 

1) 주소값에 search와 keyword를 담아서 오기

	/******************************** 검색으로 회원 조회 ********************************/
	@ApiOperation(value="검색으로 회원 조회")
	@GetMapping("/members/{search}/{keyword}/{pageNum}")
	public ResponseDto SearchMember(@PathVariable int pageNum, 
					@PathVariable SearchDto searchDto) throws Exception {

 

그런데도 실행이 되지 않아 로그를 찍어보니 Dto에 정보가 담겨있지 않았다. (죄다 null)

 

그래서 파라미터를 searchDto에서 String Search, String Keyword로 바꾸고

Dto에 직접 주입해주었다.

 

	/******************************** 검색으로 회원 조회 ********************************/
	@ApiOperation(value="검색으로 회원 조회")
	@GetMapping("/members/{search}/{keyword}/{pageNum}")
	public ResponseDto SearchMember(@PathVariable int pageNum, 
					@PathVariable String search,
					@PathVariable String keyword) throws Exception {
		
		SearchDto searchDto = new SearchDto();
		searchDto.setSearch(search); 
        	searchDto.setKeyword(keyword);
            
		log.info(searchDto.toString());

 

이렇게 하니 로그에 찍힌 DTO 값이 null 이 아닌 내가 입력한 값으로 잘 나왔다.

 

 

 

 

2. 동적 SQL문 문제

 

 

컨트롤러~매퍼까지 잘못 입력한게 없는 것 같은데 프론트로 도착하는 데이터를 보면 무언가 이상했다.

 

'민' 이 들어간 회원 이름을 검색했는데 도착한 데이터들을 보면 '민'이 들어가지 않은 회원의 이름도 보였다.

 

아무리 봐도 잘못한게 없는 것 같고,

이전 프로젝트 때에도 검색 기능을 문제없이 구현했던 터라 도대체 무엇이 문제일까 골똘히 생각했다.

생각을 하고, 검색을 해도 답을 찾지 못해 옆 자리 분께 여쭤보니 똑같은 문제로 골치 아팠다며 단번에 해결책을 주셨다....

 

그건 바로.. 사용하는 데이터베이스의 종류였다...

 

옆자리 분과 1차 프로젝트도 함께 하고 이번 파이널 프로젝트까지 함께 하게 됐는데,

그 분도 나와 같은 실수를 했던 것이었다....

 

1차 때 사용한 데이터베이스는 오라클이었고, 이번에는 MySQL을 사용하고 있기 때문에... ㅜㅜㅜ

 

-- 오라클

	<select id="doSearch" parameterType="SearchDto" resultType="MemberDto">
		select * from member
		<where>
			<if test="keyword != null and search != null">
				${search} like '%'||#{keyword}||'%'
			</if>
		</where>
	</select>

 

-- MySQL

	<select id="doSearch" parameterType="SearchDto" resultType="MemberDto">
		select * from member
		<where>
			<if test="keyword != null and search != null">
				${search} like CONCAT('%',#{keyword},'%')
			</if>
		</where>
	</select>

 

 

 

 

내가 생각해서 답을 찾는 것도 좋지만,

아무리 생각해봐도 답이 나오지 않으면 여기저기 물어보고 다니는 게 좋은 것 같다.

 

 

 

 

 

@RequestBody : Json을 DTO 객체에 매핑

@ModelAttibute 

컨트롤러의 메소드 파라미터 자리에 선언하지 않아도 자동으로 이것을 통해 데이터를 받아온다

GET 방식으로 값을 받아온다 (URL 끝에 /?id=1234&pw=1234 이런 형식)

현재 맞닥뜨린 문제

 

회원 정보 수정폼을 열어서 

폼에 입력한 값을 프론트 -> 백으로 전달->DB에 업데이트를 해야 하는데

 

프론트 -> 백 사이에 문제가 있다.

 

 

 

수정폼을 넘기면 프론트에서 넘어갈 때에는 console 창에 값이 잘 찍히는데 

백에 도착해서는 전부 null 값으로 찍힌다

 

 

 

 

 

이 문제를 하루나 붙잡고 있었는데 해결이 딱히 안되고 있다...

fetch post 로 하고 있었는데 그냥 ajax로 변경할까 생각도 들고..

 

 

 

백 MemberApiController

 

	/******************************** 회원정보수정 실행 ********************************/
	@ApiOperation(value = "회원 정보 수정")
	@PutMapping(value="/modify/{mC}")
	public ResponseDto ModifyOne (@PathVariable(value = "mC") String mC, 
				      @RequestBody MemberModifyDto memberModifyDto) {
				
		log.info("프론트에서 넘어온 수정할 정보↓");
		log.info(memberModifyDto.toString());
		
		//memberDto.getMember_name()으로 update SQL문 실행하기
		int result = memberService.modifyOne(memberModifyDto);
		ResponseDto responseResult = new ResponseDto(memberModifyDto.getMember_code()+" 수정 완료", result);
		
		log.info("mC: "+mC);
		log.info("responseResult: "+responseResult);
		
		return responseResult;
		
	}

 

 

 

 

프론트 doModifyForm 함수

 

   /********************* 회원정보수정 폼 *********************/

    function doModifyForm(member_code) {

        var member_code = document.getElementById("memberCode").value;
        var url = "http://localhost/api/member/modifyForm/"

        fetch(url+member_code, {
            method: "GET",
            mode:'cors',
            headers: {
                'Content-Type' : 'application/json',
            }
        })

        .then(response => response.json())
        .then(response => {

            var memKeys = Object.keys(response.data);
            var memValues = Object.values(response.data);

            console.log(memValues[0]);

            var data =
            /* <form action="javascript: doModify(${memValues[0]})" id="frmData"> */
                // <input type="hidden" name="_method" value="PUT"/>
            `
            <form method="put" id="frmData">
            회원코드 : <input type="text" id="member_code" name="member_code" value="${memValues[0]}" readOnly><br>
            이름 : <input type="text" id="member_name" name="member_name" value="${memValues[1]}"><br>
            핸드폰 : <input type="text" id="mobile_no" name="mobile_no" value="${memValues[2]}"><br>
            주소 : <input type="text" id="address" name="address" value="${memValues[3]}"><br>
            나이 : <input type="text" id="age" name="age" value="${memValues[4]}"><br>
            성별 : <input type="text" id="sex" name="sex" value="${memValues[5]}"><br>
            비밀번호 : <input type="text" id="password" name="password" value="${memValues[7]}"><br><br>
            <button type="button" onClick="doModify()"> 수정 </button>
            </form>
            `

            document.getElementById("modifyFormArea").innerHTML = data;
            
        })
        .catch (error => {
            console.log(error);
            alert(error);
            alert("에러입니다");
        })

    }

 

 

 

 

 

프론트 doModify 함수

 

    /********************* 회원정보수정 실행 *********************/
    function doModify() {
        
        var member_code = document.getElementById("member_code").value;
        var member_name = document.getElementById("member_name").value;
        var mobile_no = document.getElementById("mobile_no").value;
        var address = document.getElementById("address").value;
        var age = document.getElementById("age").value;
        var sex = document.getElementById("sex").value;
        var password = document.getElementById("memberCode").value;
        
        console.log(member_code);
        console.log(member_name);

        var url = "http://localhost/api/member/modify/";
        var data1 = $("#frmData").serialize();
        alert(data1);
        // JSON.stringify({
            //     "member_code" : member_code, 
            //     "member_name" : member_name,
            //     "mobile_no" : mobile_no,
            //     "address" : address,
            //     "age" : 10,
            //     "sex" : sex,
            //     "password" : password
            // })
        fetch(url+member_code, {
            method: "PUT",
            // mode:'cors',
            headers: {
                // 'Content-Type' : 'application/json',
            },
            body: data1
        })
        
        .then(response => response.json())
        .then((data) => {
            console.log(data);
        })
        .catch(error => {
            console.log("에러입니다");
            alert(error);
        })
    }

 

 

 


 

 

 

fetch 말고 ajax로 해결했다

백은 @PutMapping만 @PostMapping으로 고쳤다.

 

기존에 백에서 사용하던 @PutMapping에 맞춰서 ajax함수의 타입을 put으로 설정했는데 이건 오류가 났다.

ajax의 타입은 Post, 백의 어노테이션은 @PostMapping.

 

fetch로 하루를 붙들고 있었는데

ajax로 고치자마자 바로 해결되어서 얼떨떨하다.. 이럴수가

 

   /********************* 회원정보수정 실행 *********************/
    function doModify() {
        
        var member_code = document.getElementById("member_code").value;
        var member_name = document.getElementById("member_name").value;
        var mobile_no = document.getElementById("mobile_no").value;
        var address = document.getElementById("address").value;
        var age = document.getElementById("age").value;
        var sex = document.getElementById("sex").value;
        var password = document.getElementById("memberCode").value;
        
        console.log(member_code);
        console.log(member_name);

        var url1 = "http://localhost/api/member/modify/";
        var data1 = $("#frmData").serialize();

        $(function() {
        
            $.ajax({
                type : "post",
                url : url1 + member_code,
                data : data1,
                success : function(result) {
                    alert(result);
                    alert("회원정보수정 완료!");
                }
            }); // ajax end
            
        }); // jQuery function end

    }

전체 회원 목록의 페이징 처리 완료

 

 

 

특정 회원 조회 폼에서 수정폼 불러오기

 

 

.then, .catch

 

<script>

    var fetched = fetch ('http://jsonplaceholder.typicode.com/posts')	// 특정 url에서 값을 가져옴

    fetched.then (function(response) {	// url에서 값을 가져오는 것이 성공할 경우 실행할 콜백함수
    	console.log("response: ", response);
    } );	
    
    fetched.catch (function(reason) {	// url에서 값을 가져오는데 실패하거나 에러 발생시 실행할 콜백함수
    	console.log("reason: ", reason);
    } );

</script>

 

 

 

간소화

 

<script>

    fetch ('http://jsonplaceholder.typicode.com/posts');	// 특정 url에서 값을 가져옴

    .then (function(response) {	// url에서 값을 가져오는 것이 성공할 경우 실행할 콜백함수
    	console.log("response: ", response);
    } );	
    
    .catch (function(reason) {	// url에서 값을 가져오는데 실패하거나 에러 발생시 실행할 콜백함수
    	console.log("reason: ", reason);
    } );
    
</script>

 

 

 

더 간소화

 

<script>

    fetch ('http://jsonplaceholder.typicode.com/posts');	// 특정 url에서 값을 가져옴

    .then (function(response) {	// url에서 값을 가져오는 것이 성공할 경우 실행할 콜백함수
    	console.log("response: ", response);
    } );	
    
    .catch (function(reason) {	// url에서 값을 가져오는데 실패하거나 에러 발생시 실행할 콜백함수
    	console.log("reason: ", reason);
    } );
    
</script>

 

 

 

response의 속성

response.text(), response.json(), 기타등등

응답받은 데이터를 text 타입이나 json으로 가공

 

 

 

 

 

지난 1차 프로젝트 때 구현하고 싶었으나 시간, 체력의 한계로 미처 처리하지 못한 것이 있었으니

체크박스 체크 유무에 따라 불러오는 정보를 다르게 보여주는 것이었다.

비동기로!!!

 

결국은 동기적으로 처리했고,

'탈퇴 회원 포함' 이라는 이름을 가진 체크박스를 선택하면

주소값이 바뀌면서 탈퇴 회원을 포함한 member 테이블의 모든 정보를 출력한다.

 

 

 

하지만 이번 파이널 프로젝트를 진행하면서 이걸 해냈다.

해결하기 전까지는 이전에 회피한 문제가 부메랑처럼 돌아서 나에게 꽂히는 느낌이었지만 ^^

성공하고 나니 세상은 이래서 살만한 것 같은 느낌이 들고 행복하네요...

진짜 별 거 아닌데 지금 이 프로젝트 진행하면서 내가 이것밖에 안되는 구나.. 하면서 좌절하고 있기 때문에

이런 고양감 성취감 중요하다구요

 

 

 

 

처음 회원정보 페이지가 로드 되었을 때

 

 

 

 

 

관리자 회원정보만 불러왔을 때

 

 

 

 

 

모든 회원 정보를 불러왔을 때

 

 

 

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>전체 회원 정보</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
    <script src='main.js'></script>
</head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>

    /****************** 회원 정보 출력 ******************/
    function findAll() {

    if ($("#aC").is(":checked")) {  // 관리자 체크박스가 checked 상태일 때
        alert("관리자 회원의 정보를 불러옵니다.");
        var url = "http://localhost:80/member/admins";
    } else {
        if (confirm("모든 회원의 정보를 불러오시겠습니까?")) {
            alert("모든 회원의 정보를 불러옵니다.");
            var url = "http://localhost:80/member/members";
        } else {
            $("#members").empty();
            return false;
        }
    }
        fetch(url, {
            method: "GET",
            mode: 'cors',
            headers: {
            'Content-Type' : 'application/json',
            }
        })
        
        .then(response => response.json())
        .then(response => {

            $("#members").empty();

            var tableColumnL = (response.data.length); // 행 길이
            
                for (var j=0; j<tableColumnL; j++){

                    var memValues = Object.values(response.data[j]);
                    // memValues.length                    // 열 길이 (22개 고정)
                    
                    $("#members").append(`<tr>`);
                    $("#members").append(`<td>${j+1}</td>`);

                    var i=0;
                    while (i < memValues.length) {

                        var data = `
                        <td>${memValues[i]}</td>
                        `
                        i++
                        $("#members").append(data);
                    }   // while end (td 추가 끝)
                    
                    console.log(memValues[0]);
                    var member_code = memValues[0];
                    var data = `<td><button onClick="doModify(${member_code})">수정${j+1}</button></td>
                    <td><button onClick="doDelete(${member_code})">삭제${j+1}</button></td></tr>`
                    $("#members").append(data);
                }   //for end

        })

        .catch(error => {
            console.log(error);
            alert(error);
        });
    } // findAll end
</script>
<body>

<button onClick="findAll()">회원정보 불러오기</button>
<span id="adminCheck">
    <input type="checkbox" id="aC" onClick="findAll()"> 
    <label for="aC"> 관리자 여부 </label>
</span>
<br><br><br>
<div id="allMemList">
    <table border="1">
        <thead>
            <tr>
                <th></th>
                <th>회원코드</th>
                <th>이름</th>
                <th>핸드폰</th>
                <th>주소</th>
                <th>나이</th>
                <th>성별</th>
                <th>동의여부</th>
                <th>비밀번호</th>
                <th>가입승인여부</th>
                <th>가입승인일시</th>
                <th>활동중지여부</th>
                <th>활동중지일시</th>
                <th>관리자여부</th>
                <th>관리자등록일</th>
                <th>누적포인트</th>
                <th>가용포인트</th>
                <th>사용포인트</th>
                <th>비고</th>
                <th>등록자</th>
                <th>등록일시</th>
                <th>변경자</th>
                <th>변경일시</th>
                <th></th><th></th>
            </tr>
        </thead>
        <tbody id="members" name="members"></tbody>
    </table>
</div>
</body>
</html>

 

 

 

 

중요한 것은 

 

1) 체크박스의 체크 유무 검사

2) 특정 영역에 불러온 내용 출력하기 / 그 영역에 기존에 로드된 내용이 있다면 그 내용 제거하기

 

 

 

aC 라는 이름의 체크박스의 유무 검사하기

<script>
function checked() {
	if ( $("#aC").is(":checked") ) {
	    alert( "체크되었습니다." );
	} else {
    	    alert( "체크 해제 되었습니다." );
    }
}
</script>

<span id="adminCheck">
    <input type="checkbox" id="aC" onClick="findAll()"> 
    <label for="aC"> 관리자 여부 </label>
</span>

'프로젝트 > 파이널 프로젝트' 카테고리의 다른 글

프로젝트 15일차  (0) 2022.12.05
fetch 와 promise  (0) 2022.12.03
프로젝트 12일차 / 자바스크립트 append 문제 해결  (0) 2022.12.02
프로젝트 10일차  (0) 2022.11.30
롬복 어노테이션  (0) 2022.11.28

회원 전체의 정보 받아와 테이블로 출력하기

 

 

 

 

 

백 쪽의 코드

 

 

MemberApiController.java

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberApiController {
	
	private final MemberService memberService;

	/******************************** 회원 전체목록 조회 ********************************/
	@ApiOperation(value="회원 전체목록 조회")
	@GetMapping("/members")
	public ResponseDto MemberDtoList() throws Exception{
		
		Map<String, Object> memberObj = new HashMap<>();
		memberObj.put("data", memberService.findAll());
		ResponseDto result = new ResponseDto("회원 전체목록 구하기 성공", memberObj.get("data"));
		log.info("회원 전체목록 조회 완료");
		
		return result;
	}
}

 

 

MemberService.java (원래 컨트롤러는 경로만 지정하고 서비스 쪽에 기능을 구현해야 하는건데... ^^)

@Service
@RequiredArgsConstructor
public class MemberService {
	
	private final MemberRepository memberRepository;
	
	public List<MemberDto> findAll() {
		List<MemberDto> memberList = memberRepository.findAll();
		return memberList;
	}
}

 

 

 

 

MemberRepository.java

@Slf4j
@Repository
@RequiredArgsConstructor
public class MemberRepository implements MemberMapper {

	@Override
	public List<MemberDto> findAdmins() {
		return memberMapper.findAdmins();
	}
}

 

 

 

MemberMapper.java

@Mapper
public interface MemberMapper {
	
	List<MemberDto> findAll();
}

 

 

member.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nordic.repository.member.MemberMapper">

	<select id="findAll" resultType="MemberDto">
		select * from member
	</select>
    
</mapper>

 

 

 

 

 

프론트 쪽의 전체코드

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>전체 회원 정보</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
    <script src='main.js'></script>
</head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>

	function findAll() {
        fetch("http://localhost:80/member/members", {
            method: "GET",
            mode: 'cors',
            headers: {
                'Content-Type' : 'application/json',
            }
        }) // fetch end
        .then(response => response.json())
        .then(response => {
                
            var tableColumnL = (response.data.length); 		//1438 (행 길이)
            console.log(Object.values(response.data[0]));   // 회원의 상세정보

                for (var j=0; j<tableColumnL; j++){

                    var memValues = Object.values(response.data[j]);
                    // memValues.length                    //22 (열 길이)
                    
                    $("#members").append(`<tr>`);

                    var data1 = (`<td>${j+1}</td>`);
                    $("#members").append(data1);

                    var i=0;
                    while (i < memValues.length) {

                        var data2 = `
                        <td>${memValues[i]}</td>
                        `
                        $("#members").append(data2);
                        i++
                    }   // while end (td 추가 끝)

                    $("#members").append("</tr>");
                }   //for end
        })
        .catch(error => {
            console.log(error);
            alert(error);
        });
    } // findOne end
</script>
<body>

<button onClick="findAll()">회원정보 불러오기</button>
<div id="adminCheck">
    <input type="checkbox" id="aC" value=1> 
    <label for="aC"> 관리자 여부 </label>
</div>
<br><br><br>
<table border="1" id="members">
    <tr>
        <th></th>
        <th>회원코드</th>
        <th>이름</th>
        <th>핸드폰</th>
        <th>주소</th>
        <th>나이</th>
        <th>성별</th>
        <th>동의여부</th>
        <th>비밀번호</th>
        <th>가입승인여부</th>
        <th>가입승인일시</th>
        <th>활동중지여부</th>
        <th>활동중지일시</th>
        <th>관리자여부</th>
        <th>관리자등록일</th>
        <th>누적포인트</th>
        <th>가용포인트</th>
        <th>사용포인트</th>
        <th>비고</th>
        <th>등록자</th>
        <th>등록일시</th>
        <th>변경자</th>
        <th>변경일시</th>
    </tr>

</table>
</body>
</html>

 

 

 

 

 

script 영역에서 fetch로 가져온 데이터를 for문으로 돌려서

body 영역의 테이블에 계속해서 추가하는 것을 원했는데 자꾸 이렇게 나왔다...

내가 쓴 for문은 틀리지 않았는데... ㅜㅜ

 

		var tableColumnL = (response.data.length); //1438 (행 길이)
		console.log(Object.values(response.data[0]));   // 회원의 상세정보

                for (var j=0; j<tableColumnL; j++){

                    var memValues = Object.values(response.data[j]);
                    // memValues.length                    //22 (열 길이)
                    
                    $("#members").append(`<tr>`);	// id가 members인 테이블에 <tr> 태그 추가

                    var data1 = (`<td>${j+1}</td>`);	// id가 members인 테이블에 인덱스 번호 열 추가
                    $("#members").append(data1);

                    var i=0;
                    while (i < memValues.length) {

                        var data2 = `
                        <td>${memValues[i]}</td>
                        `
                        $("#members").append(data2);
                        i++
                    }   // while end (td 추가 끝)	// json 데이터의 회원 정보를 뽑아와
							// id가 members인 테이블에 열 추가
                    $("#members").append("</tr>");	// id가 members인 테이블에 </tr> 추가
                }   //for end

 

 

대체 왜 행 바꾸기가 안되는 거냐고~!!!!

 

 

 

 

정답은 tbody 태그였다 ^^

 

F12를 눌러 개발자 도구의 요소 검사를 통해 보니 

<tr></tr>만 1438개가 생성되어 있었다....

그리고 가장 마지막에 회원 정보 데이터가 행바꿈이 하나도 안된채로 가로로 길게 나열되어 있었음...

1438명의 회원데이터가 모두..... 테이블 컬럼이 22개나 되는건데... 

 

 

 

진짜 어이없었음 내가 짠 for문은

 

1) <tr> 추가

2) 회원정보 데이터를 while문으로 뽑아내서 추가

3) </tr> 추가

 

이렇게 순서대로 요소가 table에 추가되도록 만든 건데...

 

 

 

 

 

그래서 이걸 어떻게 해결했냐면.. 정답은 tbody 였다.

 

내가 테이블을 만들때 thead와 tbody를 따로 지정하지 않았는데 그게 문제였다.

<table id="members"> 가 아닌

<tbody id="members"> 로 지정하여

그 영역에 for문으로 뽑아낸 회원 데이터를 추가했어야 하는 거였다.

 

그랬더니 해결!

 

 

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>전체 회원 정보</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
    <script src='main.js'></script>
</head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>

	function findAll() {
        fetch("http://localhost:80/member/members", {
            method: "GET",
            mode: 'cors',
            headers: {
                'Content-Type' : 'application/json',
            }
        }) // fetch end
        .then(response => response.json())
        .then(response => {
                
		var tableColumnL = (response.data.length); //1438 (행 길이)
		console.log(Object.values(response.data[0]));   // 회원의 상세정보

                for (var j=0; j<tableColumnL; j++){

                    var memValues = Object.values(response.data[j]);
                    // memValues.length                    //22 (열 길이)
                    
                    $("#members").append(`<tr>`);	// 테이블의 tbody 영역에 <tr> 태그 추가

                    var data1 = (`<td>${j+1}</td>`);	// 테이블의 tbody 영역에 인덱스 번호 열 추가
                    $("#members").append(data1);

                    var i=0;
                    while (i < memValues.length) {

                        var data2 = `
                        <td>${memValues[i]}</td>
                        `
                        $("#members").append(data2);
                        i++
                    }   // while end (td 추가 끝)	// json 데이터의 회원 정보를 뽑아와
							// 테이블의 tbody 영역에 열 추가
                    $("#members").append("</tr>");	// 테이블의 tbody 영역에 </tr> 추가
                }   //for end
        })
        .catch(error => {
            console.log(error);
            alert(error);
        });
    } // findOne end
</script>
<body>

<button onClick="findAll()">회원정보 불러오기</button>
<div id="adminCheck">
    <input type="checkbox" id="aC" value=1> 
    <label for="aC"> 관리자 여부 </label>
</div>
<br><br><br>
<table border="1">
    <tr>
    	<thead>
        <th></th>
        <th>회원코드</th>
        <th>이름</th>
        <th>핸드폰</th>
        <th>주소</th>
        <th>나이</th>
        <th>성별</th>
        <th>동의여부</th>
        <th>비밀번호</th>
        <th>가입승인여부</th>
        <th>가입승인일시</th>
        <th>활동중지여부</th>
        <th>활동중지일시</th>
        <th>관리자여부</th>
        <th>관리자등록일</th>
        <th>누적포인트</th>
        <th>가용포인트</th>
        <th>사용포인트</th>
        <th>비고</th>
        <th>등록자</th>
        <th>등록일시</th>
        <th>변경자</th>
        <th>변경일시</th>
    </tr>
    </thead>
    <tbody id="members">
    
    </tbody>
</table>
</body>
</html>

 

 

 

테이블 만들 때 thead, tbody 영역을 잘 지정해줘야겠다.

+ Recent posts