728x90

출처 - https://inf.run/XKQg

 

1. DB

// 데이터베이스 생성
create database test;

// 데이터베이스 사용
use test;

// 테이블 생성
create table fruits (
    id bigint auto_increment,
    name varchar(20) not null,
    warehousingDate date not null,
    price bigint not null,
    isSold boolean default false,
    primary key (id)
);

 

 

2. Controller 코드

@RestController
public class FruitController {
    private final JdbcTemplate jdbcTemplate;

    public FruitController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @PostMapping("/api/v1/fruit")
    public void insertFruits(@RequestBody FruitRequest fruitRequest) {
        String sql = "INSERT INTO fruits (name, warehousingDate, price) VALUES (?, ?, ?)";
        jdbcTemplate.update(sql, fruitRequest.getName(), 
        fruitRequest.getWarehousingDate(), fruitRequest.getPrice());
    }
 }
  • 생성자를 사용해 JdbcTemplate 객체를 주입 받는다.
  • Post요청으로 RequestBody 어노테이션을 사용하여 HTTP body 에서 과일 데이터(FruitRequest)를 받아온다.
  • 과일에 대한 정보(이름, 등록 날짜, 가격)을 넣어준다.
  • JdbcTemplate의 update메서드를 사용하여 쿼리를 실행한다.

 

3. DTO 코드

import java.time.LocalDate;

public class FruitRequest {
    private long id;
    private String name;
    private LocalDate warehousingDate;
    private long price;

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public LocalDate getWarehousingDate() {
        return warehousingDate;
    }

    public long getPrice() {
        return price;
    }
}

 

4. 실행 결과

 

 

[질문] - 위 API에서 long 타입을 사용하는 이유는?

자바에서 대표적으로 사용하는 정수형 타입엔 int와 long이 있다. (byte와 short 도 있음)
하지만 여기서 long을 사용하는 이유는 무엇일까?

int형 데이터 타입에 저장 될 수 있는 정수의 범위는 –2,147,483,648 ~ 2,147,483,647으로 약 -21억 ~ 21억이다.
하지만 long 타입은  -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,808이다.

int타입에 비하면 엄청나게 많은 숫자이다.
작은 프로그램을 만들때에는 int형 데이터 타입으로도 충분히 저장 가능하다.

하지만 은행과 같은 숫자를 많이 다루는 대형 프로그램에서는 int형 넘어가는 범위의 숫자가 잘못 저장되는 것을 방지하기 위해
또, 나중에 프로그램이 커질 것을 대비하여 int타입으로 사용하기 보다는 처음부터 long타입으로 지정 하는 것이다.
(나중에 다시 변환하려고 하면 머리 아프니까..)

그렇다고 무조건 long타입이 좋은 것은 아니다 프로젝트 규모에 따라 잘 설계하는 것이 가장 좋은 설계인 것 같다.

 

 

출처 - https://inf.run/XKQg

 

1. Controller 코드

@RestController
public class FruitController {
    private final JdbcTemplate jdbcTemplate;

    public FruitController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @PutMapping("/api/v1/fruit")
    public void updateFruits(@RequestBody FruitUpdateRequest request) {
        String readSql = "SELECT * FROM fruits WHERE ID = ?";
        boolean isExist = jdbcTemplate.query(readSql, (rs, rowNum) -> rs.getString("id"), request.getId()).isEmpty();
        if (isExist) {
            throw new RuntimeException("존재 하지 않는 과일입니다.");
        }
        String updateSql = "UPDATE fruits SET isSold = true where id = ?";
        jdbcTemplate.update(updateSql, request.getId());
    }
}

 

  • 위 코드는 PUT 메서드로 데이터 수정을 위해 사용하는 HTTP 메서드이다.
  • @RequestBody 어노테이션으로 HTTP Body에서 과일 데이터를 받아온다.
  • 해당 과일 id를 가진 과일이 없다면 "존재하지 않는 과일"이라고 보여준다. (예외를 발생시킨다.)
  • 만약 있다면 해당 id를 가진 과일을 isSold 컬럼을 true로 바꿔준다.

 

2. DTO

public class FruitUpdateRequest {
    private long id;
    private String name;

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

 

3. 실행 결과

 

[실행 전 데이터]

 

[실행 후 데이터]

  • 1, 3번 데이터를 실행해보겠다. (3번은 생략)

요청 결과 200 반환

 

 

위와 같이 1번, 3번 데이터의 isSold 컬럼이 1로 바뀐 것을 볼 수 있다.

(mysql에서는 1은 true, 0은 false이다. 일반적으로 프로그래밍에서도 동일하다.)

 

출처 - https://inf.run/XKQg

 

1. Controller 코드

@RestController
public class FruitController {
    private final JdbcTemplate jdbcTemplate;

    public FruitController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @GetMapping("/api/v1/fruit/stat")
    public FruitResponse selectFruits(@RequestParam String name) {
        String sale = "SELECT SUM(price) as salesAmount FROM fruits 
        				WHERE isSold = true AND name = ?";
        String notSale = "SELECT SUM(price) as notSalesAmount FROM fruits 
        				WHERE isSold = false AND name = ?";

        long salesAmount = jdbcTemplate.queryForObject(sale, (rs, rowNum) 
        					-> rs.getLong("salesAmount"), name);
        long notSalesAmount = jdbcTemplate.queryForObject(notSale, (rs, rowNum) 
        					-> rs.getLong("notSalesAmount"), name);

        return new FruitResponse(salesAmount, notSalesAmount);
    }
}

 

