[스프링 입문] 5. 회원 관리 예제 - 웹 MVC 개발

코린이서현이·2023년 11월 5일
0

😊들어가면서😊

  • 웹을 만들어보자.

📌 회원 웹 기능 - 홈 화면 추가
📌 회원 웹 기능 - 등록
📌 회원 웹 기능 - 조회

➕ 웹 MVC란?
애플리케이션을 Model-View-Controller로 나누는 것이다.

🎯 웹 MVC를 만들자.

📌 회원 웹 기능 - 홈 화면 추가

🔥 홈 컨트롤러 추가
📄 HomeController

@Controller
public class HomeController {
  
  @GetMapping("/")
  public String home() {
   return "home";
  }
}

🔥 회원 관리용 홈
📂 templates
📄 home.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
  <div>
    <h1>Hello Spring</h1>
    <p>회원 기능</p>
    <p>
      <a href="/members/new">회원 가입</a>
      <a href="/members">회원 목록</a>
    </p>
  </div>
</div> <!-- /container -->
</body>
</html>

📂


📌 회원 웹 기능 - 등록

회원 등록 폼 개발
📄 MemberController

@Controller
public class MemberController {

  private final MemberService memberService;
 
  @Autowired
  public MemberController(MemberService memberService) {
    this.memberService = memberService;
  }
 
  @GetMapping(value = "/members/new")
  public String createForm() {
    return "members/createMemberForm";
  }
}

회원 등록 폼 HTML
📄 createMemberForm

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <!-- Post 방식으로 넘어감-->
    <form action="/members/new" method="post">
        <div class="form-group">
            <label for="name">이름</label>
            <input type="text" id="name" name="name" placeholder="이름을 입력하세요">
        </div>
        <button type="submit">등록</button>
    </form>
</div> <!-- /container -->
</body>
</html>

📄 MemberForm

  • 웹 등록 화면에서 데이터를 전달 받을 폼 객체
    📍 컨트롤러는 아님
public class MemberForm {
  private String name;

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

}

⚒️create

  • 멤버컨트롤러에서 회원을 실제 등록하는 기능
  //같은 URL이지만 방식에 따라서 다르게 매핑된다.
  //HTML에서 MemberForm에 있는 name에 매핑해줌.
  
  @PostMapping("/members/new")
  public String create(MemberForm form) {
    Member member = new Member();
    member.setName(form.getName());

    memberService.join(member);

    return "redirect:/";
  }

📌 회원 웹 기능 - 조회

⚒️ list

  • 회원 컨트롤러에서 조회 기능
  @GetMapping("/members")
  public String list(Model model) {
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    return "members/memberList";
  }

📄 memberList

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <table>
            <thead>
            <tr>
                <th>#</th>
                <th>이름</th>
            </tr>
            </thead>
            <tbody>
            <!--타임리프 분법으로 돌리는 구문-->
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
</div> <!-- /container -->
</body>
</html>

<조회 기능 화면>

🔍 기능 뜯어보기 - controller

HelloController - 이거는 다른 예제에서 한 것!!
HomeController - 첫 화면을 띄워줌. 위 컨트롤러가 정적 예제이기 떄문에 홈 컨트롤러가 우선됨.
📌컨트롤러가 정적 파일보다 우선순위가 높다.
MemberController - 회원을 등록하고 조회하는 기능을 제공하는 컨트롤러
MemberForm - 실제 컨트롤러는 아니고, 사용자로부터 입력받는 이름을 전달받는 객체이다.

⚒️ HomeController

@Controller
public class HomeController {
  @GetMapping("/")
  public String home() {
    return "home";
  }
}

🤔 @GetMapping과 @PostMapping

  • @RequestMapping
    Spring 프레임워크에서 URL을 핸들링하고 요청을 처리하는 데 사용되는 어노테이션이다. 이 어노테이션은 특정 메서드가 특정 URL 경로에 매핑되도록 지정한다.
    👉 사용 방법

    @@RequestMapping(url)
    자바메서드...
  • @GetMapping - Get method 로 RequestMapping을 합니다.

  • @PostMapping - Post method 로 RequestMapping을 합니다.

➕ 흐음... 괄호안에 url이 해당 경로를 뜻하는 것은 알겠어. 하지만 @GetMapping("/")@GetMapping()의 차이가 궁금한걸?
👉 실제로 @GetMapping()로 해도 기능의 차이가 없다고..!!

GPT 답변.. 이건 따로 포스팅을 하도록 하자.

@GetMapping("/")과 @GetMapping() 모두 루트 경로(/)에 대한 요청을 처리하는데 
사용될 수 있지만, 두 가지 사례가 동일한 결과를 가져온다면, 
이는 Spring Framework의 동작 방식에 기인합니다.

@GetMapping("/")은 명시적으로 / 경로로 들어오는 GET 요청을 처리하는 방법을 정의합니다. 
한편, @GetMapping()은 아무런 경로를 지정하지 않았기 때문에, 
모든 요청에 대해 일반적인 디폴트 동작을 수행합니다.

