79DAYS) [프로젝트] 솔로 프로젝트 - 웹 애플리케이션 설계 (2)

nacSeo (낙서)·2023년 2월 9일
0

◉ 학습목표

1. 클라이언트의 요청에 따라 적절한 응답을 보내는 웹 애플리케이션을 설계할 수 있다.
2. Restful API에 대해 이해하고 설계할 수 있다.​
  1. 웹 애플리케이션 설계

⦿ 학습내용

☞ To-Do App 실습 내용

✔︎ 단순한 CRUD 기능만 구현

  • Create
    • 할 일 목록등록할 수 있어야 함
  • Read
    • 등록된 전체 할 일 목록을 조회할 수 있어야 함
    • 등록되어 있는 할 일의 특정 id를 입력하여 조회할 수 있어야 함
  • Update
    • 이미 한 일에는 완료 표시를 할 수 있어야 함
    • 할 일의 내용수정할 수 있어야 함
  • Delete
    • 등록된 전체 할 일을 삭제할 수 있어야 함
    • 등록되어 있는 할일의 특정 id를 입력하여 삭제할 수 있어야 함

✔︎ 테이블 구성 명세

  • id : 할 일의 번호 (PRIMARY KEY)
  • title : 할 일의 내용
  • todo_order : 할 일의 번호
  • completed : 완료 표시

☞ 전체적인 설계 순서

✔︎ API 계층 구현
Controller 클래스 작성
Dto 클래스 작성
※ 간단한 애플리케이션 작성이기에 유효성 검증 부분 생략

✔︎ 서비스 계층 구현
Service 클래스 작성

  • API 계층과 소통하는 Entity 클래스 추가 작성

Mapper 인터페이스 작성

  • Dto 클래스에 ResponseDto 추가
  • MapStruct를 이용한 mapper 자동 생성
    • build.gradle 파일 설정 추가

      dependencies {
      			...
      			...
      			implementation 'org.mapstruct:mapstruct:1.4.2.Final'
      			annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
      }
    • MapStruct기반 Mapper 인터페이스 정의

      import com.codestates.todoappv2.dto.TodoDto;
      import com.codestates.todoappv2.entity.Todo;
      import org.mapstruct.Mapper;
      
      @Mapper(componentModel = "spring")
      public interface TodoMapper {
      Todo todoPostDtoToTodo(TodoDto.TodoPostDto todoPostDto);
      Todo todoPatchDtoToTodo(TodoDto.TodoPatchDto todoPatchDto);
      TodoDto.TodoResponseDto todoToTodoResponseDto(Todo todo);
      }
    • Controller 클래스에 import

      import com.codestates.member.mapstruct.mapper.MemberMapper;
  • DTO 클래스 ↔︎ Entity 클래스 매핑

✔︎ 예외 처리 (비즈니스 로직)

  • 이후 데이터 액세스 계층 때, Service 수정 시 특정 id 할 일 조회를 위해 필요 (할 일이 비어있을 경우가 있으므로)
  • BuisnessLogicException 클래스, ExceptionCode Enum 작성

✔︎ 데이터 액세스 계층 (JDBC 기반)
build.gradle에 starter 추가

dependencies {
	...
	...
	implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
	runtimeOnly 'com.h2database:h2'
}

※ 인메모리 DB인 H2 사용

② H2 관련 설정 (application.yml)

spring:
  h2:
    console:
      enabled: true
      path: /h2     # Context path 변경
  datasource:
    url: jdbc:h2:mem:test     # JDBC URL 변경
  sql:
    init:
      schema-locations: classpath*:db/h2/schema.sql   # 테이블 생성 파일 경로

schema.sql 파일 설정 (src/main/resources/db/h2)

CREATE TABLE IF NOT EXISTS TODO (
    todo_id bigint NOT NULL AUTO_INCREMENT,
    title varchar(100) NOT NULL,
    todo_order int NOT NULL,
    completed boolean NOT NULL,
    PRIMARY KEY (todo_id)
);

Repository 인터페이스 정의

  • CRUD를 구현하므로 CrudRepository 인터페이스 상속

☞ 결과 확인

✔︎ Postman과 Todo backend 사이트를 통해 각 API에 대한 응답 확인

https://todobackend.com/client/index.html?{URI}
(예시) https://todobackend.com/client/index.html?http://localhost:8080/
  • 보내고 싶은 URI 주소 작성
  • 예시처럼 작성한다면 로컬에서 8080번 포트로 실행한 서버에 요청을 보냄
    • localhost:8080 또는 127.0.0.1:8080
  1. Tomcat을 이용한 수동 배포

⦿ 학습내용

☞ 톰캣 설치

✔︎ 톰캣 공식 사이트

  • MAC OS 유저 : tar.gz 설치