  • HTTP 메서드는 GET 메서드로 name(과일 이름)을 매개변수로 받고 있다.
  • sale은 isSold가 true이면서 매개 변수로 받은 과일 이름과 일치하는 과일의 가격을 더한다.
  • notSale은 isSold가 false이면서 매개 변수로 받은 과일과 일치하는 과일의 가격을 더한다.
  • 그렇게 해서 출력 방식인 salesAmount와 notSaleAmount를 리턴을 한다.

2. 실행 결과

[실행 전 데이터]

 

[실행 후 데이터]

 

 

 

[질문] - SUM과 GROUP BY 키워드

SUM: 주어진 열(컬럼)의 값들을 모두 더하는 SQL 집계 함수이다. 위와 같이 가격을 합산해주는 용도로 사용한다.
GROUP BY: 집계 함수와 함께 사용되고, 특정 열(컬럼)의 값에 따라 결과를 그룹화합한다.

 

 

 

강의 링크 👉 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

728x90
728x90

자바의 람다식은 왜 등장했을까?

람다는 함수형 프로그래밍이다.  함수형 프로그래밍은 프로그램을 작성하는 데 있어서 함수의 조합을 중심으로 하는 프로그래밍이다. 이는 병렬 처리 및 동시성 프로그래밍을 강조하고, 불변성과 순수 함수를 중시하여 안정적이고 예측 가능한 코드를 작성한다.

 

자바는 과거부터 객체지향 프로그래밍 언어로서의 강점을 가지고 있었지만, 함수형 프로그래밍의 이점도 놓치지 않기 위해 Java 8에서 람다식이 도입되었다. 람다는 코드의 간결성과 가독성을 높이고 병렬성을 활용할 수 있다. 또, 함수형 프로그래밍은 요즘 개발에 있어 중요한 요소로 자리 잡았다. 자바도 객체지향 프로그래밍을 보완하면서, 시대의 변화에 맞게 변화하기 위해 도입하였다.

 

 

람다식과 익명 클래스는 어떤 관계가 있을까?

 

1. 익명 클래스란?

Java에서 클래스는 사용자가 정의한 타입을 만드는

설계도로 객체를 생성하고 코드의 재사용성을 높이는 역할을 한다.

 

하지만 익명 클래스는 내부 클래스의 일종으로 말 그대로 이름 없는 클래스를 말한다.

익명 클래스는 단발성으로 한번만 사용해야 하는 객체일 경우 사용한다.

즉, 클래스와 같이 재사용성이 없고, 오히려 확장하여 사용하는 것이 불리할 때 사용한다.

 

그렇기 때문에 생성자를 선언할 수 없고, 단 하나의 클래스, 인터페이스를 상속 받거나 구현할 수 있다.

public class Anonymous {
    public static void main(String[] args){
        className variableName = new className(){ // 클래스이름 참조변수이름 = new 클래스이름
            // 내용 작성
        }
    }
}

 

2. 함수형 프로그래밍이란?

순수 함수를 조합하고 공유 상태를 변경 가능한 데이터 및 부작용을 피해 소프트웨어를 만든는 프로그래밍 방법이다.
선언형 프로그래밍으로, 애플리케이션의 상태는 순수 함수를 통해 전달된다.

(명령형 프로그래밍은 어떻게 할지 표현하고, 선언형 프로그래밍은 무엇을 할 것인지 표현한다.)

 

  • 순수 함수 (Pure Function)
    • 순수 함수는 동일한 입력 값에 대해 항상 같은 값을 반환해준다.
    • 전역 변수를 사용하거나, 변경하면서 생기는 부작용이 없다.

 

  • 1급 객체 (Frist Class Citizen)
    • 변수나 데이터 구조안에 담을 수 있다.
    • 파라미터로 전달 할 수 있다.
    • 반환값으로 사용할 수 있다.
    • 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다. 
    • class가 없어도 독립적으로 메서드의 인자로 전달되고나 return 값으로 전달 받을 수 있다.
      즉, 함수를 데이터 다루듯이 사용할 수 있다.
  • 고차 함수(High Order Function)
    • 함수를 매개변수로 사용하거나 함수를 반환하는 함수.
  • 불변성(Immutable)
    • 데이터는 변하지 않는 불변성을 가지고 있다.
    • 데이터의 변경이 필요할 경우, 원본 데이터는 변경하지 않고 복사본을 만들어 변경하고 사용한다.

 

3. 함수형 인터페이스(FunctionalInterface)

함수형 인터페이스는 오직 한 개의 추상 메서드를 갖는 인터페이스이다.

@FunctionalInterface
interface FuncInterface {
    // 추상메서드
    int sum(int a, int b);
    
    // default 메서드
    default int minus(int a, int b);
    
