본문 바로가기

개발 일지/TIL

[ #21 ] TIL

✏️ 0514      


Spring 입문 1주차 강의

수준별 학습: 스탠다드반 OT


Spring 입문_1주차

겨우..다 들었다

 


Spring MVC 에 Front Controller 패턴이 적용되어있지 않았다면
단 4개의 API를 처리하기 위해 무려 3개의 클래스를 만들어야 한다

 

@WebServlet(urlPatterns = "/user/login")
public class UserLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        // ... 
    }
}

요런게 각 클래스마다 있는 거...

 

 

효율적인 API 처리를 위해 Front Controller 패턴을 만들었고 API 마다 파일을 만들 필요는 없어졌다

보통 하나의 Contoller 에 모든 API 를 넣지는 않고 유사한 성격의 API 를 하나의 Controller 로 관리

 

@Controller
@RequestMapping("/user")
public class UserController {
    @GetMapping("/login")
    public String login() {
        // ...
    }

    @PostMapping("/login")
    public String login() {
        // ...
    }
}


위의 코드처럼 경로는 중복될 수 있지만 메서드(GET, POST)까지 중복되면 안된다

@RequestMapping 적어주면 중복되는 경로를 통합해 줄 수 있다

 

 

정적 페이지 & 동적 페이지

 

 

 

  • 정적 페이지
@GetMapping("/static-hello")
public String hello() {
    return "hello.html";
}


맵핑은 되지 않고 localhost:8080/hello.html 해야 불러올 수 있다  => 직접 접근
이런 경우 controller 에 거쳐서 올 필요가 없어진다
   => 타임리프 의존성이 걸려잇기 때문에

@GetMapping("/html/redirect")
public String htmlStatic() {
    return "redirect:/hello.html";
}

 

템플릿 엔진을 적용한 상태에서 static 폴더의 html 파일을 Controller를 통해서 처리하고 싶다면

"redirect:/hello.html" <= redirect 요청을 문자열로 반환

 

@GetMapping("/html/templates")
public String htmlTemplates() {
    return "hello";
}

 

브라우저에서 바로 접근하지 못하게 하고 싶거나 특정 상황에 Controller 를 통해서 제어하고 싶다면

templates 폴더에 해당 정적 html 파일을 추가하고 해당 html 파일명인  "hello" 문자열을 반환하여 처리할 수 있다

  => .html은 생략가능

 

 

  • 동적 페이지
private static long visitCount = 0;
@GetMapping("/html/dynamic")
public String htmlDynamic(Model model) {
    visitCount++;
    model.addAttribute("visits", visitCount);
    return "hello-visit";
}

// HTML
// 새로고침할때마다 visits 숫자가 올라간다
(방문자 수: <span th:text="${visits}"></span>)

 

thymeleaf 는 동적 페이지 처리를 위한 템플릿 엔진이다

추가하면 자동으로 Controller 에서 html 파일 찾는 경로를 /resources/templates 로 설정해준다

 

JSON 데이터

 

탬플릿 엔진이 적용된 SpringBoot 에서는 Controller 에서 문자열을 반환하면

templates 폴더에서 해당 문자열의 '.html' 파일을 찾아서 반환해준다

따라서, html 파일이 아닌 JSON 데이터를 브라우저에 반환하고 싶다면

해당 메서드에 @ RestController 애너테이션을 추가해줘야 한다

 

@Controller
@RequestMapping("/response")
public class ResponseController {
    // [Response header]
    // Content-Type: text/html
    
    // [Response body]
    // {"name":"Robbie","age":95}
    
    @GetMapping("/json/string")
    @ResponseBody
    public String helloStringJson() {
        return "{\"name\":\"Robbie\",\"age\":95}";
    }
}

 

Java 는 JSON 타입을 지원하지 않기 때문에 String 타입으로 변환해서 사용해야 한다

 

@Controller
@RequestMapping("/response")
public class ResponseController {
    // [Response header]
    // Content-Type: application/json
    
    // [Response body]
    // {"name":"Robbie","age":95}
    
    @GetMapping("/json/class")
    @ResponseBody
    public Star helloClassJson() {
        return new Star("Robbie", 95);
    }
}

 