- bin : 톰캣을 실행하거나 종료할 수 있는 스크립트 파일 존재
- conf : 서버 설정 파일 존재
- webapps
: 톰캣 위에 실행할 웹 애플리케이션의 기본 저장 경로,
.war파일을 이 곳에 이동시키거나, 설정파일에서 경로를 변경하여 실행 가능

✔︎ 서버 실행 및 종료 명령어

  • bin 디렉토리에서 진행
./startup.sh	# 톰캣 실행
./shutdown.sh	# 톰캣 종료

☞ 톰캣으로 웹 애플리케이션 실행

✔︎ JAR → WAR 포맷 변경

  • build.gradle 수정
plugins {
    id 'org.springframework.boot' version '2.4.2'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'war' // 추가
    id 'java'
}
...
  • {project}Application 파일 수정
@SpringBootApplication
public class sampleApplication extends SpringBootServletInitializer { // (1)

    public static void main(String[] args) {
        SpringApplication.run(sampleApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { // (2)
        return builder.sources(sampleApplication.class);
    }
}
- (1) : SpringBootServletInitializer 상속
- (2) : config를 Override

✔︎ 프로젝트 빌드

  • ./gradlew build 명령어 사용
  • 기존 .jar 대신 .war파일 확인
  • .war파일을 톰캣의 webapps 디렉토리로 이동

✔︎ server.xml 파일 수정

...
<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
        <Context path="/" docBase="sample"  reloadable="false" > </Context>
        
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
...
- `docBase` : "프로젝트 이름"

※ 톰캣 포트 변경

  • server.xml 파일 수정
...
<Connector port="8090" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
...
- 8080대신 8090으로 입력
- 외장 톰캣에서는 8090 포트로 실행
- IDE에서 실행하는 Spring boot(Embeded Tomcat)에서는 8080포트에서 실행
  1. Ngrok을 이용해 로컬에서 서버 실행

⦿ 학습내용

☞ Ngrok 설치

✔︎ Ngrok 다운로드

  • Zip 파일 다운로드
  • 터미널에 $ sudo unzip ~/Downloads/~ 내용 복사/붙여넣기
  • 터미널에서 ngrok -h 명령어 실행 시, 명령어 옵션에 관한 내용이 나온다면 설치 완료

☞ Ngrok 실행

# ngrok http {port} 의 형태로 원하는 포트를 연결할 수 있습니다.
ngrok http 8080
- Forwarding에 나오는 `https://~.jp.ngrok.io`를 통해 톰캣 서버 실행 가능

※ Ngrok 홈페이지에서 회원가입 후 발급되는 Auth Token을 통해 세션 연결 지속 시간 2시간 → 24시간 변경 가능

◉ 느낀 점

☞ 분명 간단한 옵션만 구현하는 Todo App을 만드는 데도 많은 에러들을 만나고, 버벅이거나 막히는 부분이 많았다 ... 지금까지 학습하면서 실습 내용을 따라가면서 그 당시에는 이해가 됐으나, 지나고 나서 홀로 이렇게 만들어보려고 하니 간단한 프로젝트라도 상당한 노력이 필요했다 :( 그래도 실전 프로젝트에 들어가기에 앞서서 이렇게 내가 부족한 부분들을 미리 경험할 수 있고, 정리할 수 있는 정말정말 뜻깊은 시간...🥺

내장 컨테이너보단 톰캣을, JAR보단 WAR로 패키징한 경우 더 다양한 설정과 웹 환경을 구성할 수 있대서 톰캣을 이용해 WAR로 패키징하여 수동 배포도 진행해봤고,

여러 사람이 협업을 할 때를 대비하여 Ngrok 사용법에 대해서도 알아보았다.

내가 만든 TodoApp은 H2 기반으로 하기 때문에 서버를 종료할 시 데이터가 다 날라가버려서 따로 Tomcat, Ngrok으로 진행하기에는 어려움이 있었다. (데이터가 없기에 localhost:8080으로 접속하면 404 에러만...) 내가 할 줄 몰라서 못한 건가..?

그래도 "Hello Spring World!"를 GET 요청으로 띄어주는 sample Application을 후다닥 만들어서 진행해보니 잘 뜨는 걸 확인할 수 있었다!

드디어 솔로 프로젝트도 마무리다.. 이제 Pre-Project와 Main-Project가 남았다. 많이 고단하고 힘든 시간이 예상되지만 맥 붙잡고 시간과 노력을 쏟다보면 어느 새 뿌듯한 결과물이 만들어지겠지 :)

◉ 내일의 키워드

・ 회고
・ 기술면접
・ 잡서칭
profile
백엔드 개발자 김창하입니다 🙇‍♂️

0개의 댓글