반응형

 

이번 2주차 발자국 내용은 spring 테스트 코드에 대한 내용이 대부분이다.

아무래도 Spring에서 가장 중요한 요소는 테스트 코드라고 생각되어 강의를 들으면서 썼던 TEST 코드에 대해 하나하나씩 파헤쳐 볼 예정이다 !


package com.hyup.portfolio.domain.repository
	
	import com.hyup.portfolio.domain.entity.Project
	import org.springframework.data.jpa.repository.JpaRepository
	import java.util.Optional
	
	interface ProjectRepository : JpaRepository<Project, Long> {
	    fun findAllByIsActive(isActive: Boolean): List<Project>
	
	    override fun findById(id: Long): Optional<Project>
}

 

위 코드에서 궁금한 내용은 ?

[ QUESTION ] findById를 왜 override를 해서 사용하는 이유

 

-> JpaRepository가 이미 제공하는 메서드를 다시 선언하기 때문에 오버라이드를 해야함
-> override를 활용해서 재정의 하면 기능적으로 안좋다.

[ WHY ?] override를 활용해서 재정의 하면 기능적으로 안좋은 이유


1. 기본 동작의 일관성 문제

  • JpaRepository에서 제공하는 findById는 기본적인 CRUD 동작을 안정적이고 효율적으로 처리하는데,
    이를 재정의하면 예상치 못한 문제를 발생시킬 수 있음.
  • 다른 개발자들이 코드를 이해할 때, 어려움을 안겨줄 수 있음


2. 유지보수성 저하

  • JPA의 업데이트나 변경 사항이 발생했을 때 호환성 문제가 발생할 가능성이 높음
  1. 기능적 안정성 감소
    • Spring Data Jpa는 트랜잭션 관리, 데이터베이스 연결 관리, 성능 최적화 등을 내부적으로 처리. 이를 재정의 하면 내부적으로 처리되던 여러 최적화나 기능이 무시될 수 있음
  2.  

 

[ SOLVE ] 그럼 override를 활용하지 않고 어떤 방법을 사용할 수 있나?

  1. CUSTOM Repository 사용
  2. interface ProjectRepository : JpaRepository<Project, Long> { fun findAllByIsActive(isActive: Boolean): List<Project> override fun findById(id: Long): Optional<Project> }
interface CustomProjectRepository {
    fun findByIdCustom(id: Long): Optional<Project>
}

 

  1. 쿼리 메서드 활용
  2. interface ProjectRepository : JpaRepository<Project, Long> { fun findAllByIsActive(isActive: Boolean): List<Project> fun findByIdAndIsActive(id: Long, isActive: Boolean): Optional<Project> }

@DataJpaTest 메서드

@DataJpaTest 메서드를 타고 들어가면 @Transactional 이라는 어노테이션 존재

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface 
# DataJpaTest 어노테이션이 포함하고 있는 어노테이션 

이중 @Transactional 이라는 어노테이션은 테스트 메소드 하나를 하나의 트랜잭션으로 보고 메소드가 종료될 때 그 트랜잭션에서 발생한 작업들을 모두 롤백해줌

 

[ QUESTION ] 트랜잭션에서 발생한 작업들을 모두롤백해야 하는 이유

[ ANSWER ]

  1. 테스트 간 독립성 보장

테스트는 독립적으로 수행되어야 하고, 하나의 테스트가 다른 테스트에 영향을 주지 않아야 함. 트랜잭션을 롤백하면, 테스트 내에서 발생한 모든 데이터 변경이 원래 상태로 돌아가기 때문에 데이터베이스 상태가 항상 초기 상태로 유지

  1. 데이터 일관성 유지

테스트가 끝난 후에도 트랜잭션을 롤백하지 않으면, 테스트 중에 삽입되거나 수정된 데이터가 데이터베이스에 남아 있게 된다. 이렇게 되면 이후의 테스트나 실제 어플리케이션 실행에 영향을 미쳐, 데이터의 일관성이 깨질 수 있음

  1. 테스트 성능 향상

