최원종의 개발 블로그

V10-2 프로필 이미지 출력과 정적 리소스 핸들러 처리 본문

Spring boot 입문

V10-2 프로필 이미지 출력과 정적 리소스 핸들러 처리

chl6698 2026. 5. 22. 16:31

2단계 프로필 이미지 출력과 정적 리소스 핸들러 처리  

프로필 이미지 넣기 전
프로필이미지 넣은 후


header.mustach 파일 코드 수정

 <li class="nav-item">
      <a class="nav-link" href="/user/detail">마이페이지</a>
<!--  <a class="nav-link" href="/user/update-form">회원정보보기</a>-->
  </li>

 

UserController(마이페이지 요청 화면)

  // 마이페이지 요청 화면
  @GetMapping("/user/detail")
  public String detailPage(Model model, HttpSession session) {

      User sessionUser = (User) session.getAttribute("sessionUser");
      model.addAttribute("user", sessionUser);
      return "user/detail";
  }

user/detail.mustache (새로 생성)

{{> layout/header}}
<div class="container p-5 flex-grow-1">
    <div class="card">
        <div class="card-header">마이프로필</div>
        <div class="card-body">
            <!--  프로필 이미지  start  -->
            <div class="text-center mb-4">
                {{#user.profileImage}}
                    <img class="rounded-circle" src="/images/{{user.profileImage}}" alt="프로필이미지"
                      style="width:200px; height:200px"/>
                    <div class="mt-2">
                        <form action="/user/profile-image/delete" method="post">
                            <button type="submit" class="btn btn-sm btn-danger"
                            onclick="return confirm('프로필 사진을 삭제할까요?')">프로필 사진 삭제</button>
                        </form>
                    </div>
                {{/user.profileImage}}
                {{^user.profileImage}}
                    <div class="rounded-circle bg-secondary d-inline-flex
                                justify-content-center align-items-center border"
                                    style="width:200px; height:200px;">
                        <span>프로필 사진 없음</span>
                    </div>
                {{/user.profileImage}}
            </div>
            <!--  프로필 이미지   end -->
            <div class="mb-3">
                <label class="form-label fw-bold">사용자명</label>
                <p class="form-control-plaintext">{{user.username}}</p>
            </div>

            <div class="mb-3">
                <label class="form-label fw-bold">이메일</label>
                <p class="form-control-plaintext">{{user.email}}</p>
            </div>

            <div class="mb-3">
                <label class="form-label fw-bold">가입일</label>
                <p class="form-control-plaintext">{{user.createdAt}}</p>
            </div>

            <div class="mb-3">
                <a href="/user/update-form" class="btn btn-primary" >회원정보 수정</a>
                <a href="/board/list" class="btn btn-secondary" >게시글 목록</a>
            </div>

        </div>
    </div>
</div>
{{> layout/footer}}

WebMvcConfig - 정적 리소스 핸들러 설정

정적 리소스 핸들러 설정
    외부 사용자가 내 서버 컴퓨터에 특정 경로를 바로 확인을 할 수 있게 한다면
    보안상 취약 할 수 있습니다. ( 사용자에게는 가짜 경로를 보여주고 내부에서는
    실정 경로를 찾을 수 있도록 처리 하는 기법(보안상)

WebMvcConfig 코드(정적 리소스 핸들러 추가)⬇️

더보기
package com.tenco.blog._core.config;

import com.tenco.blog._core.interceptor.LoginInterceptor;
import com.tenco.blog._core.interceptor.SessionInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 자바 코드로 스프링 부트 설정 파일을 다둘 수 있다.

// @Component
@Configuration // IoC 대상 - 하나 이상의 IoC 처리를 하고 싶을 때 사용 한다.
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired // DI 처리
    private LoginInterceptor loginInterceptor;
    @Autowired // DI 처리
    private SessionInterceptor sessionInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 화면에 SessionUser 정보를 내려줄 사용 됨. 
        registry.addInterceptor(sessionInterceptor)
                .addPathPatterns("/**"); // 모든 URL 요청서 동작 함


        // 인증 처리 인터셉터 동작 함
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/board/**", "/user/**", "/reply/**")
                .excludePathPatterns(
                    // 로그인 관련(인증이 필요 없는 페이지)
                    "/login-form",  // 로그인 화면 요청 시
                    "/join-form",   // 회원 가입 화면 요청 시
                    "/logout", // 로그아웃

                    // 게시글 조회 관련 (인증 없이도 볼 수 있는 페이지)
                    "/board/list",  // 게시글 목록 화면 요청 시
                    "/"          ,  // 메인 페이지
                    "/index"          ,  // 메인 페이지
                    "/board/{id:\\d+}", // 게시글 상세보기( 숫자 ID만 허용)

                    // 정적 리소스 (CSS, JS, 이미지 등)
                    "/css/**",          // CSS 파일 제외
                    "/js/**",           // JS 파일 제외
                    "/images/**",      //  이미지 파일 제외
                    "/favicon.ico",    // 파비콘 제외

                    // H2 데이터베시스 콘솔( 개발 환경용)
                    "/h2-console/**"    // H2 콘솔 접근
                );
    }

    // 정적 리소스 핸들러 설정
    // 외부 사용자가 내 서버 컴퓨터에 특정 경로를 바로 확인을 할 수 있게 한다면
    // 보안상 취약 할 수 있습니다. ( 사용자에게는 가짜 경로를 보여주고 내부에서는
    // 실정 경로를 찾을 수 있도록 처리 하는 기법(보안상)

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/images/**")
               // 추후 C:upload/
               // C:\\upload
               .addResourceLocations("file:///C:/upload/");
    }
}

yml - 코드 수정

수정 부분
SQL 초기화 설정 주석 및 
hibernate
create -> update

 

yml 전체 코드⬇️

더보기
server:
  servlet:
    encoding:
      charset: utf-8
      force: true
  # 파일 업로드 설정
    multipart:
      enabled: true  # 파일 업로드 활성화
      max-file-size: 50MB  # 단일 파일 최대 크기 설정 (1MB)
      max-request-size: 100MB # 전체 요청(Request) 최대 크기 설정
  port: 8080



logging:
  level:
    root: INFO #모든 라이브러리는 INFO 이상만 출력
    com.tenco: DEBUG # 내 프로젝트는 DEBUG 이상 모두 출력

spring:
  mustache:
    servlet:
      # 머스태치 템플릿 엔진에서 request 객체와 세션 객체에 접근할 수 있도록 허용하는 설정 추가
      expose-session-attributes: false
      expose-request-attributes: true


  #데이터베이스 연결 설정 (MySQL)
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/myblog?serverTimezone=Asia/Seoul
    username: root
    password: root
  #    driver-class-name: org.h2.Driver
  #    url: jdbc:h2:mem:test
  #    username: sa
  #    password:
  h2:
    console:
      enabled: true

  #      초기 데이터 설정
  # SQL 초기화 설정
#  sql:
#    init:
#      mode: none  # 외부 DB(MySQL)에서도 실행되도록 설정
#      data-locations:
#        - classpath:db/data.sql

  jpa:
    # Open Session In View -> false 설정
    # true (기본 값) -> 뷰 렌더링까지 DB 세션 유지 됨(LAZY 로딩 가능)
    # false : 트랜잭션 종료시 DB 세션 종료 ( Controller, View LAZY 로딩 불가)
    # false 사용시 Service 필요한 데이터를 모두 조회하고 응답시 DTO 설계 방식으로 처리 한다.
    open-in-view: false
    hibernate:
      # create 애플리케이션 시작시 테이블 새로 생성
      # 기존 데이터는 모드 삭제됨 (개발용)
      ddl-auto: update
    #SQL 쿼리를 콘솔에 출력 (개발용)
    show-sql: true
    properties:
      hibernate:
        # SQL 쿼리를 보기 좋게 포맷팅
        format_sql: true
        # N + 1 문제를 완화 하기위한 완충 장치 설정
        # 기본 WHERE 절에서 in 절(in 쿼리로 변경 해준다)
        default_batch_fetch_size: 100
    # data.sql 파일을 하이버네티트 초기화 이후에 실행

    # data.sql 파일을 Hibernate 초기화 이후에 실행
    defer-datasource-initialization: true