화면 구성 main에서 회원가입을 클릭하면 Get 방식으로 회원가입 페이지로 이동 → 아이디, 비밀번호, 비밀번호 재확인, 이름을 입력 받고 회원가입 버튼을 클릭하면 회원가입이 가능하게 하기 회원가입 과정은 Post 방식을 이용
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>그냥 게시판</title>
</head>
<body>
<h1>회원가입</h1>
<form action="${pageContext.request.contextPath}/member/joinPro" method="post">
아이디 : <input type="text" name="id" required="required"><br>
비밀번호 : <input type="password" name="pw" required="required"><br>
비밀번호 재확인 : <input type="password" name="pwre" required="required"><br>
이름 : <input type="text" name="name" required="required"><br>
<input type="submit" value="회원가입">
</form>
</body>
</html>
화면 구성이 너무 없어보임. input 태그가 정렬 안된 느낌.. 물론 화면이 주는 아니지만 기본적으로 그냥 예의가 없는 화면...
최소한 정보를 입력받는게 정렬되게 바꿔봄
input 태그에 placeholder로 각 항목에 제약사항을 넣어봤는데 짤리는 부분이 있음. 우리나라 최고의 포털사이트 중 하나인 네이버 회원가입을 살펴보면
따로 텍스트가 없고, placeholder를 사용하고, jQuery ajax를 이용한다는 것을 알 수 있음.
최대 포털에서 이렇게 사용한다는 것은 회원 가입을 원하는 이용자가 불편함을 느끼지 않는다는 뜻이라고 생각된다.
처음부터 저렇게 만들면 좋겠지만, 조금조금씩 추가하는 방향으로 하는게 과부하를 방지할 수 있을 것 같음
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>그냥 게시판</title>
</head>
<style>
.formstyle{
width : 400px;
}
.label{
width : 200px;
}
.validation{
widows: 200px;
height: 30px;
}
</style>
<body>
<h1>회원가입</h1>
<form action="${pageContext.request.contextPath}/member/joinPro" method="post">
<div class="formstyle">
<input type="text" name="id" required="required" placeholder="아이디"><br> <%-- 영문 소문자, 숫자와 특수기호(_),(-)만 사용 가능 --%>
<input type="password" name="pw" required="required" placeholder="비밀번호"><br> <%-- 영문 대/소문자, 숫자, 특수문자를 사용 --%>
<input type="password" name="pwre" required="required" placeholder="비밀번호재확인"><br> <%-- 비밀번호를 다시 입력 --%>
<input type="text" name="name" required="required" placeholder="이름"> <%-- 한글, 영문만 입력 가능 --%>
</div>
<div class="validation"><b></b></div> <%-- 유효성 검사 시 유효성에 일치않을 때 --%>
<input type="submit" value="회원가입">
</form>
</body>
</html>
비밀번호 재확인에 name을 넣어줬는데, 이 정보는 DB에 저장하는 용도가 아닌 정보 확인용이기 때문에 해당 input 태그에 name이 필요없음 → 즉 <input type="password" required="required" placeholder="비밀번호재확인"><br>
프로젝트하면서는 전혀 신경쓰지 않았던 것 → 어노테이션, 언제쓰는지는 아는데 안에 어떻게 생긴건지 살펴 볼 시간이 없었음.
대표적으로 @Controller 어노테이션을 살펴보면
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.stereotype;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that an annotated class is a "Controller" (e.g. a web controller).
*
* <p>This annotation serves as a specialization of {@link Component @Component},
* allowing for implementation classes to be autodetected through classpath scanning.
* It is typically used in combination with annotated handler methods based on the
* {@link org.springframework.web.bind.annotation.RequestMapping} annotation.
*
* @author Arjen Poutsma
* @author Juergen Hoeller
* @since 2.5
* @see Component
* @see org.springframework.web.bind.annotation.RequestMapping
* @see org.springframework.context.annotation.ClassPathBeanDefinitionScanner
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any
*/
String value() default "";
}
@interface Controller{} 로 되어 있는 것을 알 수 있는데, 이는 커스텀 어노테이션을 정의하는 방법으로 정의되어있음
※ 커스텀 어노테이션 정의 @interface 어노테이션 이름
Controller 클래스
아키텍처에서 컨트롤러를 정의할 때 사용
- @Controller MVC
해당 클래스가 웹 애플리케이션의 컨트롤러임을 표시. HTTP 요청을 처리하고 응답을 생성하는 역할을 담당 - @Inject
종속성 주입을 수행하는 데 사용. 클래스의 필드, 생성자, 메소드 등에 적용할 수 있음. 클래스에 필요한 종속성을 자동으로 주입할 수 있음
public @interface Inject {} - @GetMapping
HTTP Get 요청을 처리하는 메소드
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
/**
* Alias for {@link RequestMapping#name}.
*/
@AliasFor(annotation = RequestMapping.class)
String name() default "";
/**
* Alias for {@link RequestMapping#value}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] value() default {};
/**
* Alias for {@link RequestMapping#path}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] path() default {};
/**
* Alias for {@link RequestMapping#params}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
/**
* Alias for {@link RequestMapping#headers}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {};
/**
* Alias for {@link RequestMapping#consumes}.
* @since 4.3.5
*/
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {};
/**
* Alias for {@link RequestMapping#produces}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {}; - PostMapping
HTTP Post 요청을 처리하는 메소드
@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {
/**
* Alias for {@link RequestMapping#name}.
*/
@AliasFor(annotation = RequestMapping.class)
String name() default "";
/**
* Alias for {@link RequestMapping#value}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] value() default {};
/**
* Alias for {@link RequestMapping#path}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] path() default {};
/**
* Alias for {@link RequestMapping#params}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
/**
* Alias for {@link RequestMapping#headers}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {};
/**
* Alias for {@link RequestMapping#consumes}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {};
/**
* Alias for {@link RequestMapping#produces}.
*/
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {}; - @ResponseBody
컨트롤러의 메소드에 적용되어 해당 메소드가 HTTP 응답의 본문을 직접 반환함. 메소드가 반환하는 객체가 HTTP 응답 본문에 직접 포함되어 클라이언트로 전송됨. 일반적으로 컨트롤러의 메소드가 String, JSON, XML 등의 데이터를 반환 할 때 사용
아무리 봐도 DI(의존성 주입)이란걸 정리해둔걸 한 줄로 요약이 되는데, 진짜 이해가 안됨. A가 B를 이용하면 A는 B에 의존한다? 그래서 검색도 해보고 유튜브 검색도 해봤음. 유튜브 5분개발지식님이 올려둔 의존성 주입 설명을 캡쳐해보았다.
위의 그림을 본다고해도 이해되는 건 아닌데, 대략적으로 이러이러한 것이다 라고 이야기는 할 수 있지 않을까?
결론은 의존성 주입이라는게 너무 추상적이다... 계속하다보면 되겠지라는 생각으로 꾸준히 이해하려고 노력해보자
여담으로 나는 프로젝트를 진행할 때 큰 틀을 만들어 놓고 → 페이지 작업 → DB 작업(스키마, 테이블, 컬럼 만들기) → 클래스 작업으로 하는 것을 선호한다.
이유는 첫째는 페이지를 만들면서, 큰 틀에서 생각해둔 DB를 수정하고 클래스 작업(Controller - Service - DAO - Mapper)을 진행하는 것이 내 입장에서는 편함. 둘째 페이지를 만들면서 이런 기능을 넣으면 좋겠는데? 넣어보자하는게 생기기 때문에 클래스 작업하거나 자바스크립트 사용해 즉각적으로 할 수 있기 때문이다.
기본적으로 수요일까지 화면 구성을 끝 마치고 DB작업 후 클래스 작업하는 순서로 진행하고자한다.
만들어야하는 페이지(view)
- member
회원가입 -> 정규표현식을 이용해서 유효성검사, ajax를 이용하여 중복확인
내 정보 → 정보 수정(이름, 비밀번호), 탈퇴 - board
게시판 리스트 + 글 조회
글 쓰기(회원만)
글 수정, 글 삭제(작성자만)
앞으로 4개의 페이지를 수요일 전까지 만들고 이어서 DB 수정하는 식으로 하자.
※
두 개의 차이 → 접근 제어자 왼쪽은 default, 오른쪽은 public 이 경우 패키지가 다를 경우 접근을 못해서 해당 객체를 사용하지 못 함.
'organize > 프로젝트' 카테고리의 다른 글
justBoard6 member (2) | 2024.09.25 |
---|---|
justBoard5 화면(view)2 (0) | 2024.09.24 |
justBoard3 xml설정, 프로그램 설치 (0) | 2024.09.21 |
justBoard2 DB구축 (0) | 2024.09.20 |
justBoard1 아주 간단한 기능 명세서, 스프링 버전 설정, 화면 구성 (0) | 2024.09.19 |