10/19/2019

스프링 게시판 만들기 #15. 댓글 작성 구현

이전글에서 댓글에 필요한 매퍼-DAO-Service까지 한번에 만들었고, 컨트롤러는 지금 당장 사용하지 않았으나 임시로 생성했습니다.

댓글 테이블의 형태는
1. rno : 댓글 고유번호
2. bno : 게시물 고유번호
3. writer : 댓글 작성자
4. content : 댓글 내용
5. regDate : 댓글 작성 날짜
로 되어있습니다.

rno(댓글 고유번호)는 테이블을 생성할때 설정한 auto_increment 값을 가지고있으니 자동으로 증가되는 값이고
bno(게시물 고유번호)는 댓글을 작성할때 조회중인 게시물의 고유번호 값,
writer(댓글 작성자)와 content(댓글 내용)은 직접 작성하는 값,
regDate(댓글 작성 날짜)는 쿼리문을 이용하여 넣어주는 값입니다.

즉, 댓글 작성시 필요한 데이터는
1. bno : 게시물 고유번호
2. writer : 댓글 작성자
3. content : 댓글 내용
이렇게 3개가 되겠습니다.

댓글을 입력할 수 있도록, 새로운 form을 추가합니다.

<div>

	<form method="post" action="/reply/write">
	
		<p>
			<label>댓글 작성자</label> <input type="text" name="writer">
		</p>
		<p>
			<textarea rows="5" cols="50" name="content"></textarea>
		</p>
		<p>
			<button type="submit">댓글 작성</button>
		</p>
	</form>
	
</div>

게시물 작성 구현과 같은 post방식의 form이지만, 자세히보면 action(액션)에 /repley/write가 있는걸 볼 수 있습니다.

form 내부의 데이터를 post형식으로 보내되, /repley/write의 경로로 보낸다는걸 추측할 수 있습니다.
게시물 작성 구현에서는 action의 값을 설정하지 않았었는데, 이 이유는 action을 지정하지 않았을 경우, 현재의 url로 데이터를 보내기 때문입니다.

즉, 댓글이 작성되는 현재 페이지는 게시물 조회중이기 때문에 루트/view?bno=?방식의 url을 가지고 있을텐데, 여기에서 action 지정없이 전송하게되면, 현재 주소로 데이터를 날리기 때문에 에러가 발생하게 됩니다.

그런데.. 위에서 댓글 작성시 필요한 데이터는 총 3개라고 했는데
form에는 댓글 작성자(writer)와 댓글 내용(content)밖에 보이질 않습니다.

bno의 값을 담은 input을 추가합니다.

<input type="hidden" name="bno" value="${view.bno}">

이 input은 type(타입)이 hidden인걸 볼 수 있는데, 이건 '실제로 값은 담고 있지만, 화면에 표시하지 않겠다'라는 의미입니다. 지금처럼, 게시물 고유번호를 굳이 표시할 필요가 없으므로 이렇게 hidden속성으로 넣어두면, 사용자에게는 보이지 않지만 우리들(개발자)는 데이터를 다룰 수 있습니다.

추가적으로 ${view.bno}게시물 조회 구현에서 컨트롤러에 생성했던 model입니다.

프로젝트를 실행하고 아무 게시물을 조회하고, 키보드의 F12를 눌러서 크롬의 개발자 도구를 실행해봅니다.
그러면 현재 조회중인 게시물 번호와, 우리가 form에 추가한 값이 동일한것을 알 수 있습니다.

이전글에서 사실상 모든 코드를 구현해두었습니다.

임시로 만들었던 ReplyController를 사용할때입니다.

// 댓글 작성
@RequestMapping(value = "/write", method = RequestMethod.POST)
public String posttWirte(ReplyVO vo) throws Exception {
	
	replyService.write(vo);
	
	return "redirect:/board/view?bno=" + vo.getBno();
}

