20220830 [Spring Boot]

Yeoonnii·2022년 8월 30일
0

TIL

목록 보기
15/52
post-thumbnail

🗝️ 오류발생시 컨트롤러에서 출력sysout하여 확인하는 습관들이기


게시글 상세페이지

board 제목 누르면 다음페이지 내용나오게 구현

📁 BoardService.java

  • public Board selectOneBoard(long no){ ➡️ entity로 받아도 된다
  • CrudRepository.findById(Long id) : Optional<Board>
    + .orElse ➡️ 해당 no가 없을경우 처리방법
    • Optional : 조회할 게시글이 있다면 no에 해당하는 Board 가져오고 없으면 null을 넣음
      = if문 처리 기능과 같다
    • .orElse : 해당 no가 없을경우 처리
    • Optional<T> : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 값을 반환함.
public Board selectOneBoard( long no ){
        try {
			// 내가 작성한 코드
            // Query query = new Query();
🗝️ 오류발생시 컨트롤러에서 출력`sysout`하여 확인하는 습관들이기
​
---
​
## 게시글 상세페이지
> board 제목 누르면 다음페이지 내용나오게 구현
![](https://velog.velcdn.com/images/yeoonnii/post/dedd740c-59c3-4647-a454-efd19c637429/image.png)
​
​
​
### 📁 BoardService.java
> * `public Board selectOneBoard(long no){` ➡️ `entity`로 받아도 된다
 * `CrudRepository.findById(Long id) : Optional<Board>` 
  \+  `.orElse` ➡️ 해당 no가 없을경우 처리방법
 >>* `Optional` : 조회할 게시글이 있다면 `no`에 해당하는 Board 가져오고 없으면 null을 넣음
 = if문 처리 기능과 같다
>>* `.orElse` : 해당 no가 없을경우 처리
>>* `Optional<T>` : 저장된 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 인수로 전달된 값을 반환함.
​
```java
public Board selectOneBoard( long no ){
        try {
            // 내가 작성한 코드
            // Query query = new Query();
            // query.addCriteria(Criteria.where("_id").is(no));
            // return mongoTemplate.findOne(query, Board.class);// Optional방식
            Board board = bRepository.findById(no).orElse(null); 
            return board;} catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

📁 BoardController.java

defaultvalue = 0
➡️ 해당 게시글이 없는경우 목록으로 가게한다(오류처리)

// 상세페이지 1개 조회
    @GetMapping(value = "/boardone.do")
    public String boardOneGET(Model model,

나가기
임시저장수정하기
20220830 [Spring Boot]

        // query.addCriteria(Criteria.where("_id").is(no));
        // return mongoTemplate.findOne(query, Board.class);

		// Optional방식
        Board board = bRepository.findById(no).orElse(null); 
        return board;

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

### 📁 BoardController.java
> `defaultvalue = 0` 
➡️ 해당 게시글이 없는경우 목록으로 가게한다(오류처리)

```java
// 상세페이지 1개 조회
    @GetMapping(value = "/boardone.do")
    public String boardOneGET(Model model,
            @RequestParam(name = "no", defaultValue = "0") long no) {

        
        if (no == 0) { // 번호가 없는경우, 오류처리
            return "redirect:/board/boardlist.do";
        }
        // 1.서비스에서 가져오기
        Board retboard = bService.selectOneBoard(no);
        System.out.println(retboard.toString());

        // 2.VIEW에서 html로 값 전달
        // 화면나오기전에 html로 데이터 보내기 => 목록
        model.addAttribute("obj", retboard ); 

        // view표시
        return "boardone";
    }

📁 boardone.html

받아오는 데이터는 obj 하나니까 반복문 돌리지 않고 바로 obj로 받으면 된다

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>상세페이지</title>
</head>

<body>
    <div style="border: 1px double #0000006e; padding: 20px;">
        <h3>상세페이지</h3>
        <hr />

        번호<span th:text="${obj.no}"></span><br />
        제목<span th:text="${obj.title}"></span><br />
        내용<span th:text="${obj.content}"></span><br />
        작성자<span th:text="${obj.writer}"></span><br />
        조회수<span th:text="${obj.hit}"></span><br />
        작성일<span th:text="${obj.regdate}"></span> <br />
    </div>

</body>

</html>

게시판 수정

수정은 화면 이동과 같다 ➡️ get이니 a태그 사용할 수 있다
삭제는 post로 보내기 떄문에 a태그를 사용할 수 없다

📁 boardupdate.html

  1. 수정버튼 클릭되면 게시판 수정 전 기존데이터 가져오기
  2. 수정할 데이터 입력 받기
  • content 내용이 길기 때문에 get이 아닌 post사용한다
  • 변경버튼 생성시 <a> + <button> 태그가 아니라 <input>태그로 바꿔줘야 <form>태그 영향을 받지 않는다 ➡️ <a> + <button>은 폼태그와 별도로 실행
  • form내부에서 데이터 입력받을때 th:value="${obj.데이터입력될변수명}"를 지정하면 해당 obj에 사용자가 입력한 데이터가 들어간다
  • name="no"는 입력데이터는 아니지만, 변경조건(=변경될 글 번호)이기 때문에 name을 지정해준다

    name ➡️ entity 변수명
    value ➡️ 실제 입력되는값

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시판변경</title>
</head>
<body>
    <form th:action="@{/board/boardupdate.do}" method="post">
    글번호<input type="text" th:value="${obj.no}" name="no" readonly/><br />
    제목<input type="text" th:value="${obj.title}" name="title"/><br />
    내용<input type="text" th:value="${obj.content}" name="content"/><br />
    작성자<input type="text" th:value="${obj.writer}" name="writer"/><br />
    조회수<input type="text" th:value="${obj.hit}" readonly/><br />
    작성일<input type="text" th:value="${obj.regdate}" readonly/><br />
    <input type="submit" value="변경" />

    <a th:href="@{/board/boardlist.do}"><input type="button" value="목록" /></a>
    <a th:href="@{/board/boardone.do(no=${obj.no})}"><input type="button" value="상세" /></a>
</form>

</body>
</html>

📁 BoardController.java

  1. 수정할 게시글 가져오기 boardUpdateGET
    ➡️ 변경버튼 누르고 수정페이지로 이동할때 기존데이터 가져온다
  2. DB 수정하기 boardUpdatePOST
  • html에서 href작성하고 해당주소 보면서 Controller 작성하면 편하다
// http://127.0.0.1:8080/ROOT/board/boardupdate.do?no=21
    // 수정할 게시글 가져오기
    @GetMapping(value = "/boardupdate.do")
    public String boardUpdateGET(
            Model model,
            @RequestParam(name = "no", defaultValue = "0") long no) {
        // 0. 오류처리
        if (no == 0) { // 번호가 없는경우, 오류처리
            return "redirect:/board/boardlist.do";
        }
        // 서비스에서 가져오기
        Board retboard = bService.selectOneBoard(no);
        System.out.println(retboard.toString());

        // 2.VIEW에서 html로 값 전달
        model.addAttribute("obj", retboard);

        // view표시
        return "boardupdate";
    }

    // ROOT/board/boardupdate.do?no=10
    // 수정하기
    @PostMapping(value = "/boardupdate.do")
    public String boardUpdatePOST(@ModelAttribute Board board) {
        int ret = bService.updateBoard(board);
        if(ret == 1){
            return "redirect:/board/boardone.do?no=" + board.getNo();
        }
        return "redirect:/board/boardupdate.do?no=" + board.getNo();
}

📁 BoardService.java

DB수정용 Service 생성
➡️ 기존데이터를 불러오고 update하는 항목만 덮어쓴다

✔️ 반드시 기존 데이터를 꺼낸 후 수정해야 한다!
기존 데이터를 꺼내지 않은 상태에서 수정하면 불러오지 않은 기존 데이터 hit, regdate는 빈칸으로 업데이트 될지도 모르기 때문이다

// 수정하기
    public int updateBoard (Board board){
        try {
            
            // 1. 기본키를 이용하여 기존데이터를 꺼냄
            Board board1 = bRepository.findById((board.getNo())).orElse(null);

            // 2. board1에 board의 값으로 변경
            board1.setTitle(board.getTitle());
            board1.setWriter(board.getWriter());
            board1.setContent(board.getContent());

            // 3. 변경된 board1을 save
            if( bRepository.save(board1) != null ){
                return 1;
            }
            return 0;

        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

게시판삭제

📁 boardone.html

  • 게시글 삭제시 만약 get을 사용한경우 누군가 주소창에 입력만 해도 데이터 삭제가 실행될 수 있으니 사용하면 안된다
    ➡️ <form>태그 내부에 삭제 코드를 작성한다
  • <div style="display: inline-block;"> ➡️ 디자인적 요소
  • <a> + <button><input type="button">으로 변경해준다
    ➡️ <a> + <button>은 폼태그와 별도로 실행된다
  • th:onclick="|javascript:deleteAction()|” ➡️ 클릭시 작성한 자바스크립트를 호출
  • <script> 태그 생성 + type="text/javascript"설정 ➡️ 삭제 버튼 클릭시 알림창 띄워주는 함수 생성
<div style="display: inline-block;">
	<form th:action="@{/board/boarddelete.do}" method="post" id="form">
    	<input type="hidden" th:value="${obj.no}" name="no" />
    	<input type="button" value="삭제" th:onclick="|javascript:deleteAction()|">
    </form>
</div>

<script type="text/javascript">
        const deleteAction = () => {
            const ret = confirm('삭제할까요?');
            if (ret === true) {
                document.getElementById("form").submit(); // id = form 을 찾아 submit
            } //취소하면 아무일도 일어나지 않음
        }
...

       

📁 BoardController.java

// http://127.0.0.1:8080/ROOT/board/boarddelete.do
    // 삭제하기
    @PostMapping(value = "/boarddelete.do")
    public String boardDeletePost(
        @RequestParam(name = "no") long no){
            int ret = bService.deleteBoard(no);
            if(ret == 1){
                return "redirect:/board/boardlist.do";
            }
            // http://127.0.0.1:8080/ROOT/board/boardone.do?no=24
            return "/board/boardone.do?no=" + no;
        }

📁 BoardService.java

// 삭제하기
    public int deleteBoard(long no) {
        try {
            bRepository.deleteById(no);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }

게시판 이전글/다음글

이전글/다음글 이동시 바로 한 페이지전으로 이동한다고 생각하면 안된다
해당 페이지보다 작은/큰 페이지중 가장 큰/작은 페이지를 가져와야 한다

이전글 조회 조건

  1. _id가 전송되고 있는 no 보다 더 작아야 함
  2. 1.에서 찾은 작은수들 중 내림차순 정렬
  3. 내림차순으로 정렬된 수 중 1개만 가져오기

다음글 조회 조건

  1. _id가 전송되고 있는 no보다 더 커야 함
  2. 1.에서 찾은 큰수들 중 오름차순 정렬
  3. 오름차순으로 정렬된 수 중 1개만 가져오기

📁 BoardRepository.java

  • gte는 이상 gt는 초과 lt 미만 lte 이하
  • @Aggregation ➡️ 통계낼때 사용 ,쿼리보다 복잡한 조건을 줄 수 있다
  • $project사용시 service에서 _id만 꺼내어 쓰지 않아도 된다! 바로 리턴 가능
// 이전글
    @Aggregation(pipeline = {
        // _id가 전송되고 있는 no 보다 더 작아야 함
        "{ '$match'  : { '_id' : {$lt : ?0} } }",
        // 작은것 중 내림차순 정렬
        "{ '$sort'   : { '_id' : -1 } }",
        // 1개만 가져오기
        "{ '$limit'  : 1 }"
    })
    // long no => 현재 글 번호
    public Board selectBoardPrev( long no );

    // 다음글
    @Aggregation(pipeline = {
         // _id가 전송되고 있는 no 보다 더 커야 함
         "{ '$match'      : { '_id' : {$gt : ?0} } }",
        //  아예 가져올때 번호만 가져온다 
        "{ '$project' : { '_id' : 1 } }",         
         // 큰것 중 오름차순 정렬
         "{ '$sort'       : { '_id' : 1 } }",
         // 1개만 가져오기
         "{ '$limit'      : 1 }"
     })
     // long no => 현재 글 번호
     public long selectBoardNext( long no );

📁 BoardService.java

    // 이전글 조회 => 컨트롤러 boardone 에 추가
    public long prevBoard(long no) {
        try {
            // Boardrepository 에서 projection 사용안한경우 아래 코드 사용
            Board board = bRepository.selectBoardPrev(no);
            return board.getNo(); //가져온 board에서 no를 꺼내주어야 함

        } catch (Exception e) {
            e.printStackTrace();
            return 0L;
        }
    }

    // 다음글 조회 => 컨트롤러 boardone 에 추가
    public long nextBoard(long no) {
        try {
            // Boardrepository 에서 project 사용한경우 selectBoardNext자체를 리턴
            return bRepository.selectBoardNext(no);

        } catch (Exception e) {
            e.printStackTrace();
            return 0L;
        }
    }

📁 BoardController.java

// 상세페이지 1개 조회
 @GetMapping(value = "/boardone.do")
    public String boardOneGET(Model model,
            @RequestParam(name = "no", defaultValue = "0") long no) {
...
	// 1.1 이전글
    long prevNo = bService.prevBoard(no);
    // 1.2 다음글
    long nextNo = bService.nextBoard(no);
...
	model.addAttribute("prev", prevNo); // 이전글 번호 정보
	model.addAttribute("next", nextNo); // 다음글 번호 정보
...
	return "boardone";

📁 boardone.html

  • <input type="button"> ➡️ <form> 내부에 작성된 <submit> 에 반응
  • <a>+<button> ➡️ <form>내부에 있어도 반응하지 않음
    <a th:if="${prev != 0}" th:href="@{/board/boardone.do(no=${prev})}">
     <button>이전글</button>
    </a>
	<div style="display: inline-block;">
	<!-- http://127.0.0.1:8080/ROOT/board/boardone.do?no=23 -->
	<!-- 이전글이 없는경우 no=0인경우는 반응하면 안된다! =>if문 사용하기 -->
		<a th:if="${prev != 0}" th:href="@{/board/boardone.do(no=${prev})}">
        <button>이전글</button>
        </a>
	</div>

    <div style="display: inline-block;">
		<a th:if="${next != 0}" th:href="@{/board/boardone.do(no=${next})}">
		<button>다음글</button>
		</a>
	</div>

🤯 오류


💡 "{ '$projection' : { '_id' : 1 } }" 으로 잘못 작성하여 생긴 오류였다
"{ '$project' : { '_id' : 1 } }"로 수정해주니 오류없이 작동한다


댓글등록/조회

📁 boardone.html

  • <table>생성 반복문 돌려서 출력
    ➡️ 댓글이 있는경우/없는경우 두가지로 나누어 출력한다
    ➡️ thymeleaf if list empty 검색하여 if 사용법 참고
  • 원본게시글 번호를 html <form>태그안에 hidden으로 잡아둔다
  • 사용자가 입력하는건 댓글 내용과 작성자
  • 원래는 댓글 등록시 임시비밀번호를 지정하게 하고 삭제시 비밀번호 일치하면 지울 수 있게끔 해야한다
  • 원본 게시글 번호는 obj.no 이다
    입력되는 데이터를 BoardReply에 맞게 name 을 지정해준다
...
        <form th:action="@{/board/boardreplyinsert.do}" method="post">
            <input type="hidden" th:value="${obj.no}" name="boardno" />
            <textarea rows="4" placeholder="답글내용" name="content"></textarea>
            <input type="text" placeholder="작성자" name="writer">
            <input type="submit" value="답글" />
        </form>

        <table border="1">
            <!-- 댓글이 있는경우 -->
            <tr th:if="${not #lists.isEmpty(rlist)}" th:each="tmp, idx : ${rlist}">
                <td th:text="${idx.count}"></td>
                <!-- <td th:test="${tmp.no}"></td> //삭제시에는 no가 필요 -->
                <td th:text="${tmp.content}"></td>
                <td th:text="${tmp.writer}"></td>
                <td th:text="${tmp.regdate}"></td>
                <td><button th:onclick="|javascript:deleteAction('${tmp.no}')|">삭제</button></td>
            </tr>
            <!-- 댓글이 없는경우 -->
            <tr th:if="${#lists.isEmpty(rlist)}">
                <td colspan="5"> 댓글이 없습니다</td>
            </tr>
        </table>
...
        // form 만들어도 된다. script에서도 폼 생성 가능
        const deleteReplyAction = (no) => {
            if (confirm('댓글을 삭제할까요?')) {
                // 스크립트가 <form> 생성
                const form = document.createElement("form");
                // <form action="aaaaa">
                form.setAttribute("action", "")
                // 메소드 생성<form action="aaaaa" method="post">
                form.setAttribute("method", "post");
                document.body.appendChild(form);
                form.submit();
            }

📁 entity / BoardReply.java

  • 원본게시글이 있어야 하위에 댓글 작성 가능함
    ➡️ entity / BoardReply.java 에 외래키로 원본게시글 번호가 있어야한다
  • 댓글과 게시판 기능은 컨트롤러, 서비스는 같은파일에 코드 작성할 수는 있지만 Repository(저장소)는 같은 파일에 쓸 수 없다 entity 생성되면 Repository는 따로 생성해야 한다.
@Getter
@Setter
@ToString
@NoArgsConstructor
@Document(collection = "boot_board_reply") // DB컬렉션 생성

public class BoardReply {

    @Id
    private long no; // 답글번호(시퀀스), 기본키
    private long boardno = 0L; //원본 게시글 번호, 외래키(게시물 존재하는 것)

    private String content; // 답글내용
    private String writer; // 답글작성자
    private Date regdate;

}

📁 BoardController.java

상세페이지 1개가 조회되는 시점에 댓글 목록도 같이 호출되어 있어야 한다

    // 상세페이지 1개 조회
    @GetMapping(value = "/boardone.do")
    public String boardOneGET(Model model,
            @RequestParam(name = "no", defaultValue = "0") long no) {

...

	//1.3 댓글 목록
		List<BoardReply> rlist = bService.selectBoardReplyList(no);
        
	// VIEW에서 html로 값 전달
    model.addAttribute("rlist", rlist); // 답글목록
    
    return "boardone";

📁 BoardService.java

...
// 댓글 등록하기
    public int insertBoardReply(BoardReply boardReply){
        try {
            // 시퀀스 사용하기
            long seq = cService.generateCounter("SEQ_BOARD_REPLY_NO");
            // 기본키 no 와 regdate안만들어진 상태
            boardReply.setNo(seq);
            boardReply.setRegdate(new Date());

            // 저장소에 저장
            if( brRepository.save(boardReply) != null){
                return 1;
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    
    // 해당 게시글에 등록된 댓글 목록 가져오기
    // 게시판 원본 글 번호
    public List<BoardReply> selectBoardReplyList( long boardno ){
        try {
            // 댓글을 _id기준으로 내림차순 정렬
            Sort sort = Sort.by(Direction.DESC, "_id");
            return brRepository.findByBoardno(boardno, sort);
            
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
...

📁 BoardReplyRepository.java

  • 기본적인 CRUD(추가, 수정, 삭제, 조회) 기능이 포함되어 있다
  • boardno에 해당하는 댓글들을 list로 가져오기
  • Query 말고 findby변수명 사용
    ➡️ 쿼리는 db에 맞춰져있어서 db변경되면 같이 변경해야함 되도록이면 쿼리를 안쓰는게 좋다
import com.example.entity.BoardReply;
@Repository
public interface BoardReplyRepository extends MongoRepository<BoardReply, Long>{
	public List<BoardReply> findByBoardno(long boardno, Sort sort);
}

게시물 조회수 증가

별도의 저장소 필요없음! save 사용하여 변경사항 바로 저장

📁 BoardService.java

일종의 수정과 같다!
1. 게시물 조회 하기
2. 조회한 게시물의 기존 조회수hit를 꺼내기
3. hit + 1증가

// 게시물 클릭시 조회수 1 증가
    public int boardUpdateHit( long no ){
        try {

            // 1. 게시물 꺼내기
            Board board = bRepository.findById(no).orElse(null);
            // 기존조회수 꺼내기 + 1
            board.setHit( board.getHit() + 1L );

            // 2. 저장하기
            if(bRepository.save(board) != null){
                return 1;
            }
         return 0;

        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

📁 BoardController.java

게시글 클릭하여 조회된 게시글을 확인하는 시점에
해당 개시글은 조회수가 이미 증가된 상태여야 하니
조회수 증가 코드는 상세페이지 조회 상단에 위치해야 한다

  • 📢 해결해야할 문제점
    해당 글을 새로고침하는 경우 조회수 계속 증가한다
    이 문제는 나중에 세션으로 처리하기!
    // 상세페이지 1개 조회
    @GetMapping(value = "/boardone.do")
    public String boardOneGET(Model model,
            @RequestParam(name = "no", defaultValue = "0") long no) {

        if (no == 0) { // 번호가 없는경우, 오류처리
            return "redirect:/board/boardlist.do";
        }
        // 0. 조회수 증가 
        // 나중에 세션으로 처리하기
        bService.boardUpdateHit(no);
...

회원가입시 아이디 중복확인

📁 MemberRepository.java

  • 아이디 중복확인용 저장소 생성
  • 해당아이디의 존재여부 확인하는 @Query를 작성 ➡️ findbyId도 이용가능
  • MongoRepository <Member, string>
    ➡️ MongoRepository <entity, entity id의 타입>
@Repository
public interface MemberRepository extends MongoRepository<Member, String>{
    // 아이디 중복확인용
    // 해당아이디의 존재여부 확인 
    @Query(value="{_id : ?0}", exists = true)
    public boolean selectIdCheck(String id);
}

📁 MemberService.java

  • 아이디 중복확인시 일치하는 아이디 1개 조회니까 string으로 보낸다
    ➡️ 조회할 항목이 2개 이상 이었다면 entity를 보내는데,
    조회할 항목이 1개인 경우 entity로 보내면 다시 꺼내어 써야하니 더 번거롭다
  • selectIdCheck 또는 findById 사용하여 조회
if(mRepository.findById(id).orElse(null) != null){
    public int selectIdCheck( String id ){
        try {
        // if(mRepository.findById(id).orElse(null) != null){
            if(mRepository.selectIdCheck(id)){
                return 1; 
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();;
            return -1;
        }
    }

📁 MemberController.java

주소가 변경되면 idcheck 수행하고 return
➡️ idcheck 수행되는 시점은 중복확인버튼 클릭시이며, 이때 새로운 주소로 이동하여 결과 알려주는 방식으로 진행
* return 되는 idcheckidcheck.html을 의미한다

 // 아이디 중복확인
    // 127.0.0.1:8080/ROOT/member/idcheck.do?id=aaa
    @GetMapping(value = "/idcheck.do")
    public String idCheckGET(
        Model model,
        @RequestParam(name="id", defaultValue = "") String id){
            
            int ret = mService.selectIdCheck(id);
            model.addAttribute("ret", "사용가능");
            if( ret == 1 ){
                model.addAttribute("ret", "사용불가");
            }
            return "idcheck";
        } 

📁 join.html

  • <a>는 입력되어 받아오는 값이 아닌 정해진 값을 사용한다.
    사용자 에게서 입력받을 id값을 넣어야 하는데 입력받을 값을 모르기 때문에 스크립트를 사용하여 사용자가 입력한 id를 받아와야 한다
  • join.html에서 중복확인 버튼 클릭시 MemberController.java에서 ret + 사용가능/사용불가를 결과 값으로 받으며 , return시 idcheck.html로 이동한다
...
<form th:action="@{/member/join.do}" method="post">
            <label style="display: inline-block; width: 100px;">
                아이디
                </label><input type="text" name="id"/>
            <input type="button" value="중복확인" th:onclick="|javascript:idcheckAction()|" />
            <br />
...
<script type="text/javascript">
        const idcheckAction = () => {
            // 1. 사용자가 입력한 아이디 받아오기
                const id = document.getElementsByName("id")[0];
                // getElementsByName => 복수형이라 배열로 받는다.
                console.log(id.value);
            // 2.get으로 전송
                // 스크립트가 <form> 생성
                location.href = "/ROOT/member/idcheck.do?id=" + id.value;
        }
    </script>
...

📁 idcheck.html

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>아이디중복확인</title>
</head>
<body>
    <div th:text="${ret}"></div>

</body>
</html>

🤯 오류

💡 idcheck.html을 생성하지 않아 발생한 오류였다
idcheck.html을 생성 후 실행하니 오류없이 작동한다

0개의 댓글