스프링과 JPA 기반 웹 애플리케이션 개발 #20 첫 페이지 보완

Jake Seo·2021년 5월 30일
0

스프링과 JPA 기반 웹 애플리케이션 개발 #20 첫 페이지 보완

해당 내용은 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발의 강의 내용을 바탕으로 작성된 내용입니다.

강의를 학습하며 요약한 내용을 출처를 표기하고 블로깅 또는 문서로 공개하는 것을 허용합니다 라는 원칙 하에 요약 내용을 공개합니다. 출처는 위에 언급되어있듯, 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발입니다.

제가 학습한 소스코드는 https://github.com/n00nietzsche/jakestudy_webapp 에 지속적으로 업로드 됩니다. 매 커밋 메세지에 강의의 어디 부분까지 진행됐는지 기록해놓겠습니다.


첫 페이지 보완

  • 첫 페이지 보완
    • 네비게이션 바에 font-awesome으로 아이콘 추가하기
    • 이메일 인증을 마치지 않은 사용자에게 메세지 보여주기
    • jdenticon으로 프로필 기본 이미지 생성하기
  • NPM으로 프론트엔드 라이브러리 설치
    • npm install font-awesome
    • npm install jdenticon
  • font-awesome 아이콘 사용하기
    • <i class="fa fa-XXXX"></i>
  • jdenticon으로 아바타 생성하기
    • <svg width="80" height="80" data-jdenticon-value="user127"></svg>
  • 타임리프 조건문 활용
    • th:if
  • 부트스트랩 경고창
<div class="alert alert-warning" role="alert" th:if="${account != null && !account?.emailVerified}">
  스터디올래 가입을 완료하려면 <a href="#" th:href="@{/check-email}" class="alert-link">계정 인증 이메일을 확인</a>하세요
</div>

정적 리소스 가져오는 방식 약간 변경

# 로컬 환경에서 실행할 때
spring.profiles.active=local
spring.mvc.static-path-pattern=/static/**

위와 같이, spring.mvc.static-path-pattern을 재설정해주었다. 저렇게 설정하면 기본 도메인/static/...와 같은 경로로 내 정적 리소스에 접근이 가능하다.

SpringSecurity 내부 PathRequest의 한계

spring.mvc.static-path-pattern을 설정한 첫번째 이유는 Spring Security 내부에 있는 PathRequest의 한계 때문이다.

기존에 설정했던 방식은 아래와 같다.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}

결국 위 .atCommonLocations()라는 메소드가 정해준 일반적 정적 리소스 경로에서만 정적 리소스 자료를 가져와야 하는데, 그렇게 하면 유연성이 떨어진다. 결국 저 메소드는 계륵같은 느낌을 지울 수 없다.

public enum StaticResourceLocation {
    CSS(new String[]{"/css/**"}),
    JAVA_SCRIPT(new String[]{"/js/**"}),
    IMAGES(new String[]{"/images/**"}),
    WEB_JARS(new String[]{"/webjars/**"}),
    FAVICON(new String[]{"/favicon.*", "/*/icon-*"});

    private final String[] patterns;

    private StaticResourceLocation(String... patterns) {
        this.patterns = patterns;
    }

    public Stream<String> getPatterns() {
        return Arrays.stream(this.patterns);
    }
}

위처럼, 그냥 자주 쓰이는 경로에 대해서만 처리해준다. 사실 현재 프로젝트 상황은 node_modules라는 외부 디렉토리에 라이브러리를 의존하고 있는 상황이다.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .mvcMatchers("/", "/login", "/sign-up", "/check-email", "/check-email-token",
                        "/email-login", "/check-email-login", "login-link", "/node_modules/**", "/static/**").permitAll()
            .mvcMatchers(HttpMethod.GET, "/profile/*").permitAll()
            .anyRequest().authenticated();
}

위와 같이 /static/**을 추가해주어서, 그냥 static 디렉토리 내부에 있는 자료들은 전부 정적 리소스로 가져올 수 있게 만들어놨다.

Intellij의 intellisense 문제

/static/을 먼저 입력하고 ctrl + space를 눌렀을 때는 위와 같이 경로에 대한 추천을 제공한다.

/node_modules를 먼저 입력하고 ctrl + space를 눌렀을 때는 위와 같이 경로에 대한 추천을 제공하지 않는다.

결론적으로 Intellisense는 경로에 대한 실수를 하지 않게 하는데 중요한 역할을 하므로, Intellisense가 설정된 그대로 사용하는게 편의상 낫다고 생각해서 spring.mvc.static-path-pattern을 변경하여 /static/으로 접근하게 한 이유도 있다.

프론트엔드 라이브러리 추가

font-awesome

아이콘을 제공하는 라이브러리이다.

npm install font-awesome

jdenticon

아바타를 제공하는 라이브러리이다.

npm install jdenticon

fragment :: head에 프론트엔드 라이브러리 추가

  <link rel="stylesheet" href="/static/node_modules/bootstrap/dist/css/bootstrap.min.css">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="/static/node_modules/font-awesome/css/font-awesome.min.css">

  <!-- 부트스트랩 JS -->
  <script src="/static/node_modules/jquery/dist/jquery.js"></script>
  <script src="/static/node_modules/bootstrap/dist/js/bootstrap.bundle.js"></script>
  <!-- jdenticon-->
  <script src="/static/node_modules/jdenticon/dist/jdenticon.min.js"></script>
  <!-- 자바스크립트를 닫을 때 <script /> 로 닫으면 안된다. <script></script> 로 닫아야 한다.  -->

여기서 약간의 팁은 <script></script> 태그의 경우 귀찮다고 <script />로 마무리해선 안된다. <script></script>로 마무리해주어야 정상적으로 불러와진다.

실제 내용에 프론트엔드 라이브러리 적용해서 아이콘 넣기

    <img src="/static/images/logo_sm.png" width="30" height="30">
  </a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
          aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
	@@ -157,14 +160,20 @@
        <a class="nav-link" th:href="@{/sign-up}">가입</a>
      </li>
      <li class="nav-item" sec:authorize="isAuthenticated()">
        <a class="nav-link" th:href="@{/notifications}">
          <!-- font-awesome에서 readme를 읽고 쓰고싶은 이모티콘을 찾으면 된다. -->
          <!-- https://fontawesome.com/v4.7/icon/ 앞의 경로에서 검색하면 된다. -->
          <i class="fa fa-bell-o"></i>
        </a>
      </li>
      <li class="nav-item" sec:authorize="isAuthenticated()">
        <a class="nav-link btn btn-outline-primary" th:href="@{/notifications}">
          <i class="fa fa-plus"></i> 스터디 개설
        </a>
      </li>
      <li class="nav-item dropdown" sec:authorize="isAuthenticated()">
        <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          <svg width="24" height="24" data-jdenticon-value="user127" th:data-jdenticon-value="${#authentication.name}" class="rounded border bg-light"></svg>

<i></i> 태그를 이용하면 된다. 사용하고 싶은 아이콘은 font-awesome 공식 페이지를 이용하여 찾아보면 된다.

항상 라이브러리에 대해 궁금한 게 있을 때는 readme.md 문서를 꼼꼼하게 보는 습관을 가지자.

태그 속성에 서버에서 넘겨진 값 넣기

<svg width="24" height="24" data-jdenticon-value="user127" th:data-jdenticon-value="${#authentication.name}" class="rounded border bg-light"></svg>

위처럼 th:속성값=${}와 같은 형식으로 넣으면 된다. 스프링 시큐리티를 이용하여 인증 정보를 넣고 싶다면 ${#authentication.멤버}와 같은 형식으로 넣으면 된다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글