    // static 메서드
    static int mul(int a, int b);
}

 

위 코드와 같이 @FunctionalInterface 어노테이션이 붙고, 오로지 추상 메서드는 한 개 있거나,

default가 붙거나 static이 붙은 메서드가 있는 것을 말한다.

이때 default 메서드와 static이 붙은 메서드는 함수형 인터페이스에 아무런 영향을 미치지 않는다.

 

Java에서는 기본적으로 많이 사용되는 함수형 인터페이스를 제공한다.

java.util.fuction 패키지는 일반적으로 자주 쓰이는 함수형 이터페이스를 미리 정의한 패키지이다.

그러므로 함수형 인터페이스를 만들기 보다는 이 패키지를 활용하는 것이 좋다.

출처 - https://joomn11.tistory.com/22

 

 

4. 람다란?

람다 함수는 함수형 프로그래밍 언어에서 사용되는 개념으로 익명 함수라고도 한다.
Java 8 부터 지원하고, 불필요한 코드를 줄여 가독성을 향상 시킨다.

 

  • 람다의 특징
    • 익명 함수로 이름을 가질 필요가 없다. 
    • 메소드의 매개변수로 전달되거나, 변수에 저장될 수 있다.
    • 익명 클래스는 생성할 때 많은 코드를 작성해야 하지만 람다는 불필요한 코드를 작성하지 않아도 된다.
    • 람다는 메서드처럼 특정 클래스에 종속되지 않는다. 하지만 메서드와 동일하게 사용할 수 있다.(파라미터, 리턴 등)
  • 람다의 장점
    • 코드를 간결하게 만들 수 있다.
    • 코드에 개발자의 의도가 명확히 드러나 가독성이 높다진다.
    • 함수를 만드는 과정 없이 한번에 처리 가능하여 생산성이 높아진다.
    • 병렬 프로그래밍에 용이하다.
  • 람다의 단점
    • 람다로 사용한 익명함수는 재사용이 불가능하다.
    • 재귀로 사용하기엔 부적절하다.
    • 디버깅이 어렵다.
    • 람다로만 사용하게 되면 중복 생성이 될 가능성이 있다.
  • 람다 사용 방법
interface Calculator{
	public void calc(int a, int b);
}

public class Main{
    public static void main(String[] args){
        Calculator sum = (a, b) -> {
            int answer = a + b;
            System.out.println("sum: " + answer);
        }
        sum.calc(10, 20);
    }
}

// 람다 방식
// (매개변수 선언) -> { 문장들 }

 

 

[정리]

익명 클래스로 작성한 코드보단 람다식으로 작성한 코드가 훨씬 가독성이 좋고 간결성 있다.

람다는 매개변수 타입을 추론할 수 있지만, 익명 클래스는 인터페이스의 타입을 선언해야한다.

interface Calculator{
	public void calc(int a, int b);
}


// 익명
public class Main {
    public static void main(String[] args) {
        Calculator sum = new Calculator() {
            @Override
            public void calc(int a, int b) {
                int answer = a + b;
                System.out.println("sum: " + answer);
            }
        };
        sum.calc(10, 20);
    }
}

// 람다
public class Main{
    public static void main(String[] args){
        Calculator sum = (a, b) -> {
            int answer = a + b;
            System.out.println("sum: " + answer);
        }
        sum.calc(10, 20);
    }
}

 

 

강의 링크 👉 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

728x90
728x90

1. 두 수를 입력하여, 다음과 같은 결과가 나오는 GET API 만들기

[결과 예시]

{
	"add": 덧셈 결과,
	"minus": 뺄셈 결과,
	"multiply": 곱셈 결과
 }

 

[작성 코드]

public class Inflearn{
    @GetMapping("/api/v1/calc")
    public Calculator calculator(
    @RequestParam("number1") int number1, 
    @RequestParam("number2") int number2) 
    {
        return new Calculator(number1, number2);
    }
}


public class Calculator {
    public int add;
    public int minus;
    public int multiply;

    public Calculator(int number1, int number2) {
        this.add = number1 + number2;
        this.minus = number1 - number2;
        this.multiply = number1 * number2;
    }
}

 

[코드 설명]

  • Get API로 만들어야 하기 때문에 @GetMapping을 사용하였다.
  • calculator 메서드는 number1, number2 두 개의 숫자를 파라미터로 받고 Caculator 객체를 리턴 해준다.
  • Caculator 클래스에서 생성자는 두 수를 받아 덧셈, 뺄셈, 곱셈을 하여 저장한다.
  • Caculator 클래스에서 작업이 끝나면 결과를 반환해준다.

 

[실행 결과]

 

2. 날짜를 입력하면, 무슨 요일인지 알려주는 GET API를 만들기

[결과 예시]

 {
	"dayOfTheWeek": "MON"
 }

 

[작성 코드]

public class Inflearn{
    @GetMapping("/api/v1/day-of-the-week")
    public DayOfTheWeek getDate(@RequestParam("date") String date) {
        return new DayOfTheWeek(date);
    }
}


import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;

public class DayOfTheWeek {
    public String dayOfTheWeek;

    public DayOfTheWeek(String date) {
        String[] dateArr = date.split("-");
        
        LocalDate localDate = LocalDate.of(Integer.parseInt(dateArr[0]), 
        Integer.parseInt(dateArr[1]), Integer.parseInt(dateArr[2]));
        
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        
        String day = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.ENGLISH);
        