자바 객체 => JSON 으로 변환

Spring 에서 자동으로 Java 객체를 JSON 으로 변환해준다

 

 

@RestController
@RequestMapping("/response/rest")
public class ResponseRestController {
    @GetMapping("/json/string")
    public String helloStringJson() {
        return "{\"name\":\"Robbie\",\"age\":95}";
    }
}

 

@RestController  = @Controller + @ResponseBody

 

@RestController 를 사용하면 해당 클래스의 모든 메서드에

@ResponseBody 애너테이션이 자동으로 적용되는 기능있어 생략이 가능해진다

 

 

< @Controller 와 @RestController 차이점>

 

@Controller는 주로 View(화면)를 반환하기 위해 사용
데이터를 반환하기 위해 @ResponseBody 어노테이션을 활용

Model 객체를 만들어 데이터를 담고 View를 찾는 것

 

@RestController의 주 용도는 Json 형태로 객체 데이터를 반환하는 것

단순히 객체만을 반환하고 객체 데이터는 JSON 또는 XML 형식으로 HTTP 응답에 담아서 전송

 

 

 

 

Jackson

 

Jackson
JSON 데이터 구조를 처리해주는 라이브러리

 

 

 

Object 를 JSON 타입의 String 으로 변환

JSON 타입의 String 을 Object 로 변환

 

직접 소스 코드를 작성하여 JSON 데이터를 처리하지 않아도 자동으로 처리해준다

 

@DisplayName("Object To JSON : get Method 필요")
void test1() throws JsonProcessingException {
    Star star = new Star("Robbie", 95);
	
	// Jackson 라이브러리의 ObjectMapper
    ObjectMapper objectMapper = new ObjectMapper();
    String json = objectMapper.writeValueAsString(star);

    System.out.println("json = " + json);
}

@DisplayName("JSON To Object : 기본 생성자 & (get OR set) Method 필요")
void test2() throws JsonProcessingException {
    String json = "{\"name\":\"Robbie\",\"age\":95}";

    ObjectMapper objectMapper = new ObjectMapper();

    Star star = objectMapper.readValue(json, Star.class);
    System.out.println("star.getName() = " + star.getName());
}

 

 

 

Path Variable 과 Request Param

 

  • Path Variable 방식
// GET http://localhost:8080/hello/request/star/Robbie/age/95
@GetMapping("/star/{name}/age/{age}")
@ResponseBody
public String helloRequestPath(@PathVariable String name, @PathVariable int age) {
    return String.format("Hello, @PathVariable.<br> name = %s, age = %d", name, age);
}

 

폴더 위치와 비슷한 형태의 URL 주소

{ } 중괄호를 사용해 데이터를 받고자 하는 곳을 설정

 

  • Request Param 방식
// GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95
@GetMapping("/form/param")
@ResponseBody
public String helloGetRequestParam(@RequestParam String name, @RequestParam int age) {
    return String.format("Hello, @RequestParam.<br> name = %s, age = %d", name, age);
}

 

? 까지 URL 경로

& 와 = 을 이용해 데이터 key 값과 value 값을 구별한 URL 주소

 

일상생활에서 보이는 주소는 대부분 이 방식을 사용하고 있다

데이터를 받아오는 방법은 @RequestParam 애너테이션을 사용해서 받아올 수 있다

 

생략이 가능하지만 값을 입력받지 않았을 때 오류가 발생하므로
@RequestParam(required = false) String name

=> required = false

코드를 사용해서 해당 값이 없어도 실행 가능하게 설정해둬야 한다

값을 받지 않을 때 null 을 반환하며 기본 디폴트 값은 trun 값이 들어가 있다

 

 

 

HTTP 데이터를 객체로 처리하는 방법

 

// GET http://localhost:8080/hello/request/form/param/model?name=Robbie&age=95
// getter, setter or 생성자가 필요함
// 데이터가 안들어올 때 이 부분에 대해 확인할 필요가 있다
@GetMapping("/form/param/model")
@ResponseBody
public String helloRequestParam(@ModelAttribute Star star) {
    return String.format("Hello, @ModelAttribute.<br> (name = %s, age = %d) ", star.name, star.age);
}

