상세 컨텐츠

본문 제목

[웹 개발 챌린지] 10. JAVA & 11. Controller

[SW]/웹 개발 (2025)

by 시원00 2025. 2. 1. 22:46

본문

728x90

웹 개발 챌린지 : 나만의 웹 서비스 만들기

https://bootcamp.likelion.net/courses/technology/next_myweb

더보기

목차

챕터 10. JAVA
10-1. 프로그래밍 언어 기초
10-2. 자료형, 변수
10-3. 함수
10-4. 조건문, 반복문
10-5. 클래스 개념
10-6. 클래스 상속
10-7. 인터페이스

챕터11. Controller
11-1. 요청방식 요청경로
11-2. 컨트롤러 함수 리턴 | 뷰, 데이터
11-3. 쿼리 파라메터
11-4. Model로 뷰에 데이터 넣기

 

챕터 10. JAVA

10-1. 프로그래밍 언어 기초

프로그래밍 언어에서 가장 중요한 개념 5가지

1. 데이터 타입(자료형)

프로그래밍에서 사용되는 정보(데이터)

어떠한 프로그램의 로직이 구동되거나 영향을 미치려면 데이터(정보)가 존재해야 하며 이러한 데이터들이 변화하면서 로직이 수행된다.

데이터 형태를 정의하는 데이터 타입이 존재한다. 일반적으로 숫자, 문자를 가장 많이 사용한다. (프로그래밍 코드가 사람이 알 수 있는 형태로 구성되어야 하기 때문)

 

데이터는 크게 2가지 형태로 나누어진다.

- 1개만 받을 수 있는 데이터 타입: int, long, String, boolean 등

- 여러 개를 받을 수 있는 데이터 타입: 리스트(배열) 형식 [ ], 맵 형식 { key : value }

 

2. 함수

로직모듈화, 함수인자(매개변수), 함수리턴

자주 등장하는 코드를 함수로 저장해서 사용한다.

 

3. 조건문

조건에 따라서 다르게 수행되는 로직이 필요할 때 사용한다. (if문)

 

4. 반복문

같은 로직이 연속적으로 반복이 될 때 반복문을 사용한다. (for문)

 

5. 클래스(객체지향)

여러 개를 받을 수 있는 데이터 타입

정확한 양식(형태)이 있으며 필드(데이터) 및 함수까지도 선언이 가능한 데이터 타입이다.


10-2. 자료형, 변수

데이터타입 변수명 = 값;

 

많이 사용되는 데이터 타입

1. 숫자형 타입(정수, 실수)

//int
int a = 10;
int b;
b = 20;

int c = a % b;

System.out.println(a);
System.out.println(b);
System.out.println(c);

출력: 10 20 10

//float
float pi = 3.14f;
System.out.println(pi);

출력: 3.14

 

2. 문자형 타입

//String
String name = "철수";
String first = "";

String full = first+name; //이어붙이기
System.out.println(full);

출력: 김철수

 

3. 배열/리스트

인덱스로 접근

//array
String[] team = {"사랑", "민지", "철수", "지원"};
String one = team[2]; //0부터 접근
System.out.println(one);

출력: 철수

 

4. 맵(HashMap)

키값으로 접근

//map
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "시원");
map.put("address", "서울");

String myName = (String)map.get("name"); //get: 최상위 클래스. 모든 데이터를 받을 수 있음
System.out.println(myName);

출력: 시원

 

5. 불리안(Boolean, 참/거짓)

가독성을 위해 의문사 형태로 변수명을 정함

//boolean
boolean check = true;
boolean check2 = false;

System.out.println(check);
System.out.println(check2);

출력: true false

 

데이터 타입 분류

- 1개만 받을 수 있는 데이터 타입: int, long, String, ...

- 여러 개 받을 수 있는 데이터 타입: [ ], { key: value }


10-3. 함수

함수의 기본 컨셉: 로직에 이름을 정해서 사용하는 것

 

기본 구조

리턴값_데이터타입 함수명 (데이터타입 변수명, ...) {
	// 로직
    return 리턴값;
}

 

함수에서 가장 중요한 개념 3가지

1. 로직 모듈화

public class Main2 {

  //함수 선언
  static void add10_20() {
    int a = 10;
    int b = 20;
    int c = a + b;
    System.out.println(c);
  }

  public static void main(String[] args) {
    add10_20();
    add10_20();
    add10_20();
  }
}

출력: 30 30 30

 

2. 함수 매개변수(인자)

사용하지 않는 매개변수를 받아도 됨(오류X)

public class Main2 {

  //함수 선언
  static void addTwoNumbers(int num1, int num2) {
    int sum = num1 + num2;
    System.out.println(sum);
  }

  public static void main(String[] args) {
    addTwoNumbers(10, 20);
    addTwoNumbers(100, 30);
  }
}