테스트 중 데이터베이스에 많은 데이터를 삽입하거나 수정하는 경우, 이를 실제로 영구 저장하는 것보다 트랜잭션을 롤백하는 것이 성능 면에서 유리.


인스턴스 생명주기

  1. PER_METHOD (기본값)
  • 각 테스트 메서드마다 새로운 인스턴스가 생성
  • 각 테스트 메서드는 독립적인 상태 유지
  • 테스트마다 새로운 인스턴스가 생성되므로, 테스트 클래스의 상태를 공유할 수 없고 테스트 간의 의존성도 없어야 함.
@TestInstance(TestInstance.Lifecycle.PER_METHOD) // 생략 가능 (기본 값)
class ExampleTest {
    
    @BeforeEach
    void setUp() {
        // 테스트 메서드 실행 전 호출됨
    }
    
    @Test
    void testA() {
        // testA 실행 시 새로운 인스턴스가 생성됨
    }
    
    @Test
    void testB() {
        // testB 실행 시 또 다른 새로운 인스턴스가 생성됨
    }
}

PER_METHOD는 각 테스트마다 독립적으로 실행되어서 서로의 상태에 영향을 주지 않지만 상태를 공유하는 것이 불가능하다.

 

2. PER_CLASS

  • 하나의 인스턴스만 생성되고, 모든 테스트 메서드에서 이 인스턴스가 재사용된다.
  • @BeforeAll을 사용하면 클래스 전체에서 한 번만 실행되므로 성능을 향상시킬 수 있음
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ExampleTest {

    @BeforeAll
    void initAll() {
        // 모든 테스트 메서드 실행 전 한 번만 호출됨
    }

    @Test
    void testA() {
        // testA 실행 시 동일한 인스턴스가 사용됨
    }

    @Test
    void testB() {
        // testB 실행 시에도 동일한 인스턴스가 사용됨
    }
}

PER_CLASS는 상태를 공유할 수 있어 성능이 향상되지만 테스트 간 인스턴스 상태가 공유되므로, 테스트 간 의존성이 발생함.


@BeforeAll, @AfterAll

  • @BeforeAll : PER_CLASS에서만 사용되며, 모든 테스트 전에 한 번만 실행
  • @AfterAll : PER_METHOD와 PER_CLASS 모두에 사용되고 모든 테스트 전에 한 번만 실행 됨

[QUESTION] @BeforeAll 이 PER_CLASS에서만 사용되는 이유, @AfterAll은 PER_METHOD, PER_CLASS 모두 사용가능한 이유

[ANSWER]

@BeforeAll은 클래스 수준에서 한 번만 실행되는 메서드. 즉 테스트 클래스의 모든 테스트 메서드가 실행되기 전에 딱 한 번 실행됨

PER_CLASS에서는 테스트 클래스에 대해 하나의 인스턴스만 생성되므로, @BeforeAll 메서드가 클래스 인스턴스에서 한 번 실행되고, 이후의 모든 테스트가 동일한 인스턴스를 사용

@AfterAll 은 모든 테스트 메서드가 실행된 후에 한 번만 실행되는 메서드이다. 여기서 PER_CLASS에서는 클래스 인스턴스가 하나만 생성되므로, 모든 테스트가 끝나고 한번만 호출되면 된다.

PER_METHOD에서는 각 테스트마다 새로운 인스턴스가 생성되지만, @AfterAll이 테스트 메서드가 모두 끝난 후에 한 번 호출되도록 관리할 수 있다.


미션 - REST API 설계

 

이번 미션에서는 REST API 설계하는 미션이 주어졌다.

 

HTTP 주요 메서드 정리 (GET / POST / PUT / PATCH / DELETE)

  • GET : 리소스 조회
  • POST : 요청 데이터 처리, 주로 등록에 사용
  • PUT : 리소스를 대체, 즉 덮어쓰기 수행
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제