        this.dayOfTheWeek = day;
    }

}

 

[코드 설명]

  • GET API로 만들어야 하기 때문에 @GetMapping을 사용하였다.
  • getDate 메서드는 문자열 date를 파라미터로 받고 날짜 객체를 리턴 한다.
  • DayOfTheWeek 클래스에서 생성자는 문자열 형식의 date를 받아 처리를 한다.
    • 문자열 date를 "-" 기준으로 자른다.
    • LocalDate.of() 파라미터에는 년, 월, 일이 순서대로 들어가고 LocalDate 객체를 생성한다.
    • LocalDate 객체인 localDate에서 getDayOfWeek() 메서드를 사용하여 요일을 가져온다.
    • 가져온 요일을 getDisplayName()메서드를 사용하여 dayOfTheWeek 필드에 요일을 할당한다.
  • DayOfTheWeek 클래스에서 작업이 끝나면 dayOfTheWeek 필드에 할당된 값을 리턴한다.

[실행 결과]

 

💡 LocalDate.of()

더보기

LocalDate 클래스에서 제공해주는 LocalDate.of()를 살펴 보았다. 이 메서드는Year-Month-DayOfMonth순서로

파라미더가 들어가고,해당 날짜를 나타내는LocalDate객체를 생성하는 역할을 한다.

 

💡 getDayOfWeek()

더보기

getDayOfWeek()가  어떻게 동작하는지 궁금해서 확인해 보았다.

getDayOfWeek() 메서드는 enum을 반환하고, 이 enum은 요일을 나타내는데 사용한다.
그럼 위 코드에서 enum은 어떤 형식인지 궁금해서 또 들어가봤다.

of(int dayOfWeek) 메서드는 "MONDAY, TUESDAY"등 요일이 적힌 enum 클래스를 리턴 하고 있고,

이 메서드는 ISO-8601 표준에 따라 1부터 7까지의 값을 가지고, 1은 월요일을 나타내고, 7은 일요일을 나타낸다고 한다.

 

3. 여러 수를 받아 총 합을 반환하는 POST API 만들기

[결과 예시]

 {
	"numbers": [1, 2, 3, 4, 5]
 }

 

[작성 코드]

public class Inflearn{
    @PostMapping("/api/v1/sum")
    public int sum(@RequestBody NumberList numbers) {
        int sum = 0;
        for (Integer num : numbers.numbers) {
            sum += num;
        }

        return sum;
    }
}


import java.util.List;

public class NumberList {
    public List<Integer> numbers;
}

 

[코드 설명]

  • POST API로 만들어야 하기 때문에 @PostMapping을 사용하였다.
  • sum 메서드는 NumberList 객체인 numbers를 받는다.
  • NumberList 객체는 숫자 목록을 저장하기 위한 클래스이다.
    • numbers 필드는 숫자 목록을 저장하는 List<Integer> 타입이다.
  • NumberList 객체에 포함된 숫자 리스트를 반복하여 모든 숫자를 더한 값을 반환한다.

[실행 결과]

 

 

강의 링크 👉 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

728x90
728x90

1. 어노테이션이란?

먼저 어노테이션을 설명하기 전에 메타데이터에 대해 조금 알고 가야할 것 같다.

 

  • 메타데이터(Metatdata)란?
    • 데이터의 대한 속성 정보이다. '데이터에 관한 구조화 된 데이터', '다른 데이터를 설명해 주는 데이터'라고도한다.
    • 대량의 정보 가운데에서 찾고 있는 정보를 효율적으로 찾아내서 이용하기 위해 일정한 규칙에 따라 콘텐츠에 대하여 부여 되는 데이터라고 한다.
  • 어노테이션이란? 
    • 메타데이터의 일종이다.
    • 프로그램을 처리할 때 실행 과정에서 어떻게 데이터를 처리할지 알려주는 서브 데이터라고 한다.
    • 코드에서 @를 붙여 사용하는 코드
    • JDK 1.5버전 이상부터 사용가능

 

2. 어노테이션을 사용하는 이유 (효과) 는 무엇일까?

  • 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공해준다.
  • 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공해준다.
  • 런타임 시 특정 기능을 실행하도록 정보를 제공해준다.

위와 같은 이유에서 사용한다. 그럼 어노테이션의 종류는 무엇이 있을까?

@Override

컴파일러에게 오버라이딩 하라는 메소드라고 알려준다.

 

@Service

스프링프레임 워크에서 자주 쓰이는 어노테이션으로 핵심 비즈니스 로직을 담은 서비스를 클래스 빈에 등록하기 위해 사용한다.

 

@SpringBootApplication

스프링 실행 시 필요한 다양한 설정을 알아서 자동으로 해준다. 

 

@GetMapping

스프링 프레임워크에서 자주 쓰이는 어노테이션으로 Http get요청이 오면 @GetMapping이 붙은 메소드가 실행된다.

 

위와 같이 많은 어노테이션이 있고 상황에 따라 알맞은 어노테이션을 사용하면 된다.

 

3. 나만의 어노테이션은 어떻게 만들 수 있을까?

1. 어노테이션 생성

어노테이션은 인터페이스 앞에 @를 붙여 만들 수 있다.

