블로그

솔 (Sol)

개발 기술 스택 심볼 & 마스코트 톺아보기

‘노트북 꾸미기’ 좋아하세요? 많은 개발자들이 노트북에 자기가 쓰고 있거나 좋아하는 기술 스택 로고 스티커를 붙이며 나만의 개성을 표현하곤 하는데요. 혹시 여러분의 노트북엔 어떤 스티커가 붙어 있나요?귀엽고 멋진 건 놓칠 수 없는 개발자라면 주목! 수많은 개발자들의 마음을 사로잡은 기술 스택에 숨은 아기자기한 심볼과 마스코트 몇 가지를 가볍게 소개할게요.썸네일 속 노트북은 인프런 백엔드 개발자 제이의 노트북!지금 쓰고 있는 스택(GraphQL 등...)이나 앞으로 배우고 싶은 스택(Go 등...), “Think Twice Code Once” 같은 개발자 밈 스티커까지 컨퍼런스나 주변 개발자 분들께 받은 스티커가 붙어 있어요. 🥰프로그래밍 언어 로고/심볼자바 (Java) 모락모락 김이 나는 귀여운 커피 컵! 자바 개발자들은 인도네시아 자바 섬에서 난 원두로 만든 커피를 마시곤 했대요. 몇 시간 동안 머리를 맞대고 토의한 끝에 정한 이름이라고 합니다.파이썬 (Python)‘비단뱀’이라는 뜻의 파이썬. 심볼 속 뱀 두 마리를 찾으셨나요? 파이썬을 만든 귀도 반 로섬(Guido van Rossum)이 영국 코미디 그룹 몬티 파이튼(Monty Python)에서 이름을 따왔다고 해요.스위프트 (Swift) iOS, macOS 개발에 쓰이는 스위프트는 ‘칼새’ 혹은 ‘신속한, 재빠른’이라는 뜻의 영단어 Swift에서 따온 이름이에요. 로고 모양도 날쌘 칼새를 닮았죠? 신속함을 강조하는 스위프트의 정체성을 잘 보여주네요.코틀린 (Kotlin) 자바와 비슷하면서도 간결한 문법으로 이목을 끄는 코틀린! 코틀린을 개발한 젯브레인(JetBrains) 사의 R&D 센터가 있는 러시아 코틀린(Ко́тлин) 섬에서 이름을 따왔는데요. 자바 역시 섬 이름인 걸 보면 두 언어의 관계가 재미있죠. 심볼 역시 머리글자 K를 간결하게 변형한 모양이에요.•••다양한 기술 스택 속 귀여운 마스코트깃허브 (Github) - 옥토캣 (Octocat) 복잡한 코드를 결합하고 관리하는 깃허브의 문어 다리 달린 고양이 마스코트 ‘옥토캣’. 3개 이상의 브랜치를 결합하는 작업을 가리키는 Octopus Merge에서 영감을 얻었다고 해요.리눅스 (Linux) - 턱스 (Tux) 믿거나 말거나! 리눅스를 만든 리누스 토르발스(Linus Torvalds)는 호주 캔버라 동물원에서 펭귄에게 물어뜯겨 펭귄염(?)에 걸린 적이 있다고 해요. 리눅스 마스코트로 삼을 정도면 그만큼 강렬한 경험이었던 모양이죠? 😅PHP (PHP: Hypertext Preprocessor) - 코끼리 (ElePHPant) 대문자로 쓴 PHP라는 글자를 옆에서 비스듬히 보면 코끼리처럼 보인다는 이유로 코끼리 마스코트를 갖게 된 PHP. elePHPant라는 말장난도 왠지 귀엽지 않나요?러스트 (Rust) - 페리스 (Ferris) 최근 개발자들 사이에 코어한 인기를 끄는 언어, 러스트의 비공식 마스코트는 주황색 게 모양이죠. 갑각류(Crustacean)에서 따온 듯한 요 마스코트 덕에 러스트 개발자들은 스스로를 Rustacean이라고 부른다고 하네요.고 (Golang) - 고 고퍼 (Go Gopher) 일러스트레이터 르네 프렌치(Renee French)가 그린 고퍼는 프로그래밍 언어 Go를 상징하는 주머니고퍼(흙파는쥐) 모양의 마스코트예요. 원래는 특별히 정해진 색이 없었다가 Google I/O 2011에서 Go App Engine 런타임을 출시하면서 파란색이 되었다고 해요.안드로이드 (Android) - 안드로보이 (Androboi) 단순한 듯 귀여운 녹색 로봇 마스코트 안드로보이! 안드로이드는 버전 1.1부터 OS 버전에 따라 디저트 이름을 붙이기로 유명한데 (컵케이크, 도넛, 오레오, 롤리팝…) 디저트 모양에 따라 달라지는 안드로보이의 모습을 보는 소소한 재미도 있죠.셀 수 없이 많은 기술 스택만큼, 매력적인 심볼과 마스코트도 무궁무진한데요. 여러분이 좋아하는 기술 심볼/마스코트는 어떻게 생겼나요? 댓글로 여러분의 최애 스킬(!)의 모습을 소개해주세요. 🥰