이번 미션과 발자국을 하면서 백엔드 개발자가 HTTP 주요 메서드에 대해 집중해야 된다는 것을 알 수 있었다. api를 설계할려면 어쩔수 없이 각 HTTP 메서드에 대해 알아야 URL을 설정할 때 어떻게 만들어야 되는지를 알 수 있기 때문이다. 이번주 는 개인 일정이 너무 많아서 아쉽게도 진도를 다 따라가지 못했다. 발자국은 만들어야 되기 때문에 여기서 내가 가장 공부해볼만한 것이 TEST 코드에 대해서 조사를 하는 것이기 때문에 열심히 하였다.

GET, POST, PUT, PATCH, DELETE 메서드에 대해서 조금이라도 공부할 수 있어서 좋았고, 따로 공부해서 블로그에 올려야 겠다고 생각하였다!

반응형
반응형

 

 

발자국 내용은 딱히 형식이 정해져 있지 않아서 발자국 쓰기 전날까지 들었던 강의들 중, 모르는 내용들을 적어서 내가 다시 봤을 때, "아 맞다!" 라는 말이 나올 정도로만 적을 예정이다!


 

목차

  1. 모르는 내용 정리
  2. 미션 해결 과정
  3. 회고

 


1. 모르는 내용 정리

 

<Gradle>

Gradle : Gradle은 Groovy를 기반한 빌드 관리 도구.

  • 빌드 관리 도구 : 프로젝트 내에서 다양하게 외부 라이브러리와 로컬 레포지토리에서도 라이브러리 별로 버전 관리를 해야할 때 용이
  • Gradle이 왜 필요할까?
    • Gradle
      • groovy 언어를 사용한 Domain-specific-language를 사용 ( 코드가 간결)
      • 어느 task가 업데이트 되었는지 체크
      • 이미 반영된 빌드 부분은 더이상 재 실행되지 않는다. -> 빌드 시간 단축
    • Maven
      • java8용 프로젝트 관리 도구 apache의 ant 대안
      • 외부 저장소에서 필요한 라이브러리, 플러그인들을 다운로드 한 후 , 로컬 시스템의 캐시에 모두 저장
    • 그래서 왜 Gradle인데!!!
      • Gradle은 작업 의존성을 그래프, Maven은 고정적이고 선형적 모델을 기반
      • Gralde은 어떤 task가 업데이트되었고 안되었는지를 체크
      • Gradle은 이미 업데이트 된 task에 대해서는 작업이 실행되지 않으므로 빌드 시간 단축
      • 빌드 설정 규모가 작으면 큰 차이를 느끼지 못하지만 규모가 크면 훨씬 Gradle의 빌드 시간이 단축된다는걸 알 수 있다.
  • Gradle과 Maven 차이를 알면 Gradle이 왜 필요한지 알 수 있다.

<Dependencies>

  • Spring Web : 웹 어플리케이션을 개발하기 위한 핵심 기능 제공
  • Thymeleaf : View Template, 동적으로 화면을 구성할 수 있게 해줌
  • Spring Data JPA : JPA를 이요한 구현체를 더 추상화시켜 더 쉽고 간편하게 JPA를 이용 가능
  • mysql driver : mysql를 연동할 때 필요한 dependency
  • h2 database : RDBMS, 테스트 단계 또는 작은 규모의 프로젝트에서 사용
  • validation : 데이터에 대한 유효성 검증 처리를 수행
  • Spring Security : 홈페이지에 인증 및 권한 기능을 빠르게 부여해 인증 및 권한 보호 기능을 손쉽게 추가할 수 있음.

 

<프로그램이 시작되는 시작되는 코드>

src/main/kotlin/PortfolioApplicatioin.kt

fun main(args: Array<String>) {
    runApplication<PortfolioApplication>(*args)
}

Whitelabel Error Page 오류가 뜨는 이유 : 어플리케이션이 뭘 해야 할지 모르기 때문에 Whitelabel Error Page를 보내줌.(정상)

 

<Git 용어>

Git : 분산 버전 관리 시스템 ⇒ 협업을 쉽게 해주는 툴 : GitHub

Commit : git에 저장하는 단계

Rollback : 이력 되돌리기