// POST http://localhost:8080/hello/request/form/json
// Header
//  Content type: application/json
// Body
//  {"name":"Robbie","age":"95"}
@PostMapping("/form/json")
@ResponseBody
public String helloPostRequestJson(@RequestBody Star star) {
    return String.format("Hello, @RequestBody.<br> (name = %s, age = %d) ", star.name, star.age);
}

 

  • @ModelAttribute
    • 생략 가능
    • Spring은 해당 파라미터(매개변수)가 SimpleValueType이라면
      @RequestParam 으로 간주하고 아니라면 @ModelAttribute가 생략 되어있다 판단한다
    • SimpleValueType은 원시타입(int), Wrapper타입(Integer), Date등의 타입을 의미
  • @RequestBody
    • HTTP Body에 JSON 데이터를 담아 서버에 전달할 때 해당 Body 데이터를 Java의 객체로 전달 받을 수 있
    • 해당 객체의 필드에 데이터를 넣어주기 위해 set or get 메서드 또는 오버로딩된 생성자가 필요
    • 객체로 데이터를 받아올 때 데이터가 제대로 들어오지 않는다면
      우선 해당 객체의 set or get 메서드 또는 오버로딩된 생성자의 유무를 확인

아 @..너무 많아 헷갈려

애너테이션인지  에바테이션인지(?)

 

 

DTO

 

 

DTO ( Data Transfer Object )
데이터 전송 및 이동을 위해 생성되는 객체를 의미

 

 

Client에서 보내오는 데이터를 객체로 처리할 때 사용
서버의 계층간의 이동에도 사용

DB와의 소통을 담당하는 Java 클래스를 그대로 Client에 반환하는 것이 아니라 DTO로 한번 변환한 후 반환할 때도 사용

 

 

 

Request의 데이터를 처리할 때 사용되는 객체는 RequestDto,

Response를 할 때 사용되는 객체는 ResponseDto라는 이름을 붙여 DTO 클래스를 만들 수 있다

 

절대적인 규칙은 아니고 조직에 따라 규칙이 다를 수 있다

 

 

Database

 

Database
데이터의 집합

 

 

DB는 우리가 매일 사용하는 카톡 메시지, 인스타그램의 사진 등의 정보를 저장하고 관리해준다

 

DBMS ( Database Management System ) : Database를 관리하고 운영하는 소프트웨어

 

RDBMS ( Relational DBMS ) : 관계형 데이터베이스

테이블(table)이라는 최소 단위로 구성되며, 이 테이블은 열(column)과 행(row)으로 이루어져 있다

테이블 간 FK(Foreign Key)를 통해 다른 데이터를 조합해서 함께 볼수 있다라는 장점이 존재한다

 

 

 

SQL

 

SQL ( Structured Query Language )
RDBMS에서 사용되는 언어

 

 

수 많은 정보를 Database에서 조작하고 관리하기 위해서는 SQL 언어를 사용하고 있다

 

대표적인 프로그램으로는 ORACLE, MySQL, MongoDB 등 여러가지 다양하게 있고

각자의 장점과 단점이 다르니 알아보고 사용하면 좋다

 

MySQL 은 Spring 과 궁합이 좋아서 많은 회사에서 사용하고 있다고 한다

 

 

  • DDL ( Data Definition Language )
    테이블이나 관계의 구조를 생성하는데 사용

CREATE : 새로운 데이터베이스 및 테이블을 생성
ALTER : 데이터베이스와 테이블의 내용을 수정
DROP : 데이터베이스와 테이블을 삭제 / 데이터 및 테이블 전체를 삭제
TRUNCATE : 데이터베이스와 테이블을 삭제 / 최초 테이블이 만들어졌던 상태 즉, 컬럼값만 남긴다

 

  • DCL ( Data Control Language )
    데이터의 사용 권한을 관리하는데 사용

GRANT : 사용자 또는 ROLE 에 대해 권한을 부여
REVOKE : 사용자 또는 ROLE 에 부여한 권한을 회수

 

  • DML ( Data Manipulation Language )
    테이블에 데이터를 검색, 삽입, 수정, 삭제하는데 사용