출력: 30 130

 

3. 함수 리턴

return을 반드시 받지 않아도 됨(옵션)

public class Main2 {

  //함수 선언
  static int addTwoNumbers(int num1, int num2) {
    int sum = num1 + num2;
    return sum;
  }

  public static void main(String[] args) {
    int result1 = addTwoNumbers(10, 20);
    int result2 = addTwoNumbers(100, 30);

    System.out.println(result1);
    System.out.println(result2);
  }
}

출력: 30 130


10-4. 조건문, 반복문

조건문 if

연산자를 이용한 조건식의 결과: boolean

public class Main2 {

  //함수 선언
  static int addTwoNumbers(int num1, int num2) {
    int sum = num1 + num2;
    return sum;
  }

  public static void main(String[] args) {
    int score = addTwoNumbers(49, 50);

    if (score == 100) {
      System.out.println("100입니다.");
    } else if (score > 0) {
      System.out.println("0보다 큽니다.");
    } else {
      System.out.println("100이 아닙니다.");
    }
  }
}

출력: 0보다 큽니다.

 

비교연산자: ==(같음), !=(다름), >, <: 대소 비교

논리연산자: !(논리부정), &&(논리곱, and), ||(논리합, or)

 

반복문 for

String[] members = {"a", "b", "c", "d"};
for (int i=0; i<members.length; i++) {
  String member = members[i];
  System.out.println(member);
}

출력: a b c d


10-5. 클래스 개념

Class (객체지향)

This: '나'를 지칭하는 지시어

package my_java;

public class Main3 {

    public static void main(String[] args) {

        Animal dog = new Animal("강아지", "멍멍이", 2);
        Animal cat = new Animal("고양이", "야옹이", 3);

        dog.sayAge();
        cat.sayAge();
    }
}

class Animal {
    //필드(멤버변수)
    String type;
    String name;
    int age;

    void sayAge() {
        System.out.println(name+"의 나이는 "+age);
    }

    //생성자
    Animal(String type, String name, int age) {
        this.type = type; //this: '나'(해당 클래스)를 지칭하는 지시어
        this.name = name;
        this.age = age;
    }
}

출력:

  멍멍이의 나이는 2
  야옹이의 나이는 3


10-6. 클래스 상속

class 상속

Person 클래스에서 Korea 클래스의 필드 및 함수 등을 사용하고 싶을 경우 

class Person extends Korea

package my_java;

public class Main4 {
    public static void main(String[] args) {
        Person A = new Person("시원", 25, "부산");

        System.out.println(A.nationName); //상속받았으므로 부모 클래스의 필드에도 접근 가능
        System.out.println(A.city); //같은 이름의 변수가 부모, 자식 모두 있는 경우 자식 클래스의 변수에 접근

        A.getInfoSuperCity(); //super를 이용하여 부모의 city 변수 접근
        A.getInfoThisCity(); //this를 이용하여 자식의 city 변수 접근
    }
}

class Korea{
    String nationName="대한민국";
    String city = "서울";
    int population = 51740000;

    //+1000개의 필드가 있다고 가정
}

class Person extends Korea{ //Person: 자식클래스, Korea: 부모클래스
    String name;
    int age;
    String city;

    void getInfoSuperCity() {
        System.out.println(super.city); //super는 부모클래스 지칭
    }
    void getInfoThisCity() {
        System.out.println(this.city); //this는 해당클래스(자식클래스) 지칭
    }

    Person(String name, int age, String city) {
        this.name = name;
        this.age = age;
        this.city = city;
    }
}

출력:

  대한민국
  부산
  서울
  부산

 

상속 더 알아보기

한 번에 두 개 이상의 클래스를 상속 받을 수 없음 (super 사용 시 구분이 어렵기 때문)

아래 코드와 같이 C->B, B->A 하나씩 상속

package my_java;

public class Main4 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.aName);
        System.out.println(a.bName); //B클래스 접근 가능
        System.out.println(a.cName); //C클래스 접근 가능
    }
}

class A extends B{ //B가 C를 상속받았기 때문에 A는 B와 C를 모두 받음
    String aName = "a";
}

class B extends C{
    String bName = "b";
}

class C{
    String cName = "c";
}

출력: a b c


10-7. 인터페이스

인터페이스는 클래스와 함께 자주 사용되는 개념이다.

여러 클래스가 동일한 함수를 사용할 때 interface에 함수를 만든 후, class에 implements하여 사용 (함수명을 통일해서 사용할 수 있음)

class 클래스명 implements 인터페이스명 { ... }

로직은 각 class에 구현

 

인터페이스 선언

interface Action{
  //추상 메소드 (구현부가 없는 함수)
  void run();
}

 

implements 인터페이스명으로 사용하기

