Repository: codesquad-members-2025/be-spring-cafe
Pull request #22: [Elbin] step 4-2 스프링 카페 - 글 쓰기 기능 구현
Author: login: guzzang
Labels: name: Step4-2
description: 스프링 카페 - 글 쓰기 기능 구현
Created: 2025-03-20T10:59:36Z | Merged: 2025-03-21T01:05:10Z

## 구현 내용

질문을 작성하는 기능과 질문의 상세내용 확인 기능을 구현하였습니다.
추가로 회원의 정보를 수정할 수 있는 기능도 구현하였습니다. 

## 고민 사항

User 객체의 식별자라고 할 수 있는 userId 필드를 String 타입으로 선언했더니, User를 보관하는 List에서 User를 불러올 때 코드가 길어지게 되었습니다.
예를 들어 userId 필드를 int 타입으로 선언했으면 List에서 get 메서드를 통해 바로 불러올 수 있지만, 제가 선언한 타입은 String이라 get 메서드를 사용할 수 없기 때문입니다.

for (User user : userList) {
            if(user.getUserId().equals(userId)){
                if(!user.getPassword().equals(password)){
                    redirectAttributes.addFlashAttribute("errorMessage", "비밀번호가 일치하지 않습니다.");
                    return "redirect:/users/{userId}/form";
                }
                user.setName(name);
                user.setEmail(email);
            }
        }
        return "redirect:/users";
    }

코드 예시입니다.
여기서 코드를 줄이기 위해 userId 타입을 int와 같은 숫자 타입으로 바꾸려고 하는데 변경해도 괜찮은지가 고민입니다.

추가적으로 회원 정보를 수정할 때 Put 메서드를 사용해야한다는 요구사항이 있는데, Post 메서드로 구현하였습니다.
Post 메서드로 구현하였어도 기능 동작엔 문제가 없어 따로 수정은 하지 않았는데, 정보를 수정하는 경우에 Put 메서드를 쓰지 않고 Post를 메서드를 써도 괜찮은지, 괜찮다면 Put 메서드는 존재 이유가 뭔지 궁금합니다.