INSERT : 테이블에 새로운 행을 추가
SELECT : 테이블의 행을 선택
UPDATE : 테이블의 행의 내용을 수정
DELETE : 테이블의 행를 삭제

 

  • 제약조건
    • AUTO_INCREMENT : 컬럼의 값이 중복되지 않게 1씩 자동으로 증가, 고유번호를 생성
    • NOT NULL : 해당 필드는 NULL 값을 저장 불가능
    • UNIQUE : 해당 필드는 서로 다른 값을 가져야만 한다
    • PRIMARY KEY : 해당 필드가 NOT NULL과 UNIQUE 제약 조건의 특징을 모두 가지게 된다
    • FOREIGN KEY : 하나의 테이블을 다른 테이블에 의존하게 만들며 데이터의 무결성을 보장
    • CASCADE : FOREIGN KEY 로 연관된 데이터를 삭제, 변경할 수 있다

 

 

JOIN

 

JOIN
나누어진 테이블을 하나로 합치기 위해 데이터베이스가 제공하는 기능

 

 

SELECT s.name, s.major_code, m.major_name FROM STUDENT s JOIN MAJOR m ON s.major_code = m.major_code;
SELECT s.name, s.major_code, m.major_name FROM STUDENT s, MAJOR m WHERE s.major_code = m.major_code;

 

ON 이라는 키워드를 통해 기준이 되는 컬럼을 선택하여 2개의 테이블을 합쳐준다

JOIN을 할 때에는 적어도 하나의 컬럼을 서로 공유하고 있어야 하기 때문에

테이블에 외래 키(FK : foreign key)가 설정 되어 있다면 해당 컬럼을 통해 JOIN을 하면 조건을 충족

위의 코드처럼 WHERE 문으로도 사용 가능하다

 

다만 JOIN을 하기 위해 외래 키를 설정하는 것이 항상 좋은 선택이 아닐 수도 있다
- 외래 키를 설정하면 데이터 무결성을 확인하는 추가 연산이 발생
- 또한 무결성을 지켜야하기 때문에 상황에 따라 개발하는데 불편

 

항상 테이블에 모든 제약조건을 걸어야 하는 것은 아니므로

프로젝트의 상황에 따라 가장 효율적인 제약 조건을 테이블에 적용하는 것이 가장 베스트

그게 어려운거 아닐까요T0T

 

 

JDBC

 

JDBC ( Java Database Connectivity )
DB에 접근할 수 있도록 Java에서 제공하는 API

 

 

JDBC에 연결해야하는 DB의 JDBC 드라이버를 제공하면 DB 연결 로직을 변경할 필요없이 DB 변경이 가능

 

DB 회사들은 자신들의 DB에 맞도록 JDBC 인터페이스를 구현한 후 라이브러리로 제공하는데 이를 JDBC 드라이버

MySQL 드라이버를 사용해 DB에 연결을 하다 PostgreSQL 서버로 변경이 필요할 때 드라이버만 교체하면 손쉽게 DB 변경이 가능

 

처음 인텔리제이에서 DB 를 연결할 때 다운받으라는 드라이버가 해당 이야기이다

 

 

회고

 

지난번 자바 강의보단 내용이 뭔가 적은 것 같으면서도

이론이 많아서 그것도 아닌 것 같고

2주차부터 또 내용이 와르륵 쏟아져 나올까봐 무섭고..

이전 팀원분이 그런말 쏙 들어갈거라고했따무섭따....

 

1주차 강의 들었으니 과제 한번 만져보려고 했는데

다들 2주차까지 다 듣고 해야할 것 같다고 하셨당... 더 들어야하는 걸까 ㅠㅠ

강의늪에 빠졌다

'개발 일지 > TIL' 카테고리의 다른 글

[ #23 ] TIL  (3) 2024.05.19
[ #22 ] TIL  (1) 2024.05.17
[ #20 ] TIL  (4) 2024.05.13
[ #19 ] TIL  (2) 2024.05.10
[ #18 ] TIL  (0) 2024.05.09