public @interface MakeAnnotaion {
    
}

 

2. 메타 어노테이션

메타 어노테이션에는 아래와 같은 종류가 있다.

 

@Target : 사용할 어노테이션에 적용할 대상을 지정하는데 사용한다.

ElementType.ANNOTATION_TYPE 어노테이션
ElementType.CONSTRUCTOR 생성자
ElementType.FIELD 멤버변수, Enum 상수
ElementType.LOCALVARIABLE 지역변수
ElementType.METHOD 메서드
ElementType.PACKAGE  패키지
ElementType.PARAMETER 매개변수
ElementType.TYPE 타입(클래스, 인터페이스, Enum)
ElementType.TYPE_PARAMETER 타입 매개변수(제네릭과 같은 매개변수)
ElementType.TYPE_USE 타입이 사용되는 모든 대상

 

@Documented : 어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 하는 어노테이션이다.

자바에서 제공하는 표준 어노테이션과 메타 어노테이션 중에 @Override와 @SuppressWarnings 어노테이션을 제외하고 모든 어노테이션에 @Documented 어노테이션이 적용되어 있다.

 

@Inherited : 하위 클래스가 어노테이션을 상속받도록 한다.

상위 클래스에 @Inherited를 붙이면 하위 클래스에서도 동일하게 사용된다.

 

@Retention : 어노테이션의 지속 시간을 결정하는 데 사용한다.

RetentionPolicy.SOURCE 컴파일 전까지 지속됨, 컴파일 이후엔 사라진다.
RetentionPolicy.CLASS 런타임이 실행되기 전까지만 존재한다.
RetentionPolicy.RUNTIME
런타임 시 사용되된다. (즉, 클래스 파일까지 존재하며 실행시 사용된다.)

 

@Repeatable : 어노테이션을 반복하여 사용할 수 있도록 허용하는 어노테이션이다.

@Retention(RetentionPolicy.RUNTIME) // 어노테이션은 특정 어노테이션의 지속 시간을 결정하는 데 사용
@Inherited // 하위 클래스가 어노테이션을 상속받도록 함
@Documented // 어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함
@Target(ElementType.METHOD)// 사용할 어노테이션을 적용할 대상을 지정
public @interface MakeAnnotaion {
    
}

 

 

위의 코드는 컴파일 이후에도 사용할 수 있는 @Retention(RetentionPolicy.RUNTIME) 사용하였고, 하위 클래스에서 어노테이션을 상송 받을 수 있도록 하였다. 또, @Documented를 사용하여 해당 어노테이션에 대한 정보가 문서로 저장될 수 있도록 하였고, 메서드 선언 시 적용할 수 있도록 @Target(ElementType.METHOD)를 사용하였다.

위와 같이 필요한 어노테이션을 상황에 맞게 적용하여 만들면 된다.

 

출처 - https://ittrue.tistory.com/160

 

3. 만든 어노테이션 사용하기

@MakeAnnotation(name = "HelloController")
@RequestMapping("/hello")
public class HelloController {

}

public class HelloController2 {
	@MakeAnnotation
	String str = null;
    
    @MakeAnnotation
    public void test(){
    
    }
}

 

위와 같이 만든 어노테이션을 적용할 수 있다.

 

[느낀점]

어노테이션에 대해 궁금해 하지 않았는데 이번 기회로 어노테이션이 어떤건지 알 수 있게 되었다.

커스텀 어노테이션도 구현하는 것이 마냥 어렵다고 느꼈는데 각각 어떤 기능을 하는지 어디에 필요한지 정리하면 생각보다 쉽게 커스텀 어노테이션 구현이 가능하다는 것을 알게 되었다.

조금 더 공부해서 직접 어노테이션을 만들어 프로젝트에도 한번 적용해보아야겠다.😁

 

강의 링크 👉 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

728x90
728x90

어? 강의가 되게 재밌어 보이네?

오랜 기간 취업 준비를 하는 도중 프로젝트 없이 공부만 하다보니 개발이 재미 없어지기 시작하였습니다.

물론 오랜 취업 준비 기간으로 힘든 것도 있지만 내가 직접 만드는 서비스가 없다보니 흥미가 떨어진 것 같다고 생각하였습니다. 그렇게 어떤 프로젝트를 할까, 개인으로 할까? 팀으로 할까? 많은 고민을 하던 중 '자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!' 라는 강의를 알게 되었습니다.

강의 목차를 보니 웹 개발에 필요한 기술부터 네트워크, AWS 등 정말 백엔드로서 필요한 지식을 한 강의에서 제공해주는 것에 매력을 느꼈습니다. 하지만 돈 없는 취준생은 듣고 싶지만 부담이 되었습니다.😭

 

이건 꼭 해야해..!

그렇게 며칠을 고민하던 중 지식 공유자께서 직접 참여를 하고, 다양한 사람들과 의견을 주고 받을 수 있는 스터디가 열린다는 것을 알게 되었습니다. 거기에 대상 강의가 바로..! 제가 구매할지 말아야할지 고민하던 '자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지!' 였습니다.

