본문 바로가기

개발 일지

[TIL]이노베이션 캠프 16일차

Spring 입문 주차 8.12(금) ~ 8.18(목)

1. 개인 과제: 게시판 CRUD 기능을 하는 백엔드 서버 만들기, AWS 배포
2. 팀 과제: Spring 핵심 키워드 정리(필수 4개, 선택 4개)

 

진행 계획

- 12일(금) Spring 핵심 키워드 정리

- 13일(토) Spring 핵심 키워드 정리

- 14일(일) 개인과제에 필요한 강의 수강 및 공부

- 15일(월) API 명세서 작성, Use Case 그리기

- 16일(화) 게시판 CRUD 기능 코드 작성

- 17일(수) 게시판 CRUD 기능 코드 작성

- 18일(목) 게시판 CRUD 기능 코드 작성 및 AWS 배포

 

1. 개인 과제 진행 상황

1) 게시글 생성시간과 수정시간을 조회하기 위해 클래스 생성: Timestamped 

@Getter // get메소드 일괄 생성
@MappedSuperclass // 부모 클래스임을 명시, 해당 클래스를 상속할 때 컬럼으로 인식하게 함
@EntityListeners(AuditingEntityListener.class) // 해당 클래스에 Auditing(감시) 기능을 포함하여 생성시간, 수정 시간을 자동으로 반영하도록 설정
public abstract class Timestamped { //abstract(추상)는 직접 구현 불가, 상속으로만 사용 가능

    // createdAt, modifiedAt 멤버 2개
    @CreatedDate // 생성 일시
    private LocalDateTime createdAt; // 시간을 나태나는 자바의 자료형 LocalDateTime

    @LastModifiedDate // 수정 일시
    private LocalDateTime modifiedAt;
}

 

DB 생성 및 변경을 감지하여 자동으로 수정될 수 있도록 최상단 클래스인 application에 @EnableJpaAuditing 추가

@EnableJpaAuditing // JPA에서 DB가 변경되는 것을 감지하여 시간 자동 변경하도록 함
@SpringBootApplication // 스프링 부트임을 선언
public class Task03Application {

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

}

 

 

2) 게시글 객체 생성: Post

@NoArgsConstructor // 기본생성자를 대신 생성해줍니다.
@Entity // 테이블임을 나타냅니다.
public class Post {

    @Id // ID 값, Primary Key로 사용하겠다는 뜻입니다.
    @GeneratedValue(strategy = GenerationType.AUTO) // 자동 증가 명령입니다.
    private Long id;

    @Column(nullable = false) // 컬럼 값이고 반드시 값이 존재해야 함을 나타냅니다.
    private String title;

    @Column(nullable = false)
    private String content;
    
    @Column(nullable = false)
    private String username;
    
    @Column(nullable = false)
    private String password;

    public String getTitle() {
        return this.title;
    }

    public String getContent() {
        return this.content;
    }
    
    public String getUsername() {
        return this.username;
    }
    
    public String getPassword() {
        return this.password;
    }

    // 게시글 생성, Post 클래스 생성자 추가
    public Post(PostRequestDto postRequestDto) { //파라미터를 RequestDto로 받음
        this.title = requestDto.getTitle();
        this.content = requestDto.getContent();
        this.username = requestDto.getUsername();
        this.password = requestDto.getPassword();
    }
    
    // 게시글 수정
    public void update(PostRequestDto postRequestDto) {
        this.title = post.title;
        this.tutor = post.content;
        this.username = post.username;
        this.password = post.password;
}
}

 

3) 요청과 응답을 처리 할 컨트롤러 생성: PostController

@RequiredArgsConstructor  // final로 선언된 멤버 변수를 자동으로 생성
@RestController // JSON으로 응답 반환
public class PostController {

    private final PostRepository postRepository; // postRepository를 멤버 변수로 하고, 필수로 필요하니까 final

