Project kakao Day1

김지원·2022년 6월 21일
0

WebDevelop

목록 보기
8/21

새로운 프로젝트 시작.

kakao project 생성

  • Spring Boot 2.6.8 버전 사용.

  • Spring Web, Thymeleaf, Spring Boot DevTools dependency 추가

-> 의존성 추가

  • ExeptionUtils와 DateUtils을 사용하기 위해 apache 추가

  • controllers, mappers, services 패키지 생성

-> StandardController 추가

  • Controller 생성자 만듬. 접근 권한 제어자 : protected

-> SystemService @Service 어노테이션만 추가

-> ISystemMapper 추가

  • @Mapper 어노테이션 추가

-> SystemService

  • final인 멤버변수 추가

-> StandardController

  • ExceptionHandler에 ModelAndView를 사용해도 객체화를 해주지 않아서 수동 객체화해야한다.

-> templates패키지에 error.html 생성

  • _error인 이유는 특정맵핑을 위해 존재하는 html이 아니라 공용으로 이용할 것이기 때문이다.

-> StandardController

  • 오류가 handle됐더라도 우리가 어떤 오류인지 알아야 하기 때문에 exception.printStackTrace(); 추가한다.
  • final protected 추가로 더 이상 재정의 할 수 없도록 해준다.

-> RootController 추가 (HomeController로도 사용가능.)

  • StandardController를 상속받는데 StandardController는 생성자가 하나밖에 없으니 상속받을 때 구현을 해주어야 한다.