Branch : branch 생성 및 제거, 확인등의 기능을 하는 명령어

Merge : 브랜치 병합

Conflict : 충돌

Repository : 원격 저장소 , 인터넷이나 네트워크 어딘가에 있는 저장소

Push : 로컬 브랜치를 원격 저장소로 푸시할 때 사용하는 기본 명령어

 

<Git 명령어>

  • git init : git 공간으로 초기화
  • git status 명령어 입력시 Untracked files 라는 게 있는데 이건 git에서 따로 설정을 안한다는 소리
  • https://www.toptal.com/developers/gitignore/ : gitignore 파일을 자동으로 만들어줌

 

<github에 PUSH 방법>

  1. 터미널에서 git init
  2. git remote “git 저장소”
  3. → 인텔리제이(GUI)로 할 시에는 git → Manage Remote
  4. commit
  5. push

 

<application-default.yml , application-docker.yml>

profile이 default 이면, application-default.yml 파일에서 환경변수를 가져오고

profile이 docker 이면, application-docker.yml 파일에서 환경변수를 가져온다.

 

application-default.yml 파일에서 spring:jpa:hibernate:ddl-auto:create 인데

왜 application-docker.yml 파일에서는 spring:jpa:hibernamte:ddl-auto:none 일까?

=> application-default.yml 에서는 개발 목적으로 데이터베이스 스키마를 매번 재생성할 필요가 있지만, application-docker.yml 에서는 베포 및 운영 환경에 적합하게 데이터베이스 구조가 변경되지 않도록 하기 위한 설정

 

<어노테이션 정리>

@Id : 해당 테이블의 PK 필드를 의미

@Entity : JPA를 사용해 테이블과 매핑할 클래스에 붙여주는 어노테이션

@GeneratedValue : JPA에서 Entity의 PK를 생성하여 주는 기능

-> @GeneratedValue(name="member_id") : PK로 사용될 Entity의 프로퍼티에 @Id 어노테이션 선언

-> @GeneratedValue(strategy=GenerationType.IDENTITY) : 기본 키 생성을 데이터베이스에 위임한다.

-> @GeneratedValue(strategy=GenerationType.AUTO) : 기본값으로 DB 방언에 맞춰 자동으로 설정하여 준다.

@Column : 객체 필드와 DB 테이블 칼럼을 맵핑한다.

@Component : 클래스를 자동으로 빈으로 등록하기 위해 클래스 레벨에서 사용

@Profile : 빈이나, 컴퓨넌트에게 프로필을 정해줄 수 있음

@PostConstruct : 객체의 생성이 일어난 직 후에 초기화를 수행하는 메서드에 부착한다.

@ManyToOne : 단방향 관계이고 FK관리에 있어서 가장 자연스럽다. @JoinColumn 어노테이션과 같이 쓰인다.

@JoinColumn : 엔티티 테이블에 FK 칼럼을 정의해준다.

 

자료형뒤에 ? 는 무슨 의미일까 ?

ex ) Long?

자료형 뒤에 ? 가 오는 것은 Kotlin에서 사용되는 문법이고 ?를 자료형 뒤에 붙이는 방식은 nullable 여부를 나타낸다. 예를 들면 var name: String? = null 이 코드는 해당 변수 name에 null 값이 올 수도 있다는 뜻이다.

 

 

<코드 분석>

  • var type: SkillType = SkillType.valueOf(type) : SkillType.valueOf(type) 은 type이라는 문자열을 SkillType 열거형의 값으로 변환. 만약 type이 열거형에 없는 값이면 예외 발생
  • var cookies: String? = httpServletRequest.cookies ?.map {"${it.name}:${it.value}"} ?.toString() : httpServletRequest에서 쿠키 정보를 가져오고, 쿠키 이름과 값을 "이름:값" 형식으로 변환하는 코드
  • var referer: String? = httpServletRequest.getHeader("referer") : HTTP 요청에서 "Referer" 헤더 값을 가져온다. 이 코드는 사용자가 어떤 페이지에서 현재 페이지로 이동했는지 나타냄
  • @OneToManyvar details: MutableList<ExperienceDetail> = mutableListOf() : JPA 관계를 나타내고, 엔티티 간의 일대다(One-to-Many) 관계를 나타냄


