[Spring Boot] 07. 회원 가입 ①, 가입 확인 메일 전송

shr·2022년 2월 17일
0

Spring

목록 보기
7/23
post-thumbnail

회원 가입 ①


💡 mapper.xml 없이 자바만 이용한 방법이다.

  1. 회원 정보를 저장할 DB 테이블 작성

     create table member (
        username varchar2(10 char),
        password varchar2(60 char),
        irum varchar2(10 char),
        email varchar2(50 char),
        birthdaty date,
        joinday date,
        enabled number(1),
        authority varchar2(20 char),
        checkcode varchar2(20 char),
        -- 멤버 테이블의 기본 키는 username이다.
        constraint member_pk_username primary key(username)
    );

    우리가 가지고 있어야 할 회원 정보
    아이디, 비밀번호, 이름, 이메일, 생일, 가입일, enabled, 권한, 체크코드

    회원 가입을 하려는 사용자가 입력하게 될 정보
    아이디, 비밀번호, 이름, 이메일, 생일

    📝 백엔드에서 가입일, enabled, 권한, 체크코드를 추가해서 저장한다.

    💡 enabled : 스프링 시큐리티에서 요구하는 필수 요건이며 0은 비활성화 상태, 1은 활성화 상태를 의미한다. (가입할 때 디폴트 값은 비활성화)


  1. Win+R - cmd - sqlplus - system/비밀번호 접속 후 관리자 계정 생성

    -- 오라클 18c 버전이기 때문에 이전 문법 사용을 위한 요청
    ALTER SESSION SET "_ORACLE_SCRIPT"=true;
    
    create user 관리자 계정 identified by 비밀번호;
    
    grant connect, resource to 관리자 계정;
    
    conn 관리자 계정/관리자 계정 비밀번호;
    
    -- 작성해 둔 테이블 복사 + 붙여넣기
    create table member ();

  1. src/main/java - com.example.demo.entity - Member 클래스 생성

    package com.example.demo.entity;
    
    import java.time.LocalDate;
    
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class Member {
        private String username;
        private String password;
        private String irum;
        private String email;
        private LocalDate birthday;
        private LocalDate joinday;
        private Boolean enabled;
        private String authority;
        private String checkcode;
        private Integer count;
        private Level levels;
    }

    Level은 enum 클래스로 따로 빼 준다.

    package com.example.demo.entity;
    
    public enum Level {
        BRONZE, SILVER, GOLD;
        // 각각 0, 1, 2가 됨!
    }

  1. src/main/java - com.example.demo.dao - MemberDao 클래스 생성

    package com.example.demo.dao;
    
    import org.apache.ibatis.annotations.*;
    
    import com.example.demo.entity.*;
    
    public interface MemberDao {
        @Insert("insert into member(username, password, irum, email, birthday) values(#{username}, #{password}, #{irum}, #{email}, #{birthday})")
        public Integer save(Member member);
    
        @Select("select * from member where username=#{username}")
        public Member findById(String username);
    }

  1. src/main/java - com.example.demo 패키지 속 전체 MyBatis 설정 파일에 @MapperScan 어노테이션 걸어 주기

    @MapperScan("com.example.demo.dao")


  1. src/test/java - com.example.demo - MemberDaoTest 클래스 생성 후 테스트

    package com.example.demo;
    
    import static org.junit.jupiter.api.Assertions.assertNotNull;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import com.example.demo.dao.MemberDao;
    
    @SpringBootTest
    public class MemberDaoTest {
        @Autowired
        private MemberDao dao;
    
        @Test
        public void initTest() {
            assertNotNull(dao);
        }
    }


