2023.02.09.THU

ronglong·2023년 2월 9일
0

1. 톰캣 수동 배포

  • plain.war, plain.jar 와 plain이 붙지 않은 파일의 차이
    : 플레인 붙으면 의존성 하나도 반영 안 된 순수 소스 코드라고 생각하면 됨.
    https://dev-j.tistory.com/22
  • 인텔리제이 내장 톰캣 말고, 톰캣으로 war 파일 실행하려 했는데, 404 에러 났다. 검색하다가 마땅치 않아서 일단 에러 로그를 열어봄.
    DB가 없는 게 문제인건가?
    -> ㄴㄴ. war 파일 이름 바꿔서 경로 못 찾은 것임.
    server.xml 설정 파일에도 생성된 war 파일 기본 풀네임으로 작성할 것.
<Context path="/" docBase="war파일이름"  reloadable="false" > </Context>

//

2. Ngrok

  • 네트워크 설정 없이 (방화벽 뚫고) 외부에서 로컬 환경에 접근하게 해주는 터널링 프로그램
    - ngrok http {port} 명령어로 로컬 주소:포트에 임시 도메인을 연결하여 외부에서 접근할 수 있도록 설정. 프론트랑 협업할 때 사용 가능.
  • 서버를 로컬에서 돌리면, 외부에서 해당 임시 도메인으로 내 로컬 서버에 접근 가능.

//

3. Todo 앱 만들기

  • Todo 앱 만들기 기본 설정은 다음과 같이 작성했다.
    엔티티 하나 밖에 없어서 DTO랑 Service 클래스도 안 만들고, 2시간만에 와랄라 만들어버림 ㅋㅋㅋㅋ
    그래도 그동안 개인적으로 공부한 게 효과가 있는지 만드는 게 크게 어렵지 않았다 :)
  • DB에 저장될 때랑 응답 받을 때 순서 마음에 안 들었는데, 엔티티에 변수명 하나(id)를 실수로 대문자로 시작해서 어긋난 것이었다. ㅋㅋ 찾아주신 도토리님 무한 감사!
    생성자에 @Builder를 쓰는 방법을 사용하자!
    https://velog.io/@mooh2jj/%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%97%94%ED%8B%B0%ED%8B%B0-Builder-%EC%82%AC%EC%9A%A9%EB%B2%95
  • 도토리님이 알려주신 @RequiredArgsConstructor DI 생성자 따로 안 만들어도 됨.
    대신 final or @NonNull 이 필드에 붙어있어야 함.
    https://dreamcoding.tistory.com/83
  • @AutoWired 생성자 하나일 때는 생략 가능한데, 지금까지 무지성으로 늘 DI 받을 인자들을 묶어서 생성자 하나로만 만들었어서 생략하는 게 익숙하여 너무 낯설어진 애너테이션,, 까먹지 말기. 무지성 미쳤음,,
  • DTO 없어서 @Requestbody 말고 @RequestParam 썼다. 오랜만에 쓰니까 헷갈려서 찾아봄 ㅎ 파라미터 이름 생략해도 된다. 그럼 옆의 변수명으로 알아서 지정됨.
    @RequestParam int test 이런 식으로.
    https://heavenly-appear.tistory.com/302
  • 엔티티를 바로 @RequestBody로 받았어도 됐었다. ★
  • MissingServletRequestParameterException 파라미터 쓰니까 이런 에러를 새로 처리해야 했다. 일단 메세지를 가져와서 에러 처리는 했다.
    다만, 요청할 때 파라미터를 여러 개 빼먹는다면, 해당 파라미터들의 이름과 타입을 한 번에 리스트로 담아서 주고 싶었는데,1개씩 밖에 못 가져옴..
  • 귀찮아서 대충 간략히 막 만들었지만 포트스맨과 뷰에서 잘 돌아간다! 굿굿
    https://todobackend.com/client/index.html?{서버URI} 로 확인 가능.
  • 중간에 페이지 전체 내용 조회하면 ClassCastException 났었는데, 혹시 몰라서 파라미터와 필드 타입도 다 맞춰줬고, 디버그 찍어서 살펴보니 Pagable 타입 import 경로를 잘못해서 그런 것이었다. 해결!
    https://nhj12311.tistory.com/156

//