Diff:
diff --git a/src/main/java/codesquad/codestagram/controller/Article.java b/src/main/java/codesquad/codestagram/controller/Article.java
new file mode 100644
index 00000000..2b373310
--- /dev/null
+++ b/src/main/java/codesquad/codestagram/controller/Article.java
@@ -0,0 +1,49 @@
+package codesquad.codestagram.controller;
+
+public class Article {
+
+    private static int count = 0;
+
+    private int index;
+
+    private String writer;
+
+    private String title;
+
+    private String contents;
+
+    public Article(String writer, String title, String contents) {
+        this.index = ++count;
+        this.writer = writer;
+        this.title = title;
+        this.contents = contents;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public String getWriter() {
+        return writer;
+    }
+
+    public void setWriter(String writer) {
+        this.writer = writer;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getContents() {
+        return contents;
+    }
+
+    public void setContents(String contents) {
+        this.contents = contents;
+    }
+}
diff --git a/src/main/java/codesquad/codestagram/controller/ArticleController.java b/src/main/java/codesquad/codestagram/controller/ArticleController.java
new file mode 100644
index 00000000..f8143ede
--- /dev/null
+++ b/src/main/java/codesquad/codestagram/controller/ArticleController.java
@@ -0,0 +1,39 @@
+package codesquad.codestagram.controller;
+
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Controller
+public class ArticleController {
+
+    private static final List<Article> articleList = new ArrayList<>();
+
+    @PostMapping("/articles")
+    public String writeArticle(@ModelAttribute Article article){
+        articleList.add(article);
+        return "redirect:/";
+    }
+
+    @GetMapping("/")
+    public String showArticles(Model model){
+        model.addAttribute("articles", articleList);
+        return "article/index";
+    }
+
+    @GetMapping("/articles/{index}")
+    public String showArticle(@PathVariable int index, Model model){
+        Article article = articleList.get(index - 1);
+        model.addAttribute("article", article);
+        return "article/show";
+    }
+
+
+}
diff --git a/src/main/java/codesquad/codestagram/controller/UserController.java b/src/main/java/codesquad/codestagram/controller/UserController.java
index eae63a29..c21cf197 100644
--- a/src/main/java/codesquad/codestagram/controller/UserController.java
+++ b/src/main/java/codesquad/codestagram/controller/UserController.java
@@ -2,10 +2,8 @@
 
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
 import java.util.ArrayList;
 
@@ -34,6 +32,36 @@ public String getUser(@PathVariable String userId, Model model){
         return "user/profile";
     }
 
+    @GetMapping("/users/{userId}/form")
+    public String getUpdateForm(@PathVariable String userId, Model model){
+        for (User user : userList) {
+            if(user.getUserId().equals(userId)) model.addAttribute("user", user);
+        }
+        return "user/updateForm";
+    }
+
+    @PostMapping("/users/{userId}/update")
+    public String updateUser(@PathVariable String userId,
+                             @RequestParam String password,
+                             @RequestParam String name,
+                             @RequestParam String email,
+                             RedirectAttributes redirectAttributes){
+
+        for (User user : userList) {
+            if(user.getUserId().equals(userId)){
+                if(!user.getPassword().equals(password)){
+                    redirectAttributes.addFlashAttribute("errorMessage", "비밀번호가 일치하지 않습니다.");
+                    return "redirect:/users/{userId}/form";
+                }
+                user.setName(name);
+                user.setEmail(email);
+            }
+        }
+        return "redirect:/users";
+    }
+
+
+
 
 
 
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 3789afc4..8a25d8a9 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1 +1,2 @@
 spring.application.name=codestagram
+spring.mvc.hiddenmethod.filter.enabled=true
diff --git a/src/main/resources/static/qna/form.html b/src/main/resources/static/qna/form.html
index cc9dca8d..e0236bb2 100644
--- a/src/main/resources/static/qna/form.html
+++ b/src/main/resources/static/qna/form.html
@@ -76,7 +76,7 @@
 <div class="container" id="main">
    <div class="col-md-12 col-sm-12 col-lg-10 col-lg-offset-1">
       <div class="panel panel-default content-main">
-          <form name="question" method="post" action="">
+          <form name="question" method="post" action="/articles">
               <div class="form-group">
                   <label for="writer">글쓴이</label>
                   <input class="form-control" id="writer" name="writer" placeholder="글쓴이"/>
diff --git a/src/main/resources/templates/article/index.html b/src/main/resources/templates/article/index.html
new file mode 100644
index 00000000..85156a75
--- /dev/null
+++ b/src/main/resources/templates/article/index.html
@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<html lang="kr">
+	<head>
+		<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+		<meta charset="utf-8">
+		<title>SLiPP Java Web Programming</title>
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+		<link href="css/bootstrap.min.css" rel="stylesheet">
+		<!--[if lt IE 9]>
+			<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
+		<![endif]-->
+		<link href="css/styles.css" rel="stylesheet">
+	</head>
+	
+	<body>
+<nav class="navbar navbar-fixed-top header">
+ 	<div class="col-md-12">
+        <div class="navbar-header">
+
+            <a href="index.html" class="navbar-brand">SLiPP</a>
+          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse1">
+          <i class="glyphicon glyphicon-search"></i>
+          </button>
+      
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse1">
+          <form class="navbar-form pull-left">
+              <div class="input-group" style="max-width:470px;">
+                <input type="text" class="form-control" placeholder="Search" name="srch-term" id="srch-term">
+                <div class="input-group-btn">
+                  <button class="btn btn-default btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button>
+                </div>
+              </div>
+          </form>
+          <ul class="nav navbar-nav navbar-right">             
+             <li>
+                <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-bell"></i></a>
+                <ul class="dropdown-menu">
+                  <li><a href="https://slipp.net" target="_blank">SLiPP</a></li>
+                  <li><a href="https://facebook.com" target="_blank">Facebook</a></li>
+                </ul>
+             </li>
+             <li><a href="./user/list.html"><i class="glyphicon glyphicon-user"></i></a></li>
+           </ul>
+        </div>	
+     </div>	
+</nav>
+<div class="navbar navbar-default" id="subnav">
+    <div class="col-md-12">
+        <div class="navbar-header">
+            <a href="#" style="margin-left:15px;" class="navbar-btn btn btn-default btn-plus dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-home" style="color:#dd1111;"></i> Home <small><i class="glyphicon glyphicon-chevron-down"></i></small></a>
+            <ul class="nav dropdown-menu">
+                <li><a href="../templates/user/profile.html"><i class="glyphicon glyphicon-user" style="color:#1111dd;"></i> Profile</a></li>
+                <li class="nav-divider"></li>
+                <li><a href="#"><i class="glyphicon glyphicon-cog" style="color:#dd1111;"></i> Settings</a></li>
+            </ul>
+            
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse2">
+            	<span class="sr-only">Toggle navigation</span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            </button>            
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse2">
+            <ul class="nav navbar-nav navbar-right">
+                <li class="active"><a href="index.html">Posts</a></li>
+                <li><a href="user/login.html" role="button">로그인</a></li>
+                <li><a href="user/form.html" role="button">회원가입</a></li>
+                <!--
+                <li><a href="#loginModal" role="button" data-toggle="modal">로그인</a></li>
+                <li><a href="#registerModal" role="button" data-toggle="modal">회원가입</a></li>
+                -->
+                <li><a href="#" role="button">로그아웃</a></li>
+                <li><a href="#" role="button">개인정보수정</a></li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+<div class="container" id="main">
+   <div class="col-md-12 col-sm-12 col-lg-10 col-lg-offset-1">
+      <div class="panel panel-default qna-list">
+          <ul class="list">
+              <li th:if="${articles == null or #lists.isEmpty(articles)}">
+                  <div class="wrap">
+                      <div class="main">
+                          <strong class="subject">게시글이 없습니다.</strong>
+                      </div>
+                  </div>
+              </li>
+
+              <li th:each="article : ${articles}">
+                  <div class="wrap">
+                      <div class="main">
+                          <strong class="subject">
+                              <a th:href="@{/articles/{index}(index=${article.index})}" th:text="${article.title}"></a>
+                          </strong>
+                          <div class="auth-info">
+                              <i class="icon-add-comment"></i>
+                              <span class="time">2025-03-19 22:30</span>
+                              <td th:text="${article.writer}">작성자</td>
+                          </div>
+                          <div class="reply" title="댓글">
+                              <i class="icon-reply"></i>
+                              <span class="point">8</span>
+                          </div>
+                      </div>
+                  </div>
+              </li>
+          </ul>
+          <div class="row">
+              <div class="col-md-3"></div>
+              <div class="col-md-6 text-center">
+                  <ul class="pagination center-block" style="display:inline-block;">
+                      <li><a href="#">«</a></li>
+                      <li><a href="#">1</a></li>
+                      <li><a href="#">2</a></li>
+                      <li><a href="#">3</a></li>
+                      <li><a href="#">4</a></li>
+                      <li><a href="#">5</a></li>
+                      <li><a href="#">»</a></li>
+                </ul>
+              </div>
+              <div class="col-md-3 qna-write">
+                  <a href="./qna/form.html" class="btn btn-primary pull-right" role="button">질문하기</a>
+              </div>
+          </div>
+        </div>
+    </div>
+</div>
+
+<!--login modal-->
+<!--
+<div id="loginModal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
+  <div class="modal-dialog">
+  <div class="modal-content">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+          <h2 class="text-center"><img src="https://lh5.googleusercontent.com/-b0-k99FZlyE/AAAAAAAAAAI/AAAAAAAAAAA/eu7opA4byxI/photo.jpg?sz=100" class="img-circle"><br>Login</h2>
+      </div>
+      <div class="modal-body">
+          <form class="form col-md-12 center-block">
+              <div class="form-group">
+                  <label for="userId">사용자 아이디</label>
+                  <input class="form-control" name="userId" placeholder="User ID">
+              </div>
+              <div class="form-group">
+                  <label for="password">비밀번호</label>
+                  <input type="password" class="form-control" name="password" placeholder="Password">
+              </div>
+              <div class="form-group">
+                  <button class="btn btn-primary btn-lg btn-block">로그인</button>
+                  <span class="pull-right"><a href="#registerModal" role="button" data-toggle="modal">회원가입</a></span>
+              </div>
+          </form>
+      </div>
+      <div class="modal-footer">
+          <div class="col-md-12">
+          <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
+      </div>  
+      </div>
+  </div>
+  </div>
+</div>
+-->
+
+<!--register modal-->
+<!--
+<div id="registerModal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
+  <div class="modal-dialog">
+  <div class="modal-content">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
+          <h2 class="text-center"><img src="https://lh5.googleusercontent.com/-b0-k99FZlyE/AAAAAAAAAAI/AAAAAAAAAAA/eu7opA4byxI/photo.jpg?sz=100" class="img-circle"><br>회원가입</h2>
+      </div>
+      <div class="modal-body">
+          <form class="form col-md-12 center-block">
+              <div class="form-group">
+                  <label for="userId">사용자 아이디</label>
+                  <input class="form-control" id="userId" name="userId" placeholder="User ID">
+              </div>
+              <div class="form-group">
+                  <label for="password">비밀번호</label>
+                  <input type="password" class="form-control" id="password" name="password" placeholder="Password">
+              </div>
+              <div class="form-group">
+                  <label for="name">이름</label>
+                  <input class="form-control" id="name" name="name" placeholder="Name">
+              </div>
+              <div class="form-group">
+                  <label for="email">이메일</label>
+                  <input type="email" class="form-control" id="email" name="email" placeholder="Email">
+              </div>
+            <div class="form-group">
+              <button class="btn btn-primary btn-lg btn-block">회원가입</button>
+            </div>
+          </form>
+      </div>
+      <div class="modal-footer">
+          <div class="col-md-12">
+          <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
+      </div>  
+      </div>
+  </div>
+  </div>
+</div>
+-->
+
+<!-- script references -->
+<script src="js/jquery-2.2.0.min.js"></script>
+<script src="js/bootstrap.min.js"></script>
+<script src="js/scripts.js"></script>
+	</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/article/show.html b/src/main/resources/templates/article/show.html
new file mode 100644
index 00000000..84af1fad
--- /dev/null
+++ b/src/main/resources/templates/article/show.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html lang="kr">
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <meta charset="utf-8">
+    <title>SLiPP Java Web Programming</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+    <link href="../css/bootstrap.min.css" rel="stylesheet">
+    <!--[if lt IE 9]>
+    <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link href="../css/styles.css" rel="stylesheet">
+</head>
+<body>
+<nav class="navbar navbar-fixed-top header">
+    <div class="col-md-12">
+        <div class="navbar-header">
+
+            <a href="../index.html" class="navbar-brand">SLiPP</a>
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse1">
+                <i class="glyphicon glyphicon-search"></i>
+            </button>
+
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse1">
+            <form class="navbar-form pull-left">
+                <div class="input-group" style="max-width:470px;">
+                    <input type="text" class="form-control" placeholder="Search" name="srch-term" id="srch-term">
+                    <div class="input-group-btn">
+                        <button class="btn btn-default btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button>
+                    </div>
+                </div>
+            </form>
+            <ul class="nav navbar-nav navbar-right">
+                <li>
+                    <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-bell"></i></a>
+                    <ul class="dropdown-menu">
+                        <li><a href="https://slipp.net" target="_blank">SLiPP</a></li>
+                        <li><a href="https://facebook.com" target="_blank">Facebook</a></li>
+                    </ul>
+                </li>
+                <li><a href="../user/list.html"><i class="glyphicon glyphicon-user"></i></a></li>
+            </ul>
+        </div>
+    </div>
+</nav>
+<div class="navbar navbar-default" id="subnav">
+    <div class="col-md-12">
+        <div class="navbar-header">
+            <a href="#" style="margin-left:15px;" class="navbar-btn btn btn-default btn-plus dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-home" style="color:#dd1111;"></i> Home <small><i class="glyphicon glyphicon-chevron-down"></i></small></a>
+            <ul class="nav dropdown-menu">
+                <li><a href="../../templates/user/profile.html"><i class="glyphicon glyphicon-user" style="color:#1111dd;"></i> Profile</a></li>
+                <li class="nav-divider"></li>
+                <li><a href="#"><i class="glyphicon glyphicon-cog" style="color:#dd1111;"></i> Settings</a></li>
+            </ul>
+            
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse2">
+            	<span class="sr-only">Toggle navigation</span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            </button>            
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse2">
+            <ul class="nav navbar-nav navbar-right">
+                <li class="active"><a href="../index.html">Posts</a></li>
+                <li><a href="../user/login.html" role="button">로그인</a></li>
+                <li><a href="../user/form.html" role="button">회원가입</a></li>
+                <li><a href="#" role="button">로그아웃</a></li>
+                <li><a href="#" role="button">개인정보수정</a></li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+<div class="container" id="main">
+    <div class="col-md-12 col-sm-12 col-lg-12">
+        <div class="panel panel-default">
+          <header class="qna-header">
+              <h2 class="qna-title" th:text="${article.title}"></h2>
+          </header>
+          <div class="content-main">
+              <article class="article">
+                  <div class="article-header">
+                      <div class="article-header-thumb">
+                          <img src="https://graph.facebook.com/v2.3/100000059371774/picture" class="article-author-thumb" alt="">
+                      </div>
+                      <div class="article-header-text">
+                          <a href="/users/92/kimmunsu" class="article-author-name" th:text="${article.writer}"></a>
+                          <a href="/questions/413" class="article-header-time" title="퍼머링크">
+                              2015-12-30 01:47
+                              <i class="icon-link"></i>
+                          </a>
+                      </div>
+                  </div>
+                  <div class="article-doc">
+                      <p th:text="${article.contents}"></p>
+                  </div>
+                  <div class="article-util">
+                      <ul class="article-util-list">
+                          <li>
+                              <a class="link-modify-article" href="/questions/423/form">수정</a>
+                          </li>
+                          <li>
+                              <form class="form-delete" action="/questions/423" method="POST">
+                                  <input type="hidden" name="_method" value="DELETE">
+                                  <button class="link-delete-article" type="submit">삭제</button>
+                              </form>
+                          </li>
+                          <li>
+                              <a class="link-modify-article" href="/index.html">목록</a>
+                          </li>
+                      </ul>
+                  </div>
+              </article>
+
+              <div class="qna-comment">
+                  <div class="qna-comment-slipp">
+                      <p class="qna-comment-count"><strong>2</strong>개의 의견</p>
+                      <div class="qna-comment-slipp-articles">
+
+                          <article class="article" id="answer-1405">
+                              <div class="article-header">
+                                  <div class="article-header-thumb">
+                                      <img src="https://graph.facebook.com/v2.3/1324855987/picture" class="article-author-thumb" alt="">
+                                  </div>
+                                  <div class="article-header-text">
+                                      <a href="/users/1/자바지기" class="article-author-name">자바지기</a>
+                                      <a href="#answer-1434" class="article-header-time" title="퍼머링크">
+                                          2016-01-12 14:06
+                                      </a>
+                                  </div>
+                              </div>
+                              <div class="article-doc comment-doc">
+                                  <p>이 글만으로는 원인 파악하기 힘들겠다. 소스 코드와 설정을 단순화해서 공유해 주면 같이 디버깅해줄 수도 있겠다.</p>
+                              </div>
+                              <div class="article-util">
+                                  <ul class="article-util-list">
+                                      <li>
+                                          <a class="link-modify-article" href="/questions/413/answers/1405/form">수정</a>
+                                      </li>
+                                      <li>
+                                          <form class="delete-answer-form" action="/questions/413/answers/1405" method="POST">
+                                              <input type="hidden" name="_method" value="DELETE">
+                                              <button type="submit" class="delete-answer-button">삭제</button>
+                                          </form>
+                                      </li>
+                                  </ul>
+                              </div>
+                          </article>
+                          <article class="article" id="answer-1406">
+                              <div class="article-header">
+                                  <div class="article-header-thumb">
+                                      <img src="https://graph.facebook.com/v2.3/1324855987/picture" class="article-author-thumb" alt="">
+                                  </div>
+                                  <div class="article-header-text">
+                                      <a href="/users/1/자바지기" class="article-author-name">자바지기</a>
+                                      <a href="#answer-1434" class="article-header-time" title="퍼머링크">
+                                          2016-01-12 14:06
+                                      </a>
+                                  </div>
+                              </div>
+                              <div class="article-doc comment-doc">
+                                  <p>이 글만으로는 원인 파악하기 힘들겠다. 소스 코드와 설정을 단순화해서 공유해 주면 같이 디버깅해줄 수도 있겠다.</p>
+                              </div>
+                              <div class="article-util">
+                                  <ul class="article-util-list">
+                                      <li>
+                                          <a class="link-modify-article" href="/questions/413/answers/1405/form">수정</a>
+                                      </li>
+                                      <li>
+                                          <form class="form-delete" action="/questions/413/answers/1405" method="POST">
+                                              <input type="hidden" name="_method" value="DELETE">
+                                              <button type="submit" class="delete-answer-button">삭제</button>
+                                          </form>
+                                      </li>
+                                  </ul>
+                              </div>
+                          </article>
+                          <form class="submit-write">
+                              <div class="form-group" style="padding:14px;">
+                                  <textarea class="form-control" placeholder="Update your status"></textarea>
+                              </div>
+                              <button class="btn btn-success pull-right" type="button">답변하기</button>
+                              <div class="clearfix" />
+                          </form>
+                      </div>
+                  </div>
+              </div>
+          </div>
+        </div>
+    </div>
+</div>
+
+<script type="text/template" id="answerTemplate">
+	<article class="article">
+		<div class="article-header">
+			<div class="article-header-thumb">
+				<img src="https://graph.facebook.com/v2.3/1324855987/picture" class="article-author-thumb" alt="">
+			</div>
+			<div class="article-header-text">
+				<a href="#" class="article-author-name">{0}</a>
+				<div class="article-header-time">{1}</div>
+			</div>
+		</div>
+		<div class="article-doc comment-doc">
+			{2}
+		</div>
+		<div class="article-util">
+		<ul class="article-util-list">
+			<li>
+				<a class="link-modify-article" href="/api/qna/updateAnswer/{3}">수정</a>
+			</li>
+			<li>
+				<form class="delete-answer-form" action="/api/questions/{3}/answers/{4}" method="POST">
+					<input type="hidden" name="_method" value="DELETE">
+                     <button type="submit" class="delete-answer-button">삭제</button>
+				</form>
+			</li>
+		</ul>
+		</div>
+	</article>
+</script>
+
+<!-- script references -->
+<script src="../js/jquery-2.2.0.min.js"></script>
+<script src="../js/bootstrap.min.js"></script>
+<script src="../js/scripts.js"></script>
+	</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/user/list.html b/src/main/resources/templates/user/list.html
index 4154de20..6fc5e022 100644
--- a/src/main/resources/templates/user/list.html
+++ b/src/main/resources/templates/user/list.html
@@ -91,7 +91,7 @@
                     <td th:text="${user.name}"></td>
                     <td th:text="${user.email}"></td>
                     <td>
-                        <a href="#" class="btn btn-success" role="button">수정</a>
+                        <a th:href="@{/users/{userid}/form (userid=${user.userId})}" class="btn btn-success" role="button">수정</a>
                     </td>
                 </tr>
               </tbody>
diff --git a/src/main/resources/templates/user/updateForm.html b/src/main/resources/templates/user/updateForm.html
new file mode 100644
index 00000000..03d91a22
--- /dev/null
+++ b/src/main/resources/templates/user/updateForm.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html lang="kr">
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <meta charset="utf-8">
+    <title>SLiPP Java Web Programming</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+    <link href="/css/bootstrap.min.css" rel="stylesheet">
+    <!--[if lt IE 9]>
+    <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link href="/css/styles.css" rel="stylesheet">
+</head>
+<body>
+<nav class="navbar navbar-fixed-top header">
+    <div class="col-md-12">
+        <div class="navbar-header">
+
+            <a href="../index.html" class="navbar-brand">SLiPP</a>
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse1">
+                <i class="glyphicon glyphicon-search"></i>
+            </button>
+
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse1">
+            <form class="navbar-form pull-left">
+                <div class="input-group" style="max-width:470px;">
+                    <input type="text" class="form-control" placeholder="Search" name="srch-term" id="srch-term">
+                    <div class="input-group-btn">
+                        <button class="btn btn-default btn-primary" type="submit"><i class="glyphicon glyphicon-search"></i></button>
+                    </div>
+                </div>
+            </form>
+            <ul class="nav navbar-nav navbar-right">
+                <li>
+                    <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-bell"></i></a>
+                    <ul class="dropdown-menu">
+                        <li><a href="https://slipp.net" target="_blank">SLiPP</a></li>
+                        <li><a href="https://facebook.com" target="_blank">Facebook</a></li>
+                    </ul>
+                </li>
+                <li><a href="list.html"><i class="glyphicon glyphicon-user"></i></a></li>
+            </ul>
+        </div>
+    </div>
+</nav>
+<div class="navbar navbar-default" id="subnav">
+    <div class="col-md-12">
+        <div class="navbar-header">
+            <a href="#" style="margin-left:15px;" class="navbar-btn btn btn-default btn-plus dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-home" style="color:#dd1111;"></i> Home <small><i class="glyphicon glyphicon-chevron-down"></i></small></a>
+            <ul class="nav dropdown-menu">
+                <li><a href="../../templates/user/profile.html"><i class="glyphicon glyphicon-user" style="color:#1111dd;"></i> Profile</a></li>
+                <li class="nav-divider"></li>
+                <li><a href="#"><i class="glyphicon glyphicon-cog" style="color:#dd1111;"></i> Settings</a></li>
+            </ul>
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse2">
+            	<span class="sr-only">Toggle navigation</span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            	<span class="icon-bar"></span>
+            </button>            
+        </div>
+        <div class="collapse navbar-collapse" id="navbar-collapse2">
+            <ul class="nav navbar-nav navbar-right">
+                <li class="active"><a href="../index.html">Posts</a></li>
+                <li><a href="login.html" role="button">로그인</a></li>
+                <li><a href="../user/form.html" role="button">회원가입</a></li>
+                <li><a href="#" role="button">로그아웃</a></li>
+                <li><a href="#" role="button">개인정보수정</a></li>
+            </ul>
+        </div>
+    </div>
+</div>
+
+
+
+<div class="container" id="main">
+   <div class="col-md-6 col-md-offset-3">
+      <div class="panel panel-default content-main">
+          <div th:if="${errorMessage}" class="alert alert-danger">
+              <p th:text="${errorMessage}"></p>
+          </div>
+          <form name="question" th:action="@{/users/{userId}/update (userId=${user.userId})}"  method="post" >
+              <div class="form-group">
+                  <label for="userId" hidden>사용자 아이디</label>
+                  <input type="hidden" class="form-control" id="userId" name="userId" placeholder="User ID">
+              </div>
+              <div class="form-group">
+                  <label for="password">비밀번호</label>
+                  <input type="password" class="form-control" id="password" name="password" placeholder="Password">
+              </div>
+              <div class="form-group">
+                  <label for="name">이름</label>
+                  <input class="form-control" id="name" name="name" placeholder="Name">
+              </div>
+              <div class="form-group">
+                  <label for="email">이메일</label>
+                  <input type="email" class="form-control" id="email" name="email" placeholder="Email">
+              </div>
+              <button type="submit" class="btn btn-success clearfix pull-right">수정</button>
+              <div class="clearfix"></div>
+          </form>
+        </div>
+    </div>
+</div>
+
+<!-- script references -->
+<script src="/js/jquery-2.2.0.min.js"></script>
+<script src="/js/bootstrap.min.js"></script>
+<script src="/js/scripts.js"></script>
+	</body>
+</html>
\ No newline at end of file


Reviews:
user: login: honux77
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T01:02:23Z
user: login: honux77
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T01:02:47Z
user: login: honux77
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T01:03:19Z
user: login: honux77
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T01:04:33Z
user: login: honux77
body: 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T01:05:02Z

Review comments:
diff_hunk: @@ -0,0 +1,49 @@
+package codesquad.codestagram.controller;
+
+public class Article {
+
+    private static int count = 0;
path: src/main/java/codesquad/codestagram/controller/Article.java
user: login: honux77
body: 변수명이 모호합니다. 뭘 카운트하는걸까요?
created_at: 2025-03-21T01:02:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,49 @@
+package codesquad.codestagram.controller;
+
+public class Article {
+
+    private static int count = 0;
+
+    private int index;
path: src/main/java/codesquad/codestagram/controller/Article.java
user: login: honux77
body: 이것도 이상해요. index의 의미는 뭔가요? 
created_at: 2025-03-21T01:02:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,39 @@
+package codesquad.codestagram.controller;
+
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Controller
+public class ArticleController {
+
+    private static final List<Article> articleList = new ArrayList<>();
+
+    @PostMapping("/articles")
+    public String writeArticle(@ModelAttribute Article article){
+        articleList.add(article);
+        return "redirect:/";
+    }
+
+    @GetMapping("/")
+    public String showArticles(Model model){
+        model.addAttribute("articles", articleList);
+        return "article/index";
+    }
+
+    @GetMapping("/articles/{index}")
path: src/main/java/codesquad/codestagram/controller/ArticleController.java
user: login: honux77
body: ```suggestion
    @GetMapping("/articles/{id}")

```
created_at: 2025-03-21T01:03:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,6 +32,36 @@ public String getUser(@PathVariable String userId, Model model){
         return "user/profile";
     }
 
+    @GetMapping("/users/{userId}/form")
+    public String getUpdateForm(@PathVariable String userId, Model model){
+        for (User user : userList) {
+            if(user.getUserId().equals(userId)) model.addAttribute("user", user);
+        }
+        return "user/updateForm";
+    }
+
+    @PostMapping("/users/{userId}/update")
+    public String updateUser(@PathVariable String userId,
+                             @RequestParam String password,
+                             @RequestParam String name,
+                             @RequestParam String email,
+                             RedirectAttributes redirectAttributes){
+
+        for (User user : userList) {
+            if(user.getUserId().equals(userId)){
+                if(!user.getPassword().equals(password)){
+                    redirectAttributes.addFlashAttribute("errorMessage", "비밀번호가 일치하지 않습니다.");
+                    return "redirect:/users/{userId}/form";
+                }
+                user.setName(name);
+                user.setEmail(email);
+            }
+        }
+        return "redirect:/users";
path: src/main/java/codesquad/codestagram/controller/UserController.java
user: login: honux77
body: 이 부분 코드가 살짝 이상하긴 하네요 ㅎㅎ
created_at: 2025-03-21T01:04:33Z
author_association: CONTRIBUTOR

PR comments:
user: login: honux77
created_at: 2025-03-21T01:01:14Z
body: User 객체의 식별자라고 할 수 있는 userId 필드를 String 타입으로 선언했더니, User를 보관하는 List에서 User를 불러올 때 코드가 길어지게 되었습니다.
예를 들어 userId 필드를 int 타입으로 선언했으면 List에서 get 메서드를 통해 바로 불러올 수 있지만, 제가 선언한 타입은 String이라 get 메서드를 사용할 수 없기 때문입니다.

for (User user : userList) {
if(user.getUserId().equals(userId)){
if(!user.getPassword().equals(password)){
redirectAttributes.addFlashAttribute("errorMessage", "비밀번호가 일치하지 않습니다.");
return "redirect:/users/{userId}/form";
}
user.setName(name);
user.setEmail(email);
}
}
return "redirect:/users";
}

코드 예시입니다.
여기서 코드를 줄이기 위해 userId 타입을 int와 같은 숫자 타입으로 바꾸려고 하는데 변경해도 괜찮은지가 고민입니다.

--> 이건 뭔가 질문과 고민이 엄청 복잡하게 얽혀있네요. 수업때 잠깐 봐도 좋을 것 같아요. 
author_association: CONTRIBUTOR
user: login: honux77
created_at: 2025-03-21T01:01:53Z
body: 추가적으로 회원 정보를 수정할 때 Put 메서드를 사용해야한다는 요구사항이 있는데, Post 메서드로 구현하였습니다.
Post 메서드로 구현하였어도 기능 동작엔 문제가 없어 따로 수정은 하지 않았는데, 정보를 수정하는 경우에 Put 메서드를 쓰지 않고 Post를 메서드를 써도 괜찮은지, 괜찮다면 Put 메서드는 존재 이유가 뭔지 궁금합니다.
--> 이런 건 스스로 공부해야 되겠죠? 중요한 내용이니 꼭 확인해 보세요.
author_association: CONTRIBUTOR