프로젝트를 진행하기 전에 고객의 요구사항을 인식하고, 이를 설계하는 과정이 필요합니다. 이를 흔히 요구사항 분석 설계
라고 하는데, 고객이 원하는 내용이 무엇이고, 어느 정도까지 구현할 것인가에 대한 프로젝트의 범위를 정하는 것을 목적으로 합니다.
요구사항은 실제로 상당히 방대해 질 수 있으므로, 프로젝트에서는 단게를 정확히 구분해주는 것이 좋습니다. 만일 팀원들이 경험이 풍부하다면 초기 버전을 상당히 많은 기능을 포함시켜 개발을 진행할 수 있지만, 그렇지 못하다면 최대한 단순하고 눈에 보이는 결과를 만들어 내는 형태로 진행하는 것이 좋습니다.
요구사항은 온전한 문장으로 정리하는 것이 좋습니다. 주어는 고객
이고 목적어는 대상
이 됩니다. 여기서의 대상은 결국 데이터의 베이스 설계와 시스템 설계에서 가장 중요한 용어가 됩니다. 예를 들어, 게시판의 경우 다음과 같이 요구사항을 정리할 수 있습니다.
이 경우 대상은 게시물이 되므로, 게시물이라는 용어가 필요하게 되고, 게시물의 구조를 판단해서 데이터베이스 테이블을 설계하게 됩니다. 예를 들어, 게시물의 경우 xxx_board
라는 테이블을 설계하게 되고 테이블과 관련된 VO 클래스 역시 com.example.domain.BoardVO와 같은 이름으로 설계될 수 있고 com.example.domain.BoardDTO와 같은 이름으로 설계될 수 있습니다. 게시물과 관련된 로직은 com.example.service.BoardService가 될 수 있고, com.example.controller.BoardController라는 이름의 클래스를 생성하는 연속적인 과정을 거치게 됩니다.
요구사항에서 나오는 용어를 기준으로 테이블이나 클래스 이름들이 정해지듯이 요구사항은 화면에도 영향을 미치게 됩니다. 게시글을 등록할 수 있는 화면을 고객에게 보여주려면 view를 구성하는 것들을 말합니다. 실제 프로젝트에서는 스토리보드
를 만들게 됩니다.
이러한 화면을 설계할 때는 주로 Mock-up(목업) 툴을 이용하는 경우가 많습니다. 대표적으로는 PowerPoint를 이용하면 좋습니다.
각 화면을 설게하는 단계에서는 사용자가 입력해야 하는 값과 함께 전체 페이지의 흐름이 설계됩니다. 이 화면의 흐름을 URL로 구성하게 되는데 이 경우 GET/POST 방식에 대해서 같이 언급해두는 것이 좋습니다.
1) devtools 설정하기
spring.devtools.livereload.enabled=true
spring.devtools.restart.enabled=true
spring:
devtools:
livereload:
enabled: true
restart:
enabled: true
위 코드를 적어준다.
여기에는 dependencies에 developmentOnly 'org.springframework.boot:spring-boot-devtools'
을 적어준다.
나머지 설정은 위에 적었으므로 생략하겠습니다.
2) JUnit4, logback 제외하기
여기에서 코드를 쳐줘야 합니다.
// JUnit4 제외시키기
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group : 'org.junit.vintage', module: 'junit-vintage-engine'
}
// JUnit5 가져오기
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2'
all {
//logback과의 충돌 방지
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
// log4j
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
2번 같은 경우는 굳이 할 필요가 없다.
3) MySQL 사용시
runtimeOnly 'com.mysql:mysql-connector-j'
# MySQL 설정
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# DB Source URL
spring.datasource.url=jdbc:mysql://localhost:3306/study01
# DB username
spring.datasource.username=root
# DB userpassword
spring.datasource.password=1234
# MySQL 설정
spring:
datasource:
driver-class-name : com.mysql.cj.jdbc.Driver
# DB Source URL
url : jdbc:mysql://localhost:3306/study01
# DB username
username : root
# DB userpassword
password : 1234
4) H2 database
# DataSource ??
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:~/test
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/test
username: sa
password:
driver-class-name: org.h2.Driver
runtimeOnly 'com.h2database:h2'
5) Mybatis 사용시
# mybatis config
mybatis.mapper-locations=mybatis/mapper/**/*.xml
mybatis.type-aliases-package=com.example.study01.mapper
// https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter
implementation group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '3.0.1'
6) thymeleaf 설정
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
# thymeleaf
spring.thymeleaf.prefix=classpath:templates/thymeleaf/
# 템플릿 위치 존재 확인 - templates 디렉토리에 파일이 있는지 없는지 체크, 없으면 에러를 발생
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
# true로 하면 개발된 화면을 수정했을 때 매번 프로젝트를 다시 시작해야 한다.
# thymeleaf 템플릿에 대한 캐시를 남기지 않음
# cache=false 설정하고 개발하다 운영시에는 true로 변경
spring.thymeleaf.cache=false
7) log 설정
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
이렇게 4개를 넣으면 테스트하는 곳에서도 log를 사용할 수 있습니다.
8) JPA 사용시
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// Querydsl 추가 시작
implementation 'com.querydsl:querydsl-jpa'
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
// querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
// java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
// java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// Querydsl 설정부
def generated = 'src/main/generated'
// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)
}
application.yml
spring:
config:
activate:
on-profile:
- jwt
devtools:
livereload:
enabled: true
restart:
enabled: true
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/shopping
username: root
password: 1234
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
# 영속성 컨텍스트의 생존 범위를 트랜잭션 범위로 한정
# 실시간 트래픽이 중요한 API 애플리케이션에는 false로 유지
open-in-view: true
# JPA 처리 시에 발생하는 SQL을 보여줄 것인지 결정합니다.
show-sql: true
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
# 실제 JPA의 구현체인 Hibernate 가 동작하면서 발생하는 SQL을 포맷팅해서 출력합니다.
# 실행되는 SQL의 가독성을 높여 줍니다.
format_sql: true
# 일대다 컬렉션 조회 시 성능 최적화
default_batch_fetch_size: 500
mvc:
pathmatch:
matching-strategy: ant_path_matcher
logging:
level:
org:
hibernate:
type:
descriptor:
sql: trace
9) thymeleaf-extras-security5
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
10) spring security test
testImplementation 'org.springframework.security:spring-security-test'
11) validation
implementation 'org.springframework.boot:spring-boot-starter-validation' // validation
폴더구조
src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── backend_rest
│ │ ├── controller
│ │ │ └── TodoEntity
│ │ │
│ │ ├── dto
│ │ │ └── TodoDTO
│ │ │ └── ResponseDTO
│ │ │
│ │ ├── service
│ │ │ └── TodoService
│ │ │
│ │ ├── model
│ │ │ └── TodoEntity
│ │ │
│ │ │
│ │ ├── persistence
│ │ └── TodoRepository
│ │
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── com
└── example
└── backend_rest
└── TodoApplicationTests.java