4. 기타

  • 유튜브 애플코딩의 git 강의 3개 봤다. 곧 프로젝트라서 협업 대비,,
  • branch는 복사본을 만든다고 생각하면 편함. 회사에서도 늘 원본 말고 복사본에 작업하니까!
  • git branch 브랜치명 : 브랜치 생성됨. 복사본.
  • git switch 브랜치명 : 브랜치 이동
  • 메인 브랜치에서 git merge 브랜치명 : 메인 브랜치에 다른 브랜치 합침
    -> 충돌나면 원하는 코드만 남겨서 해결 후 add, commit
    https://gmlwjd9405.github.io/2017/10/27/how-to-collaborate-on-GitHub-1.html

//

5. JMT 주문시스템 & 게시판 만들기

  • docker에서 DB 굴리기 (h2 인메모리 DB 썼더니, 어플리케이션 재실행할 때마다 포스트맨 확인할 때, post 계속 해줘야하는 번거로움을 줄이기 위해)
docker run -p 5432:5432 -e 
POSTGRES_PASSWORD=비밀번호 -e POSTGRES_USER=아이디 -e
POSTGRES_DB=springboot --name postgres_boot -d postgres
  • 위 명령어를 터미널에 입력하면 도커에서 postgres db가 생성/실행된다.
    어플리케이션의 yml파일과 build.gradle 파일 DB 부분 수정해서 사용하면 됨.
build.gradle의 dependency 중.
runtimeOnly 'org.postgresql:postgresql' // 런타임 때 사용하는 디비

.yml 중.
spring:
  datasource: #도커에서 실행하는 DB
    url: jdbc:postgresql://localhost:5432/springboot
    password: 1234
    username: test
  • 지금까지 구성한 JMT 환경 설정 파일 (docker DB 추가하지 않은 버전)
[build.gradle] 

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.8'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
	id "org.asciidoctor.jvm.convert" version "3.3.2" // .adoc 파일 생성을 위한 플러그인
}

ext {
	set('snippetsDir', file("build/generated-snippets"))
	// snippetsDir : 테스트 실행시 생성되는 응답을 저장할 디렉토리 지정
}

group = 'CoffeeOrderWebApp'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
	asciidoctorExtensions
	// asciidoctorExtensions : Asciidoctor의 확장 기능을 사용하기 위한 설정
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'

	implementation 'org.springframework.boot:spring-boot-starter-validation'
	implementation 'org.mapstruct:mapstruct:1.5.3.Final'
	annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'

	implementation 'com.google.code.gson:gson:2.9.0'

	testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
	asciidoctorExtensions 'org.springframework.restdocs:spring-restdocs-asciidoctor'

//	testImplementation("org.junit.vintage:junit-vintage-engine") {
//		exclude group: "org.hamcrest", module: "hamcrest-core"
//	}
}

tasks.named('test') {
	outputs.dir snippetsDir // test 할 때 snippetsDir에 생성된 응답을 asciidoctor로 변환하여 .adoc 파일 생성
	useJUnitPlatform()
}

// (7) asciidoctor를 사용하기 위해서 asciidoctor task에 asciidoctorExtensions 설정
tasks.named('asciidoctor') {
	configurations "asciidoctorExtensions"
	inputs.dir snippetsDir
	dependsOn test
}

// (8) asciidoctor task 실행시 생성된 html 파일을 src/main/resources/static/docs 디렉토리에 카피
task copyDocument(type: Copy) {
	dependsOn asciidoctor            // (8-1)
	from ("${asciidoctor.outputDir}/html5")   // (8-2)
	into ("src/main/resources/static/docs")   // (8-3)
}

build {
	dependsOn copyDocument  // (9) 빌드되기전 copyDocument task 실행
}

bootJar {
	dependsOn asciidoctor
	from ("${asciidoctor.outputDir}") {  // (10-2) bootJar에 asciidoctor task에서 생성된 html 파일 추가
		into 'static/docs'     // (10-3) bootJar에 추가될 경로
	}
}
[application.yml]

spring:
  h2:
    console:
      enabled: true
      path: /h2
  datasource:
    url: jdbc:h2:mem:test
  jpa:
    properties:
      hibernate:
        highlight_sql: true 
        format_sql: true  # SQL pretty print
    hibernate:
      ddl-auto: create  # 테이블 자동 구성(드랍 & 생성)
    show-sql: true      # SQL 보기
  sql:
    init:
      data-locations: classpath*:db/h2/data.sql
  output:
    ansi:
      enabled: always # debug, trace
logging:
  level:
    org:
      hibernate:
        type:
          descriptor:
            sql: TRACE # hibernate 
      springframework:
        orm:
          jpa: DEBUG

0개의 댓글