2. 미션

미션 1과 2를 제출하는건데, 미션1은 테이블 설계하기와 깃허브 리포지토리에 프로젝트 올리기이다.

 

미션 1 : https://github.com/HyupTech/LMS/commit/fa47b404d36b3ce418f16213e3bb30ca96b812ed

미션 2 : https://github.com/HyupTech/LMS/commit/0993897036a0e17e7a366031b950235edd5d506e

  


 

3. 회고

발자국을 작성하면서 나는 이제까지 강의를 보면서 공부를 했지만 다시 한번 이렇게 정리를 해가면서 강의를 보지 않았다. 왜냐하면 시간이 너무 아까웠고, 차라리 정리하는 시간에 강의를 하나 더 보자는 마인드였다. 하지만 발자국을 써보면서 왜 이렇게 좋은걸 내가 안했을까라는 후회가 들고, 이렇게 정리를 해가면서 했으면 아마 실력이 조금이라도 더 올랐지 않았나 라는 생각이 들었다. 앞으로 발자국도 쓰고, 내가 따로 공부하고 있는것도 정리해가면서 공부를 해야겠다.

 

3-1. 미션 회고 

이번 미션에서 처음으로 ERD를 구성하고 어디에 PK를 주고 관계 설정을 어떻게 할지에 대한 고민이 많았던 것 같다. 현재 대학교 2-2에 재학중인데 데이터베이스 과목을 수강중인데 꽤 도움이 되었던 것 같고, 백엔드 개발자가 될려면 데이터베이스 공부도 놓지 말아야겠다고 생각이 들었다. 앞으로 더 많은 미션들이 기다리고 있는데 열심히 공부를 해야겠다! 

반응형
반응형

spring을 사용하면서 재시작 버튼을 누르는게 너무 귀찮다...

 

그래서 찾아봤더니 Spring 재시작 버튼을 안눌러도 자동으로 재시작 해주는 기능을 찾았다.

 


 

일단 첫번째로 지금 쓰고 있는 프로젝트에

 

build.gralde - dependencies에 아래 코드를 추가해준다

developmentOnly 'org.springframework.boot:spring-boot-devtools'

 

 

두번째로는 Build, Exeution, Deployment > Compiler > Build project autiomaically 체크

 

세번째로Advanced Settings > Allowauto-make to start even if developed application is currently running 체크

 

이렇게 설정하면 Spring 재시작 버튼을 누르지 않아도 자동으로 재시작을 해주지만, 바로 반영은 안되고 5~6초 ? 정도 걸리는것 같다

반응형

'WEB > SPRING' 카테고리의 다른 글

Spring #5 MVC와 템플릿 엔진  (0) 2024.07.16
Spring #4 정적 컨텐츠  (0) 2024.07.16
Spring #3 View 환경설정  (0) 2024.07.16
Spring #2 라이브러리 살펴보기!  (0) 2024.07.13
Spring #1 Spring 프로젝트 생성  (0) 2024.07.13
반응형

 

1. 일단 우선적으로 입출력을 자세하게 봤는데 공백으로 나눠져 있는걸 보고, 공백 기준으로 문자열을 나눠야겠다 라고 생각했다.

2. 가장 작은 값을 넣을 변수와, 가장 큰 값은 넣을 변수를 Integer.MIN_VALUE, Integer.MAX_VALUE로 초기화

3. for문을 돌려서 가장 작은 값과, 가장 큰 값을 찾는다.

 

class Solution {
    public String solution(String s) {
        
        // 공백을 이용해서 문자로 자르기
        String[] sNum = s.split(" ");
        
        int sNumBig = Integer.MIN_VALUE;
        int sNumSmall = Integer.MAX_VALUE;
        
        for(int i = 0; i < sNum.length; i++) {
            int num = Integer.parseInt(sNum[i]); // 문자를 int형으로 변환
            
            if (num > sNumBig) {
                sNumBig = num;
            }
                
            if (num < sNumSmall) {
                sNumSmall = num;
            }           
        }
        return sNumSmall + " " + sNumBig;
    }
}
반응형
반응형