개발 · 프로그래밍 기타javapythonswiftkotlingithublinuxphpgoandroidrust

대협

[인프런 워밍업 클럽 2기 - BE] 1주차 발자국

이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다 나의 첫 인프런 블로그가 이렇게 쓰여질 줄은 몰랐다.. 그동안 인프런 강의들을 많이 애용했지만, 이렇게 블로그를 작성하지는 않아서 낯설기도 하고, 설레기도 한다.발자국 내용은 딱히 형식이 정해져 있지 않아서 발자국 쓰기 전날까지 들었던 강의들 중, 모르는 내용들을 적어서 내가 다시 봤을 때, "아 맞다!" 라는 말이 나올 정도로만 적을 예정이다! 목차모르는 내용 정리 미션 해결 과정회고   1. 모르는 내용 정리 <Gradle>Gradle : Gradle은 Groovy를 기반한 빌드 관리 도구.빌드 관리 도구 : 프로젝트 내에서 다양하게 외부 라이브러리와 로컬 레포지토리에서도 라이브러리 별로 버전 관리를 해야할 때 용이Gradle이 왜 필요할까?Gradle과 Maven 차이를 알면 Gradle이 왜 필요한지 알 수 있다.Gradlegroovy 언어를 사용한 Domain-specific-language를 사용 ( 코드가 간결)어느 task가 업데이트 되었는지 체크이미 반영된 빌드 부분은 더이상 재 실행되지 않는다. -> 빌드 시간 단축Mavenjava8용 프로젝트 관리 도구 apache의 ant 대안외부 저장소에서 필요한 라이브러리, 플러그인들을 다운로드 한 후 , 로컬 시스템의 캐시에 모두 저장그래서 왜 Gradle인데!!!Gradle은 작업 의존성을 그래프, Maven은 고정적이고 선형적 모델을 기반Gralde은 어떤 task가 업데이트되었고 안되었는지를 체크Gradle은 이미 업데이트 된 task에 대해서는 작업이 실행되지 않으므로 빌드 시간 단축빌드 설정 규모가 작으면 큰 차이를 느끼지 못하지만 규모가 크면 훨씬 Gradle의 빌드 시간이 단축된다는걸 알 수 있다. <Dependencies>Spring Web : 웹 어플리케이션을 개발하기 위한 핵심 기능 제공Thymeleaf : View Template, 동적으로 화면을 구성할 수 있게 해줌Spring Data JPA : JPA를 이요한 구현체를 더 추상화시켜 더 쉽고 간편하게 JPA를 이용 가능mysql driver : mysql를 연동할 때 필요한 dependencyh2 database : RDBMS, 테스트 단계 또는 작은 규모의 프로젝트에서 사용validation : 데이터에 대한 유효성 검증 처리를 수행Spring Security : 홈페이지에 인증 및 권한 기능을 빠르게 부여해 인증 및 권한 보호 기능을 손쉽게 추가할 수 있음. <프로그램이 시작되는 시작되는 코드>src/main/kotlin/PortfolioApplicatioin.ktfun main(args: Array<String>) { runApplication<PortfolioApplication>(*args) } Whitelabel Error Page 오류가 뜨는 이유 : 어플리케이션이 뭘 해야 할지 모르기 때문에 Whitelabel Error Page를 보내줌.(정상) <Git 용어>Git : 분산 버전 관리 시스템 ⇒ 협업을 쉽게 해주는 툴 : GitHubCommit : git에 저장하는 단계Rollback : 이력 되돌리기Branch : branch 생성 및 제거, 확인등의 기능을 하는 명령어Merge : 브랜치 병합Conflict : 충돌Repository : 원격 저장소 , 인터넷이나 네트워크 어딘가에 있는 저장소Push : 로컬 브랜치를 원격 저장소로 푸시할 때 사용하는 기본 명령어 <Git 명령어>git init : git 공간으로 초기화git status 명령어 입력시 Untracked files 라는 게 있는데 이건 git에서 따로 설정을 안한다는 소리https://www.toptal.com/developers/gitignore/ : gitignore 파일을 자동으로 만들어줌 <github에 PUSH 방법>터미널에서 git initgit remote “git 저장소”→ 인텔리제이(GUI)로 할 시에는 git → Manage Remotecommitpush <application-default.yml , application-docker.yml>profile이 default 이면, application-default.yml 파일에서 환경변수를 가져오고profile이 docker 이면, application-docker.yml 파일에서 환경변수를 가져온다. application-default.yml 파일에서 spring:jpa:hibernate:ddl-auto:create 인데왜 application-docker.yml 파일에서는 spring:jpa:hibernamte:ddl-auto:none 일까?=> application-default.yml 에서는 개발 목적으로 데이터베이스 스키마를 매번 재생성할 필요가 있지만, application-docker.yml 에서는 베포 및 운영 환경에 적합하게 데이터베이스 구조가 변경되지 않도록 하기 위한 설정 <어노테이션 정리>@Id : 해당 테이블의 PK 필드를 의미@Entity : JPA를 사용해 테이블과 매핑할 클래스에 붙여주는 어노테이션@GeneratedValue : JPA에서 Entity의 PK를 생성하여 주는 기능-> @GeneratedValue(name="member_id") : PK로 사용될 Entity의 프로퍼티에 @Id 어노테이션 선언-> @GeneratedValue(strategy=GenerationType.IDENTITY) : 기본 키 생성을 데이터베이스에 위임한다.-> @GeneratedValue(strategy=GenerationType.AUTO) : 기본값으로 DB 방언에 맞춰 자동으로 설정하여 준다.@Column : 객체 필드와 DB 테이블 칼럼을 맵핑한다.@Component : 클래스를 자동으로 빈으로 등록하기 위해 클래스 레벨에서 사용@Profile : 빈이나, 컴퓨넌트에게 프로필을 정해줄 수 있음@PostConstruct : 객체의 생성이 일어난 직 후에 초기화를 수행하는 메서드에 부착한다.@ManyToOne : 단방향 관계이고 FK관리에 있어서 가장 자연스럽다. @JoinColumn 어노테이션과 같이 쓰인다.@JoinColumn : 엔티티 테이블에 FK 칼럼을 정의해준다. 자료형뒤에 ? 는 무슨 의미일까 ?ex ) Long?자료형 뒤에 ? 가 오는 것은 Kotlin에서 사용되는 문법이고 ?를 자료형 뒤에 붙이는 방식은 nullable 여부를 나타낸다. 예를 들면 var name: String? = null 이 코드는 해당 변수 name에 null 값이 올 수도 있다는 뜻이다.  <코드 분석>var type: SkillType = SkillType.valueOf(type) : SkillType.valueOf(type) 은 type이라는 문자열을 SkillType 열거형의 값으로 변환. 만약 type이 열거형에 없는 값이면 예외 발생var cookies: String? = httpServletRequest.cookies ?.map {"${it.name}:${it.value}"} ?.toString() : httpServletRequest에서 쿠키 정보를 가져오고, 쿠키 이름과 값을 "이름:값" 형식으로 변환하는 코드var referer: String? = httpServletRequest.getHeader("referer") : HTTP 요청에서 "Referer" 헤더 값을 가져온다. 이 코드는 사용자가 어떤 페이지에서 현재 페이지로 이동했는지 나타냄@OneToManyvar details: MutableList<ExperienceDetail> = mutableListOf() : JPA 관계를 나타내고, 엔티티 간의 일대다(One-to-Many) 관계를 나타냄2. 미션미션 1과 2를 제출하는건데, 미션1은 테이블 설계하기와 깃허브 리포지토리에 프로젝트 올리기이다. 미션 1 : https://github.com/HyupTech/LMS/commit/fa47b404d36b3ce418f16213e3bb30ca96b812ed미션 2 : https://github.com/HyupTech/LMS/commit/0993897036a0e17e7a366031b950235edd5d506e   3. 회고발자국을 작성하면서 나는 이제까지 강의를 보면서 공부를 했지만 다시 한번 이렇게 정리를 해가면서 강의를 보지 않았다. 왜냐하면 시간이 너무 아까웠고, 차라리 정리하는 시간에 강의를 하나 더 보자는 마인드였다. 하지만 발자국을 써보면서 왜 이렇게 좋은걸 내가 안했을까라는 후회가 들고, 이렇게 정리를 해가면서 했으면 아마 실력이 조금이라도 더 올랐지 않았나 라는 생각이 들었다. 앞으로 발자국도 쓰고, 내가 따로 공부하고 있는것도 정리해가면서 공부를 해야겠다. 3-1. 미션 회고 이번 미션에서 처음으로 ERD를 구성하고 어디에 PK를 주고 관계 설정을 어떻게 할지에 대한 고민이 많았던 것 같다. 현재 대학교 2-2에 재학중인데 데이터베이스 과목을 수강중인데 꽤 도움이 되었던 것 같고, 백엔드 개발자가 될려면 데이터베이스 공부도 놓지 말아야겠다고 생각이 들었다. 앞으로 더 많은 미션들이 기다리고 있는데 열심히 공부를 해야겠다!   

