3년전 코드 뜯어보기 (1)

화나·2020년 11월 30일
0

안녕🤗 likeyCakey

오랜만에 깃허브를 들어가보니 3년전 교육원에서 진행했던 프로젝트가 눈에 들어왔다.
그때 당시에는 잘 만들었다고 생각했는데, 지금와서보니 왜 사용하는지도 모르고 붙여넣었던 코드들과 동작하는데 의의를 뒀던 코드들이 마구잡이로 섞여있었다. 고쳐야겠다.
지금부터 시작되는 우당탕탕 코딩일기..🤪

어떻게 고쳐볼까

지금의 나는 3년전의 나와 다르게 붙여넣기를 남발하지 않고 나름의 클린코드(..?)를 작성하려고 노력한다. 새롭게 알게된 것들을 활용해서 최대한 고쳐봐야지

4년전 개발환경현재 개발환경(예정)
windown10, Git Hub, Apache tomcat 8.0window10, Git Hub, gradle, JDK 11.0.9
JAVA, CSS, HTML, JavaScript, JQuery, JSP, JSTL, AjaxJAVA, CSS, HTML, Java Script, Thymeleaf, Ajax
EclipseIntelliJ
Spring Framework 5.0.4Spring Boot 2.3.5
MybatisJPA
Oracle 11gOracle 19c

내가 맡았던 기능 먼저 뜯어보기

우리의 케이크 플랫폼은 케이크를 주문하는 일반회원과 케이크를 제작해서 판매하는 사업자 회원으로 나뉘어져 있었다. 그 중에서 나는 사업자 회원을 맡아서 사업자 회원가입, 사업자 로그인, 케이크 등록 등 사업자와 관련된 전반적인 기능을 개발했었다.

먼저 플랫폼 이용에 가장 기본이 되는 회원가입을 수정해보자

[Thymeleaf] 새로운 템플릿엔진 사용하기

이전에는 JSP, JSTL을 사용하여 동적인 페이지를 생성했지만 Spring Boot에서는 JSP를 지원하지 않는다고 한다. 그래서 Spring Boot가 지원하는 4가지 템플릿 엔진(FreeMarker, Groovy, Thymeleaf, Mustache) 중 Thymeleaf를 사용할 것이다.

Spring Boot 프로젝트 생성 시 Thymeleaf를 포함하여 생성하였다.

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

이제 자동으로 스프링이 src > main > resources > templates 경로에 있는 뷰 파일을 찾아준다.
templates 폴더안에 파일이 있더라도 이 파일이 Thymeleaf를 사용한다는것을 명시해줘야한다.

<html xmlns:th="http://www.thymeleaf.org"></html>

JSP를 사용했을 때는 include file 태그를 사용하여 header.jsp와 footer.jsp를 모든 파일에 작성해주었다. 타임리프에도 비슷한 기능이 있는가 하고 검색을 해봤더니 layout-dialect 라이브러리가 있었다. include 태그보다 훨씬 더 편안하게 사용이 가능했다!!👏🏻👏🏻
기본 틀을 만들어 놓고 바뀌는 내용만 html파일로 작성하여 포함시켜주면 된다.
라이브러리를 사용하기 위해서 build.gradle 파일에 코드를 추가해줬다.

compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.5.1'

그리고 기본 틀이 될 html파일들을 생성해주었다.

  • fragments/header.html
  • fragments/footer.html
  • fragments/head.html : css 등 head에서 관리되는 리소스들
  • layout/default.html : header, footer, head, content를 포함할 가장 기본적인 틀
  • bizJoin.html(content) : 계속해서 변경되는 html파일의 내용

default.html 파일에 header, footer, head, content파일이 각자의 영역에 들어간다고 생각하면 된다.

//default.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

//head.html 영역  
<head th:replace="fragments/head :: headFragment">
  <title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">default</title>
</head>
  
<body>
    //header.html 영역  
    <header th:replace="fragments/header :: headerFragment"></header>
    //bizJoin.html 영역  
    <div layout:fragment="content"></div>
    //footer.html 영역  
    <footer th:replace="fragments/footer :: footerFragment"></footer>
</body>
  
</html>

<xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
이 네임스페이스는 지금 페이지가 레이아웃 페이지라는것을 알려준다.

<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">default</title>
(Layout에 정의된 타이틀+' : '+컨텐츠페이지 타이틀) 형태로 타이틀을 생성해준다.

<head th:replace="fragments/head :: headFragment">
내용 변동없이 고정되는 head, header, footer부분은 <th:replace> 속성을 사용한다. <th:replace> 속성을 사용하게되면 default.html의 <header> 태그가 header.html의 <header> 태그로 대체된다.
:: 을 기준으로 앞부분은 head.html 파일의 경로를 적어주고 뒷부분은 head.html <head> 태그에 작성해준 fragment이름을 작성해주면 된다.

<div layout:fragment="content"></div>
내용이 변동이 되는 부분은 해당 속성을 이용하여 작성한다.