    // 전체 게시글 목록 조회  
    @GetMapping("/api/posts") // /api/posts Get요청
    public List<Post> getPost() { // Post에 List를 반환하는 getPost()메소드를 실행해라
        return postRepository.findAllByOrderByModifiedAtDesc(); //postRepository에서 수정시간 내림차순으로 findAll해서 전부 찾아 반환
    }
        
    // 게시글 작성
    @PostMapping("/api/posts") // /api/posts Post요청, PostMapping으로 같은 주소라도 방식이 다름을 구분
    public Post createPost(@RequestBody PostRequestDto postRequestDto) { //  RequestBody: 요청 받는 형태
        Post post = new Post(requestDto); // 저장은 Dto가 아니라 Post, Dto의 정보를 post에 담아야 합니다.
        return postRepository.save(post); // JPA를 이용하여 DB에 저장하고, 그 결과를 반환합니다.
    }    
   
}

 

4) 데이터 관리를 위한 리포지토리 생성: PostRepository

// Interface: JPA는 Repository를 통해서만 사용할 수 있음, 클래스에서 멤버가 빠진, 메소드 모음집이라고 보면 됨
public interface PostRepository extends JpaRepository<Post, Long> {

// 전체 조회, ModifiedAt 멤버 변수(수정 시간 내림차순으로)기준으로 정렬, post 리스트에 넣음
List<Post> findAllByOrderByModifiedAtDesc(); 

}

 

5) 요청과 데이터를 담을 DTO 생성: PostRequestDto

@Getter
@Setter
public class PostRequestDto {
    private String title;
    private String content;
    private String username;
    private String password;

}

 

 

 

2. 개발 중 발생한 이슈와 해결

spring.jpa.open-in-view 경고

spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. 

Explicitly configure spring.jpa.open-in-view to disable this warning

해결 방법

application.properties에 아래 코드 입력

spring.jpa.open-in-view=false

원인: Spring Boot에서는 spring.jpa.open-in-view를 true로 설정하고 있는데 *OSIV측면에서 성능이나  확장성을 위해false로 해야 하는데 true로 하고 있어 warning 경고 사인 발생

 

*OSIV(Open Session In View): 트랜잭션, 영속성 컨텍스트 생명주기 측면에서 영속성 컨텍스트가 살아있으면 엔티티는 영속 상태로 유지 됨에 따라 뷰에서도 지연로딩을 사용할 수 있음

 

 

3. 오늘 새로 배운 것

1) 상속(extends)

class Person {
	private String name;
	private String getName() {
		return this.name;
	}
}

class Tutor extends Person {
	private String address;
	// Person 클래스를 상속했기 때문에,
	// name 멤버변수와 getName() 메소드를 가지고 있습니다.
}

 

2) 자바 어노테이션(Java Annotation): 자바 소스코드에 "@"기호를 앞에 붙여 사용, 스프링한테 이런 역할이 있다 알려주는 역할로

빌드 시 코드를 자동으로 생성할 수 있게하고, 컴파일러에게 코드 작성 문법 에러 체크하게 하고, 실행(런타임) 시 특정 기능 실행하도록 정보를 제공하는 역할

 

3) Lombok: 자바 프로젝트를 진행하는데 거의 필수적으로 필요한 메소드/생성자 등을 자동생성해줌으로써 코드를 절약할 수 있도록 도와주는 라이브러리

Lombok 어노테이션 설명
@Getter getter 메소드 자동 작성
public String getTitle() { return this.title; }
public String getTutor() { return this.tutor;}
@NoArgsConstructor 기본생성자 코드 작성
@RequiredArgsConstructor 생성자를 통해, Service 클래스를 만들 때 Repository를 넣어주도록 코드 작성
public CourseService(CourseRepository courseRepository)
{this.courseRepository = courseRepository;}

 

 

 

4. 오늘 한 일 / 회고

- 개인 과제: 게시글 생성, 조회 기능 구현 완료

 

5. TO-DO LIST

- 개인 과제: 게시글 수정, 삭제 기능 구현, 비밀번호 조회 기능 구현