저는 개발 실력도 중요하지만 네트워킹에 참여하는 것도 중요하다고 생각하였는데 이 기회는 두마리의 토끼를 동시에 잡을 수 있는 매력적인 이벤트였습니다. 강의를 사야할지 말아야할지 고민하던 저는 주저 없이 스터디를 신청하게 되었고, 강의도 바로 구매하였습니다.😁

 

그렇게 시작한 OT(0일차)

16일 금요일 스터디의 시작을 알리는 OT를 하였습니다. 지식공유자이신 최태현님께서 대략적인 스터디 일정을 알려주셨고, 자바의 역사에 대해 알려주셨습니다.

스터디 일정을 보니 정말 타이트하고 힘들 것 같지만 저는 시간 많은 취준생 아니..백수이기 때문에 열심히 스터디 일정에 맞춰서 달려보겠습니다. 이번 기회로 참여하신 다른 러너분들과 많은 이야기와 정보를 주고 받고 싶습니다.

 

오랜 취업준비를 하였지만 그런 것 치고는 큰 실력향상이 있진 않았던 것 같아 이번 기회에 제대로 마음 잡고 공부해보려고 합니다..! 화이팅..! (급 종료)

 

 

강의 링크 👉 자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

728x90
728x90

구축하게 된 이유

평소 주변 지인이 서버를 구성하고 운영하는 것이 매우 흥미로워 보였다.

항상 서버를 구축해보고 내 프로젝트를 올려보고 싶었으나, 부담되는 금액과 당장 먼저 해야할 것들이 많아 잠시 미뤄둔 상태였다.

 

그러던 중 6개월 뒤 프리티어의 계정이 만료된다는 것을 알게 되었다. 

개인 프로젝트를 AWS 프리티어를 사용하여 배포해놓았다.

과금이 되지 않는 것을 확인했고, 과금이 되지 않도록 잘 설정하였지만 언제 어떻게 과금될까 불안한 마음이 항상 있었다. 

 

이외에도 만료 되면 다시 배포해야하나?

내 개인 블로그도 개발해서 한번 배포하고 싶은데 방법이 없을까?

백엔드 개발자라면 서버 구축을 해서 웹 사이트 배포해보는 것도 좋지 않을까?  라는 생각이 계속 들어

이것 저것 찾아보던 중 우연히 컴퓨터 3대가 생기게 되었고, 이것으로 서버를 구축해보게 되었다.

 

PC 사양

단순 웹 서비스 배포용 PC는 사양이 크게 중요하지 않는다고 한다.

cpu의 성능 보다도 ram의 성능이 더 우선시 된다. (그렇다고 아예 중요하지 않은 것은 아니다.)

 

CPU: i5-4469

RAM: 16gb

SSD: 500gb

 

운영체제

Proxmox

  • Proxmox란 데비안 리눅스 기반으로, 오픈 소스 플랫폼이기 때문에 많은 기능을 무료로 사용할 수 있다.
  • KVM 가상화와 LXC 컨테이너 기술을 사용하여 가상 머신과 컨테이너를 생성, 관리 및 모니터링할 수 있다. 
  • 사용자는 하나의 물리적 서버에서 여러 개의 가상 머신 및 컨테이너를 실행할 수 있다.
  • 웹 기반 관리 인터페이스를 제공하여 간편하게 리소스를 관리하고 모니터링 할 수 있다.

Linux

  • Ubuntu Server 22.04.3 lts
  • CentOS도 경험해보고 싶었으나 Ubuntu를 더 많이 사용하기 때문에 Ubuntu 먼저 경험해보기로 결정하였다.

정리를 하자면 Proxmox는 Aws와 같은 것이고, 그 위에 리눅스를 설치하고 Vm은 Aws의 ec2같은 것이라고 생각 하면 될 것 같다.

정리

서버를 구축하고 나니 빨리 내 프로젝트를 서버에 올려보고 싶다.

지금까지 개발 공부를 하면서 이렇게 즐겁진 않았는데,

너무 설레고 빨리 공부하고 배포해보고 싶어 아침에 눈도 일찍 더진다.😁

 

아직 네트워크에 관해 많은 지식이 많이 부족하지만 빨리 공부해서

어떻게 하면 서버를 최적화할 것인가 등 다양한 고민을 해볼 수 있었으면 좋겠다.

 

다음 포스팅엔 설치 방법에 관해 포스팅 해보겠다..!

728x90

'서버' 카테고리의 다른 글

개인 홈 서버 - VM 만들기  (1) 2024.02.26
개인 홈 서버 - Proxmox 설치하기  (1) 2024.02.26
728x90

[문제 설명]

다음 규칙을 지키는 문자열을 올바른 괄호 문자열이라고 정의합니다.

  • (), [], {} 는 모두 올바른 괄호 문자열입니다.
  • 만약 A가 올바른 괄호 문자열이라면, (A), [A], {A} 도 올바른 괄호 문자열입니다. 예를 들어, [] 가 올바른 괄호 문자열이므로, ([]) 도 올바른 괄호 문자열입니다.
  • 만약 A, B가 올바른 괄호 문자열이라면, AB 도 올바른 괄호 문자열입니다. 예를 들어, {}  ([]) 가 올바른 괄호 문자열이므로, {}([]) 도 올바른 괄호 문자열입니다.