class SoccerPlayer implements Action{
  String name;

  @Override
  public void run() {
    System.out.println(name+" runs..");
  }

  SoccerPlayer(String name){
    this.name=name;
  }
}

 

전체 코드

package my_java;

public class Main5 {
    public static void main(String[] args) {
        SoccerPlayer sp = new SoccerPlayer("김철수");
        GolfPlayer gp = new GolfPlayer("이민지");
        BaseballPlayer bp = new BaseballPlayer("김우현");

        sp.run();
        gp.run();
        bp.run();

        sp.eat("피자");
        gp.eat("햄버거");
        bp.eat("고기");
    }
}

interface Action{
    //추상 메소드 (구현부가 없는 함수)
    void run();
    void eat(String food);
}

class SoccerPlayer implements Action{
    String name;

    @Override
    public void run() {
        System.out.println(name+" runs..");
    }

    @Override
    public void eat(String food) {
        System.out.println(name+" eats "+food);
    }

    SoccerPlayer(String name){
        this.name=name;
    }
}

class GolfPlayer implements Action{
    String name;

    @Override
    public void run() {
        System.out.println(name+" runs..");
    }

    @Override
    public void eat(String food) {
        System.out.println(name+" eats "+food);
    }

    GolfPlayer(String name) {
        this.name=name;
    }
}

class BaseballPlayer implements Action{
    String name;

    @Override
    public void run() {
        System.out.println(name+" runs..");
    }

    @Override
    public void eat(String food) {
        System.out.println(name+" eats "+food);
    }

    BaseballPlayer(String name) {
        this.name = name;
    }
}

출력:

  김철수 runs..
  이민지 runs..
  김우현 runs..
  김철수 eats 피자
  이민지 eats 햄버거
  김우현 eats 고기

 


챕터 11. Controller

11-1. 요청방식 요청경로

프론트와 데이터베이스를 연결해주는 백엔드

백엔드의 시작 Controller

 

스프링 프로젝트 생성

(참고)https://siwon-swu18.tistory.com/84

 

Controller의 중요한 개념

1. @어노테이션

2. 요청 경로 및 요청 방식 (GET, POST)

3. 컨트롤러 함수 리턴 (뷰, 데이터) - @ResponseBody 여부

4. 컨트롤러 함수 인자 - @RequestParam

5. Model로 뷰에 데이터 넣기

 

Controller의 기본 구조

@Controller //@어노테이션
public class HomeController {

  @GetMapping("/")
  public String home() { return "home"; }
}

 

@어노테이션이란?

클래스, 함수 등에 특별한 기능을 부여하는 것 (자바 + @어노테이션 => 웹 기능)

일반적으로 데이터 타입, 함수, 클래스 앞에 붙여 자바 컴파일러 실행 시 어노테이션에 정의된 특정 기능을 실행하도록 한다.

주로 프레임워크에서 미리 정의된 것들을 사용하며 웹 개발자가 직접 만들어 사용하는 경우는 극히 드물다.

//단순히 클래스 이름이 HomeController인 클래스. 스프링에서 요청 처리를 할 수 없음.
class HomeController{ ... }
//@Controller 어노테이션을 추가하여 해당 클래스가 스프링에서 컨트롤러 역할을 할 수 있도록 함.
@Controller //@어노테이션
public class HomeController { ... }

 

요청 경로 및 요청 방식 (GET, POST)

순수한 자바에 어노테이션을 붙이면서 웹의 기능을 구현

웹 브라우저 주소창에 http://127.0.0.1:8080/... 로 요청하면 페이지가 호출된다.

@GetMapping("/") : 경로는 "/"이며, 요청 방식은 GET 방식으로 한다.

package com.my.likelion_backend.controller;

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

@Controller //@어노테이션
public class HomeController {

  @GetMapping("/") //@어노테이션
  public String home() { return "home"; }
}

 

요청 시에는 반드시 경로와 요청 방식이 모두 일치해야 컨트롤러 함수를 호출할 수 있다.

GET : 일반적으로 데이터를 가져오는 방식 (웹 브라우저 주소창에 요청하는 방식)

POST : DB 추가, 수정, 삭제 등 (웹 브라우저에서 쉽게 주소창으로 요청할 수 없음)

   위의 코드에서 @PostMappling("/") 하는 경우 405 error 발생 (Method No Allowed)

 

GET 방식은 주소창에서 쉽게 요청이 되기 때문에 DB 추가, 수정 등에는 사용하지 않음 (보안 상 위험)

이를 방지하기 위해 POST 방식 사용


11-2. 컨트롤러 함수 리턴 | 뷰, 데이터

경로와 요청 방식을 맞추어 요청하면 컨트롤러의 함수를 호출한다.

 

컨트롤러 함수의 리턴 방식 2가지