가입 확인 메일 전송


  1. New - Spring Starter Project 생성
    이대로 선택하면 된다.

  1. pom.xml에 의존성 주입
    <!-- 아파치 commons : 랜덤 문자열 생성 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
            </dependency>
            <!-- log4jdbc -->
            <dependency>
                <groupId>org.bgee.log4jdbc-log4j2</groupId>
                <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
                <version>1.16</version>
            </dependency>

  1. src/main/resources - application.properties 수정

    server.port=8081
    
    spring.datasource.driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    spring.datasource.url=jdbc:log4jdbc:oracle:thin:@192.168.0.113:1521:XE
    spring.datasource.username=관리자 계정
    spring.datasource.password=관리자 비밀번호
    
    mybatis.type-aliases-package = com.example.demo.entity
    mybatis.mapper-locations = mapper/*.xml
    
    spring.mail.host=smtp.gmail.com
    spring.mail.port=587
    spring.mail.username=관리자 메일 계정
    spring.mail.password=관리자 메일 계정 비밀번호
    spring.mail.properties.mail.smtp.auth=true
    spring.mail.properties.mail.smtp.timeout=5000
    spring.mail.properties.mail.smtp.starttls.enable=true

    💡 Java MailSender

    자바로 메일을 보내려면 메일 서버(smtp 서버)가 필요하다. 보통은 네이버나 다음, Gmail 등을 사용한다. 이는 우리가 직접 메일을 보내는 것이 아니라 네이버, 다음, Gmail 쪽에서 대신 메일을 보내 주는 것이다. 따라서 메일 발송에 실패(Exception)했을 경우에도 우리가 프로그램 내에서는 알 방법이 없고, 해당 메일 사이트 계정에 로그인했을 때 오류 메시지를 받아 볼 수 있다.


  1. 메일 보내기에 사용할 Gmail 계정 보안 설정 낮추기

  1. src/main/java - com.example.demo.service - MemberService 클래스 생성

    package com.example.demo.service;
    
    import javax.mail.MessagingException;
    import javax.mail.internet.*;
    
    import org.springframework.beans.factory.annotation.*;
    import org.springframework.mail.javamail.*;
    import org.springframework.stereotype.Service;
    
    @Service
    public class MemberService {
        @Autowired
        private JavaMailSender javaMailSender;
    
        // 메일 전송 메소드
        public void sendMail(String from, String to, String title, String content) throws MessagingException {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, false, "utf-8");
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(title);
            helper.setText(content, true);
            javaMailSender.send(message);
        }
    }

    📝 MIME

    원래는 이메일의 형식을 뜻하는데, 요즘은 파일의 형식을 MIME type이라고 한다. 예를 들어, html에서 엑셀 문서를 클릭하면 'application/excel'이라는 MIME type이 브라우저로 전달된다. 그러면 브라우저는 윈도우에 엑셀이 있는지 찾고, 엑셀이 있으면 엑셀로 실행한다. 엑셀이 없으면, 즉 application/excel이란 MIME type이 알 수 없는 타입이라면 다운로드한다.


  1. src/test/java - com.example.demo - MemberServiceTest 생성 후 테스트

    package com.example.demo;
    
    import javax.mail.MessagingException;
    
    import org.apache.commons.lang3.RandomStringUtils;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import com.example.demo.service.MemberService;
    
    @SpringBootTest
    public class MemberServiceTest {
        @Autowired
        private MemberService service;
    
        @Test
        public void sendMailTest() {
            // 이 보내는 주소는 상대방이 확인할 수 없다. 이메일에 찍히는 "보낸 사람"은 로그인한 아이디이다.
            String from = "admin@icia.com";
            String to = "메일 받아 볼 계정";
            String title = "가입 확인 메일입니다. o(*'▽'*)/☆゚’";
    
            /*
                <p>가입하려면 아래 링크를 클릭하세요.</p>
                <p><a href='http://localhost:8081/member/join/check?checkcode=1234'>클릭하세요.</a></p>
             */
    
            String checkcode = RandomStringUtils.randomAlphanumeric(20);
    
            StringBuilder builder = new StringBuilder("<p>가입하려면 아래 링크를 클릭하세요.</p>")
                    .append("<p><a href='http://localhost:8081/member/join/check?checkcode=")
                    .append(checkcode).append("'>클릭하세요.</a></p>");
    
            try {
                service.sendMail(from, to, title, builder.toString());
            } catch (MessagingException e) {
                e.printStackTrace();
            }
    
        }
    }

StringBuiler

String은 내용을 바꿀 수 없는 불변(immutable) 클래스이다. 따라서 문자열끼리 덧셈을 했을 때 많은 중간 문자열 객체가 생성되어 비효율적인 코드가 생성된다. 이때 문자열을 변경할 수 있는 문자열 변수 클래스인 StringBuilder를 사용할 수 있다.
같은 역할을 하는 StringBuffer와의 차이점은, StringBuilder는 스레드 비안전이고 StringBuffer는 스레드 안전이라는 점이다. 스레드 비안전(thread unsafe)는 각 스레드가 작업 시간을 분배받고, 작업 시간이 끝나면 무조건 CPU를 돌려주어야 하기 때문에 병렬 작업을 할 때 데이터가 안전하지 않지만, StringBuffer는 작업 시간이 끝나더라도 일단 시작한 작업의 종료는 보장된다는 점에서 차이가 있다.


  1. 메일 수신 여부 확인


profile
못하다 보면 잘하게 되는 거야 ・ᴗ・̥̥̥

0개의 댓글