대괄호, 중괄호, 그리고 소괄호로 이루어진 문자열 s가 매개변수로 주어집니다. 이 s를 왼쪽으로 x (0 ≤ x < (s의 길이)) 칸만큼 회전시켰을 때 s가 올바른 괄호 문자열이 되게 하는 x의 개수를 return 하도록 solution 함수를 완성해주세요.

 

[입출력 예]

s result
"[](){}" 3
"}]()[{" 2
"[)(]" 0
"}}}" 0

 

[차근 차근 생각해보기]

  1. s를 이어 붙여서 회전한 모습을 만든다.
  2. isCorrect 함수를 만들어 온전한 괄호인지 판별한다.
    • 열린 괄호일 경우 stack에 넣어준다.
    • 닫힌 괄호이고 stack에 들어간 괄호와 짝이 맞을 경우 stack에 있는 괄호는 빼준다.
    • 만약 닫힌 괄호가 열린 괄호보다 먼저 들어갈 경우 return false를 해준다.
  3. isCorrect 함수에서 true일 경우 answer에 1을 더해주고 return 해준다.

 

[코드]

import java.util.*;
class Solution {
    public int solution(String s) {
        int answer = 0;
        
        String newStr = s + s;
        for(int i = 0; i < s.length(); i++){
            if(isCorrect(newStr.substring(i, s.length() + i))){
                answer += 1;
            }
        }
        
        return answer;
    }
    
    boolean isCorrect(String s){
        String[] str = s.split("");
        Stack<String> stack = new Stack<>();
        
        for(int i = 0; i < str.length; i++){
            if(str[i].equals("(") || str[i].equals("[") || str[i].equals("{")){
                stack.push(str[i]);
            }else if(stack.empty()){
                return false;
            }else if(str[i].equals(")") && stack.peek().equals("(")){
                stack.pop();
            }else if(str[i].equals("]") && stack.peek().equals("[")){
                stack.pop();
            }else if(str[i].equals("}") && stack.peek().equals("{")){
                stack.pop();
            }
        }
        
        if(stack.empty()){
            return true;
        }
        
        return false;
    }
}

 

[반성할 점]

괄호 문제는 스택으로 푸는 문제이다.

회전을 위해 문자열 s를 한번 더 더한다는 아이디어가 정말 흥미로웠다.

아이디어를 주신분께선 경험의 차이라는데 과연 경험의 차이가 맞을까 의심된다..

 

아직까지 생각하는 코드를 구현해내는 것이 많이 부족하다.

알고리즘 이외에도 다른 문제를 풀면서 구현력을 기르도록 노력해야겠다.

728x90
728x90

[문제 설명]

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같이 특별한 방법으로 섞어 새로운 음식을 만듭니다.

섞은 음식의 스코빌 지수 = 가장 맵지 않은 음식의 스코빌 지수 + (두 번째로 맵지 않은 음식의 스코빌 지수 * 2)

 

Leo는 모든 음식의 스코빌 지수가 K 이상이 될 때까지 반복하여 섞습니다.
Leo가 가진 음식의 스코빌 지수를 담은 배열 scoville과 원하는 스코빌 지수 K가 주어질 때, 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 섞어야 하는 최소 횟수를 return 하도록 solution 함수를 작성해주세요.

 

[입출력 예]

scoville K return
[1, 2, 3, 9, 10, 12] 7 2

 

[차근 차근 생각해보기]

  1. 스코빌 지수가 K이상이 되어야 하기 때문에 PriorityQueue에 넣어준다.(오름차순 정렬이 됨)
  2. 가장 작은 수에서 두번째로 작은 수 * 2를 더해준다.
  3. 계속 반복하면서 첫번째 원소가 K이상일때 멈춰준다.

 

[코드]

import java.util.*;
class Solution {
    public int solution(int[] scoville, int K) {
        PriorityQueue<Integer> lowList = new PriorityQueue<>();

        for (int i = 0; i < scoville.length; i++) {
            lowList.add(scoville[i]);
        }

        int answer = 0;
        while (lowList.peek() < K) {
            if (lowList.size() < 2) {
                return -1;
            }else{
                answer++;
                lowList.add(lowList.poll() + (lowList.poll() * 2));
            }
        }
        return answer;
    }
}

 

 

[반성할 점]

알고 보면 되게 간단한 문제였는데 우선순위 큐라는 존재를 몰라 복잡하게 풀려다가 못풀었던 문제였다.

이제는 자료구조를 공부할 때이다.

언능 공부해서 그동안 풀었던 문제들도 다시 풀어보고 싶다..!

728x90
728x90

[문제 설명]

숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.

 

각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.

 

예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.

 

기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.

 

[입출력 예]

number limit power
result
5 3 2 10
10 3 2 21

 

[차근 차근 생각해보기]

  1. 1부터 number까지 각각의 약수의 개수를 구하기
    • 1의 약수 1개, 2의 약수 2개, 3의 약수 2개 등등
  2. 약수의 개수가 limit보다 크면 power로 바꿔준다.(제한된 수보다 크면 공격력이 power인 무기를 구매해야하기 때문)
  3. answer에 cnt를 더해주고 return해준다.

 

[코드]