지금까지 정적컨텐츠, MVC를 통해 사이트를 만들어봤습니다.

이제는 API를 통해서 사이트를 만들어보겠습니다.

 


 

HelloController // 코드 추가

@GetMapping("hello-string")
@ResponseBody
    public String helloString(@RequestParam("name") String name) {
        return "hello" + name;
    }
    
// @ResponseBody 추가적 설명
// 사용자가 http://localhost:8080/hello-string?name="spring" 입력 후 접속시
// 뷰 리졸버가 작동하지 않고 html body에 직접 반환

 

 

HelloController // 코드 추가

// @ResponseBody 객체 반환
@GetMapping("hello-api")
    @ResponseBody
    public Hello helloApi(@RequestParam("name") String name) {
        Hello hello = new Hello();
        hello.setName(name);
        return hello;
        // 객체를 반환하면 객체가 JSON으로 변환됨
    }

    static class Hello {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

 

객체를 반환하게 되면 Spring에서는 json 형태로 반환한다.

 

-> http://localhost:8080/hello-api?name=spring 접속


동작 과정 : 

1. http://localhost:8080/hello-api?name=spring을 사용자가 입력하여 접속

2. @GetMapping을 통해서 hello-api 에 해당하는 helloApi 메서드 호출

3. @RequestParam("name") String name 을 통해서 name 파라미터 값을 받아옴

4. hello 객체 생성후 name에 파라미터 값 주입

5. hello 객체 반환, 객체를 반환하게 되면 json 형태로 반환됨.

 


위 강의는 김영한님의 Spring 입문 강의를 바탕으로 글을 썼습니다.

 

반응형
반응형

이번에는 MVC 패턴에 대해서 알아보겠습니다

 

MVC : Model, View, Controller 로써, 앞 글자를 따와서 MVC라는 단어가 생성이 되었습니다

Spring에서는 관심사를 분리하기 위해서 MVC패턴을 사용합니다.

 

그럼 코드를 직접 짜보겠습니다!


 

package helloo.helloo_spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {

    @GetMapping("hello") // get 요청 처리
    public String hello(Model model) { // model 객체 매개변수, 문자열 반환
        model.addAttribute("data", "hello!");
        // model 객체에 data 속성 추가, 그 값을 hello! 설정
        return "hello"; // 뷰의 이름
        // 뷰 리졸버를 통해서 뷰 파일을 찾고 hello.html 반환
    }

    @GetMapping("hello-mvc") // 사용자가 hello-mvc URL을 접속하면 메서드 호출
    public String helloMvc(@RequestParam("name") String name, Model model) {
        // @RequestParam 어노테이션은 URL 쿼리 파라미터중 "name" 이라는 키를 가지고 오겠다 라는 의미
        model.addAttribute("name", name);
        return "hello-template";
    }
}

// @RequestParam 추가적 설명
// 사용자가 http://localhost:8080/hello-mvc?name="spring" 입력 후 접속시
// @RequestParam("name")에서 name을 찾아 추출 후 name 매개변수로 전달

 

helloMvc 메서드를 보시면 될거 같습니다.

 

hello-template.html

<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>

 


 

사용자가 http://localhost:8080/hello-mvc?name="spring" 을 입력후 접속하면

 

 

이렇게 뜨는걸 볼 수 있습니다

 


여기서 추가적인 작업을 해보도록 하겠습니다

- 사용자가 index를 입력하면 자동적으로 name 쿼리 파라미터를 전달함.

- 전달된 인자를 화면에 보여주는 페이지

 

1. 사용자가 입력할 수 있는 폼을 만들겠습니다

templates/input.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>폼 입력 페이지</title>
</head>
<body>
  <h1>이름을 입력하세요</h1>
  <form action="/hello-mvc-test" method="get">
    <label for="name">이름:</label>
    <input type="text" id="name" name="name" />
    <button type="submit">Submit</button>
  </form>
</body>
</html>

 

여기서 form action을 /hello-mvc-test로 했기 때문에 submit을 했을때 text에 적힌 name이 /hello-mvc-test로 전달됩니다.

 

 

2. input.html을 처리하기 위해서 Controller를 만들겠습니다

package helloo.helloo_spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {

    @GetMapping("hello") // get 요청 처리
    public String hello(Model model) { // model 객체 매개변수, 문자열 반환
        model.addAttribute("data", "hello!");
        // model 객체에 data 속성 추가, 그 값을 hello! 설정
        return "hello"; // 뷰의 이름
        // 뷰 리졸버를 통해서 뷰 파일을 찾고 hello.html 반환
    }

    @GetMapping("hello-mvc") // 사용자가 hello-mvc URL을 접속하면 메서드 호출
    public String helloMvc(@RequestParam("name") String name, Model model) {
        // @RequestParam 어노테이션은 URL 쿼리 파라미터중 "name" 이라는 키를 가지고 오겠다 라는 의미
        model.addAttribute("name", name);
        return "hello-template";
    }

    // 여기부터
    @GetMapping("/")
    public String input() {
        return "input";
    }

    @GetMapping("hello-mvc-test")
    public String helloMvcTest(@RequestParam("name") String name, Model model) {
        model.addAttribute("name", name);
        return "hello-template-test";
    }
    // 여기까지
}

// @RequestParam 추가적 설명
// 사용자가 http://localhost:8080/hello-mvc?name="spring" 입력 후 접속시
// @RequestParam("name")에서 name을 찾아 추출 후 name 매개변수로 전달

 

이미 static 폴더에 index.html이 있기때문에 GetMapping을 안해주면 static/index.html을 반환하기 때문에

GetMapping을 통해서 경로를 다시 설정해줍니다.

그리고 사용자가 입력 폼을 통해서 입력하고 제출했을때 보여주는 페이지 경로를 설정했습니다.

 

3. 결과값을 보여주는 페이지

templates/hello-template-test.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>사용자가 입력한 값 출력</title>
</head>
<body>
  <h1>Hello, <span th:text="${name}">!</span></h1>
</body>
</html>

 

4. 결과

localhost:8080에 들어오게 되면

이런 페이지가 뜨고, 이름에 spring을 입력한 후 submit을 누르면

 

 

이런 화면이 뜨고 URL도 http://localhost:8080/hello-mvc-test?name=spring 
으로 변경된걸 확인 할 수 있습니다

 


 

실행과정

1. localhost:8080에 들어가게 되면 사용자가 입력할 수 있는 input.html을 보여줌

2. name을 입력하고 submit을 누르게 되면 name값이 hello-mvc-test로 전달된다.

그렇게 되면 http://localhost:8080/hello-mvc-test?name=입력된값 을 브라우저가 요청을 보냅니다.

3. hello-mvc-test 경로에 대한 요청을 처리하는 메서드를 호출한 후 요청 파라미터에서 name값을 모델에 추가한 후

4. hello-template-test.html 뷰가 렌더링된다.

 


위 글은 김영한님의 spring 입문 강의를 바탕으로 적었습니다!

반응형

'WEB > SPRING' 카테고리의 다른 글

Spring 자동 재시작  (0) 2024.07.25
Spring #4 정적 컨텐츠  (0) 2024.07.16
Spring #3 View 환경설정  (0) 2024.07.16
Spring #2 라이브러리 살펴보기!  (0) 2024.07.13
Spring #1 Spring 프로젝트 생성  (0) 2024.07.13
반응형

Spirng 에서 정적 컨텐츠는 Controller에서 따로 Mapping 해주는것이 아니라 사용자가 직접 링크를 입력해서 들어가는 페이지를 

정적 컨탠츠라고 한다.

 

그럼 직접 한번 만들어보겠습니다.


 

resources/static/hello-spring.html 생성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
hello-spring page (정적 컨텐츠)
</body>
</html>

 

이후 Spring을 다시 실행한후 자신의 로컬 주소를 입력한 후 뒤에 /hello-spring.html을 입력해주면

 

 

이런 페이지가 나오는걸 볼 수 있다.

 


 

Spring Boot에서 resources/static 디렉토리에 정적 파일을 생성하면 Spring에서 자동으로 매핑되어서 URL을 통해 접근이 가능하다.

위에서 hello-spring.html 파일을 생성했으므로, http://localhost:8080/hello-spring.html 로 접근이 가능하다.

 

결론적으로 Spring에서 정적 컨텐츠는 컨트롤러를 통해서 따로 매핑하지 않고 디렉토리에 파일을 생성하면 Spring에서 자동적으로 매핑하여 제공한다.

 

 


위 글은 김영한님의 Spring 입문 강의를 바탕으로 글을 썼습니다!

반응형

'WEB > SPRING' 카테고리의 다른 글

Spring 자동 재시작  (0) 2024.07.25
Spring #5 MVC와 템플릿 엔진  (0) 2024.07.16
Spring #3 View 환경설정  (0) 2024.07.16
Spring #2 라이브러리 살펴보기!  (0) 2024.07.13
Spring #1 Spring 프로젝트 생성  (0) 2024.07.13
반응형

이번에 해볼것은 정적페이지 구성과 welcomepage를 한번 구성해보는걸 해볼려고 한다.

 


 

welcompage 는 resources/static/index.html 을 구성해주면 Spring에서 자동적으로 welcompage를 만들어준다.

 

resources/static/index.html 파일을 만들어주고 나서 코드를 삽입한다.

<!DOCTYPE HTML>
<html>
<head>
    <title>Hi!!!Spring</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello Spring!!
<a href="/hello">Hello Spring Link</a>
</body>
</html>

 

만들어주고나서 Spring을 껐다 켜주면!!

 

이렇게 welcomepage가 구축이 되었다. welcomepage는 정적 페이지로 사용자가 웹사이트에 접속을 했을때

기본적으로 제공되는 페이지이다. 

 

다음은 정적 페이지를 만들어보겠다.

 


 

위 사진에서 Hello Spring Link라는 글씨가 a태그로 감싸져 있는데 글씨를 누르면 /hello로 페이지로 이동하는 코드를

만들어보겠다.

 

1. 첫번째로는 controller를 만들어줘야 한다.

 - controller는 사용자가 다른 페이지로 이동할때 거기에 맞는 페이지를 Mapping 시켜주는 역할을 한다.

 

2. controller라는 패키지를 만들고 HelloController class를 생성해준다.

package helloo.helloo_spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController {

    @GetMapping("hello") // get 요청 처리
    public String hello(Model model) { // model 객체 매개변수, 문자열 반환
        model.addAttribute("data", "hello!");
        // model 객체에 data 속성 추가, 그 값을 hello! 설정
        return "hello"; // 뷰의 이름
        // 뷰 리졸버를 통해서 뷰 파일을 찾고 hello.html 반환
    }
}

 

 

3. templates 폴더에 hello.html 생성

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Hello</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" ></p>
</body>
</html>

 

HelloController hello 메서드에서 data 의 값이 hello!로 지정했기 때문에 

<p th:text="'안녕하세요. ' + ${data}" ></p>

 

여기서 data 값이 hello! 가 되는것이다.

 


 

위 글은 김영한님의 Spring 입문 강의 바탕으로 글을 썼습니다!

반응형

'WEB > SPRING' 카테고리의 다른 글

Spring 자동 재시작  (0) 2024.07.25
Spring #5 MVC와 템플릿 엔진  (0) 2024.07.16
Spring #4 정적 컨텐츠  (0) 2024.07.16
Spring #2 라이브러리 살펴보기!  (0) 2024.07.13
Spring #1 Spring 프로젝트 생성  (0) 2024.07.13

+ Recent posts