**-> StandardController**
> ![](https://velog.velcdn.com/images/zirccon/post/8177df75-09d2-432e-a72f-f33fff97fd55/image.png)

-> index.html 추가

  • 나중에 unsigned.html 로 변경할 것임.

사용자 추가 (DB계정 생성)


  • 계정이름 : 'daemom_kakao'@'localhost'
    권한 : 모든 스키마 / 테이블에 모든 권한 부여

-> application.properties


테이블 생성

스키마를 분리해서 사용할 것이다.

-> error_logs 테이블 생성

CREATE SCHEMA `kakao_system`;

CREATE TABLE `kakao_system`.`error_logs`
(
    `index`       BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    `created_at`  DATETIME(6)     NOT NULL DEFAULT NOW(6),
    `client_ip`   VARCHAR(50)     NOT NULL,
    `client_ua`   VARCHAR(500)    NOT NULL,
    `request_uri` VARCHAR(500)    NOT NULL,
    `message`     VARCHAR(1000)   NOT NULL,
    `stacktrace`  VARCHAR(10000)  NOT NULL,
    CONSTRAINT PRIMARY KEY (`index`)
);


-> ErrorLogEntity 추가

private long index;
private Date createdAt;
private String clientIp;
private String clientUa;
private String requestUri;
private String message;
private String stacktrace;
  • GetterSetter 도 추가.
  • 분류로써 prefix(프리픽스)가 붙어 class의 이름이 길어지는 것을 방지하기 위해서 패키지를 분류하여 생성하자.
    = SystemErrorLogEntity -> ErrorLogEntity

-> SystemService

 public void putErrorLog(ErrorLogEntity errorLogEntity)
  • putErrorLog 메서드 생성

-> ISystemMapper

  • int타입을 반환하는 insertErrorLog 추가
  • @SuppressWarnings("UnusedReturnValue") 넣는 방법.
    어노테이션 사용 전에는 insertErrorLog 가 노란색 박스로 뜨면서 spring이 void 타입을 쓰라고 경고를 주고 있는데 우리는 int로써 사용을 하고 싶기 때문에 어노테이션을 사용해서 경고를 없앤다.

-> 다시 SystemService

  • ISystemMapper에 있는 메서드 호출

-> resources, mappers 패키지 생성 후 SystemMapper.xml 생성

  • <mapper namespace="dev.jwkim.kakao.mappers.ISystemMapper">
    인터페이스의 풀네임을 namespace에 적어준다.

IFNULL 함수

IFNULL(? , x)
? 자리에 들어가는 값이 null이라면 대신 뒤에 것(x)을 사용하겠다는 의미.

errorLogEntity를 객체화하는데 created_at을 NULL로 두고 insert로 호출하게 되면 그 뒤에 것 DEFLAULT( )를 사용하겠다는 의미이다.
=> 열 이름에 해당하는 전달된 열의 기본값을 사용한다.
created_at의 기본값을 NOW(6)로 지정해주었음으로
결과적으로 created_at이 NULL이면 created_at의 열에 DEFLAULT = 기본 값이 들어간다.


-> StandardController

  • 예외가 터졌을 때 값을 insert 해야한다.
    try catch로 모든 예외를 받아서 아무런 조치도 취해주지 않는다.
    ErrorLogEntity errorLogEntity = new ErrorLogEntity();객체화 해준다.
    -> created_at을 해주지 않아도 된다는 의미이다. null로 두게 되면 현재시간이 들어가게 된다.
    "User_Agent"은 null이 나올 수도 있기 때문에 따로 뺴준다.

-> 테이블 생성

  • users테이블에서 외래키를 걸기위해 테이블 생성
CREATE TABLE `kakao_member`.`statuses`
(
    `code` VARCHAR(10) NOT NULL ,
    CONSTRAINT PRIMARY KEY (`code`)
);
CREATE TABLE `kakao_member`.`genders`
(
    `code` TINYINT(1) UNSIGNED NOT NULL,
    CONSTRAINT PRIMARY KEY (`code`)
);
CREATE TABLE `kakao_member`.`contact_companies`
(
    `code` VARCHAR(5) NOT NULL ,
    `name` VARCHAR(10) NOT NULL ,
    CONSTRAINT PRIMARY KEY (`code`),
    CONSTRAINT UNIQUE (`name`)
);
CREATE TABLE `kakao_member`.`contact_firsts`
(
    `number` VARCHAR(4) NOT NULL ,
    CONSTRAINT PRIMARY KEY (`number`)
);

-> users 테이블 추가

CREATE TABLE `kakao_member`.`users`
(
    `email`                VARCHAR(50)         NOT NULL,
    `password`             VARCHAR(128)        NOT NULL COMMENT 'SHA-512',
    `created_at`           DATETIME            NOT NULL DEFAULT NOW(),
    `status_code`          VARCHAR(10)         NOT NULL,
    `status_at`            DATETIME            NOT NULL DEFAULT NOW(),
    `profile_nickname`     VARCHAR(10)         NOT NULL,
    `profile_thumbnail`    MEDIUMBLOB          NOT NULL,
    `profile_message`      VARCHAR(100)        NOT NULL,
    `personal_name`        VARCHAR(5)          NOT NULL,
    `personal_birth`       DATE                NOT NULL,
    `personal_gender_code` TINYINT(1) UNSIGNED NOT NULL,
    `contact_company_code` VARCHAR(5)          NOT NULL,
    `contact_first_number` VARCHAR(4)          NOT NULL,
    `contact_second`       VARCHAR(4)          NOT NULL,
    `contact_third`        VARCHAR(4)          NOT NULL,
    CONSTRAINT PRIMARY KEY (`email`),
    CONSTRAINT UNIQUE (`email`),
    CONSTRAINT UNIQUE (`profile_nickname`),
    CONSTRAINT UNIQUE (`contact_first_number`, `contact_second`, `contact_third`),
    CONSTRAINT FOREIGN KEY (`status_code`) REFERENCES `kakao_member`.`statuses` (`code`)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY (`personal_gender_code`) REFERENCES `kakao_member`.`genders` (`code`)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY (`contact_company_code`) REFERENCES `kakao_member`.`contact_companies` (`code`)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    CONSTRAINT FOREIGN KEY (`contact_first_number`) REFERENCES `kakao_member`.`contact_firsts` (`number`)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);
 	`created_at`           # 회원가입 일자
    `status_code`          # 회원의 상태
    `status_at`            # 마지막으로 회원 상태가 변경된 일시
    `profile_nickname`     # 별명
    `profile_thumbnail`    # 프로필 사진
    `profile_message`      # 상태 메세지
    `personal_name`        # 실명 / 개인정보
    `personal_birth`       # 생년월일 / 개인정보
    `personal_gender_code` # 주민등록번호 뒷자리 첫자 / 개인정보
    `contact_company_code` # KT LGU SKT
    `contact_first_number` # 전화번호 첫번째자리
    `contact_second`       # 전화번호 두번째자리
    `contact_third`        # 전화번호 세번째자리

-> entitis 패키지에 member 패키지 생성, UserEntity 추가


-> sessions 담당 테이블 추가 : 중복 로그인을 막기 위해

-> SessionEntity 추가

	`kakao_member`.`sessions` # 중복 로그인을 막기 위해
    `created_at`   # 세션 생성 일자
    `expires_at`   # 로그인 후 아무것도 안한 채로 1시간이 지나면 자동으로 로그아웃시키겠다.
    `expired_flag` # 사용자가 로그아웃을 직접 누르면 true로 업데이트
    `last_at`      # 이 사람이 마지막으로 활동한 ip, uri(주소)를 추적할 것
    `last_ip`      # 마지막 활동 ip
    `last_uri`     # 마지막 활동 주

-> 테이블 열 추가

contact_companies
contact_firsts
genders
statues


@SessionAttributes(이름) {class}

: 정해준 이름으로 Model에 객체가 추가될 경우 실제로 Model이 아닌 세션에 저장한다.

@SessionAttribute {variable}

: 세션 저장소에서 객체를 받아온다.

@ModelAttribute {variable, method}

: 모델 저장소에서 객체를 받아온다.


-> StandardController

  • 파란줄 추가
 @ModelAttribute(name = UserEntity.ATTRIBUTE_NAME)
    protected UserEntity userEntity() {
        return null;
 }
  • SessionAttributes 추가

-> UserEntity에 추가

  • public static final String ATTRIBUTE_NAME = "userEntity";

-> unsigned.html / signed.html

  • 로그인 했을 때 / 로그인 하지 않았을 때 이 두개의 경우를 동일한 주소에서 다른 페이지로 보내기 위해 생성. (index.html -> unsigned.html 로 변경)
    이름 두개 변경하였고 unsigned.html 로그인 내용 추가

-> RootController

  • 세션 저장소에서 객체를 받아온다. SessionAttributes에서 가져오는 것.

Css

font 링크로 추가

  • link 걸어준다.

-> resources 패키지에 images 패키지 생성. 카카오톡 logo이미지 추가

-> unsigned.html

-> stylesheets 패키지에 common.css / index.css 추가

-> index.css

@charset "UTF-8";

body.unsigned {
    width: 100%;
    height: 100%;
    background-color: rgb(var(--common-color-yellow-default));
    position: absolute;
}

body.unsigned > .cover {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 50%);
    position: fixed;
}
body.unsigned > .login-form {
    top: 50%;
    left: 50%;
    align-items: stretch;
    background-color: rgb(var(--common-color-yellow-default));
    border: 0.0625rem sollid rgba(var(--common-color-yellow-default), 90%);
    border-radius: 0.5rem;
    display: flex;
    flex-direction: column;
    box-shadow: 0 0 0.5rem 0.0625rem rgba(50,50,50,50%);
    padding: 5rem 2.75rem;
    position: fixed;
    transform: translate(-50%, -50%);
    z-index: 1;
}

body.unsigned > .login-form > .logo {
    width: 7.5rem;
    user-select: none;
    -webkit-user-drag: none;
}

-> common.css

@charset "UTF-8";

@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard-dynamic-subset.css');

:root {
    --common-color-brown-default:60, 30, 30;
    --common-color-yellow-default: 254, 229, 0;
    --common-text-color-default: 24,22,0;
}

html {
    color: rgb(var(--common-text-color-default));
    font-family: 'Pretendard', sans-serif;
    font-size: 1rem;
    font-weight: 400;
}
body {
    margin: unset;
}

-> 현재까지 브라우저로 보이는 결과

-> 경로 설정 (static)

  • command + ;
    • 누르고 해당 경로를 작성하거나 찾아서 넣으면 된다.
  • 내가 설정한 경로.
  • 자동완성 되는 것을 확인 할 수 있다.

0개의 댓글