📢 오늘의 목표 📢
✔️ 알고리즘, SQL 문제 풀이
✔️ 알고리즘 코드카타
✔️ SQL 코드카타
✔️ 프로그래머스 Level 2
✔️ 스프링 입문 개인 과제
✔️ 9단계
✔️ use-case-diagram
✔️ 스프링 공부 - 스프링 입문을 위한 자바 객체 지향의 원리와 이해
✔️ 7장 - 스프링 삼각형과 설정 정보: AOP, PSA
⏱️ 오늘의 일정 ⏱️
9:00 ~ 10:00 - 알고리즘 코드카타
10:00 ~ 13:00 - 스프링 입문 개인 과제
13:00 ~ 14:00 - 점심시간
14:00 ~ 16:00 - 스프링 입문 개인 과제
16:00 ~ 18:00 - 스프링 공부
18:00 ~ 19:00 - 저녁 시간
19:00 ~ 20:00 - 공부할 것 탐색하기
20:00 ~ 21:00 - TIL 작성
📜 Chapter 1. 알고리즘 문제 풀기
✔️ 알고리즘 코드카타
나누어 떨어지는 숫자 배열
✔️ SQL 코드카타
고양이와 개는 몇 마리 있을까
✔️ 프로그래머스 Level 2
[1차] 캐시
의상
이걸 풀면서 생각해 보니 코드카타 시트에 있는 후반부 문제들을 풀고 있는 거라 나중에는 코드카타 할 문제가 없다.
그리고 푼 문제는 미리 알고리즘 제출을 해둬야 하나...?
라는 고민에 빠져들었다.
📜 Chapter 2. 스프링 입문 개인 과제
✔️ 9단계
Mockito에 대해 제대로 이해하지 못했어서 화요일에는 하다 관두었지만 지금은 드디어 방법을 터득했다.
https://adjh54.tistory.com/346
https://adjh54.tistory.com/347
위 블로그에 정말 정말 자세하게 Mockito에 대해 설명이 되어있으니 꼭 참고하자.
도큐먼트 급으로 정리가 잘 되어있다👍
@DisplayName("일정 작성 성공")
@Test
void createSchedule() throws Exception {
objectMapper.getFactory().configure(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature(), true);
// given
ScheduleRequestDto requestDto =
new ScheduleRequestDto("제목", "내용", "damdang@email.com", "1234");
ScheduleResponseDto responseDto =
new ScheduleResponseDto(1L, "제목", "내용", "damdang@email.com", LocalDateTime.now());
String content = objectMapper.writeValueAsString(requestDto);
given(service.createSchedule(any(ScheduleRequestDto.class))).willReturn(responseDto);
// when
ResultActions actions = mockMvc.perform(post("/sprig-introduction/schedule")
.contentType(MediaType.APPLICATION_JSON)
.content(content));
// then
MvcResult result = actions.andExpect(status().isOk())
.andDo(print())
.andReturn();
System.out.println("result: " + result.getResponse().getContentAsString());
}
@DisplayName("일정 작성 실패")
@Test
void createScheduleFail() throws Exception {
objectMapper.getFactory().configure(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature(), true);
// given
ScheduleRequestDto requestDto =
new ScheduleRequestDto("제목", "내용", "damdang@email.com", "");
ScheduleResponseDto responseDto =
new ScheduleResponseDto(1L, "제목", "내용", "damdang@email.com", LocalDateTime.now());
String content = objectMapper.writeValueAsString(requestDto);
given(service.createSchedule(any(ScheduleRequestDto.class))).willReturn(responseDto);
// when
ResultActions actions = mockMvc.perform(post("/sprig-introduction/schedule")
.contentType(MediaType.APPLICATION_JSON)
.content(content));
// then
MvcResult result = actions.andExpect(status().is4xxClientError())
.andDo(print())
.andReturn();
System.out.println("result: " + result.getResponse().getContentAsString());
}
Mockito를 이용한 일정 작성 성공, 실패 테스트를 가져왔다.
Mockito로 테스트 케이스를 어떻게 만드는지 처음 감을 잡는 게 어려웠고 하나 만들고 나니 그 뒤로는 쉬웠다.
그러나 80퍼센트 이상의 커버리지를 만드는 것이 정말 오래 걸렸다...
저 given의 의미가 뭔지, 왜 output을 직접 만들어 줘야 작동하는지 기본적인 개념이 안 잡혀 있었어서 애먹었는데
저건 데이터 베이스 접근하는 등의 번거로움을 피하기 위해 (어차피 컨트롤러 계층의 테스트고 서비스 계층 테스트는 따로 만든다.) 인풋 아웃풋 모양만 흉내 낸 가짜 객체라는 것.
컨트롤러의 역할을 잘 수행하고 있는지만 테스트해 본 것이다.
@DisplayName("일정 작성 성공")
@Test
void createSchedule() {
LocalDateTime now = LocalDateTime.now();
// given
Schedule schedule = new Schedule(1L, "제목", "내용", "damdang@email.com", "1234", now);
ScheduleRequestDto requestDto =
new ScheduleRequestDto("제목", "내용", "damdang@email.com", "1234");
ScheduleResponseDto responseDto =
new ScheduleResponseDto(1L, "제목", "내용", "damdang@email.com", now);
given(repository.save(any(Schedule.class)))
.willReturn(schedule);
// when
ScheduleResponseDto testResponseDto = service.createSchedule(requestDto);
// then
Assertions.assertEquals(responseDto.getId(), testResponseDto.getId());
Assertions.assertEquals(responseDto.getTitle(), testResponseDto.getTitle());
Assertions.assertEquals(responseDto.getContents(), testResponseDto.getContents());
Assertions.assertEquals(responseDto.getCharge(), testResponseDto.getCharge());
Assertions.assertEquals(responseDto.getCreatedAt(), testResponseDto.getCreatedAt());
}
서비스 계층 테스트는 또 따로 만들어줬다.
여기서는 레지스트리를 가짜 객체로 생경해 줬다.
일단 과제 기준이 커버리지 80% 이상이라 턱걸이하였다.
파일 업로드의 경우 어떻게 테스트하는 게 좋을지 방법을 잘 모르겠다 ㅠㅠ
✔️ use-case-diagram
그리고 api, erd는 만들어 놓고 방치한 use-case-diagram...
이 녀석에 대해서는 처음 배워 봐서 뒤로 미루다 보니 결국 과제를 다 끝내고 나서 까지 미뤄져 버렸다.
이거 맞나?
모르겠다... 그냥 나중에 피드백받으련다.
과제를 너무 열심히 해서 피곤하다...
📜 Chapter 3. 스프링 공부
슬슬 이 책을 다 끝낼 때가 와 간다.
오늘 7장을 끝내면 부록만 남게 된다.
✔️ AOP
AOP는 Aspect-Oriented Programming의 약자로 관점 지향 프로그래밍이라는 뜻이다.
다수의 모듈에 공통적으로 나타나는 부분이 존재하는데 이를 횡단 관심사(cross-cutting concern)라고 한다.
개발자들은 중복 코드를 싫어하기 때문에 이런 횡단 관심사는 단 한 번만 작성하고 싶다.
그때 AOP를 사용한다.
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<aop:aspectj-autoproxy/>
<bean id="myAspect" class="aop002.MyAspect"/>
<bean id="boy" class="aop002.Boy"/>
</beans>
aop 기능을 불러오는 거야 중요한 게 아니고,
저기 myAspect라는 클래스를 bean으로 등록한 것이 보이는데 딱 봐도 "관점"에 관한 클래스 같다.
autoproxy라는 말이 aop가 어떤 기능을 하는지 참 자알 설명해주고 있다.
@Aspect
public class MyAspect {
@Before("execution(public void aop002.Boy.runSomething ())")
public void before(JoinPoint joinPoint) {
System.out.println("얼굴 인식 확인: 문을 개방하라");
}
}
@Aspect 어노테이션은 이 클래스를 AOP에서 사용하겠다는 뜻
@Before 어노테이션은 대상 메서드 실행 전에 이 메서드를 실행하겠다는 의미다.
public class Start {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("aop002.xml");
Person romeo = context.getBean("boy", Person.class);
romeo.runSomething();
}
}
런타임 시에 메서드가 삽입이 된다고 한다.
@Aspect
public class MyAspect {
@Before("execution(* runSometing())")
public void before(JoinPoint joinPoint) {
System.out.println("얼굴 인식 확인: 문을 개방하라");
}
}
어노테이션을 좀 수정하였다. 이렇게 하면 boy 뿐만 아니라 girl의 runSometime도 주입할 수 있단 것 같다.
근데 이러면 Person 인터페이스를 구현한 클래스가 아니어도 다 주입되는 거 아닌가?
@Aspect
public class MyAspect {
@Before("execution(public void aop002.Person.runSomething())")
public void before(JoinPoint joinPoint) {
System.out.println("얼굴 인식 확인: 문을 개방하라");
}
}
라는 의문이 들어 이렇게 코드를 수정해 봤는데 잘 돌아가는 걸 보면 이게 맞는 것 같은데 여기에 대해 자세한 설명이 없어서 잘 모르겠다.
어찌 됐든 중요한 것은 아래 세 개다.
- 스프링 AOP는 인터페이스 기반이다.
- 스프링 AOP는 프록시 기반이다.
- 스프링 AOP는 런타임 기반이다.
예시에서는 @Before을 사용했지만 프록시가 개입할 수 있는 시점은 5가지이다.
- Arround
- Before
- After
- AfterReturning
- AfterThrowing
용어
- Pointcut - Aspect 적용 위치 지정자 : public void aop002.Person.runSomething()
- 여기서는 정규식과 AspectJ 표현식 등을 사용할 수 있다.
- [접근제한자패턴] 리턴타입패턴 [패키지&클래스패턴] 매서드이름패턴(파라미터패턴) [throws 예외패턴]
- [] 대괄호는 생략이 가능하다.
- JoinPoint - 연결점 : JoinPoint joinPoint
- Aspect 적용이 가능한 모든 지점. 이 중 Pointcut에만 적용하는 것이니 Pointcut은 JoinPoint의 부분집합인 셈이다.
- 스프링 AOP에서는 스프링 프레임워크가 관리하는 빈의 모든 메서드에 해당한다.
- Pointcut의 메서드가 호출되면 JointPoint에 그 메서드가 들어올 것이다.
- Advice - 언제 무엇을 : @Before() public void before(JoinPoint joinPoint) { System.out.println("...");}
- pointcut에 적용할 로직과 적용 시점
- Aspect - Advice, Pointcut 들의 집합체.
- Advisor - 언제 어디서 무엇을 : 한 개의 Advice + 한 개의 Pointcut
- Advisor는 스프링 AOP에서만 사용하는 용어이며 이제 쓰지 말라고 권고하는 기능이다.
그리고 스프링 프레임워크에 종속되지 않도록 POJO와 XML 기반으로 AOP를 만드는 법에 대해 나와있는데 쓸 일이 없을 것 같아서 패스했다.
스프링 부트의 AOP에 대해서는 아까 Mockito를 설명해주신 분 블로그에 포스트가 하나 있다.
https://adjh54.tistory.com/133
참 정리를 잘하시는 듯
✔️ PSA - 일괄성 있는 서비스 추상화
PSA(Portable Service Abstraction) 일관성 있는 서비스 추상화.
스프링 삼각형의 마지막 요소이다.
서비스 추상화의 예로 JDBC가 있다.
어댑터 패턴을 활용하여 같은 일을 하는 기술들을 공통의 인터페이스로 제어할 수 있게 한 것을 서비스 추상화라고 한다.
스프링 프레임워크에서는 서비스 추상화를 위해 다양한 어댑터를 제공한다.
📜 Chapter 4. 공부할 것 탐색하기
이제 부록만 남았는데 스프링 부트가 아닌 스프링 MVC라 할지 말지 고민이 된다.
그럼 이제 뭐 하지...?
김영한의 스프링 강의
https://www.inflearn.com/roadmaps/373
이전에 들어보려 북마크 해뒀던 강의이다.
그러나 팀원들 얘기를 들어보니 전체 강의를 사서 들어도 그렇게 좋은 강의는 아니라 하고... 무료 강의는 들어보자 싶었지만 전체 5시간 21분 밖에 안 되고... 또 이런 입문 강의는 사실상 두 번이나 돌았으니 설렁설렁 스킵하면서 듣게 될 텐데...?
그래서 이건 패스했다.
하이퍼 스킬
https://hyperskill.org/tracks/12
팀원 분을 통해 알게 된 프로그래밍 학습 사이트이다.
실습을 통해 새로운 스택을 쌓을 수 있다고 한다.
책과 강의로는 쌓을 수 없는 것들이 있기 때문에 꽤 괜찮은 선택 같아 보인다.
단점은 유료라는 것(물론 무료 기능도 있음).
그리고 영어라는 것.
근데 이 아저씨는 뭐지?
알고리즘 공부
그리고 마지막으로 생각난 건 꼭 스프링만 공부할 필요가 있냐는 것이다.
C++ 이긴 하지만 공부하다 만 알고리즘 책이 눈에 밟힌다.
그리고 프로그래머스, 백준 문제도!
그렇다면 알고리즘 공부를 하는 것도 좋은 선택이 아닐까?
혼자 공부하는 네트워크
https://youtube.com/playlist?list=PLVsNizTWUw7HfOCgvlfHIDPPo3TE-2iQM&si=LuaRyAdaDIXE-SHY
혼공 시리즈에서 얼마 전에 네트워크 책이 나왔다!
혼공 컴운으로 cs 지식을 잘 쌓았었는데 같은 저자님이셔서 벌써부터 믿음이 간다.
일단 이건 언제가 될진 모르겠지만 꼭 책 사서 공부해야겠다.
🌙 오늘을 마치며 🌙
원래 어제 춘천에 가서 자전거를 타려고 했는데 비가 와서 닭갈비만 먹고 왔다.
그런데 내가 보는 채널에서 딱 오늘 이 영상을 올리는 것이었다 ㅋㅋㅋㅋ
https://www.youtube.com/watch?v=SasDklaS1_w&list=RDCMUC6JR7bt78jyhnO89w5aGV2w&start_radio=1
꼭 다시 춘천가서 자전거 타고와야지... 하고 다시 한 번 다짐했다.
어쨌든 어제 비만 쫄딱 맞고 돌아왔더니 너무 피곤하고 몸살이 난 것 같다.
그래서 오늘은 할당량도 다 채웠으니~ 공부를 살짝 일찍 마쳤다.
'공부 기록 > 내배캠Java_5기' 카테고리의 다른 글
[내배캠][TIL] 24일 차 - 월요일 (0) | 2024.05.20 |
---|---|
[내배캠][TIL] 23일 차 - 금요일, 수준별 수업 전부 듣기 (0) | 2024.05.17 |
[내배캠][TIL] 21일 차 - 화요일, 스프링 개인 과제를 해보자 (0) | 2024.05.14 |
[내배캠][TIL] 20일 차 - 월요일, 스프링 입문 강의 뽀개기 (0) | 2024.05.13 |
[내배캠][TIL] 19일 차 - 금요일, 자바 주차 끝! (0) | 2024.05.10 |