1. String = 뷰(JSP) 리턴 (@ResponseBody 없음)

@GetMapping("/")
public String home() { return "home"; }

 

2. @ResponseBody 데이터타입 = 데이터 리턴

@GetMapping("/datatype_ex1")
@ResponseBody //데이터("home"이라는 String)를 리턴
public String ex1() { return "home"; }

@GetMapping("/datatype_ex2")
@ResponseBody //Int로 반환도 가능
public int ex2() { return 23; }

 

이전에 api로 받은 파일들이 @ResponseBody 데이터 리턴 방식이다.


11-3. 쿼리 파라메터

url에서 데이터 받기

컨트롤러에 url로 요청하는 상황에서 경로뿐만 아니라 정보(데이터)를 같이 요청하는 경우가 있다.

   ex. 회원가입 요청 시 클라이언트가 input에 타이핑한 데이터를 제공하는 경우

이러한 경우 QueryString(쿼리스트링)을 이용하여 요청주소에 데이터를 넣는다.

 

@Controller 함수에서 요청주소에 데이터를 요구할 수 있다. (매개변수 개념)

 

@RequestParam으로 url에서 데이터 받기 (가장 많이 사용)

@RequestParam(value="key") 데이터타입 변수명

@GetMapping("/saveUser")
@ResponseBody
public String saveUser(
    @RequestParam(value="uid") String id
  ) {

    //회원가입 로직..

    return "ok"; //회원가입이 되었다는 의미
}

위의 코드로 실행하면 400 error 발생 (Bad Request): 주소에 매개변수가 없기 때문(?key=vlaue 형태)

 

요청주소에서 데이터 주입하기

요청경로?key1=value1&key2=value2&...

http://localhost:8080/saveUser?uid=siwon 로 접근하면 ok 출력

 

주소창으로 받아온 id를 console 창으로 확인해보기

siwon 확인 가능

 

여러 개를 받으려면 @RequestParam을 여러 번 선언한다.

upw 추가하기

@GetMapping("/saveUser")
@ResponseBody
public String saveUser(
    @RequestParam(value="uid") String id,
    @RequestParam(value="upw") String pw
  ) {

    //회원가입 로직..

    return "ok"; //회원가입이 되었다는 의미
}

http://localhost:8080/saveUser?uid=siwon&upw=abcd 로 접속

 

이 외 요청 데이터를 받는 방식(간략)

1. @PathVariable

경로에서 파라메터 추출

@GetMapping("/getUser/{userIdx}")
@ResponseBody
public String addUser(
    @PathVariable("userIdx") int userIdx //userIdx를 바로 입력
  ) {
    return "ok";
}

쇼핑몰의 제품 상세보기 등에서 사용 (상품의 고유 코드, 회원의 고유 코드 등)

ex. 쇼핑몰의 제품 상세보기에서 상품의 고유 코드를 넣어 사용

 

2. @RequestBody

파라메터를 java 객체로 변환 (POST 방식에서만 가능)

@PostMapping("/addUser")
@ResponseBody
public String addUser(
    @RequestBody User user
  ) {
    return "ok";
}

11-4. Model로 뷰에 데이터 넣기

@RequestParam으로 컨트롤러에서 받은 데이터를 뷰에 주입시키는 방법: Model 이용

컨트롤러 함수 인자로 Model 객체를 받는다. (Model model)

(Controller) Model 객체에 addAttribute("key", value); 으로 데이터를 주입한다.

(jsp) 뷰에서 보여줄 때는 ${key} 사용한다. (여러 번 호출 가능)

 

HomeController.java

package com.my.likelion_backend.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 HomeController {

...

    //회원 상세 정보를 볼 수 있는 페이지
    @GetMapping("/detail-user")
    public String detailUser(
            @RequestParam(value="uid") String id,
            Model model //model 이용
    ) {
        //@RequestParam 주소 받아온 uid를 통해 DB에서 회원정보 가져와야 함
        //현재 DB에 연결되지 않은 상태이기 때문에 변수로 지정해줌 => DB에서 받아온 데이터라고 가정
        String name = "김철수";
        String nickname = "철수1234";

        //DB에서 받아온 데이터를 detail-user에 주입 => Model 객체 이용 (view와 연결되어 있음)
        model.addAttribute("name", name);
        model.addAttribute("nick", nickname);

        return "detail-user";
    }
}

 

detail-user.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!doctype html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h2>회원 상세보기</h2>
    <h5>이름: ${name}</h5>
    <h5>닉네임: ${nick}</h5>
</body>
</html>

 

결과

http://127.0.0.1:8080/likelion_backend/detail-user?uid=abc

name(김철수)과 nick(철수1234)를 받아온 것을 확인할 수 있다.

 

 

FIN.

728x90

관련글 더보기

댓글 영역