class Solution {
    public int solution(int number, int limit, int power) {
        int answer = 0;
        for (int i = 1; i <= number; i++) {
            int cnt = 0;
            for (int j = 1; j * j <= i; j++) {
                if (j * j == i) {
                    cnt++;
                }else if(i % j == 0){
                    cnt += 2;
                }
            }
            if(cnt > limit){
                cnt = power;
            }
            answer += cnt;
        }
        return answer;
    }
}

 

[반성할 점]

약수의 개수 구하는 방법을 몰라 처음에 많이 헤맸다.

단순히 모든 수를 돌면서 약수를 구해보았는데 시간 초과가 나서 이리저리 찾아보다가

1 ~ n의 제곱근까지 돌면서 약수이면 * 2를 해주고 n의 제곱근인 경우 1개를 더해주는 방법을 찾게 되었다.

그랬더니 시간 초과 없이 잘 풀리게 되었다.

약수 구하는 방법을 조금 더 공부해보고 기록해둬야겠다.

728x90
728x90

올해는 유독 다사다난한 해였다.. 왜 이렇게 취업이 힘든지..

이 힘들었던 기억들로 내 자신이 단단해졌고 다시한번 마음 정리를 해보기 위해 첫 회고를 작성해본다.

 

회사🏢

국비 수료 후 한달도 안돼서 취업했던 첫 회사는 하루만에 그만두었고,

두번째 회사는 프로젝트 마감 당일, 수습 종료 통보를 받았다.

 

왜 나에게 이런 시련이 오는지..솔직히 생각하면 아직도 힘들고 눈물부터난다..😭

취업 시장은 점점 얼어 붙었고, 안좋은 채용 소식들만 들리고 정말 막막하다.

그럼에도 그만두고 싶다는 생각은 들지 않는다. 오히려 더 열심히 해서 꼭 성공하자 라는 생각만 가득하다.

 

조금 더 힘내서 2024년 2월 전엔 꼭 취업해야지..!💪

 

1일 1 알고리즘

퇴사를 당한(?) 후 충격이 너무 커서 공부는 하기 싫은데 뭔가 하긴 해야하고..

그렇게 찾은 것이 하루에 1개씩 알고리즘을 풀는 것이었다.

7월부터 오늘까지 깃 잔디 기록

 

그냥 내가 모든게 다 부족해보여서 당장 프로젝트 하기는 싫고 알고리즘이라도 풀면서

코드라도 만져보자며 자료구조도 모른채 0레벨부터 무작정 풀기 시작하였다.

그리고 이게 지금까지 이어져왔고 이제는 풀지 않으면 하루가 망가진 것만 같은 느낌이 든다..

 

5만등이었던 내 순위

지금까지 닥치는대로 풀었더니 50문제도 안풀려 있었던 문제들을 오늘 기준으로 총 361개를 풀었다.

등수, 점수는 그냥 많이 풀면 올라가기에 중요하진 않지만, 5개월 조금 넘는 시간동안 하루에 한문제는 꼭 풀었다는 것

그리고 문제 푸는 것이 이제는 습관이 되었다는 것이 너무나 기쁘고 뿌듯하다!

 

내년부턴 프로그래머스 외에 릿코드를 병행하며 푸는 문제 수를 늘려보려고 한다!

그리고 1일 1 알고리즘은 내년에도 계속 진행할 것이다. (여행가서도 풀 예정😁)

 

2024년 목표

2024년엔 작은 목표 두가지를 더 추가해보려고 한다.

  • 하루에 2문제씩 알고리즘 문제 풀기
  • 책 2권 이상 읽기(개발 서적 제외하고)
  • 모각코 스터디 만들어서 사람들과 소통하고 공부하기

이렇게 총 3가지의 목표를 실천해보려고 한다.

 

알고리즘으로 무슨 일이 있더라도 매일 코드 치는 습관을 기르고 싶고,

책을 읽는 습관이 되어 있지 않아 최소 2권 이상의 책을 읽고 독서에 흥미를 가져보려고 한다.

 

현재 개발자 지인들과 온라인에서 조금씩 공부를 진행하고 있는데, 이를 통해 공부 습관을 기르고 싶고

2024년엔 오프라인 모임도 진행하여 다양한 사람들과 소통하는 커뮤니티를 만들어보려고 한다.

 

혼자 공부하고 정보를 수집하기 보다는 다른 사람들과 소통하는 것이 나를 성장 시키는데

더 효율적이고 효과적인 방법이라고 생각하기 때문이다.

 

마무리

두루 뭉실했던 나의 목표들이 개발자의 길을 들어오고선 뚜렷한 목표들로 바뀌기 시작했다.

2024년엔 얼마나 더 다양한 목표들이 생기고 새로운 아이디어가 떠오를지 너무 기대되고 설레인다.

올 한해 정말 너무나도 힘들고 슬픈 일이 많았지만 2024년엔 목표한 것들도 꼭 실천하고, 행복한 일만 있었으면 좋겠다!

 

728x90

'주절주절' 카테고리의 다른 글

코끼리를 냉장고에 넣는 방법  (2) 2023.12.29
멘토링 진작 할걸..!!  (0) 2023.12.19
체대생에서 개발자로  (1) 2023.06.07

+ Recent posts