스프링에서는 URL을 매핑할 때, 가장 구체적인 매핑이 가장 우선시되는데, 
/는 루트 경로로서 가장 구체적인 URL 경로 중 하나입니다. 
그래서, @GetMapping("/")과 @GetMapping() 두 경우 모두 루트 경로를 처리하는데, 
하지만 @GetMapping()의 경우는 어떠한 경로에도 매핑이 가능하기 때문에, 
디폴트로 가장 구체적인 경로인 /와 동일한 동작을 보일 수 있습니다.

Spring은 요청이 들어왔을 때, 가능한 모든 매핑을 검사하여 해당 요청과 
일치하는 핸들러 메소드를 찾습니다. 
만약 /에 대한 매핑을 명시적으로 정의하지 않고, 다른 경로들에 대한 매핑만 정의되어 있다면, 
/에 대한 요청은 가장 일반적인 디폴트 매핑인 @GetMapping()으로 처리될 수 있습니다.

이러한 동작은 Spring의 URL 매핑 및 요청 처리 우선순위에 따른 것이며, 
특정 상황에 따라 명시적으로 경로를 지정하는 것과 
그렇지 않은 것의 동일한 결과를 가져올 수 있을 수 있습니다.

⚒️ MemberController

@Controller
public class MemberController {
  // 공용으로 쓸 수 있게
  //private final MemberService memberService = new MemberService();

  private final MemberService memberService;

  @Autowired
  //생성자의 Autowired?? ->
    public MemberController(MemberService memberService) {
    this.memberService = memberService;
  }

  @GetMapping(value = "/members/new")
  public String createForm() {
    //단순한 이동 기능
    return "members/createMemberForm";
    //탬플릿에서 members/createMemberForm를 찾는다.
  }

  //같은 URL이지만 방식에 따라서 다르게 매핑된다.
  //HTML에서 MemberForm에 있는 name에 매핑해줌.
  @PostMapping("/members/new")
  public String create(MemberForm form) {
    Member member = new Member();
    member.setName(form.getName());

    memberService.join(member);

    return "redirect:/";
  }

  @GetMapping("/members")
  public String list(Model model) {
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    return "members/memberList";
  }

}

이 코드는 생성자 부분과 메서드 3개로 나눠볼 수 있다. 또한 등록과 조회의 기능을 하고 있다.
천천히 살펴보자 😊

⚒️ 생성자 부분

  @Autowired
  public MemberController(MemberService memberService) {
    this.memberService = memberService;
  }

📍@Autowired

  • 필요한 의존 객체의 "타입"에 해당하는 빈을 찾아 주입한다.
    MemberService라는 빈을 등록해두었기 때문에 주입해주는 것이다. 해당 빈이 없다면 오류가 발생한다.

⚒️ createForm()create(MemberForm form)

😮 헉 같은 url의 RequestMapping이 두 개나?
👉 하지만 방식이 다르기 때문에 각자 다르게 동작한다!!

  @GetMapping(value = "/members/new")
  public String createForm() {
    return "members/createMemberForm";
  }

➡️ 탬플릿에서 members/createMemberForm를 찾아 제공한다.

  //같은 URL이지만 방식에 따라서 다르게 매핑된다.
  //HTML에서 MemberForm에 있는 name에 매핑해줌.
  @PostMapping("/members/new")
  public String create(MemberForm form) {
    Member member = new Member();
    member.setName(form.getName());

    memberService.join(member);

    return "redirect:/";
  }

⚒️ list

  @GetMapping("/members")
  public String list(Model model) {
    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    return "members/memberList";
  }

😰 나는 파라미터를 따로 준 적이없는데 왜 파라미터가 있을까??ㅜㅜ
(정말 자바스프링 어렵고 짜증나!!🫤)

model.addAttribute("members", members);
➡️ 위에서 추가된 멤버리스트를 Model객체에 추가하는 것이다.
(흠.. 추가될 때 쓰이는 군..)

➕ Model 객체

이것도 따로 포스팅을 해야겠당..

Spring MVC에서 Model 객체는 컨트롤러가 뷰로 데이터를 전달하는 데 사용되는 매개변수 중 하나입니다. 
이 매개변수는 메소드 시그니처에서 파라미터로 명시되지만, 직접적으로 클라이언트에서 전달되는 HTTP 요청 파라미터가 아닙니다.

Spring의 MVC 프레임워크는 요청을 처리할 때 
해당 메소드 시그니처의 매개변수를 자동으로 인식하고 채웁니다. 
Model 객체는 뷰로 전달할 데이터를 보유하는데 사용됩니다. 
이것은 Spring MVC의 동작 방식 중 하나이며, 
Model은 개발자가 직접 요청에서 파라미터를 추출하거나 사용자 입력을 처리하는 용도가 아니라, 
뷰로 데이터를 전달하기 위해 사용됩니다.

🚨마무리하면서🚨

하 공부는 쉽지 않아
profile
24년도까지 프로젝트 두개를 마치고 25년에는 개발 팀장을 할 수 있는 실력이 되자!

0개의 댓글