//header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header th:fragment="headerFragment">
.
.

header.html에는 해당 파일이 대체될 조각이라고 표현해주기 위해서 <th:fragment> 속성을 사용한다. default.html에서 사용하기 위해 fragment 이름(headerFragment)도 적어준다.
( footer.html과 head.html도 동일하게 작성하면 되기때문에 생략 )


<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorator="layout/default">
<head>
</head>
<body layout:fragment="content">
  
  .
  .
  .
  

layout:decorator="layout/default" 네임스페이스를 사용해서 bizJoin.html을 삽입할 파일을 정의해주고 default.html에게 내가 동적으로 변경될 페이지다!! 라고 알려줄 <body layout:fragment="content"> 태그도 작성해준다.

이렇게하면 default.html을 만들어놓고 언제든지 가져다 쓰면서 변경되는 부분만 작성해주면 된다.

Spring Boot의 파일구조 이해하기

(현재 12월 10일) 그동안 html만 작성해놓고 손을 놓고 있었던 이유는 CSS가 이상하게 적용되었는데 원인을 못찾고 삽질을 하고있었다. 이럴땐 머리를 비워야 한다고 생각해서 다른 공부를 하며 틀린곳이 보일때까지 기다렸다. 파일 구조도 이해못하고 잘못된 곳에 CSS파일을 두번 넣은 내 자신이 보였다😥

<내가 알고있던 사실>
Spring Boot의 resources 폴더 아래에는 static 폴더와 templates 폴더 두가지가 기본으로 제공된다.
static 폴더는 주로 정적인 파일들을 관리하고 templates 폴더는 동적인 파일을 주로 관리한다.

<문제 발생>
그래서 resources > css 폴더를 resources > static > css 의 경로로 복사했다.

<문제 발견>
Spring Boot가 자동으로 인식하는 경로는 resources > static > css인데 나는 resources > css 경로의 파일들을 고치고 있었으니.. 이 사실을 알아내서 잘못된 경로의 css 폴더를 삭제해 주었더니 문제가 말끔하게 해결이 되었다^-ㅠ

[JPA, REST API] 회원가입

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
    <persistence-unit name="jpa-project">
        <properties>
            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
            <property name="javax.persistence.jdbc.user" value="유저이름"/>
            <property name="javax.persistence.jdbc.password" value="비밀번호"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521/orcl"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
          </properties>
    </persistence-unit>
</persistence>
  • JPA의 필요한 설정 정보를 관리한다. META-INF/persistence.xml 경로에 있으면 JPA가 인식한다.
  • <persistence-unit name="jpa-project"> : JPA설정은 영속성 유닛이라는 것부터 시작하는데 연결할 데이터베이스당 하나의 영속성 유닛을 등록한다. 그리고 이 영속성 유닛에는 고유한 이름을 부여해야한다. 내가 사용한 이름은 jpa-project이다.
  • <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/> : 데이터 베이스 방언 설정

//Member.java
@Entity
@SequenceGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        sequenceName = "MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
        initialValue = 1, allocationSize = 1)
@Table(name="MEMBER")
public class Member {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
    private int idx;
    private String id;
    private String password;
    private String name;
    private String email;
    private String post;
    @Column(name="basic_addr")
    private String basicAddr;
    @Column(name = "detail_addr")
    private String detailAddr;
    private String phone;
    @Column(name = "black_cnt")
    private int blackCnt = 0;
    private int status = 0;
    private int type = 0;
    
   //getter, setter 생략
  • @Entity : Member.java 클래스를 테이블과 매핑한다고 JPA에게 알려준다.
  • @Table : Member.java 클래스에 매핑할 테이블 정보를 알려준다. 이 어노테이션을 생략하면 클래스 이름을 테이블 이름으로 매핑한다.
  • @SequenceGenerator : 회원 가입시 회원번호를 자동으로 넣어주기 위해 시퀀스를 생성한다.
  • @Id : Member.java의 idx 필드를 테이블의 기본키에 매핑한다.
  • @Column : 이름이 일치하지 않는 컬럼들은 해당 어노테이션을 사용하여 매핑해준다. 이 어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 매핑한다.
  • @GeneratedValue : 생성된 시퀀스를 사용하여 기본키에 자동으로 값을 넣어준다.

//NewMemberController
@RestController
@RequestMapping("/members")
public class NewMemberController {

    @Autowired
    NewMemberService newMemberService;

    @PostMapping
    public ResponseEntity<Member> save(Member member) {
        return new ResponseEntity<Member>(newMemberService.save(member), HttpStatus.OK);
    }
}

//NewMemberService
@Service
public class NewMemberService {
    @Autowired
    NewMemberRepository newMemberRepository;

    public Member save(Member member){
        newMemberRepository.save(member);
        return member;
    }
}

//NewMemberRepository
@Repository
public interface NewMemberRepository extends JpaRepository<Member, Integer> {
    Member save(Member member);
}

0개의 댓글