백엔드인프런워밍업클럽백엔드발자국javakotlin

대협

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국

[인프런 워밍업 클럽 2기 - BE] 3주차 발자국이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다1. controller test 코드 분석애너테이션 조사@AutoConfigureMockMvcMockMvc를 자동으로 설정해 주는 애너테이션. 이 애너테이션을 통해 HTTP 요청을 수행하고 응답을 확인할 수 있다.MockMvc 란 ?실제로 서버를 띄우지 않고 컨트롤러를 테스트할 수 있는 도구@DisplayName("Test")테스트 클래스를 시작할 때 테스트 클래스의 이름을 지정해서 테스트 리포트에 표시된다.위 코드를 실행시키면 리포트에 TEST 라는 이름으로 테스트 성공유무가 표시됨.@Configuration : Spring에서 Bean을 수동으로 등록하기 위해서 사용메서드 분석 @Test @DisplayName("Introductions 조회") fun testGetIntroductions() { val uri = "/api/v1/introductions" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() }api/vi/introduction을 uri 변수에 넣음.HTTP GET 요청을 보낸후, 응답을 문자열로 변환한 후에 JSONArray로 변환JSONArray의 길이가 0보다 큰지 검증, 응답 데이터가 비어 있지 않음을 확인 @Test @DisplayName("Link 조회") fun testGetLinks() { val uri = "/api/v1/links" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } api/vi/links을 uri 변수에 넣음HTTP GET 요청을 보낸후, 응답을 JSONArray로 변환배열의 크기와, 그 데이터가 존재하는지 검증@Test @DisplayName("Resume 조회") fun testGetResume() { val uri = "/api/v1/resume" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonObject = JSONObject(contentAsString) assertThat(jsonObject.optJSONArray("experiences").length()).isPositive() assertThat(jsonObject.optJSONArray("achievements").length()).isPositive() assertThat(jsonObject.optJSONArray("skills").length()).isPositive() } /api/vi/resume를 uri변수에 넣음GET요청을 보낸후, 응답을 JSONObject로 변환experiences, achievements,skills를 JSONArray로 변환 후 그 값이 양수인지와 데이터가 존재하는지 검증@Test @DisplayName("Projects 조회") fun testProjects() { val uri = "/api/v1/projects" val mvcResult = performGet(uri) val contentAsString = mvcResult.response.getContentAsString(StandardCharsets.UTF_8) val jsonArray = JSONArray(contentAsString) assertThat(jsonArray.length()).isPositive() } /api/vi/projects를 uri 변수에 넣음GET요청을 보낸후 응답 본문을 JSONArray로 변환하고, 배열의 길이가 양수인지와 데이터가 존재하는지 검증private fun performGet(uri: String): MvcResult { return mockMvc .perform(MockMvcRequestBuilders.get(uri)) .andDo(MockMvcResultHandlers.print()) .andReturn() } perform(MockMvcRequestBuilders.get(uri)) : 특정 uri에 GET 요청을 보내는 코드. 서버를 띄우지 않고 API 엔드포인트의 동작을 확인할 수 있음andDo(MockMvcResultHandlers.print()) : 요청과 응답을 콘솔에 출력andReturn() : MvcResult를 반환2. 부분 코드 분석<html *lang*="ko" *xmlns:th*="<http://www.thymeleaf.org>" *th:replace*="~{presentation/layouts/layout-main :: layout(~{::#content})}">Thymeleaf 템플릿 엔진에서 레이아웃을 정의하고 해당 레이아웃을 재사용하는 방식, 템플릿 코드의 중복을 줄이고, HTML 파일 간에 공통 요소를 재사용할 수 있게 하는 것. th:replace="~{presentation/layouts/layout-main :: layout(~{::#content})}"th:replace : 다른 파일을 가져와 현재 위치에 삽입하는 기능 수행~{presentation/layouts/layout-main :: layout(~{::#content})} :~{presentation/layouts/layout-main} : layout-main.html 파일 참조:: layout : layout 이라는 이름의 fragment를 사용하겠다는 의미, 위 코드에서는 layout fragment를 가져오겠다는 뜻(~{::#content}) : id="content" 로 지정된 부분을 layout fragment의 특정 위치에 대체할 것이라는 의미3. interceptor 코드 분석@Component class PresentationInterceptor( private val httpInterfaceRepository: HttpInterfaceRepository ) : HandlerInterceptor { override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { val httpInterface = HttpInterface(request) httpInterfaceRepository.save(httpInterface) } }private val httpInterfaceRepository: HttpInterfaceRepository의존성 주입을 통해서 Repository를 사용할 수 있다.override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) {afterCompletion : HTTP 요청 처리 후에 호출되는 메서드val httpInterface = HttpInterface(request)httpInterfaceRepository.save(httpInterface)request 정보를 담고 있는 httpInterface 객체를 생성 후, httpInterfaceRepository에 저장. @Configuration class PresentationInterceptorConfiguration( private val presentationInterceptor: PresentationInterceptor ) : WebMvcConfigurer { override fun addInterceptors(registry: InterceptorRegistry) { registry.addInterceptor(presentationInterceptor) .addPathPatterns("/**") .excludePathPatterns("/assets/**", "/css/**", "/js/**", "/admin/**", "h2**", "/favicon.ico", "/error") } }addInterceptors인터셉터를 등록하는 메서드registry.addInterceptor(presentationInterceptor)addInterceptor 메서드를 통해 presentationInterceptor를 등록addPathPatterns("/**")모든 요청 경로에 대해 인터셉터 적용excludePathPatterns(...) : 인터셉터가 동작하지 않도록 설정/assets/**: 정적 자원(예: 이미지, 폰트 등)./css/**: CSS 파일./js/**: JavaScript 파일./admin/**: 관리 페이지.h2**: H2 데이터베이스 콘솔./favicon.ico: 사이트 아이콘./error: 오류 처리 경로.[미션4] 조회 REST API 만들기-회고이번 미션을 하면서 @GetMapping 어노테이션에 대해서는 어느정도 이해를 할 수 있었다. 저번 발자국에서 @Id, @GeneratedValue 어노테이션에 대해서 적었지만 아직 부족하다는 걸 알 수 있었고, @ManyToOne 어노테이션에 대해 더 깊이 공부해야겠다는걸 깨달았다. 아직 Spring에 본질적인걸 이해를 못한걸수도 있는거 같다. 코드를 작성하면 할수록 더 깊게 공부를 해야했고, JAVA 문법도 다시 해야겠다는걸 뼈저리게 느끼면서 한것 같다...3주차 회고Spring은 하면 할수록 재밌는건 맞다. Test 코드를 작성할 때도 이래서 이코드가 작동이 되는것도 알 수 있고, 부분적인 걸 따로 모듈화? 해서 만드는것도 재밌다. 이번 워밍업 클럽도 곧 종료가 되는데 java의 중요성도 깨달아서 java공부도 열심히 하고, Spring에 대해서 더 깊게 공부할거다!참고로 중간점검 때 정보근님께서 내가 작성한 질문에 대해 답변을 해주신거 같다. 나의 질문은 이번 워밍업 클럽이 종료가 되면 java의 정석, spring공부를 할건데 추천해줄 강의가 있냐 라는 질문이었다. 답변은 역시 김영한님의 강의였고 다른 강의도 추천해주셨는데 이거는 확인해보고 글을 수정해야겠다...! 무튼, spring을 선택한건 잘한 일 같다...!

백엔드워밍업클럽javakotlinspringTest코드미션4회고록코드설명백엔드

대협

[인프런 워밍업 클럽 2기 - BE] 2주차 발자국

이 블로그는 정보근님의 입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기 강의 기반으로 코드작성과 코드설명을 적었습니다 이번 2주차 발자국 내용은 spring 테스트 코드에 대한 내용이 대부분이다.아무래도 Spring에서 가장 중요한 요소는 테스트 코드라고 생각되어 강의를 들으면서 썼던 TEST 코드에 대해 하나하나씩 파헤쳐 볼 예정이다 !package com.hyup.portfolio.domain.repository import com.hyup.portfolio.domain.entity.Project import org.springframework.data.jpa.repository.JpaRepository import java.util.Optional interface ProjectRepository : JpaRepository<Project, Long> { fun findAllByIsActive(isActive: Boolean): List<Project> override fun findById(id: Long): Optional<Project> } 위 코드에서 궁금한 내용은 ?[ QUESTION ] findById를 왜 override를 해서 사용하는 이유 -> JpaRepository가 이미 제공하는 메서드를 다시 선언하기 때문에 오버라이드를 해야함-> override를 활용해서 재정의 하면 기능적으로 안좋다.[ WHY ?] override를 활용해서 재정의 하면 기능적으로 안좋은 이유1. 기본 동작의 일관성 문제JpaRepository에서 제공하는 findById는 기본적인 CRUD 동작을 안정적이고 효율적으로 처리하는데, 이를 재정의하면 예상치 못한 문제를 발생시킬 수 있음.다른 개발자들이 코드를 이해할 때, 어려움을 안겨줄 수 있음2. 유지보수성 저하JPA의 업데이트나 변경 사항이 발생했을 때 호환성 문제가 발생할 가능성이 높음기능적 안정성 감소 Spring Data Jpa는 트랜잭션 관리, 데이터베이스 연결 관리, 성능 최적화 등을 내부적으로 처리. 이를 재정의 하면 내부적으로 처리되던 여러 최적화나 기능이 무시될 수 있음 [ SOLVE ] 그럼 override를 활용하지 않고 어떤 방법을 사용할 수 있나?CUSTOM Repository 사용interface ProjectRepository : JpaRepository<Project, Long> { fun findAllByIsActive(isActive: Boolean): List<Project> override fun findById(id: Long): Optional<Project> }interface CustomProjectRepository { fun findByIdCustom(id: Long): Optional<Project> } 쿼리 메서드 활용interface ProjectRepository : JpaRepository<Project, Long> { fun findAllByIsActive(isActive: Boolean): List<Project> fun findByIdAndIsActive(id: Long, isActive: Boolean): Optional<Project> }@DataJpaTest 메서드@DataJpaTest 메서드를 타고 들어가면 @Transactional 이라는 어노테이션 존재@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @BootstrapWith(DataJpaTestContextBootstrapper.class) @ExtendWith(SpringExtension.class) @OverrideAutoConfiguration(enabled = false) @TypeExcludeFilters(DataJpaTypeExcludeFilter.class) @Transactional @AutoConfigureCache @AutoConfigureDataJpa @AutoConfigureTestDatabase @AutoConfigureTestEntityManager @ImportAutoConfiguration public @interface # DataJpaTest 어노테이션이 포함하고 있는 어노테이션 이중 @Transactional 이라는 어노테이션은 테스트 메소드 하나를 하나의 트랜잭션으로 보고 메소드가 종료될 때 그 트랜잭션에서 발생한 작업들을 모두 롤백해줌 [ QUESTION ] 트랜잭션에서 발생한 작업들을 모두롤백해야 하는 이유[ ANSWER ]테스트 간 독립성 보장테스트는 독립적으로 수행되어야 하고, 하나의 테스트가 다른 테스트에 영향을 주지 않아야 함. 트랜잭션을 롤백하면, 테스트 내에서 발생한 모든 데이터 변경이 원래 상태로 돌아가기 때문에 데이터베이스 상태가 항상 초기 상태로 유지데이터 일관성 유지테스트가 끝난 후에도 트랜잭션을 롤백하지 않으면, 테스트 중에 삽입되거나 수정된 데이터가 데이터베이스에 남아 있게 된다. 이렇게 되면 이후의 테스트나 실제 어플리케이션 실행에 영향을 미쳐, 데이터의 일관성이 깨질 수 있음테스트 성능 향상테스트 중 데이터베이스에 많은 데이터를 삽입하거나 수정하는 경우, 이를 실제로 영구 저장하는 것보다 트랜잭션을 롤백하는 것이 성능 면에서 유리.인스턴스 생명주기PER_METHOD (기본값)각 테스트 메서드마다 새로운 인스턴스가 생성각 테스트 메서드는 독립적인 상태 유지테스트마다 새로운 인스턴스가 생성되므로, 테스트 클래스의 상태를 공유할 수 없고 테스트 간의 의존성도 없어야 함.@TestInstance(TestInstance.Lifecycle.PER_METHOD) // 생략 가능 (기본 값) class ExampleTest { @BeforeEach void setUp() { // 테스트 메서드 실행 전 호출됨 } @Test void testA() { // testA 실행 시 새로운 인스턴스가 생성됨 } @Test void testB() { // testB 실행 시 또 다른 새로운 인스턴스가 생성됨 } }PER_METHOD는 각 테스트마다 독립적으로 실행되어서 서로의 상태에 영향을 주지 않지만 상태를 공유하는 것이 불가능하다. 2. PER_CLASS하나의 인스턴스만 생성되고, 모든 테스트 메서드에서 이 인스턴스가 재사용된다.@BeforeAll을 사용하면 클래스 전체에서 한 번만 실행되므로 성능을 향상시킬 수 있음@TestInstance(TestInstance.Lifecycle.PER_CLASS) class ExampleTest { @BeforeAll void initAll() { // 모든 테스트 메서드 실행 전 한 번만 호출됨 } @Test void testA() { // testA 실행 시 동일한 인스턴스가 사용됨 } @Test void testB() { // testB 실행 시에도 동일한 인스턴스가 사용됨 } }PER_CLASS는 상태를 공유할 수 있어 성능이 향상되지만 테스트 간 인스턴스 상태가 공유되므로, 테스트 간 의존성이 발생함.@BeforeAll, @AfterAll@BeforeAll : PER_CLASS에서만 사용되며, 모든 테스트 전에 한 번만 실행@AfterAll : PER_METHOD와 PER_CLASS 모두에 사용되고 모든 테스트 전에 한 번만 실행 됨[QUESTION] @BeforeAll 이 PER_CLASS에서만 사용되는 이유, @AfterAll은 PER_METHOD, PER_CLASS 모두 사용가능한 이유[ANSWER]@BeforeAll은 클래스 수준에서 한 번만 실행되는 메서드. 즉 테스트 클래스의 모든 테스트 메서드가 실행되기 전에 딱 한 번 실행됨PER_CLASS에서는 테스트 클래스에 대해 하나의 인스턴스만 생성되므로, @BeforeAll 메서드가 클래스 인스턴스에서 한 번 실행되고, 이후의 모든 테스트가 동일한 인스턴스를 사용@AfterAll 은 모든 테스트 메서드가 실행된 후에 한 번만 실행되는 메서드이다. 여기서 PER_CLASS에서는 클래스 인스턴스가 하나만 생성되므로, 모든 테스트가 끝나고 한번만 호출되면 된다.PER_METHOD에서는 각 테스트마다 새로운 인스턴스가 생성되지만, @AfterAll이 테스트 메서드가 모두 끝난 후에 한 번 호출되도록 관리할 수 있다.미션 - REST API 설계 이번 미션에서는 REST API 설계하는 미션이 주어졌다. HTTP 주요 메서드 정리 (GET / POST / PUT / PATCH / DELETE)GET : 리소스 조회POST : 요청 데이터 처리, 주로 등록에 사용PUT : 리소스를 대체, 즉 덮어쓰기 수행PATCH : 리소스 부분 변경DELETE : 리소스 삭제이번 미션과 발자국을 하면서 백엔드 개발자가 HTTP 주요 메서드에 대해 집중해야 된다는 것을 알 수 있었다. api를 설계할려면 어쩔수 없이 각 HTTP 메서드에 대해 알아야 URL을 설정할 때 어떻게 만들어야 되는지를 알 수 있기 때문이다. 이번주 는 개인 일정이 너무 많아서 아쉽게도 진도를 다 따라가지 못했다. 발자국은 만들어야 되기 때문에 여기서 내가 가장 공부해볼만한 것이 TEST 코드에 대해서 조사를 하는 것이기 때문에 열심히 하였다.GET, POST, PUT, PATCH, DELETE 메서드에 대해서 조금이라도 공부할 수 있어서 좋았고, 따로 공부해서 블로그에 올려야 겠다고 생각하였다!

백엔드백엔드인프런javakotlin발자국

채널톡 아이콘