ReplyController를 만들었을때, 컨트롤러 자체를 /reply/*로 매핑했으므로, 이 댓글 작성 메서드에 적용되는 실제 url은 /reply/write 입니다.

return은 redirect:/board/view?bno= 로 되어있어서, 댓글을 작성했던 게시물로 다시 이동됩니다.
즉, 데이터의 순서는
1. 게시물 조회 페이지에서 댓글 작성 후 등록
2. /reply/write 에 해당되는 컨트롤러로 데이터 전달
3. service → dao → mapper를 통해 db에 데이터 등록
4. redirect:/board/view?bno=로 인해 1번에서 조회중이었던 게시물로 이동
이렇게 됩니다.

프로젝트를 실행하여 아무 게시물을 조회한 뒤 게시물을 작성해봅니다.

화면이 깜빡(리다이렉트, 새로고침)되며 댓글이 등록된걸 확인할 수 있습니다.

게시물 수정
  1. 너무 이해하기 편하고 공부하기 너무 좋아요 이런 유용한 내용 올려주셔서 너무 감사합니다. 최고에요 ㅠㅠㅠ
    여기까기 따라했는데 오류500 Column 'regDate' cannot be null 이라고 뜨는데 오타가 났나 아무리 찾아도 없고 혹시 몰라서 복붙도 해봤는데 계속 같은 오류가 발생하네요ㅜㅜ list.jsp에서는 잘됬는데 왜 view.jsp에서는 에러가 발생할까요..?

    답글삭제
    답글
    1. 해결했어요 감사합니다:)

      삭제
    2. 익명1/25/2022

      저도 같은 오류가뜨는데 어떻게 해결 하셨나요?? 거의 3일째 해결을 못하고있어서요.. mysql DB사용중인데 내용 빠짐없이 다 충실히 따라했는데도 안되네요......

      삭제
    3. 익명2/06/2024

      댓글

      삭제
  2. 스프링 입문 게시판 프로젝트는 이게 짱인거 같습니다..

    답글삭제
  3. regDate는 mariadb에서 디폴트 값으로 현재 시간이 설정되어 있고 따로 설정하는 코드가 없기 때문에 mapper에서 해당 부분은 지워 주어야 500 오류가 뜨지 않습니다.



    insert into tbl_reply(bno, writer, content)
    value(#{bno}, #{writer}, #{content})

    답글삭제
  4. 댓글에 대댓글이 달리는건 어떻게 해야 할까요.

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      댓글에 대댓글이 달리는 경우.. 바로 생각나는건 2가지 방법인데

      첫번째 방법은 대댓글용 테이블을 하나 더 만들어서, 댓글과 동일한 방식으로 crud를 하는겁니다.
      가장 간단하고 별 생각없이(!) 구현할 수 있지만, 댓글의 댓글의 댓글을 추가하려면, 다시 테이블을 또 추가해야하는 단점아닌 단점이 있습니다.

      두번째 방법은 댓글 테이블에 참조키 컬럼을 추가하는겁니다.
      작성자나 작성내용/날짜를 제외하면

      [게시판 고유번호], [댓글 고유번호]

      이런식으로 테이블이 되어있을텐데


      [게시판 고유번호], [댓글 고유번호], [댓글 참조코드]

      이렇게추가하고, 댓글 참조코드는 댓글 고유번호를 가르키도록 합니다.

      [게시판 고유번호], [댓글 고유번호], [댓글 참조코드] 순서라고 할때
      board1, rep1, null -> 참조코드가 null 이면 '댓글'
      board1, repr1, rep1 -> 참조코드가 rep1이므로, rep1의 대댓글
      board1, repr1, rep1 -> 참조코드가 rep1이므로, rep1의 대댓글
      board1, rep2, null -> 참조코드가 null 이면 '댓글'
      board1, rep3, null -> 참조코드가 null 이면 '댓글'
      board1, repr1, rep3 -> 참조코드가 rep3이므로, rep3의 대댓글

      이런식으로 구현할 수 있습니다

      첫번째 방법은 대댓글로 끝날 경우 간단하게 구현할 수 있고
      두번째 방법은 조금 복잡하긴해도 유동적으로 관리를 할 수 있으며

      두가지 방법 모두 쉽게 찾아볼 수 있는 방식입니다.

      삭제
  5. 잌 이게 마지막 강의인가요?!

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      날짜는 꽤 과거지만 올해 작성한 게시물입니다.
      초안이 저 날짜에 작성되어서요;

      일단 지금 업무가 널널해지면 계속 진행할 예정입니다..ㅠㅠ

      삭제
  6. 잘 보았습니다. 앞으로 게시물 얼마나 더 만들 계획이신지 궁금합니다. 대략적으로 알려주실 수 있으신가요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      '원래' 계획은 현재 게시물에서 [ 첨부파일, 이지윅 에디터, 회원관리, 조회수 및 좋아요 ]를 더 진행한 뒤에
      깡 jsp(...)에서 js를 사용하여 현재까지 만든 기능을 재작성하는것까지였습니다.

      어느정도 예상은했지만, 예상이상으로 바빠진것도 있고 나태함이 많이 생겨서(이게 제일 큼) 점점 늦어지네요..ㅠㅠ

      삭제
  7. 질문드립니다.
    sql을 통해 10000개가 넘는 행을 삭제 하고
    페이지상에서 게시글 작성을 하였는데요

    bno가 1번부터 다시 시작하는게 아니라 10001 이런식으로 시작 하게 됩니다. 어디를 수정해야 1번부터 시작하게 될까요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      bno는 auto_increment로 증가하는 값인데, 이 값을 초기화하는건
      ALTER TABLE [TABLE] AUTO_INCREMENT = 0; 로 해주시면 되겠습니다.

      삭제
  8. 스프링 기초 입문서 떼고 처음으로 해본 프로젝트인데 따라 해보면서 많은 공부가 되었습니다

    답글삭제
  9. 익명6/04/2021

    댓글이 있는 게시글을 삭제했는데 child? 어쩌고 오류가 뜨더라구용...어떻게 해야하나요...ㅠㅠ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      음..말씀하신것만으로는 무슨 에러인지 확인하기가 어렵습니다.

      삭제
    2. 익명7/12/2021

      댓글 달린 글 외래키 참조때문에 오류 나는거 말씀하시는듯 하시는듯하내요

      삭제
  10. 주행 잘하였습니다. 다음 탄 언제볼수 있을까요ㅜ 기다려봅니다 ㅎㅎ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      어.. 초안은 게시물 작성년도쯤에 어느정도 되어있는 상태인데
      제... 업무와 나태함-_- 때문에 늦어지네요..ㅠㅠ

      삭제
  11. 감사합니다. 스프링 게시판 관련 포스팅중에서 가장 잘 되있는것 같습니다.
    비전공 학원출신으로 아주 많이 도움이 되었습니다.
    혹시 더 진도를 나갈 계획은 없으신가요?ㅎㅎ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      어..일단 이 시리즈(?)의 초안은 작성되어있긴한데.. 최근에 하는 작업 때문에 계속-_- 늦어지고 있네요;
      나태함도 있기는 하지만... 어쨋든 작업이 마무리되면 계속 진행할 생각..입니다; 죄송합니다-_ㅠ..

      삭제
  12. 익명9/12/2021

    댓글 수정등은 ajax없이 되나요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      댓글 수정을 포함하여 대부분의 데이터 전달은 에이젝스로도 가능합니다.
      다만 현재 블로그에서는 거기까지 작성이 안되었을뿐이지요(나태지옥)

      삭제
  13. 익명9/27/2021

    스프링 게시판을 만들려고 유투브도 보고 블로그도 찾아보고 따라해봤는데 이해도 안되고 에러도 잡지 못해서 다 실패하고
    kuzuro 님의 블로그를 통해서 게시판 만들기 성공했습니다~ ^^
    자세하고 쉬운 설명으로 포기하지 않고 계속할 수 있게 해주셔서 감사드립니다~

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      다음글을 빨리 써야..겠..군..요(나태)

      가능한선에서 학원을 알아보시는게 가장 좋다고 생각합니다. 사람 대 사람의 대화라면.. 손으로 모니터를 가르키며 추상적으로 물어봐도 가능하니까요(...)

      학원 다니는데에 제한이 있다면.. 다양한 자료를 많이 보는 수밖에 없는거같습니다ㅠㅠ

      삭제
  14. 안녕하세요 ! 처음으로 오류없이 공부해보면서 완성해본 게시판이네요 ! 자세하고 알기쉽게 올려주셔서 정말 감사하드리고 도움많이 됐습니다.
    혹시 올려주신 스프링쇼핑몰 만들기도 따라해보며 공부하고싶은데 (구)스프링게시판 만들기 이후에 진행해야 할까요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      제가 작년부터 계속 바쁜 상태라ㅠㅠ
      초안은 작성해두었는데, 실제로 개시하도록 수정하려면 좀 걸릴거같습니다.
      내용 자체는 (구) 게시물하고 이어지지 않고, 현재 게시물에서 이어지기는...합니다.

      삭제
  15. 댓글을 쓴 상태에서 게시글을 삭제누르면 오류가 뜨는데
    데이터베이스에서 얼터코드를 사용하여 해결하려면 어떻게 코드를 짜야하나요? ㅠㅠ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      댓글을 작성한 상태에서 게시글을 삭제할 경우 에러가 나는건 정상입니다.
      왜냐하면, 게시물에 해당되는 테이블의 데이터를, 다시 댓글 테이블이 바라보고 있기 때문인데요

      이에 대한 내용은 제가 여유로워지면(...) 작성할 예정이지만, 언제가 될지 모르니 살짝 써보자면

      1. 게시물 삭제 버튼을 클릭
      2. service단에서 게시물 삭제 DAO에 접근하기 전에, 댓글 삭제 DAO에 먼저 접근한다
      3. 현재 게시물에 달린 댓글 내용을 모두 삭제한다.
      4. 게시물을 삭제한다

      순서가 되겠습니다.

      삭제
  16. 선생님 감사합니다 좋은 학습자료 덕분에 쉽게 공부할 수 있었습니다.

    답글삭제
  17. 우왕.. 스프링 하나도 몰라서 책이랑 유튜브 이론을 주구장창 봤는데 정말로 머리에 1도 안들어오더라구요
    무작정 프로젝트를 따라해봐야겠다 싶어서 여러가지 찾아보다가 중간에 진행이 잘 안되서 멈췄었는데
    이 블로그는 처음부터 끝까지 생초보가 따라해도 문제가 없었던 프로젝트였어요 더군다나 mvc모델이 이해가 가장 잘되는 글이였어요 감사합니다. 다음에 저와 같은 초보가 스프링 공부 입문할 때 이 블로그 추천해줘야겠어요!!!

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      나름대로 입문자 기준으로 작성하고 있는데.. 게시물을 안올리는 나태함이 생겨서 문제네요-_-;
      아, 물론 정말 아무것도 안하는건 아니긴한데..크흠;

      초안은 이미 한참전에 작서했으니 슬슬 올려야..겠..습니..다;

      삭제
  18. 공부법 질문드려요. 자바는 살짝 접해서 기초문법 대략 알구요
    전 인프런 김영한님 스프링 입문 강의 듣다가 못 따라가겠어서
    kuzuro님 게시판 따라하기 한번은 해보았습니다.
    차라리 이해하려 강의를 듣고 익히는 것 보다는
    게시판 만드는 과정 계속 리마인드 하면서 스스로 응용 해보는 방식으로 공부하는 게 더 괜찮을까요?

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      공부법은 각자 다르고, 제가 생각하는 가장 이상적인거에 근접하는게
      각각을 책으로 구분해서, 그 책을 다 떼었다면 다음껄 진행하는 방식입니다
      즉, 자바책을 전부 다 공부하고(암기 아님) 스프링책을 가지고 공부한다던가 하는 식이요.

      하지만 그렇게하려면 몹시 피곤하고 시간도 오래 걸리니
      자바는 적당히 상속이나 제네릭까지 하고(암기 아님), 스프링을 진행하면서 자바 공부와 병행하시는게 어떨까 싶습니다.

      요약하자면 프로젝트(=게시판)를 만들면서 부족한게 있다면 그걸 보충하는 방식입니다.

      삭제
  19. 감사합니다 도움 많이 되었습니다.

    답글삭제
  20. 익명7/19/2022

    다른 사이트들은 암만 봐도 이해가 안되는데 이 블로그 글이 확실히 이해하기도 쉽고 따라하기도 좋네요. 덕분에 많이 깨닫고 갑니다!! 다음글 올라올때까지 존버하겠습니다 ㅋㅋ

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다
      조만간(...)이어 쓰도록 하겠습니다(__);

      삭제
  21. 좋은 강의 너무 감사드립니다.
    ReplyController.java 파일 안에
    replyService.write(vo);에 빨간 줄이 쳐지는데 왜그런걸까요?

    답글삭제
  22. 익명9/26/2022

    감사합니다 잘 봤습니다

    답글삭제
  23. 블로그 글 보면서 많이 따라하고 있습니다.
    댓글 수정/삭제 기능도 포스팅 기다리고 있습니다.
    바쁘시더라도 올려주시면 어떨까요?

    답글삭제
  24. 마지막에 405에러 뜨면서 reques method 'post' not supported 뜨는데 어떻게해야할까요 ㅠㅠ
    form action이랑 controller맵핑 다되어있는데 안되네요..ㅠ

    답글삭제
  25. 계속 integrity constraint violation: NOT NULL check constraint 에러가 RNO쪽에 납니다. 이것 때문에 작성이 안 되는데... ㅠㅠ 살려주세요

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      해당 에러는 null이 입력되어 쿼리로 넘어가는 것 같습니다.
      매퍼까지 필요한 데이터가 잘 넘어가는지 디버깅 또는 콘솔에 출력하여 확인해보셔야 할 것 같습니다.

      삭제
  26. HTTP 상태 404 – 찾을 수 없음
    타입 상태 보고

    메시지 요청된 리소스 [/board/reply/write]은(는) 가용하지 않습니다.

    설명 Origin 서버가 대상 리소스를 위한 현재의 representation을 찾지 못했거나, 그것이 존재하는지를 밝히려 하지 않습니다.

    @RequestMapping (value = "/board/reply/write", method = RequestMethod.POST)
    했는데 에러가 나서 난감합니다

    답글삭제
    답글
    1. 안녕하세요? 방문해주셔서 감사합니다.

      톰캣 서버의 루트경로(context path)가 / 로 되어있는지 확인하셔야할텐데... 다 잘되는데 write만 안된다면..

      만약 이클립스(=STS) 사용중이시면, 상단 메뉴에서 project → clean 이후 다시 시도해보시기 바랍니다.

      삭제
  27. 익명8/23/2023

    선생님 덕분에 돈 벌어먹고삽니다.. 정말 감사합니다!!

    답글삭제
  28. 익명9/13/2023

    ㅂㅂㅂ

    답글삭제