오늘도 끄적끄적

느리더라도 꾸준하게

문제점

Time은 데이터 전체를 파싱하는데 걸린 시간이니 무시하고…
트래픽이 13MB 남짓…
사용자가 조건을 바꿔서 검색을 한다면 데이터 광탈범이 될 가능성이 다분한 상황이었다.

더 읽어보기 »

메이븐은 기본적으로 빌드할 때 프로필을 지정할 수 있는 것 같은데 gradle은 직접 삽질을 하면서 깨달았다.
다음의 글들을 보고 Spring boot 1.5.7과 Gradle 3.x(아마)? 에 맞게, 내 입맛에 맞게 각색해보았다.

Profile 구성하기

기본적인 스프링 부트 프로젝트는 다음과 같은 구조를 가질 것이다.

더 읽어보기 »

근본없이 궁금한 부분만 찾아서 공부하다보니 아직 정리가 덜 된 글이다 보니 그 점은 감안하고 보길 바란다.

컨트롤러를 만들자

Node.js(+Express)의 Router와 매우 유사한 것 같다.
URI와 http method, parameter만 매핑해주는 녀석이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/api")
public class Controller {
@GetMapping("/")
public Person sayHello(
@RequestParam String name,
@RequestParam int age,
@RequestParam(required = false) String hobby
) {
Person person = new Person();
person.setHobby(hobby);
person.setName(name);
person.setAge(age);
return person;
}

@PostMapping("/")
public void sayHello(
@RequestBody Person person
) {
System.out.println(person.getAge());
System.out.println(person.getHobby());
}
}
더 읽어보기 »

근본없이 궁금한 부분만 찾아서 공부하다보니 아직 정리가 덜 된 글이다 보니 그 점은 감안하고 보길 바란다.

properties

Node.js로 서버를 구성하다보면 포트 등등의 설정 정보를 json으로 저장하듯이 스프링 부트에서는 properties 파일을 사용하는 것 같다.
물론 YAML 파일로도 만들 수 있는 것 같은데 일단 아는 게 properties 파일이다보니 그걸로 진행해보겠다.
우선 스프링 부트를 만들면 기본 파일인 application.properties 파일을 아래와 같이 구성해보자.

1
key="asdf"
더 읽어보기 »

beans.xml 파일을 수정해보자.

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="koreanTire" class="KoreanTire"/>
<bean id="americanTire" class="AmericanTire"/>
<bean id="car" class="Car">
<property name="tire2" ref="koreanTire"/>
</bean>
</beans>

beans의 property는 getter/setter와 매핑이 된다.
Car.java를 수정해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Car.java
public class Car {
private Tire tire;
public Car() {}
public Car(Tire tire) {
this.tire = tire;
}
public Tire getTire2() {
return tire;
}
public void setTire2(Tire tire) {
this.tire = tire;
}
}
더 읽어보기 »

Car 클래스를 수정해보자.

1
2
3
4
5
6
7
8
9
10
public class Car {
@Autowired
private Tire tire33;
public Tire getTire() {
return tire33;
}
public void setTire(Tire tire) {
this.tire33 = tire;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config />
<bean id="tire33" class="KoreanTire"/>
<bean id="americanTire" class="AmericanTire"/>
<bean id="car" class="Car"/>
</beans>

@Autowired 한 멤버 변수와 bean의 id가 매칭되는 걸 볼 수 있다.
또한 <context:annotation-config />을 추가해줘야하고, property 태그의 생략이 가능하다.

더 읽어보기 »

일반 자바를 가지고 DI를 해본 v3에서는 Car 클래스를 자바 빈즈 스펙을 제대로 준수해서 만들지 않았다.
따라서 한 번 자바 빈즈 스펙에 맞춰 바꿔보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Car {
private Tire tire;
public Car() {}
public Car(Tire tire) {
this.tire = tire;
}
public Tire getTire() {
return tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
}

getter/setter와 기본 생성자가 있어야 자바 빈즈 스펙을 준수한 것이었는데 저번에는 기본 생성자가 없어서 추가했다.
그럼 이제 beans.xml 파일을 만들고 자바 빈즈 객체들을 등록해보자.

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="tire" class="KoreanTire"/>
<bean id="americanTire" class="AmericanTire"/>
<bean id="car" class="Car"/>
</beans>
더 읽어보기 »

v1에는 재사용 가능한 코드가 있음에도 불구하고 미묘(?)한 차이 때문에 계속 각국의 타이어를 장착한 자동차 클래스를 만들어야하는 단점이 있었다.
이는 자동차를 만들 때 이미 타이어를 만드는 방법이 결정되어 있기 때문에 발생하는 문제이다.
(**자동차(전체)**가 **타이어(부분)**에 의존하고 있는 코드)
즉, 자동차를 만들 때 타이어를 만드는 방법을 결정하면 되는 사항이다.
(**의존하는 부분(타이어)**을 **전체(자동차)**에 주입시키는 패턴)

1
2
3
4
// Tire.java
public interface Tire {
void wheel();
}
1
2
3
4
5
6
// KoreanTire.java
public class KoreanTire implements Tire {
public void wheel() {
System.out.println("구르다");
}
}
1
2
3
4
5
6
// AmericanTrie.java
public class AmericanTire implements Tire {
public void wheel() {
System.out.println("wheel");
}
}
더 읽어보기 »

v2에는 자동차를 생산할 때 어떤 타이어를 만들지 정할 수 있고 새로운 타이어로 교체도 가능했다.
하지만 올바른 값이 들어왔는지 유효성 검사할 방법이 없다.
사실 변경할 수는 있지만 안전하지 않고 그닥 권장하는 방법이 아니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Car.java
public class Car {
private Tire tire;
Car(Tire tire) {
this.tire = tire;
}
// setter로 유효성 검사를 위해선 어쩔 수 없이(?) tire를 얻기 위해선 getter를 써야함.
public Tire getTire() {
return tire;
}
// setter로 다음과 같이 유효성 검사가 가능해짐.
public void setTire(Tire tire) {

if(tire == null) throw new NullPointerException();
this.tire = tire;

}
}
1
2
3
4
5
6
7
8
9
10
11
// Driver.java
public class Driver {
public static void main(String[] args) {
KoreanTire koreanTire = new KoreanTire();
AmericanTire americanTire = new AmericanTire();
Car car = new Car(koreanTire);
car.getTire().wheel(); // 구르다
car.setTire(americanTire);
car.getTire().wheel(); // wheel
}
}

setter를 사용해 좀 더 안전하게(?) 타이어를 교체할 수 있게 되었다.
대부분 getter/setter를 사용하는 이유는 아마 다음과 같을 것이다.

더 읽어보기 »

이 글은 의존성 주입을 전혀 적용하지 않은, 의존성 주입이 뭔지 모르는 상태로 짠 코드이다.
우선 문제점을 먼저 파악해봐야 뭐가 되지 않을까 싶어서 막코딩을 해봤다고 가정해보자.
우선 미국산 타이어가 장착된 자동차, 한국산 타이어가 장착된 자동차를 만들어야한다고 생각해보자.
그럼 우선 미국산, 한국산 타이어 클래스 두 개가 필요할 것이다.

1
2
3
4
5
6
// KoreanTire.java
public class KoreanTire {
public void wheel() {
System.out.println("구르다");
}
}
1
2
3
4
5
6
// AmericanTire.java
public class AmericanTire {
public void wheel() {
System.out.println("wheel");
}
}

그리고 각각 미국산 타이어를 장착한 자동차, 한국산 타이어를 장착한 자동차 클래스 두 개를 만들면 끝난다.

더 읽어보기 »
0%