coupang Day04 로그아웃, CKEditor을 이용한 상품이미지 업로드.

김지원·2022년 6월 30일
0

WebDevelop

목록 보기
15/21

로그아웃

유저컨트롤러에서 로그아웃 부분

1. 어디선가 UserEntity 타입의 객체를 받아와서 이가 가진 email 이 null이 아니라면 sessions 테이블에서 이 이메일을 가진 유효한 세션 만료시키기
2. sk라는 이름을 가지는 쿠키 삭제

-> SessionInterceptor sessionEntity 추가

-> UserController getLogout

  • (SessionEntity) request.~ : SessionEntity로 형변환한 request

-> UserService expireSession

  • expired : 만료시키는 것.

-> UserController

여기까지 했다면 로그아웃이 되는 것을 확인하면 된다.

  • 로그아웃 잘된다!

상품조회

-> index.html

<main class="main">
    <aside class="aside">
        카테고리 자리임
    </aside>
    <section class="content">
        <section class="controller">
            <a class="link selected" href="#">이름순</a>
            <a class="link" href="#">낮은가격순</a>
            <a class="link" href="#">높은가격순</a>
            <span class="spring"></span>
            <a class="link" th:href="@{/product/add}" th:if="${userEntity != null && userEntity.isAdmin() == true}">상품 등록</a>
        </section>
        <section class="products">
            <a class="product" href="#">
                <img  alt="상품이미지" class="image" th:src="@{/resources/images/cider-product.png}">
                <span class="title">칠성사이다 210ml, 30개 </span>
                <span class="price">
                    <span class="number">45,550</span>
                    <span class="won"></span>
                    <img alt="로켓프레시" class="rocket" th:src="@{/resources/images/rocket-fresh.png}">
                </span>
                <span class="due">새벽 도착 보장</span>
                <span class="stars">
                     <i class="star one two three four five fa-solid fa-star"></i>
                    <i class="star two three four five fa-solid fa-star"></i>
                    <i class="star three four five fa-solid fa-star"></i>
                    <i class="star four five fa-solid fa-star"></i>
                    <i class="star five fa-solid fa-star"></i>
                </span>
            </a>
</main>

-> index.css -> index.main.css 생성 (import)

<style>
@charset "UTF-8";

body > .main {
    width: var(--content-max-width);
    align-items: flex-start;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
}

body > .main > .aside {
    border: 0.0625rem solid rgb(229, 229, 229);
    border-top: none;
    margin-right: 1rem;
}

body > .main > .content {
    flex: 1;
}

body > .main > .content > .controller {
    background-color: rgb(239,239,239);
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-top: 1rem;
    margin-bottom: 1rem;
    padding: 0.75rem 1rem;
}

body > .main > .content > .controller > .spring{
    flex: 1;
}

body > .main > .content > .controller > .link:hover {
    color: rgb(66,132,243);
}

body > .main > .content > .controller > .link.selected {
    color: rgb(66,132,243);
    font-weight: 500;
    cursor: default;
    pointer-events: none;
}

body > .main > .content > .controller > .link + .link {
    margin-left: 0.5rem;
}

body > .main > .content > .products {
    display: grid;
    grid-gap: 1.5rem;
    grid-template-columns: repeat(3, 1fr);
}

body > .main > .content > .products > .product {
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}

body > .main > .content > .products > .product > .image {
    width: 100%;
    margin-bottom: 0.75rem;
}
body > .main > .content > .products > .product > .title {
    text-align: justify;
    margin-top: 0.5rem;
}

body > .main > .content > .products > .product:hover > .title {
    color: rgb(66,132,243);
    text-decoration: underline;
}

body > .main > .content > .products > .product >.price {
    align-items: center;
    color: rgb(174,0,0);
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-bottom: 0.5rem;
}

body > .main > .content > .products > .product >.price > .number {
    font-size: 1.125rem;
    font-weight: 600;
}

body > .main > .content > .products > .product >.price > .rocket {
    height: 1.25rem;
    margin-left: 0.5rem;
}

body > .main > .content > .products > .product > .due {
    color: rgb(0, 137, 26);
    margin-bottom: 0.375rem;
}

body > .main > .content > .products > .product > .stars {
    color: rgb(205,205,205);
    letter-spacing: -0.125rem;
}

