최원종의 개발 블로그

V3-3 게시글 목록보기(연산관계로 작성자 정보 표시) 본문

Spring boot 입문

V3-3 게시글 목록보기(연산관계로 작성자 정보 표시)

chl6698 2026. 5. 11. 17:55

게시글 목록보기 화면


BoardPersistRepository 코드 ( 게시글 조회 JPQL 문법으로 그대로 사용)

    // JPQL을 사용한 게시글 목록 조회
    public List<Board> findAll() {

        String jpqlStr = "SELECT b FROM Board b ORDER BY b.id DESC";
        List<Board> boardList = em.createQuery(jpqlStr, Board.class).getResultList();
        
        return boardList;
    }
Board 에서 연관관계 설정(
@JoinColumn(name = "user_id") // 외래키 컬럼명 표시 됨
    private User user;)
으로 인해 자동으로 User에 대한 정보도 가지고 올 수 있음.

 


BoardController 코드

    @GetMapping({"/", "index"})
    public String list(Model model) {
        List<Board> boardList = boardPersistRepository.findAll();
        model.addAttribute("boardList", boardList);
        return "board/list";
    }

 

핵심 로직 흐름 정리

1. 데이터 조회: boardPersistRepository.findAll()을 호출하여 
DB(board_tb)에 있는 모든 게시글 데이터를 List<Board> 형태로 가져옴.

2. 데이터 전달: model.addAttribute("boardList", boardList)를 통해 
조회한 게시글 목록을 "boardList"라는 이름으로 모델에 담음
이제 뷰 파일에서 이 이름을 통해 데이터에 접근 가능.

3. 뷰 리턴: "board/list"를 리턴함 
이는 src/main/resources/templates/board/list.mustache(또는 .html)
파일을 찾아 사용자에게 보여주라는 명령.

 

중요 개념 요약

작동 원리	클라이언트 요청 → Controller 데이터 조회 → Model에 저장 → View(Mustache) 렌더링
핵심 객체	Model: 비즈니스 로직과 화면 사이의 데이터 징검다리 역할을 수행함
데이터 흐름	DB(board_tb) → Entity(Board) → List → Model → View(list.mustache)

EAGER 전략

더보기
2026-04-29T11:09:26.876+09:00  INFO 14708 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-04-29T11:09:26.878+09:00  INFO 14708 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2026-04-29T11:09:26.878+09:00  INFO 14708 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
Hibernate: 
    select
        b1_0.id,
        b1_0.content,
        b1_0.created_at,
        b1_0.title,
        b1_0.user_id 
    from
        board_tb b1_0 
    order by
        b1_0.id desc
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
kim
hong
cos
cos
ssar
ssar
ssar
admin
admin
admin

LAZY 전략

더보기
Hibernate: 
    select
        b1_0.id,
        b1_0.content,
        b1_0.created_at,
        b1_0.title,
        b1_0.user_id 
    from
        board_tb b1_0 
    order by
        b1_0.id desc
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
kim
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
hong
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
cos
cos
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
ssar
ssar
ssar
Hibernate: 
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.password,
        u1_0.username 
    from
        user_tb u1_0 
    where
        u1_0.id=?
admin
admin
admin

머스태치 파일 코드 추가(list.mustache)

{{> layout/header}}
<div class="container p-5 flex-grow-1">
    {{#boardList}}
        <div class="card mb-3">
            <div class="card-body">
                <h4 class="card-title mb-3">{{title}}</h4>
                <!--  머스태치 문법은 getter 메서드를 가지고 오고 get은 탈락 가능 -->
                <div> 작성자 : {{user.username}} | 작성일 : {{time}}</div>
                <a href="/board/{{id}}" class="btn btn-primary">상세보기</a>
            </div>
        </div>
    {{/boardList}}

    <ul class="pagination d-flex justify-content-center">
        <li class="page-item"><a href="" class="page-link">Previous</a></li>
        <li class="page-item"><a href="" class="page-link"> Next</a></li>
    </ul>
</div>

{{> layout/footer}}

게시글 목록에서 연관관계 사용 시 핵심 설정

 LAZY 로딩이 중요한 이유

@ManyToOne(fetch = FetchType.LAZY)  // 중요한 설정
private User user;
**EAGER 사용 시 문제점:**

- 목록 조회할 때마다 모든 User 정보를 무조건 가져옴
- 불필요한 JOIN으로 성능 저하
- 메모리 낭비 발생

**LAZY 사용 시 장점:**

- 필요할 때만 User 정보 조회
- 메모리 효율성
- 선택적 데이터 로딩 가능