body > .main > .content > .products > .product > .stars.one > .star.one {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.two > .star.two {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.three > .star.three {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.four > .star.four {
    color: rgb(255,151,0);
}

body > .main > .content > .products > .product > .stars.five > .star.five {
    color: rgb(255,151,0);
}
</style>


-> add.html 상품추가

<form class="main" method="post">
    <label class="label">
        <span class="hint">제목</span>
        <input autofocus class="input" maxlength="100" name="title" placeholder="상품 제목을 입력해주세요." type="text">
    </label>
    <label class="label">
        <span class="hint">가격</span>
        <input class="input" min="100" max="99999990" name="price" placeholder="판매 가격을 입력해주세요."step="10" type="number">
    </label>
    <label class="label">
        <span class="hint">구분</span>
        <label class="label">
            <input class="input" name="delivery" type="radio" value="normal">
            <span class="checker"></span>
            <span class="text">일반</span>
        </label>
        <label class="label">
            <input class="input" name="delivery" type="radio" value="rocket">
            <span class="checker"></span>
            <span class="text">로켓</span>
        </label>
        <label class="label">
            <input class="input" name="delivery" type="radio" value="rocketFresh">
            <span class="checker"></span>
            <span class="text">로켓프레시</span>
        </label>
    </label>
    <textarea class="editor" name="content" id="editor"></textarea>
    <div class="buttons">
        <input class="button white" type="button" value="돌아가기" onclick="if(confirm('정말로 돌아갈까요? 작성하신 정보가 모두 유실됩니다.')){window.history.back();}">
        <input class="button blue" type="submit" value="상품 등록하기">
    </div>
</form>

-> add.css

<style>
@charset "UTF-8";

body > .main {
    width: var(--content-max-width);
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    margin-top: 1rem;
    padding-bottom: 1rem;
}

body > .main > .label {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-bottom: 0.5rem;
}
body > .main > .label > .hint {
    flex: 0 0 3rem;
    white-space: nowrap;
    margin-left: 1rem;
}

body > .main > .label > .input {
    width: auto;
    flex: 1;
    border: 0.0625rem solid rgb(229, 229, 229);
    padding: 0.625rem 1rem;
    border-radius: 0.25rem;
}

body > .main > .label > .label {
    align-items: center;
    cursor: pointer;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
}

body > .main > .label > .label + .label {
    margin-left: 0.75rem;
}

body > .main > .label > .label > .checker {
    border: 0.0625rem solid rgb(229, 229, 229);
    border-radius: 50%;
    margin-right: 0.375rem;
    padding:0.5rem;
}

body > .main > .label > .label > .input:checked + .checker {
    border: 0.0625rem solid rgb(229, 229, 229);
    background-color: rgb(66,132,243);
}

body > .main > .label > .label > .text {
    white-space: nowrap;
}

body > .main > .buttons {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin-bottom: 1.5rem;
}

body > .main > .buttons > .button {
    width: auto;
    border-radius: 0.25rem;
    cursor: pointer;
    padding: 0.75rem 1.25rem;
}

body > .main > .buttons > .button +.button {
    margin-left: 0.5rem;
}

body > .main > .buttons > .button:hover {
    filter: brightness(105%);
}

body > .main > .buttons > .button:active {
    filter: brightness(95%);
}

body > .main > .buttons > .button.white {
    border: 0.0625rem solid rgb(229, 229, 229);
}

body > .main > .buttons > .button.blue {
    background-color: rgb(66,132,243);
    color: white;
}
</style>

-> ProductController

.

  • 관리자가 아니면 다른 사람이 상품 등록을 클릭하게 되면 404 뜨게 설정.

  • 관리자 아이디로 로그인 하게 되면 상품정보를 수정할 수 있게 된다.

WYSIWYG

: What you see is what you get

  • 상품 추가를 위해 CKEditor을 사용할 것이다.

  • CKEditor 5 클릭
  • Online builder 클릭
  • Classic으로 추가한다.
  • simple upload adapter 추가 / 필요한 기능을 추가해서 사용하면 된다.
  • cloudService, ckuploadadaptor, ckfinder 제외.
  • 최종 editor plugins
  • 한국어 선택
  • 다운로드 !
  • html 파일을 보면서 사용하면 된다.

-> CKEditor 옮길 파일 위치

  • 다운로드한 파일 압축 풀고 build폴더안에 있는 폴더랑 파일들을 intellj로 옮긴다. (아래에서 파일 위치 확인)

-> ckeditor 파일 추가 / add.html srcipt 링크 추가

  • resources-> libraries -> ckeditor 디렉터리 생성하고 파일 추가한다.
  • add.html script 링크 추가

-> add.html ckeditor 이 들어갈 박스 추가

  • ckeditor는 상품 제목/가격을 적는 곳과 등록 버튼 사이에 위치한다.
    textarea 로 추가!

-> add.js 추가

-> add.js

  • 현재 뜨는 화면

  • maxheight를 설정해두었기 때문에 70vh를 넘어가면 화면이 더 이상 늘어나지 않는다.

-> submit

  • submit(상품등록하기 버튼 클릭)을 하게 되면 지금은 경로가 없어서 이렇게 뜬다.
  • CKEditor을 통해 작성한 내용과 이미지는 서버의 html의 코드로 넘어간다.
  • src는 우리의 주소여야한다. 우리가 이미지를 제공한다는 의미.
    이미지 버튼을 눌러서 이미지를 업로드하는데 버튼을 누르기 전에 이미 이미지는 서버에 업로드가 되어있어야한다.
    이미지선택하고 서버의 xhr통해 이미지를 업로드하면 DB에 저장에 된다. 그 다음 그 이미지를 화면에 표시해 줄수 있게 하는 주소(맵핑)하나 만들고
    그 주소를 얘한테 알려주면 여기에 태그가 생기면서 이미지가 뜬다.
    그 다음 작성을 누르면 img태그를 포함한 html코드가 서버로 넘어가서 실제 게시글 내용은 html 코드가 저장이 되는 것이다.

이미지 업로드

-> add.js 추가

  • create할 때 오브젝트로 매개변수를 전달해준다.

  • 개발자 도구를 켜놓고 이미지를 하나 업로드해보자.
  • payload를 보면 방금 js에 작성했던 주소로 요청이 들어갔고 저 맵핑을 만들어서 formData로 들어오고 있는 업로드 된 이미지를 받아야한다.
  • binary는 이미지 데이터의 이진데이터를 의미하고 upload는 이름이 upload 라는 것인데 사실상 고정이라고 보면된다.

-> ProductController postAddUploadImage

  • 타입은 MultipartFile[]로 한다.
    postAddUploadImage 이미지를 드래그해서 여러개를 넣을 수 있기 때문에 배열로 만든다.

-> Check

  • 이미지를 추가해서 확인해보자. (alert는 아직은 떠도 상관없다.)
  • sout으로 찍어보았고 이미지 파일이름이 찍히면 성공

0개의 댓글